18bf08715SArd Biesheuvel // SPDX-License-Identifier: GPL-2.0-only 28bf08715SArd Biesheuvel /* 38bf08715SArd Biesheuvel * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. 48bf08715SArd Biesheuvel */ 58bf08715SArd Biesheuvel 68bf08715SArd Biesheuvel #include <linux/device.h> 70c3dc787SHerbert Xu #include <linux/dma-mapping.h> 88bf08715SArd Biesheuvel #include <linux/interrupt.h> 9ce163ba0SEneas U de Queiroz #include <linux/moduleparam.h> 108bf08715SArd Biesheuvel #include <linux/types.h> 11*f0878946SThara Gopinath #include <linux/errno.h> 128bf08715SArd Biesheuvel #include <crypto/aes.h> 138bf08715SArd Biesheuvel #include <crypto/internal/des.h> 148bf08715SArd Biesheuvel #include <crypto/internal/skcipher.h> 158bf08715SArd Biesheuvel 168bf08715SArd Biesheuvel #include "cipher.h" 178bf08715SArd Biesheuvel 18ce163ba0SEneas U de Queiroz static unsigned int aes_sw_max_len = CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN; 19ce163ba0SEneas U de Queiroz module_param(aes_sw_max_len, uint, 0644); 20ce163ba0SEneas U de Queiroz MODULE_PARM_DESC(aes_sw_max_len, 21ce163ba0SEneas U de Queiroz "Only use hardware for AES requests larger than this " 22ce163ba0SEneas U de Queiroz "[0=always use hardware; anything <16 breaks AES-GCM; default=" 23d069b204SEneas U de Queiroz __stringify(CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN)"]"); 24ce163ba0SEneas U de Queiroz 258bf08715SArd Biesheuvel static LIST_HEAD(skcipher_algs); 268bf08715SArd Biesheuvel 278bf08715SArd Biesheuvel static void qce_skcipher_done(void *data) 288bf08715SArd Biesheuvel { 298bf08715SArd Biesheuvel struct crypto_async_request *async_req = data; 308bf08715SArd Biesheuvel struct skcipher_request *req = skcipher_request_cast(async_req); 318bf08715SArd Biesheuvel struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); 328bf08715SArd Biesheuvel struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); 338bf08715SArd Biesheuvel struct qce_device *qce = tmpl->qce; 343e806a12SEneas U de Queiroz struct qce_result_dump *result_buf = qce->dma.result_buf; 358bf08715SArd Biesheuvel enum dma_data_direction dir_src, dir_dst; 368bf08715SArd Biesheuvel u32 status; 378bf08715SArd Biesheuvel int error; 388bf08715SArd Biesheuvel bool diff_dst; 398bf08715SArd Biesheuvel 408bf08715SArd Biesheuvel diff_dst = (req->src != req->dst) ? true : false; 418bf08715SArd Biesheuvel dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; 428bf08715SArd Biesheuvel dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; 438bf08715SArd Biesheuvel 448bf08715SArd Biesheuvel error = qce_dma_terminate_all(&qce->dma); 458bf08715SArd Biesheuvel if (error) 468bf08715SArd Biesheuvel dev_dbg(qce->dev, "skcipher dma termination error (%d)\n", 478bf08715SArd Biesheuvel error); 488bf08715SArd Biesheuvel 498bf08715SArd Biesheuvel if (diff_dst) 508bf08715SArd Biesheuvel dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src); 518bf08715SArd Biesheuvel dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); 528bf08715SArd Biesheuvel 538bf08715SArd Biesheuvel sg_free_table(&rctx->dst_tbl); 548bf08715SArd Biesheuvel 558bf08715SArd Biesheuvel error = qce_check_status(qce, &status); 568bf08715SArd Biesheuvel if (error < 0) 578bf08715SArd Biesheuvel dev_dbg(qce->dev, "skcipher operation error (%x)\n", status); 588bf08715SArd Biesheuvel 593e806a12SEneas U de Queiroz memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize); 608bf08715SArd Biesheuvel qce->async_req_done(tmpl->qce, error); 618bf08715SArd Biesheuvel } 628bf08715SArd Biesheuvel 638bf08715SArd Biesheuvel static int 648bf08715SArd Biesheuvel qce_skcipher_async_req_handle(struct crypto_async_request *async_req) 658bf08715SArd Biesheuvel { 668bf08715SArd Biesheuvel struct skcipher_request *req = skcipher_request_cast(async_req); 678bf08715SArd Biesheuvel struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); 688bf08715SArd Biesheuvel struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); 698bf08715SArd Biesheuvel struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req)); 708bf08715SArd Biesheuvel struct qce_device *qce = tmpl->qce; 718bf08715SArd Biesheuvel enum dma_data_direction dir_src, dir_dst; 728bf08715SArd Biesheuvel struct scatterlist *sg; 738bf08715SArd Biesheuvel bool diff_dst; 748bf08715SArd Biesheuvel gfp_t gfp; 758bf08715SArd Biesheuvel int ret; 768bf08715SArd Biesheuvel 778bf08715SArd Biesheuvel rctx->iv = req->iv; 788bf08715SArd Biesheuvel rctx->ivsize = crypto_skcipher_ivsize(skcipher); 798bf08715SArd Biesheuvel rctx->cryptlen = req->cryptlen; 808bf08715SArd Biesheuvel 818bf08715SArd Biesheuvel diff_dst = (req->src != req->dst) ? true : false; 828bf08715SArd Biesheuvel dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL; 838bf08715SArd Biesheuvel dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL; 848bf08715SArd Biesheuvel 858bf08715SArd Biesheuvel rctx->src_nents = sg_nents_for_len(req->src, req->cryptlen); 868bf08715SArd Biesheuvel if (diff_dst) 878bf08715SArd Biesheuvel rctx->dst_nents = sg_nents_for_len(req->dst, req->cryptlen); 888bf08715SArd Biesheuvel else 898bf08715SArd Biesheuvel rctx->dst_nents = rctx->src_nents; 908bf08715SArd Biesheuvel if (rctx->src_nents < 0) { 918bf08715SArd Biesheuvel dev_err(qce->dev, "Invalid numbers of src SG.\n"); 928bf08715SArd Biesheuvel return rctx->src_nents; 938bf08715SArd Biesheuvel } 948bf08715SArd Biesheuvel if (rctx->dst_nents < 0) { 958bf08715SArd Biesheuvel dev_err(qce->dev, "Invalid numbers of dst SG.\n"); 968bf08715SArd Biesheuvel return -rctx->dst_nents; 978bf08715SArd Biesheuvel } 988bf08715SArd Biesheuvel 998bf08715SArd Biesheuvel rctx->dst_nents += 1; 1008bf08715SArd Biesheuvel 1018bf08715SArd Biesheuvel gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? 1028bf08715SArd Biesheuvel GFP_KERNEL : GFP_ATOMIC; 1038bf08715SArd Biesheuvel 1048bf08715SArd Biesheuvel ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp); 1058bf08715SArd Biesheuvel if (ret) 1068bf08715SArd Biesheuvel return ret; 1078bf08715SArd Biesheuvel 1088bf08715SArd Biesheuvel sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ); 1098bf08715SArd Biesheuvel 110d6364b81SEneas U de Queiroz sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, req->cryptlen); 1118bf08715SArd Biesheuvel if (IS_ERR(sg)) { 1128bf08715SArd Biesheuvel ret = PTR_ERR(sg); 1138bf08715SArd Biesheuvel goto error_free; 1148bf08715SArd Biesheuvel } 1158bf08715SArd Biesheuvel 116d6364b81SEneas U de Queiroz sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg, 117d6364b81SEneas U de Queiroz QCE_RESULT_BUF_SZ); 1188bf08715SArd Biesheuvel if (IS_ERR(sg)) { 1198bf08715SArd Biesheuvel ret = PTR_ERR(sg); 1208bf08715SArd Biesheuvel goto error_free; 1218bf08715SArd Biesheuvel } 1228bf08715SArd Biesheuvel 1238bf08715SArd Biesheuvel sg_mark_end(sg); 1248bf08715SArd Biesheuvel rctx->dst_sg = rctx->dst_tbl.sgl; 1258bf08715SArd Biesheuvel 1268bf08715SArd Biesheuvel ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); 1278bf08715SArd Biesheuvel if (ret < 0) 1288bf08715SArd Biesheuvel goto error_free; 1298bf08715SArd Biesheuvel 1308bf08715SArd Biesheuvel if (diff_dst) { 1318bf08715SArd Biesheuvel ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src); 1328bf08715SArd Biesheuvel if (ret < 0) 1338bf08715SArd Biesheuvel goto error_unmap_dst; 1348bf08715SArd Biesheuvel rctx->src_sg = req->src; 1358bf08715SArd Biesheuvel } else { 1368bf08715SArd Biesheuvel rctx->src_sg = rctx->dst_sg; 1378bf08715SArd Biesheuvel } 1388bf08715SArd Biesheuvel 1398bf08715SArd Biesheuvel ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents, 1408bf08715SArd Biesheuvel rctx->dst_sg, rctx->dst_nents, 1418bf08715SArd Biesheuvel qce_skcipher_done, async_req); 1428bf08715SArd Biesheuvel if (ret) 1438bf08715SArd Biesheuvel goto error_unmap_src; 1448bf08715SArd Biesheuvel 1458bf08715SArd Biesheuvel qce_dma_issue_pending(&qce->dma); 1468bf08715SArd Biesheuvel 1478bf08715SArd Biesheuvel ret = qce_start(async_req, tmpl->crypto_alg_type, req->cryptlen, 0); 1488bf08715SArd Biesheuvel if (ret) 1498bf08715SArd Biesheuvel goto error_terminate; 1508bf08715SArd Biesheuvel 1518bf08715SArd Biesheuvel return 0; 1528bf08715SArd Biesheuvel 1538bf08715SArd Biesheuvel error_terminate: 1548bf08715SArd Biesheuvel qce_dma_terminate_all(&qce->dma); 1558bf08715SArd Biesheuvel error_unmap_src: 1568bf08715SArd Biesheuvel if (diff_dst) 1578bf08715SArd Biesheuvel dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src); 1588bf08715SArd Biesheuvel error_unmap_dst: 1598bf08715SArd Biesheuvel dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); 1608bf08715SArd Biesheuvel error_free: 1618bf08715SArd Biesheuvel sg_free_table(&rctx->dst_tbl); 1628bf08715SArd Biesheuvel return ret; 1638bf08715SArd Biesheuvel } 1648bf08715SArd Biesheuvel 1658bf08715SArd Biesheuvel static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key, 1668bf08715SArd Biesheuvel unsigned int keylen) 1678bf08715SArd Biesheuvel { 1688bf08715SArd Biesheuvel struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk); 1698bf08715SArd Biesheuvel struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm); 1707de4c2bdSEneas U de Queiroz unsigned long flags = to_cipher_tmpl(ablk)->alg_flags; 171f0d078ddSThara Gopinath unsigned int __keylen; 1728bf08715SArd Biesheuvel int ret; 1738bf08715SArd Biesheuvel 1748bf08715SArd Biesheuvel if (!key || !keylen) 1758bf08715SArd Biesheuvel return -EINVAL; 1768bf08715SArd Biesheuvel 177f0d078ddSThara Gopinath /* 178f0d078ddSThara Gopinath * AES XTS key1 = key2 not supported by crypto engine. 179f0d078ddSThara Gopinath * Revisit to request a fallback cipher in this case. 180f0d078ddSThara Gopinath */ 181f0d078ddSThara Gopinath if (IS_XTS(flags)) { 182f0d078ddSThara Gopinath __keylen = keylen >> 1; 183f0d078ddSThara Gopinath if (!memcmp(key, key + __keylen, __keylen)) 184f0d078ddSThara Gopinath return -ENOKEY; 185f0d078ddSThara Gopinath } else { 186f0d078ddSThara Gopinath __keylen = keylen; 187f0d078ddSThara Gopinath } 188f0d078ddSThara Gopinath 189f0d078ddSThara Gopinath switch (__keylen) { 1908bf08715SArd Biesheuvel case AES_KEYSIZE_128: 1918bf08715SArd Biesheuvel case AES_KEYSIZE_256: 192ce163ba0SEneas U de Queiroz memcpy(ctx->enc_key, key, keylen); 1938bf08715SArd Biesheuvel break; 194f0d078ddSThara Gopinath case AES_KEYSIZE_192: 195f0d078ddSThara Gopinath break; 196f0d078ddSThara Gopinath default: 197f0d078ddSThara Gopinath return -EINVAL; 1988bf08715SArd Biesheuvel } 1998bf08715SArd Biesheuvel 20090e2f782SArd Biesheuvel ret = crypto_skcipher_setkey(ctx->fallback, key, keylen); 2018bf08715SArd Biesheuvel if (!ret) 2028bf08715SArd Biesheuvel ctx->enc_keylen = keylen; 2038bf08715SArd Biesheuvel return ret; 2048bf08715SArd Biesheuvel } 2058bf08715SArd Biesheuvel 2068bf08715SArd Biesheuvel static int qce_des_setkey(struct crypto_skcipher *ablk, const u8 *key, 2078bf08715SArd Biesheuvel unsigned int keylen) 2088bf08715SArd Biesheuvel { 2098bf08715SArd Biesheuvel struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); 2108bf08715SArd Biesheuvel int err; 2118bf08715SArd Biesheuvel 2128bf08715SArd Biesheuvel err = verify_skcipher_des_key(ablk, key); 2138bf08715SArd Biesheuvel if (err) 2148bf08715SArd Biesheuvel return err; 2158bf08715SArd Biesheuvel 2168bf08715SArd Biesheuvel ctx->enc_keylen = keylen; 2178bf08715SArd Biesheuvel memcpy(ctx->enc_key, key, keylen); 2188bf08715SArd Biesheuvel return 0; 2198bf08715SArd Biesheuvel } 2208bf08715SArd Biesheuvel 2218bf08715SArd Biesheuvel static int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key, 2228bf08715SArd Biesheuvel unsigned int keylen) 2238bf08715SArd Biesheuvel { 2248bf08715SArd Biesheuvel struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk); 22542f730a4SThara Gopinath u32 _key[6]; 2268bf08715SArd Biesheuvel int err; 2278bf08715SArd Biesheuvel 2288bf08715SArd Biesheuvel err = verify_skcipher_des3_key(ablk, key); 2298bf08715SArd Biesheuvel if (err) 2308bf08715SArd Biesheuvel return err; 2318bf08715SArd Biesheuvel 23242f730a4SThara Gopinath /* 23342f730a4SThara Gopinath * The crypto engine does not support any two keys 23442f730a4SThara Gopinath * being the same for triple des algorithms. The 23542f730a4SThara Gopinath * verify_skcipher_des3_key does not check for all the 23642f730a4SThara Gopinath * below conditions. Return -ENOKEY in case any two keys 23742f730a4SThara Gopinath * are the same. Revisit to see if a fallback cipher 23842f730a4SThara Gopinath * is needed to handle this condition. 23942f730a4SThara Gopinath */ 24042f730a4SThara Gopinath memcpy(_key, key, DES3_EDE_KEY_SIZE); 24142f730a4SThara Gopinath if (!((_key[0] ^ _key[2]) | (_key[1] ^ _key[3])) || 24242f730a4SThara Gopinath !((_key[2] ^ _key[4]) | (_key[3] ^ _key[5])) || 24342f730a4SThara Gopinath !((_key[0] ^ _key[4]) | (_key[1] ^ _key[5]))) 24442f730a4SThara Gopinath return -ENOKEY; 24542f730a4SThara Gopinath 2468bf08715SArd Biesheuvel ctx->enc_keylen = keylen; 2478bf08715SArd Biesheuvel memcpy(ctx->enc_key, key, keylen); 2488bf08715SArd Biesheuvel return 0; 2498bf08715SArd Biesheuvel } 2508bf08715SArd Biesheuvel 2518bf08715SArd Biesheuvel static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt) 2528bf08715SArd Biesheuvel { 2538bf08715SArd Biesheuvel struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 2548bf08715SArd Biesheuvel struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); 2558bf08715SArd Biesheuvel struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req); 2568bf08715SArd Biesheuvel struct qce_alg_template *tmpl = to_cipher_tmpl(tfm); 2577de4c2bdSEneas U de Queiroz int keylen; 2588bf08715SArd Biesheuvel int ret; 2598bf08715SArd Biesheuvel 2608bf08715SArd Biesheuvel rctx->flags = tmpl->alg_flags; 2618bf08715SArd Biesheuvel rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT; 2627de4c2bdSEneas U de Queiroz keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen; 2638bf08715SArd Biesheuvel 264*f0878946SThara Gopinath /* CE does not handle 0 length messages */ 265*f0878946SThara Gopinath if (!req->cryptlen) 266*f0878946SThara Gopinath return 0; 267*f0878946SThara Gopinath 2687f19380bSEneas U de Queiroz /* qce is hanging when AES-XTS request len > QCE_SECTOR_SIZE and 2697f19380bSEneas U de Queiroz * is not a multiple of it; pass such requests to the fallback 2707f19380bSEneas U de Queiroz */ 271ce163ba0SEneas U de Queiroz if (IS_AES(rctx->flags) && 2727f19380bSEneas U de Queiroz (((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) || 2737f19380bSEneas U de Queiroz req->cryptlen <= aes_sw_max_len) || 2747f19380bSEneas U de Queiroz (IS_XTS(rctx->flags) && req->cryptlen > QCE_SECTOR_SIZE && 2757f19380bSEneas U de Queiroz req->cryptlen % QCE_SECTOR_SIZE))) { 27690e2f782SArd Biesheuvel skcipher_request_set_tfm(&rctx->fallback_req, ctx->fallback); 27790e2f782SArd Biesheuvel skcipher_request_set_callback(&rctx->fallback_req, 27890e2f782SArd Biesheuvel req->base.flags, 27990e2f782SArd Biesheuvel req->base.complete, 28090e2f782SArd Biesheuvel req->base.data); 28190e2f782SArd Biesheuvel skcipher_request_set_crypt(&rctx->fallback_req, req->src, 28290e2f782SArd Biesheuvel req->dst, req->cryptlen, req->iv); 28390e2f782SArd Biesheuvel ret = encrypt ? crypto_skcipher_encrypt(&rctx->fallback_req) : 28490e2f782SArd Biesheuvel crypto_skcipher_decrypt(&rctx->fallback_req); 2858bf08715SArd Biesheuvel return ret; 2868bf08715SArd Biesheuvel } 2878bf08715SArd Biesheuvel 2888bf08715SArd Biesheuvel return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base); 2898bf08715SArd Biesheuvel } 2908bf08715SArd Biesheuvel 2918bf08715SArd Biesheuvel static int qce_skcipher_encrypt(struct skcipher_request *req) 2928bf08715SArd Biesheuvel { 2938bf08715SArd Biesheuvel return qce_skcipher_crypt(req, 1); 2948bf08715SArd Biesheuvel } 2958bf08715SArd Biesheuvel 2968bf08715SArd Biesheuvel static int qce_skcipher_decrypt(struct skcipher_request *req) 2978bf08715SArd Biesheuvel { 2988bf08715SArd Biesheuvel return qce_skcipher_crypt(req, 0); 2998bf08715SArd Biesheuvel } 3008bf08715SArd Biesheuvel 3018bf08715SArd Biesheuvel static int qce_skcipher_init(struct crypto_skcipher *tfm) 3028bf08715SArd Biesheuvel { 30390e2f782SArd Biesheuvel /* take the size without the fallback skcipher_request at the end */ 30490e2f782SArd Biesheuvel crypto_skcipher_set_reqsize(tfm, offsetof(struct qce_cipher_reqctx, 30590e2f782SArd Biesheuvel fallback_req)); 3068ceda883SEneas U de Queiroz return 0; 3078ceda883SEneas U de Queiroz } 3088bf08715SArd Biesheuvel 3098ceda883SEneas U de Queiroz static int qce_skcipher_init_fallback(struct crypto_skcipher *tfm) 3108ceda883SEneas U de Queiroz { 3118ceda883SEneas U de Queiroz struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); 3128ceda883SEneas U de Queiroz 31390e2f782SArd Biesheuvel ctx->fallback = crypto_alloc_skcipher(crypto_tfm_alg_name(&tfm->base), 3148bf08715SArd Biesheuvel 0, CRYPTO_ALG_NEED_FALLBACK); 31590e2f782SArd Biesheuvel if (IS_ERR(ctx->fallback)) 31690e2f782SArd Biesheuvel return PTR_ERR(ctx->fallback); 31790e2f782SArd Biesheuvel 31890e2f782SArd Biesheuvel crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx) + 31990e2f782SArd Biesheuvel crypto_skcipher_reqsize(ctx->fallback)); 32090e2f782SArd Biesheuvel return 0; 3218bf08715SArd Biesheuvel } 3228bf08715SArd Biesheuvel 3238bf08715SArd Biesheuvel static void qce_skcipher_exit(struct crypto_skcipher *tfm) 3248bf08715SArd Biesheuvel { 3258bf08715SArd Biesheuvel struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm); 3268bf08715SArd Biesheuvel 32790e2f782SArd Biesheuvel crypto_free_skcipher(ctx->fallback); 3288bf08715SArd Biesheuvel } 3298bf08715SArd Biesheuvel 3308bf08715SArd Biesheuvel struct qce_skcipher_def { 3318bf08715SArd Biesheuvel unsigned long flags; 3328bf08715SArd Biesheuvel const char *name; 3338bf08715SArd Biesheuvel const char *drv_name; 3348bf08715SArd Biesheuvel unsigned int blocksize; 335bb5c863bSEneas U de Queiroz unsigned int chunksize; 3368bf08715SArd Biesheuvel unsigned int ivsize; 3378bf08715SArd Biesheuvel unsigned int min_keysize; 3388bf08715SArd Biesheuvel unsigned int max_keysize; 3398bf08715SArd Biesheuvel }; 3408bf08715SArd Biesheuvel 3418bf08715SArd Biesheuvel static const struct qce_skcipher_def skcipher_def[] = { 3428bf08715SArd Biesheuvel { 3438bf08715SArd Biesheuvel .flags = QCE_ALG_AES | QCE_MODE_ECB, 3448bf08715SArd Biesheuvel .name = "ecb(aes)", 3458bf08715SArd Biesheuvel .drv_name = "ecb-aes-qce", 3468bf08715SArd Biesheuvel .blocksize = AES_BLOCK_SIZE, 3478bf08715SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 3488bf08715SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE, 3498bf08715SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE, 3508bf08715SArd Biesheuvel }, 3518bf08715SArd Biesheuvel { 3528bf08715SArd Biesheuvel .flags = QCE_ALG_AES | QCE_MODE_CBC, 3538bf08715SArd Biesheuvel .name = "cbc(aes)", 3548bf08715SArd Biesheuvel .drv_name = "cbc-aes-qce", 3558bf08715SArd Biesheuvel .blocksize = AES_BLOCK_SIZE, 3568bf08715SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 3578bf08715SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE, 3588bf08715SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE, 3598bf08715SArd Biesheuvel }, 3608bf08715SArd Biesheuvel { 3618bf08715SArd Biesheuvel .flags = QCE_ALG_AES | QCE_MODE_CTR, 3628bf08715SArd Biesheuvel .name = "ctr(aes)", 3638bf08715SArd Biesheuvel .drv_name = "ctr-aes-qce", 364bb5c863bSEneas U de Queiroz .blocksize = 1, 365bb5c863bSEneas U de Queiroz .chunksize = AES_BLOCK_SIZE, 3668bf08715SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 3678bf08715SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE, 3688bf08715SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE, 3698bf08715SArd Biesheuvel }, 3708bf08715SArd Biesheuvel { 3718bf08715SArd Biesheuvel .flags = QCE_ALG_AES | QCE_MODE_XTS, 3728bf08715SArd Biesheuvel .name = "xts(aes)", 3738bf08715SArd Biesheuvel .drv_name = "xts-aes-qce", 3748bf08715SArd Biesheuvel .blocksize = AES_BLOCK_SIZE, 3758bf08715SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 3767de4c2bdSEneas U de Queiroz .min_keysize = AES_MIN_KEY_SIZE * 2, 3777de4c2bdSEneas U de Queiroz .max_keysize = AES_MAX_KEY_SIZE * 2, 3788bf08715SArd Biesheuvel }, 3798bf08715SArd Biesheuvel { 3808bf08715SArd Biesheuvel .flags = QCE_ALG_DES | QCE_MODE_ECB, 3818bf08715SArd Biesheuvel .name = "ecb(des)", 3828bf08715SArd Biesheuvel .drv_name = "ecb-des-qce", 3838bf08715SArd Biesheuvel .blocksize = DES_BLOCK_SIZE, 3848bf08715SArd Biesheuvel .ivsize = 0, 3858bf08715SArd Biesheuvel .min_keysize = DES_KEY_SIZE, 3868bf08715SArd Biesheuvel .max_keysize = DES_KEY_SIZE, 3878bf08715SArd Biesheuvel }, 3888bf08715SArd Biesheuvel { 3898bf08715SArd Biesheuvel .flags = QCE_ALG_DES | QCE_MODE_CBC, 3908bf08715SArd Biesheuvel .name = "cbc(des)", 3918bf08715SArd Biesheuvel .drv_name = "cbc-des-qce", 3928bf08715SArd Biesheuvel .blocksize = DES_BLOCK_SIZE, 3938bf08715SArd Biesheuvel .ivsize = DES_BLOCK_SIZE, 3948bf08715SArd Biesheuvel .min_keysize = DES_KEY_SIZE, 3958bf08715SArd Biesheuvel .max_keysize = DES_KEY_SIZE, 3968bf08715SArd Biesheuvel }, 3978bf08715SArd Biesheuvel { 3988bf08715SArd Biesheuvel .flags = QCE_ALG_3DES | QCE_MODE_ECB, 3998bf08715SArd Biesheuvel .name = "ecb(des3_ede)", 4008bf08715SArd Biesheuvel .drv_name = "ecb-3des-qce", 4018bf08715SArd Biesheuvel .blocksize = DES3_EDE_BLOCK_SIZE, 4028bf08715SArd Biesheuvel .ivsize = 0, 4038bf08715SArd Biesheuvel .min_keysize = DES3_EDE_KEY_SIZE, 4048bf08715SArd Biesheuvel .max_keysize = DES3_EDE_KEY_SIZE, 4058bf08715SArd Biesheuvel }, 4068bf08715SArd Biesheuvel { 4078bf08715SArd Biesheuvel .flags = QCE_ALG_3DES | QCE_MODE_CBC, 4088bf08715SArd Biesheuvel .name = "cbc(des3_ede)", 4098bf08715SArd Biesheuvel .drv_name = "cbc-3des-qce", 4108bf08715SArd Biesheuvel .blocksize = DES3_EDE_BLOCK_SIZE, 4118bf08715SArd Biesheuvel .ivsize = DES3_EDE_BLOCK_SIZE, 4128bf08715SArd Biesheuvel .min_keysize = DES3_EDE_KEY_SIZE, 4138bf08715SArd Biesheuvel .max_keysize = DES3_EDE_KEY_SIZE, 4148bf08715SArd Biesheuvel }, 4158bf08715SArd Biesheuvel }; 4168bf08715SArd Biesheuvel 4178bf08715SArd Biesheuvel static int qce_skcipher_register_one(const struct qce_skcipher_def *def, 4188bf08715SArd Biesheuvel struct qce_device *qce) 4198bf08715SArd Biesheuvel { 4208bf08715SArd Biesheuvel struct qce_alg_template *tmpl; 4218bf08715SArd Biesheuvel struct skcipher_alg *alg; 4228bf08715SArd Biesheuvel int ret; 4238bf08715SArd Biesheuvel 4248bf08715SArd Biesheuvel tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); 4258bf08715SArd Biesheuvel if (!tmpl) 4268bf08715SArd Biesheuvel return -ENOMEM; 4278bf08715SArd Biesheuvel 4288bf08715SArd Biesheuvel alg = &tmpl->alg.skcipher; 4298bf08715SArd Biesheuvel 4308bf08715SArd Biesheuvel snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name); 4318bf08715SArd Biesheuvel snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 4328bf08715SArd Biesheuvel def->drv_name); 4338bf08715SArd Biesheuvel 4348bf08715SArd Biesheuvel alg->base.cra_blocksize = def->blocksize; 435bb5c863bSEneas U de Queiroz alg->chunksize = def->chunksize; 4368bf08715SArd Biesheuvel alg->ivsize = def->ivsize; 4378bf08715SArd Biesheuvel alg->min_keysize = def->min_keysize; 4388bf08715SArd Biesheuvel alg->max_keysize = def->max_keysize; 4398bf08715SArd Biesheuvel alg->setkey = IS_3DES(def->flags) ? qce_des3_setkey : 4408bf08715SArd Biesheuvel IS_DES(def->flags) ? qce_des_setkey : 4418bf08715SArd Biesheuvel qce_skcipher_setkey; 4428bf08715SArd Biesheuvel alg->encrypt = qce_skcipher_encrypt; 4438bf08715SArd Biesheuvel alg->decrypt = qce_skcipher_decrypt; 4448bf08715SArd Biesheuvel 4458bf08715SArd Biesheuvel alg->base.cra_priority = 300; 4468bf08715SArd Biesheuvel alg->base.cra_flags = CRYPTO_ALG_ASYNC | 447b8aa7dc5SMikulas Patocka CRYPTO_ALG_ALLOCATES_MEMORY | 4488bf08715SArd Biesheuvel CRYPTO_ALG_KERN_DRIVER_ONLY; 4498bf08715SArd Biesheuvel alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx); 4508bf08715SArd Biesheuvel alg->base.cra_alignmask = 0; 4518bf08715SArd Biesheuvel alg->base.cra_module = THIS_MODULE; 4528bf08715SArd Biesheuvel 4538ceda883SEneas U de Queiroz if (IS_AES(def->flags)) { 4548ceda883SEneas U de Queiroz alg->base.cra_flags |= CRYPTO_ALG_NEED_FALLBACK; 4558ceda883SEneas U de Queiroz alg->init = qce_skcipher_init_fallback; 4568bf08715SArd Biesheuvel alg->exit = qce_skcipher_exit; 4578ceda883SEneas U de Queiroz } else { 4588ceda883SEneas U de Queiroz alg->init = qce_skcipher_init; 4598ceda883SEneas U de Queiroz } 4608bf08715SArd Biesheuvel 4618bf08715SArd Biesheuvel INIT_LIST_HEAD(&tmpl->entry); 4628bf08715SArd Biesheuvel tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER; 4638bf08715SArd Biesheuvel tmpl->alg_flags = def->flags; 4648bf08715SArd Biesheuvel tmpl->qce = qce; 4658bf08715SArd Biesheuvel 4668bf08715SArd Biesheuvel ret = crypto_register_skcipher(alg); 4678bf08715SArd Biesheuvel if (ret) { 4688bf08715SArd Biesheuvel kfree(tmpl); 4698bf08715SArd Biesheuvel dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name); 4708bf08715SArd Biesheuvel return ret; 4718bf08715SArd Biesheuvel } 4728bf08715SArd Biesheuvel 4738bf08715SArd Biesheuvel list_add_tail(&tmpl->entry, &skcipher_algs); 4748bf08715SArd Biesheuvel dev_dbg(qce->dev, "%s is registered\n", alg->base.cra_name); 4758bf08715SArd Biesheuvel return 0; 4768bf08715SArd Biesheuvel } 4778bf08715SArd Biesheuvel 4788bf08715SArd Biesheuvel static void qce_skcipher_unregister(struct qce_device *qce) 4798bf08715SArd Biesheuvel { 4808bf08715SArd Biesheuvel struct qce_alg_template *tmpl, *n; 4818bf08715SArd Biesheuvel 4828bf08715SArd Biesheuvel list_for_each_entry_safe(tmpl, n, &skcipher_algs, entry) { 4838bf08715SArd Biesheuvel crypto_unregister_skcipher(&tmpl->alg.skcipher); 4848bf08715SArd Biesheuvel list_del(&tmpl->entry); 4858bf08715SArd Biesheuvel kfree(tmpl); 4868bf08715SArd Biesheuvel } 4878bf08715SArd Biesheuvel } 4888bf08715SArd Biesheuvel 4898bf08715SArd Biesheuvel static int qce_skcipher_register(struct qce_device *qce) 4908bf08715SArd Biesheuvel { 4918bf08715SArd Biesheuvel int ret, i; 4928bf08715SArd Biesheuvel 4938bf08715SArd Biesheuvel for (i = 0; i < ARRAY_SIZE(skcipher_def); i++) { 4948bf08715SArd Biesheuvel ret = qce_skcipher_register_one(&skcipher_def[i], qce); 4958bf08715SArd Biesheuvel if (ret) 4968bf08715SArd Biesheuvel goto err; 4978bf08715SArd Biesheuvel } 4988bf08715SArd Biesheuvel 4998bf08715SArd Biesheuvel return 0; 5008bf08715SArd Biesheuvel err: 5018bf08715SArd Biesheuvel qce_skcipher_unregister(qce); 5028bf08715SArd Biesheuvel return ret; 5038bf08715SArd Biesheuvel } 5048bf08715SArd Biesheuvel 5058bf08715SArd Biesheuvel const struct qce_algo_ops skcipher_ops = { 5068bf08715SArd Biesheuvel .type = CRYPTO_ALG_TYPE_SKCIPHER, 5078bf08715SArd Biesheuvel .register_algs = qce_skcipher_register, 5088bf08715SArd Biesheuvel .unregister_algs = qce_skcipher_unregister, 5098bf08715SArd Biesheuvel .async_req_handle = qce_skcipher_async_req_handle, 5108bf08715SArd Biesheuvel }; 511