162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/device.h> 762306a36Sopenharmony_ci#include <linux/dma-mapping.h> 862306a36Sopenharmony_ci#include <linux/interrupt.h> 962306a36Sopenharmony_ci#include <linux/moduleparam.h> 1062306a36Sopenharmony_ci#include <linux/types.h> 1162306a36Sopenharmony_ci#include <linux/errno.h> 1262306a36Sopenharmony_ci#include <crypto/aes.h> 1362306a36Sopenharmony_ci#include <crypto/internal/des.h> 1462306a36Sopenharmony_ci#include <crypto/internal/skcipher.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "cipher.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic unsigned int aes_sw_max_len = CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN; 1962306a36Sopenharmony_cimodule_param(aes_sw_max_len, uint, 0644); 2062306a36Sopenharmony_ciMODULE_PARM_DESC(aes_sw_max_len, 2162306a36Sopenharmony_ci "Only use hardware for AES requests larger than this " 2262306a36Sopenharmony_ci "[0=always use hardware; anything <16 breaks AES-GCM; default=" 2362306a36Sopenharmony_ci __stringify(CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN)"]"); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic LIST_HEAD(skcipher_algs); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic void qce_skcipher_done(void *data) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci struct crypto_async_request *async_req = data; 3062306a36Sopenharmony_ci struct skcipher_request *req = skcipher_request_cast(async_req); 3162306a36Sopenharmony_ci struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); 3262306a36Sopenharmony_ci struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); 3362306a36Sopenharmony_ci struct qce_device *qce = tmpl->qce; 3462306a36Sopenharmony_ci struct qce_result_dump *result_buf = qce->dma.result_buf; 3562306a36Sopenharmony_ci enum dma_data_direction dir_src, dir_dst; 3662306a36Sopenharmony_ci u32 status; 3762306a36Sopenharmony_ci int error; 3862306a36Sopenharmony_ci bool diff_dst; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci diff_dst = (req->src != req->dst) ? true : false; 4162306a36Sopenharmony_ci dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; 4262306a36Sopenharmony_ci dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci error = qce_dma_terminate_all(&qce->dma); 4562306a36Sopenharmony_ci if (error) 4662306a36Sopenharmony_ci dev_dbg(qce->dev, "skcipher dma termination error (%d)\n", 4762306a36Sopenharmony_ci error); 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci if (diff_dst) 5062306a36Sopenharmony_ci dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); 5162306a36Sopenharmony_ci dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci sg_free_table(&rctx->dst_tbl); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci error = qce_check_status(qce, &status); 5662306a36Sopenharmony_ci if (error < 0) 5762306a36Sopenharmony_ci dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); 6062306a36Sopenharmony_ci qce->async_req_done(tmpl->qce, error); 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistatic int 6462306a36Sopenharmony_ciqce_skcipher_async_req_handle(struct crypto_async_request *async_req) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci struct skcipher_request *req = skcipher_request_cast(async_req); 6762306a36Sopenharmony_ci struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); 6862306a36Sopenharmony_ci struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); 6962306a36Sopenharmony_ci struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); 7062306a36Sopenharmony_ci struct qce_device *qce = tmpl->qce; 7162306a36Sopenharmony_ci enum dma_data_direction dir_src, dir_dst; 7262306a36Sopenharmony_ci struct scatterlist *sg; 7362306a36Sopenharmony_ci bool diff_dst; 7462306a36Sopenharmony_ci gfp_t gfp; 7562306a36Sopenharmony_ci int dst_nents, src_nents, ret; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci rctx->iv = req->iv; 7862306a36Sopenharmony_ci rctx->ivsize = crypto_skcipher_ivsize(skcipher); 7962306a36Sopenharmony_ci rctx->cryptlen = req->cryptlen; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci diff_dst = (req->src != req->dst) ? true : false; 8262306a36Sopenharmony_ci dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; 8362306a36Sopenharmony_ci dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci rctx->src_nents = sg_nents_for_len(req->src, req->cryptlen); 8662306a36Sopenharmony_ci if (diff_dst) 8762306a36Sopenharmony_ci rctx->dst_nents = sg_nents_for_len(req->dst, req->cryptlen); 8862306a36Sopenharmony_ci else 8962306a36Sopenharmony_ci rctx->dst_nents = rctx->src_nents; 9062306a36Sopenharmony_ci if (rctx->src_nents < 0) { 9162306a36Sopenharmony_ci dev_err(qce->dev, "Invalid numbers of src SG.\n"); 9262306a36Sopenharmony_ci return rctx->src_nents; 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci if (rctx->dst_nents < 0) { 9562306a36Sopenharmony_ci dev_err(qce->dev, "Invalid numbers of dst SG.\n"); 9662306a36Sopenharmony_ci return -rctx->dst_nents; 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci rctx->dst_nents += 1; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? 10262306a36Sopenharmony_ci GFP_KERNEL : GFP_ATOMIC; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp); 10562306a36Sopenharmony_ci if (ret) 10662306a36Sopenharmony_ci return ret; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, req->cryptlen); 11162306a36Sopenharmony_ci if (IS_ERR(sg)) { 11262306a36Sopenharmony_ci ret = PTR_ERR(sg); 11362306a36Sopenharmony_ci goto error_free; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 11762306a36Sopenharmony_ci QCE_RESULT_BUF_SZ); 11862306a36Sopenharmony_ci if (IS_ERR(sg)) { 11962306a36Sopenharmony_ci ret = PTR_ERR(sg); 12062306a36Sopenharmony_ci goto error_free; 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci sg_mark_end(sg); 12462306a36Sopenharmony_ci rctx->dst_sg = rctx->dst_tbl.sgl; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci dst_nents = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); 12762306a36Sopenharmony_ci if (!dst_nents) { 12862306a36Sopenharmony_ci ret = -EIO; 12962306a36Sopenharmony_ci goto error_free; 13062306a36Sopenharmony_ci } 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci if (diff_dst) { 13362306a36Sopenharmony_ci src_nents = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src); 13462306a36Sopenharmony_ci if (!src_nents) { 13562306a36Sopenharmony_ci ret = -EIO; 13662306a36Sopenharmony_ci goto error_unmap_dst; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci rctx->src_sg = req->src; 13962306a36Sopenharmony_ci } else { 14062306a36Sopenharmony_ci rctx->src_sg = rctx->dst_sg; 14162306a36Sopenharmony_ci src_nents = dst_nents - 1; 14262306a36Sopenharmony_ci } 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents, 14562306a36Sopenharmony_ci rctx->dst_sg, dst_nents, 14662306a36Sopenharmony_ci qce_skcipher_done, async_req); 14762306a36Sopenharmony_ci if (ret) 14862306a36Sopenharmony_ci goto error_unmap_src; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci qce_dma_issue_pending(&qce->dma); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci ret = qce_start(async_req, tmpl->crypto_alg_type); 15362306a36Sopenharmony_ci if (ret) 15462306a36Sopenharmony_ci goto error_terminate; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci return 0; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cierror_terminate: 15962306a36Sopenharmony_ci qce_dma_terminate_all(&qce->dma); 16062306a36Sopenharmony_cierror_unmap_src: 16162306a36Sopenharmony_ci if (diff_dst) 16262306a36Sopenharmony_ci dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src); 16362306a36Sopenharmony_cierror_unmap_dst: 16462306a36Sopenharmony_ci dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); 16562306a36Sopenharmony_cierror_free: 16662306a36Sopenharmony_ci sg_free_table(&rctx->dst_tbl); 16762306a36Sopenharmony_ci return ret; 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, 17162306a36Sopenharmony_ci unsigned int keylen) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk); 17462306a36Sopenharmony_ci struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); 17562306a36Sopenharmony_ci unsigned long flags = to_cipher_tmpl(ablk)->alg_flags; 17662306a36Sopenharmony_ci unsigned int __keylen; 17762306a36Sopenharmony_ci int ret; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci if (!key || !keylen) 18062306a36Sopenharmony_ci return -EINVAL; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci /* 18362306a36Sopenharmony_ci * AES XTS key1 = key2 not supported by crypto engine. 18462306a36Sopenharmony_ci * Revisit to request a fallback cipher in this case. 18562306a36Sopenharmony_ci */ 18662306a36Sopenharmony_ci if (IS_XTS(flags)) { 18762306a36Sopenharmony_ci __keylen = keylen >> 1; 18862306a36Sopenharmony_ci if (!memcmp(key, key + __keylen, __keylen)) 18962306a36Sopenharmony_ci return -ENOKEY; 19062306a36Sopenharmony_ci } else { 19162306a36Sopenharmony_ci __keylen = keylen; 19262306a36Sopenharmony_ci } 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci switch (__keylen) { 19562306a36Sopenharmony_ci case AES_KEYSIZE_128: 19662306a36Sopenharmony_ci case AES_KEYSIZE_256: 19762306a36Sopenharmony_ci memcpy(ctx->enc_key, key, keylen); 19862306a36Sopenharmony_ci break; 19962306a36Sopenharmony_ci case AES_KEYSIZE_192: 20062306a36Sopenharmony_ci break; 20162306a36Sopenharmony_ci default: 20262306a36Sopenharmony_ci return -EINVAL; 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci ret = crypto_skcipher_setkey(ctx->fallback, key, keylen); 20662306a36Sopenharmony_ci if (!ret) 20762306a36Sopenharmony_ci ctx->enc_keylen = keylen; 20862306a36Sopenharmony_ci return ret; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic int qce_des_setkey(struct crypto_skcipher *ablk, const u8 *key, 21262306a36Sopenharmony_ci unsigned int keylen) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); 21562306a36Sopenharmony_ci int err; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci err = verify_skcipher_des_key(ablk, key); 21862306a36Sopenharmony_ci if (err) 21962306a36Sopenharmony_ci return err; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci ctx->enc_keylen = keylen; 22262306a36Sopenharmony_ci memcpy(ctx->enc_key, key, keylen); 22362306a36Sopenharmony_ci return 0; 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key, 22762306a36Sopenharmony_ci unsigned int keylen) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); 23062306a36Sopenharmony_ci u32 _key[6]; 23162306a36Sopenharmony_ci int err; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci err = verify_skcipher_des3_key(ablk, key); 23462306a36Sopenharmony_ci if (err) 23562306a36Sopenharmony_ci return err; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci /* 23862306a36Sopenharmony_ci * The crypto engine does not support any two keys 23962306a36Sopenharmony_ci * being the same for triple des algorithms. The 24062306a36Sopenharmony_ci * verify_skcipher_des3_key does not check for all the 24162306a36Sopenharmony_ci * below conditions. Return -ENOKEY in case any two keys 24262306a36Sopenharmony_ci * are the same. Revisit to see if a fallback cipher 24362306a36Sopenharmony_ci * is needed to handle this condition. 24462306a36Sopenharmony_ci */ 24562306a36Sopenharmony_ci memcpy(_key, key, DES3_EDE_KEY_SIZE); 24662306a36Sopenharmony_ci if (!((_key[0] ^ _key[2]) | (_key[1] ^ _key[3])) || 24762306a36Sopenharmony_ci !((_key[2] ^ _key[4]) | (_key[3] ^ _key[5])) || 24862306a36Sopenharmony_ci !((_key[0] ^ _key[4]) | (_key[1] ^ _key[5]))) 24962306a36Sopenharmony_ci return -ENOKEY; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci ctx->enc_keylen = keylen; 25262306a36Sopenharmony_ci memcpy(ctx->enc_key, key, keylen); 25362306a36Sopenharmony_ci return 0; 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 25962306a36Sopenharmony_ci struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); 26062306a36Sopenharmony_ci struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); 26162306a36Sopenharmony_ci struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); 26262306a36Sopenharmony_ci unsigned int blocksize = crypto_skcipher_blocksize(tfm); 26362306a36Sopenharmony_ci int keylen; 26462306a36Sopenharmony_ci int ret; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci rctx->flags = tmpl->alg_flags; 26762306a36Sopenharmony_ci rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; 26862306a36Sopenharmony_ci keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci /* CE does not handle 0 length messages */ 27162306a36Sopenharmony_ci if (!req->cryptlen) 27262306a36Sopenharmony_ci return 0; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci /* 27562306a36Sopenharmony_ci * ECB and CBC algorithms require message lengths to be 27662306a36Sopenharmony_ci * multiples of block size. 27762306a36Sopenharmony_ci */ 27862306a36Sopenharmony_ci if (IS_ECB(rctx->flags) || IS_CBC(rctx->flags)) 27962306a36Sopenharmony_ci if (!IS_ALIGNED(req->cryptlen, blocksize)) 28062306a36Sopenharmony_ci return -EINVAL; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci /* 28362306a36Sopenharmony_ci * Conditions for requesting a fallback cipher 28462306a36Sopenharmony_ci * AES-192 (not supported by crypto engine (CE)) 28562306a36Sopenharmony_ci * AES-XTS request with len <= 512 byte (not recommended to use CE) 28662306a36Sopenharmony_ci * AES-XTS request with len > QCE_SECTOR_SIZE and 28762306a36Sopenharmony_ci * is not a multiple of it.(Revisit this condition to check if it is 28862306a36Sopenharmony_ci * needed in all versions of CE) 28962306a36Sopenharmony_ci */ 29062306a36Sopenharmony_ci if (IS_AES(rctx->flags) && 29162306a36Sopenharmony_ci ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || 29262306a36Sopenharmony_ci (IS_XTS(rctx->flags) && ((req->cryptlen <= aes_sw_max_len) || 29362306a36Sopenharmony_ci (req->cryptlen > QCE_SECTOR_SIZE && 29462306a36Sopenharmony_ci req->cryptlen % QCE_SECTOR_SIZE))))) { 29562306a36Sopenharmony_ci skcipher_request_set_tfm(&rctx->fallback_req, ctx->fallback); 29662306a36Sopenharmony_ci skcipher_request_set_callback(&rctx->fallback_req, 29762306a36Sopenharmony_ci req->base.flags, 29862306a36Sopenharmony_ci req->base.complete, 29962306a36Sopenharmony_ci req->base.data); 30062306a36Sopenharmony_ci skcipher_request_set_crypt(&rctx->fallback_req, req->src, 30162306a36Sopenharmony_ci req->dst, req->cryptlen, req->iv); 30262306a36Sopenharmony_ci ret = encrypt ? crypto_skcipher_encrypt(&rctx->fallback_req) : 30362306a36Sopenharmony_ci crypto_skcipher_decrypt(&rctx->fallback_req); 30462306a36Sopenharmony_ci return ret; 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic int qce_skcipher_encrypt(struct skcipher_request *req) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci return qce_skcipher_crypt(req, 1); 31362306a36Sopenharmony_ci} 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_cistatic int qce_skcipher_decrypt(struct skcipher_request *req) 31662306a36Sopenharmony_ci{ 31762306a36Sopenharmony_ci return qce_skcipher_crypt(req, 0); 31862306a36Sopenharmony_ci} 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_cistatic int qce_skcipher_init(struct crypto_skcipher *tfm) 32162306a36Sopenharmony_ci{ 32262306a36Sopenharmony_ci /* take the size without the fallback skcipher_request at the end */ 32362306a36Sopenharmony_ci crypto_skcipher_set_reqsize(tfm, offsetof(struct qce_cipher_reqctx, 32462306a36Sopenharmony_ci fallback_req)); 32562306a36Sopenharmony_ci return 0; 32662306a36Sopenharmony_ci} 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_cistatic int qce_skcipher_init_fallback(struct crypto_skcipher *tfm) 32962306a36Sopenharmony_ci{ 33062306a36Sopenharmony_ci struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci ctx->fallback = crypto_alloc_skcipher(crypto_tfm_alg_name(&tfm->base), 33362306a36Sopenharmony_ci 0, CRYPTO_ALG_NEED_FALLBACK); 33462306a36Sopenharmony_ci if (IS_ERR(ctx->fallback)) 33562306a36Sopenharmony_ci return PTR_ERR(ctx->fallback); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx) + 33862306a36Sopenharmony_ci crypto_skcipher_reqsize(ctx->fallback)); 33962306a36Sopenharmony_ci return 0; 34062306a36Sopenharmony_ci} 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic void qce_skcipher_exit(struct crypto_skcipher *tfm) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci crypto_free_skcipher(ctx->fallback); 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_cistruct qce_skcipher_def { 35062306a36Sopenharmony_ci unsigned long flags; 35162306a36Sopenharmony_ci const char *name; 35262306a36Sopenharmony_ci const char *drv_name; 35362306a36Sopenharmony_ci unsigned int blocksize; 35462306a36Sopenharmony_ci unsigned int chunksize; 35562306a36Sopenharmony_ci unsigned int ivsize; 35662306a36Sopenharmony_ci unsigned int min_keysize; 35762306a36Sopenharmony_ci unsigned int max_keysize; 35862306a36Sopenharmony_ci}; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cistatic const struct qce_skcipher_def skcipher_def[] = { 36162306a36Sopenharmony_ci { 36262306a36Sopenharmony_ci .flags = QCE_ALG_AES | QCE_MODE_ECB, 36362306a36Sopenharmony_ci .name = "ecb(aes)", 36462306a36Sopenharmony_ci .drv_name = "ecb-aes-qce", 36562306a36Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 36662306a36Sopenharmony_ci .ivsize = 0, 36762306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 36862306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 36962306a36Sopenharmony_ci }, 37062306a36Sopenharmony_ci { 37162306a36Sopenharmony_ci .flags = QCE_ALG_AES | QCE_MODE_CBC, 37262306a36Sopenharmony_ci .name = "cbc(aes)", 37362306a36Sopenharmony_ci .drv_name = "cbc-aes-qce", 37462306a36Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 37562306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 37662306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 37762306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 37862306a36Sopenharmony_ci }, 37962306a36Sopenharmony_ci { 38062306a36Sopenharmony_ci .flags = QCE_ALG_AES | QCE_MODE_CTR, 38162306a36Sopenharmony_ci .name = "ctr(aes)", 38262306a36Sopenharmony_ci .drv_name = "ctr-aes-qce", 38362306a36Sopenharmony_ci .blocksize = 1, 38462306a36Sopenharmony_ci .chunksize = AES_BLOCK_SIZE, 38562306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 38662306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 38762306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 38862306a36Sopenharmony_ci }, 38962306a36Sopenharmony_ci { 39062306a36Sopenharmony_ci .flags = QCE_ALG_AES | QCE_MODE_XTS, 39162306a36Sopenharmony_ci .name = "xts(aes)", 39262306a36Sopenharmony_ci .drv_name = "xts-aes-qce", 39362306a36Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 39462306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 39562306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE * 2, 39662306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE * 2, 39762306a36Sopenharmony_ci }, 39862306a36Sopenharmony_ci { 39962306a36Sopenharmony_ci .flags = QCE_ALG_DES | QCE_MODE_ECB, 40062306a36Sopenharmony_ci .name = "ecb(des)", 40162306a36Sopenharmony_ci .drv_name = "ecb-des-qce", 40262306a36Sopenharmony_ci .blocksize = DES_BLOCK_SIZE, 40362306a36Sopenharmony_ci .ivsize = 0, 40462306a36Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 40562306a36Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 40662306a36Sopenharmony_ci }, 40762306a36Sopenharmony_ci { 40862306a36Sopenharmony_ci .flags = QCE_ALG_DES | QCE_MODE_CBC, 40962306a36Sopenharmony_ci .name = "cbc(des)", 41062306a36Sopenharmony_ci .drv_name = "cbc-des-qce", 41162306a36Sopenharmony_ci .blocksize = DES_BLOCK_SIZE, 41262306a36Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 41362306a36Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 41462306a36Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 41562306a36Sopenharmony_ci }, 41662306a36Sopenharmony_ci { 41762306a36Sopenharmony_ci .flags = QCE_ALG_3DES | QCE_MODE_ECB, 41862306a36Sopenharmony_ci .name = "ecb(des3_ede)", 41962306a36Sopenharmony_ci .drv_name = "ecb-3des-qce", 42062306a36Sopenharmony_ci .blocksize = DES3_EDE_BLOCK_SIZE, 42162306a36Sopenharmony_ci .ivsize = 0, 42262306a36Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 42362306a36Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 42462306a36Sopenharmony_ci }, 42562306a36Sopenharmony_ci { 42662306a36Sopenharmony_ci .flags = QCE_ALG_3DES | QCE_MODE_CBC, 42762306a36Sopenharmony_ci .name = "cbc(des3_ede)", 42862306a36Sopenharmony_ci .drv_name = "cbc-3des-qce", 42962306a36Sopenharmony_ci .blocksize = DES3_EDE_BLOCK_SIZE, 43062306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 43162306a36Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 43262306a36Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 43362306a36Sopenharmony_ci }, 43462306a36Sopenharmony_ci}; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_cistatic int qce_skcipher_register_one(const struct qce_skcipher_def *def, 43762306a36Sopenharmony_ci struct qce_device *qce) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci struct qce_alg_template *tmpl; 44062306a36Sopenharmony_ci struct skcipher_alg *alg; 44162306a36Sopenharmony_ci int ret; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); 44462306a36Sopenharmony_ci if (!tmpl) 44562306a36Sopenharmony_ci return -ENOMEM; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci alg = &tmpl->alg.skcipher; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); 45062306a36Sopenharmony_ci snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 45162306a36Sopenharmony_ci def->drv_name); 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci alg->base.cra_blocksize = def->blocksize; 45462306a36Sopenharmony_ci alg->chunksize = def->chunksize; 45562306a36Sopenharmony_ci alg->ivsize = def->ivsize; 45662306a36Sopenharmony_ci alg->min_keysize = def->min_keysize; 45762306a36Sopenharmony_ci alg->max_keysize = def->max_keysize; 45862306a36Sopenharmony_ci alg->setkey = IS_3DES(def->flags) ? qce_des3_setkey : 45962306a36Sopenharmony_ci IS_DES(def->flags) ? qce_des_setkey : 46062306a36Sopenharmony_ci qce_skcipher_setkey; 46162306a36Sopenharmony_ci alg->encrypt = qce_skcipher_encrypt; 46262306a36Sopenharmony_ci alg->decrypt = qce_skcipher_decrypt; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci alg->base.cra_priority = 300; 46562306a36Sopenharmony_ci alg->base.cra_flags = CRYPTO_ALG_ASYNC | 46662306a36Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY | 46762306a36Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY; 46862306a36Sopenharmony_ci alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); 46962306a36Sopenharmony_ci alg->base.cra_alignmask = 0; 47062306a36Sopenharmony_ci alg->base.cra_module = THIS_MODULE; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci if (IS_AES(def->flags)) { 47362306a36Sopenharmony_ci alg->base.cra_flags |= CRYPTO_ALG_NEED_FALLBACK; 47462306a36Sopenharmony_ci alg->init = qce_skcipher_init_fallback; 47562306a36Sopenharmony_ci alg->exit = qce_skcipher_exit; 47662306a36Sopenharmony_ci } else { 47762306a36Sopenharmony_ci alg->init = qce_skcipher_init; 47862306a36Sopenharmony_ci } 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci INIT_LIST_HEAD(&tmpl->entry); 48162306a36Sopenharmony_ci tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; 48262306a36Sopenharmony_ci tmpl->alg_flags = def->flags; 48362306a36Sopenharmony_ci tmpl->qce = qce; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci ret = crypto_register_skcipher(alg); 48662306a36Sopenharmony_ci if (ret) { 48762306a36Sopenharmony_ci dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name); 48862306a36Sopenharmony_ci kfree(tmpl); 48962306a36Sopenharmony_ci return ret; 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci list_add_tail(&tmpl->entry, &skcipher_algs); 49362306a36Sopenharmony_ci dev_dbg(qce->dev, "%s is registered\n", alg->base.cra_name); 49462306a36Sopenharmony_ci return 0; 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_cistatic void qce_skcipher_unregister(struct qce_device *qce) 49862306a36Sopenharmony_ci{ 49962306a36Sopenharmony_ci struct qce_alg_template *tmpl, *n; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci list_for_each_entry_safe(tmpl, n, &skcipher_algs, entry) { 50262306a36Sopenharmony_ci crypto_unregister_skcipher(&tmpl->alg.skcipher); 50362306a36Sopenharmony_ci list_del(&tmpl->entry); 50462306a36Sopenharmony_ci kfree(tmpl); 50562306a36Sopenharmony_ci } 50662306a36Sopenharmony_ci} 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_cistatic int qce_skcipher_register(struct qce_device *qce) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci int ret, i; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(skcipher_def); i++) { 51362306a36Sopenharmony_ci ret = qce_skcipher_register_one(&skcipher_def[i], qce); 51462306a36Sopenharmony_ci if (ret) 51562306a36Sopenharmony_ci goto err; 51662306a36Sopenharmony_ci } 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci return 0; 51962306a36Sopenharmony_cierr: 52062306a36Sopenharmony_ci qce_skcipher_unregister(qce); 52162306a36Sopenharmony_ci return ret; 52262306a36Sopenharmony_ci} 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ciconst struct qce_algo_ops skcipher_ops = { 52562306a36Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 52662306a36Sopenharmony_ci .register_algs = qce_skcipher_register, 52762306a36Sopenharmony_ci .unregister_algs = qce_skcipher_unregister, 52862306a36Sopenharmony_ci .async_req_handle = qce_skcipher_async_req_handle, 52962306a36Sopenharmony_ci}; 530