1416d8220SZaibo Xu // SPDX-License-Identifier: GPL-2.0 2416d8220SZaibo Xu /* Copyright (c) 2019 HiSilicon Limited. */ 3416d8220SZaibo Xu 4416d8220SZaibo Xu #include <crypto/aes.h> 5416d8220SZaibo Xu #include <crypto/algapi.h> 6416d8220SZaibo Xu #include <crypto/des.h> 7416d8220SZaibo Xu #include <crypto/skcipher.h> 8416d8220SZaibo Xu #include <crypto/xts.h> 9416d8220SZaibo Xu #include <linux/crypto.h> 10416d8220SZaibo Xu #include <linux/dma-mapping.h> 11416d8220SZaibo Xu #include <linux/idr.h> 12416d8220SZaibo Xu 13416d8220SZaibo Xu #include "sec.h" 14416d8220SZaibo Xu #include "sec_crypto.h" 15416d8220SZaibo Xu 16416d8220SZaibo Xu #define SEC_PRIORITY 4001 17416d8220SZaibo Xu #define SEC_XTS_MIN_KEY_SIZE (2 * AES_MIN_KEY_SIZE) 18416d8220SZaibo Xu #define SEC_XTS_MAX_KEY_SIZE (2 * AES_MAX_KEY_SIZE) 19416d8220SZaibo Xu #define SEC_DES3_2KEY_SIZE (2 * DES_KEY_SIZE) 20416d8220SZaibo Xu #define SEC_DES3_3KEY_SIZE (3 * DES_KEY_SIZE) 21416d8220SZaibo Xu 22416d8220SZaibo Xu /* SEC sqe(bd) bit operational relative MACRO */ 23416d8220SZaibo Xu #define SEC_DE_OFFSET 1 24416d8220SZaibo Xu #define SEC_CIPHER_OFFSET 4 25416d8220SZaibo Xu #define SEC_SCENE_OFFSET 3 26416d8220SZaibo Xu #define SEC_DST_SGL_OFFSET 2 27416d8220SZaibo Xu #define SEC_SRC_SGL_OFFSET 7 28416d8220SZaibo Xu #define SEC_CKEY_OFFSET 9 29416d8220SZaibo Xu #define SEC_CMODE_OFFSET 12 30416d8220SZaibo Xu #define SEC_FLAG_OFFSET 7 31416d8220SZaibo Xu #define SEC_FLAG_MASK 0x0780 32416d8220SZaibo Xu #define SEC_TYPE_MASK 0x0F 33416d8220SZaibo Xu #define SEC_DONE_MASK 0x0001 34416d8220SZaibo Xu 35416d8220SZaibo Xu #define SEC_TOTAL_IV_SZ (SEC_IV_SIZE * QM_Q_DEPTH) 36416d8220SZaibo Xu #define SEC_SGL_SGE_NR 128 37416d8220SZaibo Xu #define SEC_CTX_DEV(ctx) (&(ctx)->sec->qm.pdev->dev) 38d6de2a59SZaibo Xu #define SEC_SQE_CFLAG 2 39d6de2a59SZaibo Xu #define SEC_SQE_DONE 0x1 40416d8220SZaibo Xu 41416d8220SZaibo Xu static DEFINE_MUTEX(sec_algs_lock); 42416d8220SZaibo Xu static unsigned int sec_active_devs; 43416d8220SZaibo Xu 44416d8220SZaibo Xu /* Get an en/de-cipher queue cyclically to balance load over queues of TFM */ 45a181647cSZaibo Xu static inline int sec_alloc_queue_id(struct sec_ctx *ctx, struct sec_req *req) 46416d8220SZaibo Xu { 47416d8220SZaibo Xu if (req->c_req.encrypt) 48416d8220SZaibo Xu return (u32)atomic_inc_return(&ctx->enc_qcyclic) % 49416d8220SZaibo Xu ctx->hlf_q_num; 50416d8220SZaibo Xu 51416d8220SZaibo Xu return (u32)atomic_inc_return(&ctx->dec_qcyclic) % ctx->hlf_q_num + 52416d8220SZaibo Xu ctx->hlf_q_num; 53416d8220SZaibo Xu } 54416d8220SZaibo Xu 55a181647cSZaibo Xu static inline void sec_free_queue_id(struct sec_ctx *ctx, struct sec_req *req) 56416d8220SZaibo Xu { 57416d8220SZaibo Xu if (req->c_req.encrypt) 58416d8220SZaibo Xu atomic_dec(&ctx->enc_qcyclic); 59416d8220SZaibo Xu else 60416d8220SZaibo Xu atomic_dec(&ctx->dec_qcyclic); 61416d8220SZaibo Xu } 62416d8220SZaibo Xu 63416d8220SZaibo Xu static int sec_alloc_req_id(struct sec_req *req, struct sec_qp_ctx *qp_ctx) 64416d8220SZaibo Xu { 65416d8220SZaibo Xu int req_id; 66416d8220SZaibo Xu 67416d8220SZaibo Xu mutex_lock(&qp_ctx->req_lock); 68416d8220SZaibo Xu 69416d8220SZaibo Xu req_id = idr_alloc_cyclic(&qp_ctx->req_idr, NULL, 70416d8220SZaibo Xu 0, QM_Q_DEPTH, GFP_ATOMIC); 71416d8220SZaibo Xu mutex_unlock(&qp_ctx->req_lock); 72416d8220SZaibo Xu if (req_id < 0) { 73416d8220SZaibo Xu dev_err(SEC_CTX_DEV(req->ctx), "alloc req id fail!\n"); 74416d8220SZaibo Xu return req_id; 75416d8220SZaibo Xu } 76416d8220SZaibo Xu 77416d8220SZaibo Xu req->qp_ctx = qp_ctx; 78416d8220SZaibo Xu qp_ctx->req_list[req_id] = req; 79416d8220SZaibo Xu return req_id; 80416d8220SZaibo Xu } 81416d8220SZaibo Xu 82416d8220SZaibo Xu static void sec_free_req_id(struct sec_req *req) 83416d8220SZaibo Xu { 84416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx = req->qp_ctx; 85416d8220SZaibo Xu int req_id = req->req_id; 86416d8220SZaibo Xu 87416d8220SZaibo Xu if (req_id < 0 || req_id >= QM_Q_DEPTH) { 88416d8220SZaibo Xu dev_err(SEC_CTX_DEV(req->ctx), "free request id invalid!\n"); 89416d8220SZaibo Xu return; 90416d8220SZaibo Xu } 91416d8220SZaibo Xu 92416d8220SZaibo Xu qp_ctx->req_list[req_id] = NULL; 93416d8220SZaibo Xu req->qp_ctx = NULL; 94416d8220SZaibo Xu 95416d8220SZaibo Xu mutex_lock(&qp_ctx->req_lock); 96416d8220SZaibo Xu idr_remove(&qp_ctx->req_idr, req_id); 97416d8220SZaibo Xu mutex_unlock(&qp_ctx->req_lock); 98416d8220SZaibo Xu } 99416d8220SZaibo Xu 100416d8220SZaibo Xu static void sec_req_cb(struct hisi_qp *qp, void *resp) 101416d8220SZaibo Xu { 102416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx = qp->qp_ctx; 103416d8220SZaibo Xu struct sec_sqe *bd = resp; 104d6de2a59SZaibo Xu struct sec_ctx *ctx; 105d6de2a59SZaibo Xu struct sec_req *req; 106416d8220SZaibo Xu u16 done, flag; 107*310ea0acSZaibo Xu int err = 0; 108416d8220SZaibo Xu u8 type; 109416d8220SZaibo Xu 110416d8220SZaibo Xu type = bd->type_cipher_auth & SEC_TYPE_MASK; 111d6de2a59SZaibo Xu if (type != SEC_BD_TYPE2) { 112416d8220SZaibo Xu pr_err("err bd type [%d]\n", type); 113416d8220SZaibo Xu return; 114416d8220SZaibo Xu } 115416d8220SZaibo Xu 116d6de2a59SZaibo Xu req = qp_ctx->req_list[le16_to_cpu(bd->type2.tag)]; 117d6de2a59SZaibo Xu req->err_type = bd->type2.error_type; 118d6de2a59SZaibo Xu ctx = req->ctx; 119d6de2a59SZaibo Xu done = le16_to_cpu(bd->type2.done_flag) & SEC_DONE_MASK; 120d6de2a59SZaibo Xu flag = (le16_to_cpu(bd->type2.done_flag) & 121d6de2a59SZaibo Xu SEC_FLAG_MASK) >> SEC_FLAG_OFFSET; 122d6de2a59SZaibo Xu if (req->err_type || done != SEC_SQE_DONE || 123*310ea0acSZaibo Xu flag != SEC_SQE_CFLAG) { 124d6de2a59SZaibo Xu dev_err(SEC_CTX_DEV(ctx), 125d6de2a59SZaibo Xu "err_type[%d],done[%d],flag[%d]\n", 126d6de2a59SZaibo Xu req->err_type, done, flag); 127*310ea0acSZaibo Xu err = -EIO; 128*310ea0acSZaibo Xu } 1291e9bc276SZaibo Xu 130d6de2a59SZaibo Xu atomic64_inc(&ctx->sec->debug.dfx.recv_cnt); 131416d8220SZaibo Xu 132d6de2a59SZaibo Xu ctx->req_op->buf_unmap(ctx, req); 133d6de2a59SZaibo Xu 134*310ea0acSZaibo Xu ctx->req_op->callback(ctx, req, err); 135416d8220SZaibo Xu } 136416d8220SZaibo Xu 137416d8220SZaibo Xu static int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req) 138416d8220SZaibo Xu { 139416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx = req->qp_ctx; 140416d8220SZaibo Xu int ret; 141416d8220SZaibo Xu 142416d8220SZaibo Xu mutex_lock(&qp_ctx->req_lock); 143416d8220SZaibo Xu ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe); 144416d8220SZaibo Xu mutex_unlock(&qp_ctx->req_lock); 145cb1eeb75SArnd Bergmann atomic64_inc(&ctx->sec->debug.dfx.send_cnt); 146416d8220SZaibo Xu 147416d8220SZaibo Xu if (ret == -EBUSY) 148416d8220SZaibo Xu return -ENOBUFS; 149416d8220SZaibo Xu 150416d8220SZaibo Xu if (!ret) { 151ca0d158dSZaibo Xu if (req->fake_busy) 152416d8220SZaibo Xu ret = -EBUSY; 153416d8220SZaibo Xu else 154416d8220SZaibo Xu ret = -EINPROGRESS; 155416d8220SZaibo Xu } 156416d8220SZaibo Xu 157416d8220SZaibo Xu return ret; 158416d8220SZaibo Xu } 159416d8220SZaibo Xu 1607c7d902aSZaibo Xu /* Get DMA memory resources */ 1617c7d902aSZaibo Xu static int sec_alloc_civ_resource(struct device *dev, struct sec_alg_res *res) 1627c7d902aSZaibo Xu { 1637c7d902aSZaibo Xu int i; 1647c7d902aSZaibo Xu 1657c7d902aSZaibo Xu res->c_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ, 1667c7d902aSZaibo Xu &res->c_ivin_dma, GFP_KERNEL); 1677c7d902aSZaibo Xu if (!res->c_ivin) 1687c7d902aSZaibo Xu return -ENOMEM; 1697c7d902aSZaibo Xu 1707c7d902aSZaibo Xu for (i = 1; i < QM_Q_DEPTH; i++) { 1717c7d902aSZaibo Xu res[i].c_ivin_dma = res->c_ivin_dma + i * SEC_IV_SIZE; 1727c7d902aSZaibo Xu res[i].c_ivin = res->c_ivin + i * SEC_IV_SIZE; 1737c7d902aSZaibo Xu } 1747c7d902aSZaibo Xu 1757c7d902aSZaibo Xu return 0; 1767c7d902aSZaibo Xu } 1777c7d902aSZaibo Xu 1787c7d902aSZaibo Xu static void sec_free_civ_resource(struct device *dev, struct sec_alg_res *res) 1797c7d902aSZaibo Xu { 1807c7d902aSZaibo Xu if (res->c_ivin) 1817c7d902aSZaibo Xu dma_free_coherent(dev, SEC_TOTAL_IV_SZ, 1827c7d902aSZaibo Xu res->c_ivin, res->c_ivin_dma); 1837c7d902aSZaibo Xu } 1847c7d902aSZaibo Xu 1857c7d902aSZaibo Xu static int sec_alg_resource_alloc(struct sec_ctx *ctx, 1867c7d902aSZaibo Xu struct sec_qp_ctx *qp_ctx) 1877c7d902aSZaibo Xu { 1887c7d902aSZaibo Xu struct device *dev = SEC_CTX_DEV(ctx); 1897c7d902aSZaibo Xu 1907c7d902aSZaibo Xu return sec_alloc_civ_resource(dev, qp_ctx->res); 1917c7d902aSZaibo Xu } 1927c7d902aSZaibo Xu 1937c7d902aSZaibo Xu static void sec_alg_resource_free(struct sec_ctx *ctx, 1947c7d902aSZaibo Xu struct sec_qp_ctx *qp_ctx) 1957c7d902aSZaibo Xu { 1967c7d902aSZaibo Xu struct device *dev = SEC_CTX_DEV(ctx); 1977c7d902aSZaibo Xu 1987c7d902aSZaibo Xu sec_free_civ_resource(dev, qp_ctx->res); 1997c7d902aSZaibo Xu } 2007c7d902aSZaibo Xu 201416d8220SZaibo Xu static int sec_create_qp_ctx(struct hisi_qm *qm, struct sec_ctx *ctx, 202416d8220SZaibo Xu int qp_ctx_id, int alg_type) 203416d8220SZaibo Xu { 204416d8220SZaibo Xu struct device *dev = SEC_CTX_DEV(ctx); 205416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx; 206416d8220SZaibo Xu struct hisi_qp *qp; 207416d8220SZaibo Xu int ret = -ENOMEM; 208416d8220SZaibo Xu 209416d8220SZaibo Xu qp = hisi_qm_create_qp(qm, alg_type); 210416d8220SZaibo Xu if (IS_ERR(qp)) 211416d8220SZaibo Xu return PTR_ERR(qp); 212416d8220SZaibo Xu 213416d8220SZaibo Xu qp_ctx = &ctx->qp_ctx[qp_ctx_id]; 214416d8220SZaibo Xu qp->req_type = 0; 215416d8220SZaibo Xu qp->qp_ctx = qp_ctx; 216416d8220SZaibo Xu qp->req_cb = sec_req_cb; 217416d8220SZaibo Xu qp_ctx->qp = qp; 218416d8220SZaibo Xu qp_ctx->ctx = ctx; 219416d8220SZaibo Xu 220416d8220SZaibo Xu mutex_init(&qp_ctx->req_lock); 221416d8220SZaibo Xu atomic_set(&qp_ctx->pending_reqs, 0); 222416d8220SZaibo Xu idr_init(&qp_ctx->req_idr); 223416d8220SZaibo Xu 224416d8220SZaibo Xu qp_ctx->c_in_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH, 225416d8220SZaibo Xu SEC_SGL_SGE_NR); 2268a6b8f4dSDan Carpenter if (IS_ERR(qp_ctx->c_in_pool)) { 227416d8220SZaibo Xu dev_err(dev, "fail to create sgl pool for input!\n"); 2287c7d902aSZaibo Xu goto err_destroy_idr; 229416d8220SZaibo Xu } 230416d8220SZaibo Xu 231416d8220SZaibo Xu qp_ctx->c_out_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH, 232416d8220SZaibo Xu SEC_SGL_SGE_NR); 2338a6b8f4dSDan Carpenter if (IS_ERR(qp_ctx->c_out_pool)) { 234416d8220SZaibo Xu dev_err(dev, "fail to create sgl pool for output!\n"); 235416d8220SZaibo Xu goto err_free_c_in_pool; 236416d8220SZaibo Xu } 237416d8220SZaibo Xu 2387c7d902aSZaibo Xu ret = sec_alg_resource_alloc(ctx, qp_ctx); 239416d8220SZaibo Xu if (ret) 240416d8220SZaibo Xu goto err_free_c_out_pool; 241416d8220SZaibo Xu 242416d8220SZaibo Xu ret = hisi_qm_start_qp(qp, 0); 243416d8220SZaibo Xu if (ret < 0) 244416d8220SZaibo Xu goto err_queue_free; 245416d8220SZaibo Xu 246416d8220SZaibo Xu return 0; 247416d8220SZaibo Xu 248416d8220SZaibo Xu err_queue_free: 2497c7d902aSZaibo Xu sec_alg_resource_free(ctx, qp_ctx); 250416d8220SZaibo Xu err_free_c_out_pool: 251416d8220SZaibo Xu hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool); 252416d8220SZaibo Xu err_free_c_in_pool: 253416d8220SZaibo Xu hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool); 254416d8220SZaibo Xu err_destroy_idr: 255416d8220SZaibo Xu idr_destroy(&qp_ctx->req_idr); 256416d8220SZaibo Xu hisi_qm_release_qp(qp); 257416d8220SZaibo Xu 258416d8220SZaibo Xu return ret; 259416d8220SZaibo Xu } 260416d8220SZaibo Xu 261416d8220SZaibo Xu static void sec_release_qp_ctx(struct sec_ctx *ctx, 262416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx) 263416d8220SZaibo Xu { 264416d8220SZaibo Xu struct device *dev = SEC_CTX_DEV(ctx); 265416d8220SZaibo Xu 266416d8220SZaibo Xu hisi_qm_stop_qp(qp_ctx->qp); 2677c7d902aSZaibo Xu sec_alg_resource_free(ctx, qp_ctx); 268416d8220SZaibo Xu 269416d8220SZaibo Xu hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool); 270416d8220SZaibo Xu hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool); 271416d8220SZaibo Xu 272416d8220SZaibo Xu idr_destroy(&qp_ctx->req_idr); 273416d8220SZaibo Xu hisi_qm_release_qp(qp_ctx->qp); 274416d8220SZaibo Xu } 275416d8220SZaibo Xu 276416d8220SZaibo Xu static int sec_skcipher_init(struct crypto_skcipher *tfm) 277416d8220SZaibo Xu { 278416d8220SZaibo Xu struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 279416d8220SZaibo Xu struct sec_cipher_ctx *c_ctx; 280416d8220SZaibo Xu struct sec_dev *sec; 281416d8220SZaibo Xu struct device *dev; 282416d8220SZaibo Xu struct hisi_qm *qm; 283416d8220SZaibo Xu int i, ret; 284416d8220SZaibo Xu 285416d8220SZaibo Xu crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_req)); 286416d8220SZaibo Xu 287416d8220SZaibo Xu sec = sec_find_device(cpu_to_node(smp_processor_id())); 288416d8220SZaibo Xu if (!sec) { 289a718cfceSZaibo Xu pr_err("Can not find proper Hisilicon SEC device!\n"); 290416d8220SZaibo Xu return -ENODEV; 291416d8220SZaibo Xu } 292416d8220SZaibo Xu ctx->sec = sec; 293416d8220SZaibo Xu qm = &sec->qm; 294416d8220SZaibo Xu dev = &qm->pdev->dev; 295a718cfceSZaibo Xu ctx->hlf_q_num = sec->ctx_q_num >> 1; 296416d8220SZaibo Xu 297416d8220SZaibo Xu /* Half of queue depth is taken as fake requests limit in the queue. */ 298a718cfceSZaibo Xu ctx->fake_req_limit = QM_Q_DEPTH >> 1; 299416d8220SZaibo Xu ctx->qp_ctx = kcalloc(sec->ctx_q_num, sizeof(struct sec_qp_ctx), 300416d8220SZaibo Xu GFP_KERNEL); 301416d8220SZaibo Xu if (!ctx->qp_ctx) 302416d8220SZaibo Xu return -ENOMEM; 303416d8220SZaibo Xu 304416d8220SZaibo Xu for (i = 0; i < sec->ctx_q_num; i++) { 305416d8220SZaibo Xu ret = sec_create_qp_ctx(qm, ctx, i, 0); 306416d8220SZaibo Xu if (ret) 307416d8220SZaibo Xu goto err_sec_release_qp_ctx; 308416d8220SZaibo Xu } 309416d8220SZaibo Xu 310416d8220SZaibo Xu c_ctx = &ctx->c_ctx; 311416d8220SZaibo Xu c_ctx->ivsize = crypto_skcipher_ivsize(tfm); 312416d8220SZaibo Xu if (c_ctx->ivsize > SEC_IV_SIZE) { 313416d8220SZaibo Xu dev_err(dev, "get error iv size!\n"); 314416d8220SZaibo Xu ret = -EINVAL; 315416d8220SZaibo Xu goto err_sec_release_qp_ctx; 316416d8220SZaibo Xu } 317416d8220SZaibo Xu c_ctx->c_key = dma_alloc_coherent(dev, SEC_MAX_KEY_SIZE, 318416d8220SZaibo Xu &c_ctx->c_key_dma, GFP_KERNEL); 319416d8220SZaibo Xu if (!c_ctx->c_key) { 320416d8220SZaibo Xu ret = -ENOMEM; 321416d8220SZaibo Xu goto err_sec_release_qp_ctx; 322416d8220SZaibo Xu } 323416d8220SZaibo Xu 324416d8220SZaibo Xu return 0; 325416d8220SZaibo Xu 326416d8220SZaibo Xu err_sec_release_qp_ctx: 327416d8220SZaibo Xu for (i = i - 1; i >= 0; i--) 328416d8220SZaibo Xu sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]); 329416d8220SZaibo Xu 330416d8220SZaibo Xu kfree(ctx->qp_ctx); 331416d8220SZaibo Xu return ret; 332416d8220SZaibo Xu } 333416d8220SZaibo Xu 334a181647cSZaibo Xu static void sec_skcipher_uninit(struct crypto_skcipher *tfm) 335416d8220SZaibo Xu { 336416d8220SZaibo Xu struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 337416d8220SZaibo Xu struct sec_cipher_ctx *c_ctx = &ctx->c_ctx; 338416d8220SZaibo Xu int i = 0; 339416d8220SZaibo Xu 340416d8220SZaibo Xu if (c_ctx->c_key) { 341416d8220SZaibo Xu dma_free_coherent(SEC_CTX_DEV(ctx), SEC_MAX_KEY_SIZE, 342416d8220SZaibo Xu c_ctx->c_key, c_ctx->c_key_dma); 343416d8220SZaibo Xu c_ctx->c_key = NULL; 344416d8220SZaibo Xu } 345416d8220SZaibo Xu 346416d8220SZaibo Xu for (i = 0; i < ctx->sec->ctx_q_num; i++) 347416d8220SZaibo Xu sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]); 348416d8220SZaibo Xu 349416d8220SZaibo Xu kfree(ctx->qp_ctx); 350416d8220SZaibo Xu } 351416d8220SZaibo Xu 352416d8220SZaibo Xu static int sec_skcipher_3des_setkey(struct sec_cipher_ctx *c_ctx, 353416d8220SZaibo Xu const u32 keylen, 354416d8220SZaibo Xu const enum sec_cmode c_mode) 355416d8220SZaibo Xu { 356416d8220SZaibo Xu switch (keylen) { 357416d8220SZaibo Xu case SEC_DES3_2KEY_SIZE: 358416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_3DES_2KEY; 359416d8220SZaibo Xu break; 360416d8220SZaibo Xu case SEC_DES3_3KEY_SIZE: 361416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_3DES_3KEY; 362416d8220SZaibo Xu break; 363416d8220SZaibo Xu default: 364416d8220SZaibo Xu return -EINVAL; 365416d8220SZaibo Xu } 366416d8220SZaibo Xu 367416d8220SZaibo Xu return 0; 368416d8220SZaibo Xu } 369416d8220SZaibo Xu 370416d8220SZaibo Xu static int sec_skcipher_aes_sm4_setkey(struct sec_cipher_ctx *c_ctx, 371416d8220SZaibo Xu const u32 keylen, 372416d8220SZaibo Xu const enum sec_cmode c_mode) 373416d8220SZaibo Xu { 374416d8220SZaibo Xu if (c_mode == SEC_CMODE_XTS) { 375416d8220SZaibo Xu switch (keylen) { 376416d8220SZaibo Xu case SEC_XTS_MIN_KEY_SIZE: 377416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_128BIT; 378416d8220SZaibo Xu break; 379416d8220SZaibo Xu case SEC_XTS_MAX_KEY_SIZE: 380416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_256BIT; 381416d8220SZaibo Xu break; 382416d8220SZaibo Xu default: 383416d8220SZaibo Xu pr_err("hisi_sec2: xts mode key error!\n"); 384416d8220SZaibo Xu return -EINVAL; 385416d8220SZaibo Xu } 386416d8220SZaibo Xu } else { 387416d8220SZaibo Xu switch (keylen) { 388416d8220SZaibo Xu case AES_KEYSIZE_128: 389416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_128BIT; 390416d8220SZaibo Xu break; 391416d8220SZaibo Xu case AES_KEYSIZE_192: 392416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_192BIT; 393416d8220SZaibo Xu break; 394416d8220SZaibo Xu case AES_KEYSIZE_256: 395416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_256BIT; 396416d8220SZaibo Xu break; 397416d8220SZaibo Xu default: 398416d8220SZaibo Xu pr_err("hisi_sec2: aes key error!\n"); 399416d8220SZaibo Xu return -EINVAL; 400416d8220SZaibo Xu } 401416d8220SZaibo Xu } 402416d8220SZaibo Xu 403416d8220SZaibo Xu return 0; 404416d8220SZaibo Xu } 405416d8220SZaibo Xu 406416d8220SZaibo Xu static int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, 407416d8220SZaibo Xu const u32 keylen, const enum sec_calg c_alg, 408416d8220SZaibo Xu const enum sec_cmode c_mode) 409416d8220SZaibo Xu { 410416d8220SZaibo Xu struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 411416d8220SZaibo Xu struct sec_cipher_ctx *c_ctx = &ctx->c_ctx; 412416d8220SZaibo Xu int ret; 413416d8220SZaibo Xu 414416d8220SZaibo Xu if (c_mode == SEC_CMODE_XTS) { 415416d8220SZaibo Xu ret = xts_verify_key(tfm, key, keylen); 416416d8220SZaibo Xu if (ret) { 417416d8220SZaibo Xu dev_err(SEC_CTX_DEV(ctx), "xts mode key err!\n"); 418416d8220SZaibo Xu return ret; 419416d8220SZaibo Xu } 420416d8220SZaibo Xu } 421416d8220SZaibo Xu 422416d8220SZaibo Xu c_ctx->c_alg = c_alg; 423416d8220SZaibo Xu c_ctx->c_mode = c_mode; 424416d8220SZaibo Xu 425416d8220SZaibo Xu switch (c_alg) { 426416d8220SZaibo Xu case SEC_CALG_3DES: 427416d8220SZaibo Xu ret = sec_skcipher_3des_setkey(c_ctx, keylen, c_mode); 428416d8220SZaibo Xu break; 429416d8220SZaibo Xu case SEC_CALG_AES: 430416d8220SZaibo Xu case SEC_CALG_SM4: 431416d8220SZaibo Xu ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode); 432416d8220SZaibo Xu break; 433416d8220SZaibo Xu default: 434416d8220SZaibo Xu return -EINVAL; 435416d8220SZaibo Xu } 436416d8220SZaibo Xu 437416d8220SZaibo Xu if (ret) { 438416d8220SZaibo Xu dev_err(SEC_CTX_DEV(ctx), "set sec key err!\n"); 439416d8220SZaibo Xu return ret; 440416d8220SZaibo Xu } 441416d8220SZaibo Xu 442416d8220SZaibo Xu memcpy(c_ctx->c_key, key, keylen); 443416d8220SZaibo Xu 444416d8220SZaibo Xu return 0; 445416d8220SZaibo Xu } 446416d8220SZaibo Xu 447416d8220SZaibo Xu #define GEN_SEC_SETKEY_FUNC(name, c_alg, c_mode) \ 448416d8220SZaibo Xu static int sec_setkey_##name(struct crypto_skcipher *tfm, const u8 *key,\ 449416d8220SZaibo Xu u32 keylen) \ 450416d8220SZaibo Xu { \ 451416d8220SZaibo Xu return sec_skcipher_setkey(tfm, key, keylen, c_alg, c_mode); \ 452416d8220SZaibo Xu } 453416d8220SZaibo Xu 454416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_ecb, SEC_CALG_AES, SEC_CMODE_ECB) 455416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_cbc, SEC_CALG_AES, SEC_CMODE_CBC) 456416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_xts, SEC_CALG_AES, SEC_CMODE_XTS) 457416d8220SZaibo Xu 458416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_ecb, SEC_CALG_3DES, SEC_CMODE_ECB) 459416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_cbc, SEC_CALG_3DES, SEC_CMODE_CBC) 460416d8220SZaibo Xu 461416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_xts, SEC_CALG_SM4, SEC_CMODE_XTS) 462416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_cbc, SEC_CALG_SM4, SEC_CMODE_CBC) 463416d8220SZaibo Xu 464a181647cSZaibo Xu static int sec_cipher_map(struct device *dev, struct sec_req *req, 465416d8220SZaibo Xu struct scatterlist *src, struct scatterlist *dst) 466416d8220SZaibo Xu { 467416d8220SZaibo Xu struct sec_cipher_req *c_req = &req->c_req; 468416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx = req->qp_ctx; 469416d8220SZaibo Xu 470416d8220SZaibo Xu c_req->c_in = hisi_acc_sg_buf_map_to_hw_sgl(dev, src, 471416d8220SZaibo Xu qp_ctx->c_in_pool, 472416d8220SZaibo Xu req->req_id, 473416d8220SZaibo Xu &c_req->c_in_dma); 474416d8220SZaibo Xu 475416d8220SZaibo Xu if (IS_ERR(c_req->c_in)) { 476416d8220SZaibo Xu dev_err(dev, "fail to dma map input sgl buffers!\n"); 477416d8220SZaibo Xu return PTR_ERR(c_req->c_in); 478416d8220SZaibo Xu } 479416d8220SZaibo Xu 480416d8220SZaibo Xu if (dst == src) { 481416d8220SZaibo Xu c_req->c_out = c_req->c_in; 482416d8220SZaibo Xu c_req->c_out_dma = c_req->c_in_dma; 483416d8220SZaibo Xu } else { 484416d8220SZaibo Xu c_req->c_out = hisi_acc_sg_buf_map_to_hw_sgl(dev, dst, 485416d8220SZaibo Xu qp_ctx->c_out_pool, 486416d8220SZaibo Xu req->req_id, 487416d8220SZaibo Xu &c_req->c_out_dma); 488416d8220SZaibo Xu 489416d8220SZaibo Xu if (IS_ERR(c_req->c_out)) { 490416d8220SZaibo Xu dev_err(dev, "fail to dma map output sgl buffers!\n"); 491416d8220SZaibo Xu hisi_acc_sg_buf_unmap(dev, src, c_req->c_in); 492416d8220SZaibo Xu return PTR_ERR(c_req->c_out); 493416d8220SZaibo Xu } 494416d8220SZaibo Xu } 495416d8220SZaibo Xu 496416d8220SZaibo Xu return 0; 497416d8220SZaibo Xu } 498416d8220SZaibo Xu 499a181647cSZaibo Xu static void sec_cipher_unmap(struct device *dev, struct sec_cipher_req *req, 500a181647cSZaibo Xu struct scatterlist *src, struct scatterlist *dst) 501a181647cSZaibo Xu { 502a181647cSZaibo Xu if (dst != src) 503a181647cSZaibo Xu hisi_acc_sg_buf_unmap(dev, src, req->c_in); 504a181647cSZaibo Xu 505a181647cSZaibo Xu hisi_acc_sg_buf_unmap(dev, dst, req->c_out); 506a181647cSZaibo Xu } 507a181647cSZaibo Xu 508416d8220SZaibo Xu static int sec_skcipher_sgl_map(struct sec_ctx *ctx, struct sec_req *req) 509416d8220SZaibo Xu { 510a181647cSZaibo Xu struct skcipher_request *sq = req->c_req.sk_req; 511416d8220SZaibo Xu 512a181647cSZaibo Xu return sec_cipher_map(SEC_CTX_DEV(ctx), req, sq->src, sq->dst); 513416d8220SZaibo Xu } 514416d8220SZaibo Xu 515416d8220SZaibo Xu static void sec_skcipher_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req) 516416d8220SZaibo Xu { 517416d8220SZaibo Xu struct device *dev = SEC_CTX_DEV(ctx); 518416d8220SZaibo Xu struct sec_cipher_req *c_req = &req->c_req; 519416d8220SZaibo Xu struct skcipher_request *sk_req = c_req->sk_req; 520416d8220SZaibo Xu 521a181647cSZaibo Xu sec_cipher_unmap(dev, c_req, sk_req->src, sk_req->dst); 522416d8220SZaibo Xu } 523416d8220SZaibo Xu 524416d8220SZaibo Xu static int sec_request_transfer(struct sec_ctx *ctx, struct sec_req *req) 525416d8220SZaibo Xu { 526416d8220SZaibo Xu int ret; 527416d8220SZaibo Xu 528416d8220SZaibo Xu ret = ctx->req_op->buf_map(ctx, req); 529416d8220SZaibo Xu if (ret) 530416d8220SZaibo Xu return ret; 531416d8220SZaibo Xu 532416d8220SZaibo Xu ctx->req_op->do_transfer(ctx, req); 533416d8220SZaibo Xu 534416d8220SZaibo Xu ret = ctx->req_op->bd_fill(ctx, req); 535416d8220SZaibo Xu if (ret) 536416d8220SZaibo Xu goto unmap_req_buf; 537416d8220SZaibo Xu 538416d8220SZaibo Xu return ret; 539416d8220SZaibo Xu 540416d8220SZaibo Xu unmap_req_buf: 541416d8220SZaibo Xu ctx->req_op->buf_unmap(ctx, req); 542416d8220SZaibo Xu 543416d8220SZaibo Xu return ret; 544416d8220SZaibo Xu } 545416d8220SZaibo Xu 546416d8220SZaibo Xu static void sec_request_untransfer(struct sec_ctx *ctx, struct sec_req *req) 547416d8220SZaibo Xu { 548416d8220SZaibo Xu ctx->req_op->buf_unmap(ctx, req); 549416d8220SZaibo Xu } 550416d8220SZaibo Xu 551416d8220SZaibo Xu static void sec_skcipher_copy_iv(struct sec_ctx *ctx, struct sec_req *req) 552416d8220SZaibo Xu { 553416d8220SZaibo Xu struct skcipher_request *sk_req = req->c_req.sk_req; 5547c7d902aSZaibo Xu u8 *c_ivin = req->qp_ctx->res[req->req_id].c_ivin; 555416d8220SZaibo Xu 5567c7d902aSZaibo Xu memcpy(c_ivin, sk_req->iv, ctx->c_ctx.ivsize); 557416d8220SZaibo Xu } 558416d8220SZaibo Xu 559416d8220SZaibo Xu static int sec_skcipher_bd_fill(struct sec_ctx *ctx, struct sec_req *req) 560416d8220SZaibo Xu { 561416d8220SZaibo Xu struct sec_cipher_ctx *c_ctx = &ctx->c_ctx; 562416d8220SZaibo Xu struct sec_cipher_req *c_req = &req->c_req; 563416d8220SZaibo Xu struct sec_sqe *sec_sqe = &req->sec_sqe; 564416d8220SZaibo Xu u8 scene, sa_type, da_type; 565416d8220SZaibo Xu u8 bd_type, cipher; 5667c7d902aSZaibo Xu u8 de = 0; 567416d8220SZaibo Xu 568416d8220SZaibo Xu memset(sec_sqe, 0, sizeof(struct sec_sqe)); 569416d8220SZaibo Xu 570416d8220SZaibo Xu sec_sqe->type2.c_key_addr = cpu_to_le64(c_ctx->c_key_dma); 5717c7d902aSZaibo Xu sec_sqe->type2.c_ivin_addr = 5727c7d902aSZaibo Xu cpu_to_le64(req->qp_ctx->res[req->req_id].c_ivin_dma); 573416d8220SZaibo Xu sec_sqe->type2.data_src_addr = cpu_to_le64(c_req->c_in_dma); 574416d8220SZaibo Xu sec_sqe->type2.data_dst_addr = cpu_to_le64(c_req->c_out_dma); 575416d8220SZaibo Xu 576416d8220SZaibo Xu sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_mode) << 577416d8220SZaibo Xu SEC_CMODE_OFFSET); 578416d8220SZaibo Xu sec_sqe->type2.c_alg = c_ctx->c_alg; 579416d8220SZaibo Xu sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_key_len) << 580416d8220SZaibo Xu SEC_CKEY_OFFSET); 581416d8220SZaibo Xu 582416d8220SZaibo Xu bd_type = SEC_BD_TYPE2; 583416d8220SZaibo Xu if (c_req->encrypt) 584416d8220SZaibo Xu cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET; 585416d8220SZaibo Xu else 586416d8220SZaibo Xu cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET; 587416d8220SZaibo Xu sec_sqe->type_cipher_auth = bd_type | cipher; 588416d8220SZaibo Xu 589416d8220SZaibo Xu sa_type = SEC_SGL << SEC_SRC_SGL_OFFSET; 590416d8220SZaibo Xu scene = SEC_COMM_SCENE << SEC_SCENE_OFFSET; 591416d8220SZaibo Xu if (c_req->c_in_dma != c_req->c_out_dma) 592416d8220SZaibo Xu de = 0x1 << SEC_DE_OFFSET; 593416d8220SZaibo Xu 594416d8220SZaibo Xu sec_sqe->sds_sa_type = (de | scene | sa_type); 595416d8220SZaibo Xu 596416d8220SZaibo Xu /* Just set DST address type */ 597416d8220SZaibo Xu da_type = SEC_SGL << SEC_DST_SGL_OFFSET; 598416d8220SZaibo Xu sec_sqe->sdm_addr_type |= da_type; 599416d8220SZaibo Xu 600416d8220SZaibo Xu sec_sqe->type2.clen_ivhlen |= cpu_to_le32(c_req->c_len); 601416d8220SZaibo Xu sec_sqe->type2.tag = cpu_to_le16((u16)req->req_id); 602416d8220SZaibo Xu 603416d8220SZaibo Xu return 0; 604416d8220SZaibo Xu } 605416d8220SZaibo Xu 606416d8220SZaibo Xu static void sec_update_iv(struct sec_req *req) 607416d8220SZaibo Xu { 608416d8220SZaibo Xu struct skcipher_request *sk_req = req->c_req.sk_req; 609416d8220SZaibo Xu u32 iv_size = req->ctx->c_ctx.ivsize; 610416d8220SZaibo Xu struct scatterlist *sgl; 611416d8220SZaibo Xu size_t sz; 612416d8220SZaibo Xu 613416d8220SZaibo Xu if (req->c_req.encrypt) 614416d8220SZaibo Xu sgl = sk_req->dst; 615416d8220SZaibo Xu else 616416d8220SZaibo Xu sgl = sk_req->src; 617416d8220SZaibo Xu 618416d8220SZaibo Xu sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), sk_req->iv, 619416d8220SZaibo Xu iv_size, sk_req->cryptlen - iv_size); 620416d8220SZaibo Xu if (sz != iv_size) 621416d8220SZaibo Xu dev_err(SEC_CTX_DEV(req->ctx), "copy output iv error!\n"); 622416d8220SZaibo Xu } 623416d8220SZaibo Xu 624*310ea0acSZaibo Xu static void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req, 625*310ea0acSZaibo Xu int err) 626416d8220SZaibo Xu { 627416d8220SZaibo Xu struct skcipher_request *sk_req = req->c_req.sk_req; 628416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx = req->qp_ctx; 629416d8220SZaibo Xu 630416d8220SZaibo Xu atomic_dec(&qp_ctx->pending_reqs); 631416d8220SZaibo Xu sec_free_req_id(req); 632416d8220SZaibo Xu 633416d8220SZaibo Xu /* IV output at encrypto of CBC mode */ 634*310ea0acSZaibo Xu if (!err && ctx->c_ctx.c_mode == SEC_CMODE_CBC && req->c_req.encrypt) 635416d8220SZaibo Xu sec_update_iv(req); 636416d8220SZaibo Xu 637ca0d158dSZaibo Xu if (req->fake_busy) 638416d8220SZaibo Xu sk_req->base.complete(&sk_req->base, -EINPROGRESS); 639416d8220SZaibo Xu 640*310ea0acSZaibo Xu sk_req->base.complete(&sk_req->base, err); 641416d8220SZaibo Xu } 642416d8220SZaibo Xu 643416d8220SZaibo Xu static void sec_request_uninit(struct sec_ctx *ctx, struct sec_req *req) 644416d8220SZaibo Xu { 645416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx = req->qp_ctx; 646416d8220SZaibo Xu 647416d8220SZaibo Xu atomic_dec(&qp_ctx->pending_reqs); 648416d8220SZaibo Xu sec_free_req_id(req); 649a181647cSZaibo Xu sec_free_queue_id(ctx, req); 650416d8220SZaibo Xu } 651416d8220SZaibo Xu 652416d8220SZaibo Xu static int sec_request_init(struct sec_ctx *ctx, struct sec_req *req) 653416d8220SZaibo Xu { 654416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx; 6557c7d902aSZaibo Xu int queue_id; 656416d8220SZaibo Xu 657416d8220SZaibo Xu /* To load balance */ 658a181647cSZaibo Xu queue_id = sec_alloc_queue_id(ctx, req); 659a181647cSZaibo Xu qp_ctx = &ctx->qp_ctx[queue_id]; 660416d8220SZaibo Xu 661416d8220SZaibo Xu req->req_id = sec_alloc_req_id(req, qp_ctx); 662416d8220SZaibo Xu if (req->req_id < 0) { 663a181647cSZaibo Xu sec_free_queue_id(ctx, req); 664416d8220SZaibo Xu return req->req_id; 665416d8220SZaibo Xu } 666416d8220SZaibo Xu 667416d8220SZaibo Xu if (ctx->fake_req_limit <= atomic_inc_return(&qp_ctx->pending_reqs)) 668ca0d158dSZaibo Xu req->fake_busy = true; 669416d8220SZaibo Xu else 670ca0d158dSZaibo Xu req->fake_busy = false; 671416d8220SZaibo Xu 6727c7d902aSZaibo Xu return 0; 673416d8220SZaibo Xu } 674416d8220SZaibo Xu 675416d8220SZaibo Xu static int sec_process(struct sec_ctx *ctx, struct sec_req *req) 676416d8220SZaibo Xu { 677416d8220SZaibo Xu int ret; 678416d8220SZaibo Xu 679416d8220SZaibo Xu ret = sec_request_init(ctx, req); 680416d8220SZaibo Xu if (ret) 681416d8220SZaibo Xu return ret; 682416d8220SZaibo Xu 683416d8220SZaibo Xu ret = sec_request_transfer(ctx, req); 684416d8220SZaibo Xu if (ret) 685416d8220SZaibo Xu goto err_uninit_req; 686416d8220SZaibo Xu 687416d8220SZaibo Xu /* Output IV as decrypto */ 688416d8220SZaibo Xu if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt) 689416d8220SZaibo Xu sec_update_iv(req); 690416d8220SZaibo Xu 691416d8220SZaibo Xu ret = ctx->req_op->bd_send(ctx, req); 692416d8220SZaibo Xu if (ret != -EBUSY && ret != -EINPROGRESS) { 693a718cfceSZaibo Xu dev_err_ratelimited(SEC_CTX_DEV(ctx), "send sec request failed!\n"); 694416d8220SZaibo Xu goto err_send_req; 695416d8220SZaibo Xu } 696416d8220SZaibo Xu 697416d8220SZaibo Xu return ret; 698416d8220SZaibo Xu 699416d8220SZaibo Xu err_send_req: 700416d8220SZaibo Xu /* As failing, restore the IV from user */ 701416d8220SZaibo Xu if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt) 7027c7d902aSZaibo Xu memcpy(req->c_req.sk_req->iv, 7037c7d902aSZaibo Xu req->qp_ctx->res[req->req_id].c_ivin, 704416d8220SZaibo Xu ctx->c_ctx.ivsize); 705416d8220SZaibo Xu 706416d8220SZaibo Xu sec_request_untransfer(ctx, req); 707416d8220SZaibo Xu err_uninit_req: 708416d8220SZaibo Xu sec_request_uninit(ctx, req); 709416d8220SZaibo Xu 710416d8220SZaibo Xu return ret; 711416d8220SZaibo Xu } 712416d8220SZaibo Xu 713a181647cSZaibo Xu static const struct sec_req_op sec_skcipher_req_ops = { 714416d8220SZaibo Xu .buf_map = sec_skcipher_sgl_map, 715416d8220SZaibo Xu .buf_unmap = sec_skcipher_sgl_unmap, 716416d8220SZaibo Xu .do_transfer = sec_skcipher_copy_iv, 717416d8220SZaibo Xu .bd_fill = sec_skcipher_bd_fill, 718416d8220SZaibo Xu .bd_send = sec_bd_send, 719416d8220SZaibo Xu .callback = sec_skcipher_callback, 720416d8220SZaibo Xu .process = sec_process, 721416d8220SZaibo Xu }; 722416d8220SZaibo Xu 723416d8220SZaibo Xu static int sec_skcipher_ctx_init(struct crypto_skcipher *tfm) 724416d8220SZaibo Xu { 725416d8220SZaibo Xu struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 726416d8220SZaibo Xu 727a181647cSZaibo Xu ctx->req_op = &sec_skcipher_req_ops; 728416d8220SZaibo Xu 729416d8220SZaibo Xu return sec_skcipher_init(tfm); 730416d8220SZaibo Xu } 731416d8220SZaibo Xu 732416d8220SZaibo Xu static void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm) 733416d8220SZaibo Xu { 734a181647cSZaibo Xu sec_skcipher_uninit(tfm); 735416d8220SZaibo Xu } 736416d8220SZaibo Xu 737d6de2a59SZaibo Xu static int sec_skcipher_param_check(struct sec_ctx *ctx, struct sec_req *sreq) 738416d8220SZaibo Xu { 739d6de2a59SZaibo Xu struct skcipher_request *sk_req = sreq->c_req.sk_req; 740416d8220SZaibo Xu struct device *dev = SEC_CTX_DEV(ctx); 741d6de2a59SZaibo Xu u8 c_alg = ctx->c_ctx.c_alg; 742416d8220SZaibo Xu 743416d8220SZaibo Xu if (!sk_req->src || !sk_req->dst) { 744416d8220SZaibo Xu dev_err(dev, "skcipher input param error!\n"); 745416d8220SZaibo Xu return -EINVAL; 746416d8220SZaibo Xu } 747d6de2a59SZaibo Xu sreq->c_req.c_len = sk_req->cryptlen; 748416d8220SZaibo Xu if (c_alg == SEC_CALG_3DES) { 749416d8220SZaibo Xu if (sk_req->cryptlen & (DES3_EDE_BLOCK_SIZE - 1)) { 750416d8220SZaibo Xu dev_err(dev, "skcipher 3des input length error!\n"); 751416d8220SZaibo Xu return -EINVAL; 752416d8220SZaibo Xu } 753416d8220SZaibo Xu return 0; 754416d8220SZaibo Xu } else if (c_alg == SEC_CALG_AES || c_alg == SEC_CALG_SM4) { 755416d8220SZaibo Xu if (sk_req->cryptlen & (AES_BLOCK_SIZE - 1)) { 756416d8220SZaibo Xu dev_err(dev, "skcipher aes input length error!\n"); 757416d8220SZaibo Xu return -EINVAL; 758416d8220SZaibo Xu } 759416d8220SZaibo Xu return 0; 760416d8220SZaibo Xu } 761416d8220SZaibo Xu 762416d8220SZaibo Xu dev_err(dev, "skcipher algorithm error!\n"); 763416d8220SZaibo Xu return -EINVAL; 764416d8220SZaibo Xu } 765416d8220SZaibo Xu 766416d8220SZaibo Xu static int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt) 767416d8220SZaibo Xu { 768416d8220SZaibo Xu struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req); 769416d8220SZaibo Xu struct sec_req *req = skcipher_request_ctx(sk_req); 770416d8220SZaibo Xu struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 771416d8220SZaibo Xu int ret; 772416d8220SZaibo Xu 773416d8220SZaibo Xu if (!sk_req->cryptlen) 774416d8220SZaibo Xu return 0; 775416d8220SZaibo Xu 776416d8220SZaibo Xu req->c_req.sk_req = sk_req; 777416d8220SZaibo Xu req->c_req.encrypt = encrypt; 778416d8220SZaibo Xu req->ctx = ctx; 779416d8220SZaibo Xu 780d6de2a59SZaibo Xu ret = sec_skcipher_param_check(ctx, req); 781d6de2a59SZaibo Xu if (unlikely(ret)) 782d6de2a59SZaibo Xu return -EINVAL; 783d6de2a59SZaibo Xu 784416d8220SZaibo Xu return ctx->req_op->process(ctx, req); 785416d8220SZaibo Xu } 786416d8220SZaibo Xu 787416d8220SZaibo Xu static int sec_skcipher_encrypt(struct skcipher_request *sk_req) 788416d8220SZaibo Xu { 789416d8220SZaibo Xu return sec_skcipher_crypto(sk_req, true); 790416d8220SZaibo Xu } 791416d8220SZaibo Xu 792416d8220SZaibo Xu static int sec_skcipher_decrypt(struct skcipher_request *sk_req) 793416d8220SZaibo Xu { 794416d8220SZaibo Xu return sec_skcipher_crypto(sk_req, false); 795416d8220SZaibo Xu } 796416d8220SZaibo Xu 797416d8220SZaibo Xu #define SEC_SKCIPHER_GEN_ALG(sec_cra_name, sec_set_key, sec_min_key_size, \ 798416d8220SZaibo Xu sec_max_key_size, ctx_init, ctx_exit, blk_size, iv_size)\ 799416d8220SZaibo Xu {\ 800416d8220SZaibo Xu .base = {\ 801416d8220SZaibo Xu .cra_name = sec_cra_name,\ 802416d8220SZaibo Xu .cra_driver_name = "hisi_sec_"sec_cra_name,\ 803416d8220SZaibo Xu .cra_priority = SEC_PRIORITY,\ 804416d8220SZaibo Xu .cra_flags = CRYPTO_ALG_ASYNC,\ 805416d8220SZaibo Xu .cra_blocksize = blk_size,\ 806416d8220SZaibo Xu .cra_ctxsize = sizeof(struct sec_ctx),\ 807416d8220SZaibo Xu .cra_module = THIS_MODULE,\ 808416d8220SZaibo Xu },\ 809416d8220SZaibo Xu .init = ctx_init,\ 810416d8220SZaibo Xu .exit = ctx_exit,\ 811416d8220SZaibo Xu .setkey = sec_set_key,\ 812416d8220SZaibo Xu .decrypt = sec_skcipher_decrypt,\ 813416d8220SZaibo Xu .encrypt = sec_skcipher_encrypt,\ 814416d8220SZaibo Xu .min_keysize = sec_min_key_size,\ 815416d8220SZaibo Xu .max_keysize = sec_max_key_size,\ 816416d8220SZaibo Xu .ivsize = iv_size,\ 817416d8220SZaibo Xu }, 818416d8220SZaibo Xu 819416d8220SZaibo Xu #define SEC_SKCIPHER_ALG(name, key_func, min_key_size, \ 820416d8220SZaibo Xu max_key_size, blk_size, iv_size) \ 821416d8220SZaibo Xu SEC_SKCIPHER_GEN_ALG(name, key_func, min_key_size, max_key_size, \ 822416d8220SZaibo Xu sec_skcipher_ctx_init, sec_skcipher_ctx_exit, blk_size, iv_size) 823416d8220SZaibo Xu 824a181647cSZaibo Xu static struct skcipher_alg sec_skciphers[] = { 825416d8220SZaibo Xu SEC_SKCIPHER_ALG("ecb(aes)", sec_setkey_aes_ecb, 826416d8220SZaibo Xu AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE, 827416d8220SZaibo Xu AES_BLOCK_SIZE, 0) 828416d8220SZaibo Xu 829416d8220SZaibo Xu SEC_SKCIPHER_ALG("cbc(aes)", sec_setkey_aes_cbc, 830416d8220SZaibo Xu AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE, 831416d8220SZaibo Xu AES_BLOCK_SIZE, AES_BLOCK_SIZE) 832416d8220SZaibo Xu 833416d8220SZaibo Xu SEC_SKCIPHER_ALG("xts(aes)", sec_setkey_aes_xts, 834416d8220SZaibo Xu SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MAX_KEY_SIZE, 835416d8220SZaibo Xu AES_BLOCK_SIZE, AES_BLOCK_SIZE) 836416d8220SZaibo Xu 837416d8220SZaibo Xu SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb, 838416d8220SZaibo Xu SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE, 839416d8220SZaibo Xu DES3_EDE_BLOCK_SIZE, 0) 840416d8220SZaibo Xu 841416d8220SZaibo Xu SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc, 842416d8220SZaibo Xu SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE, 843416d8220SZaibo Xu DES3_EDE_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE) 844416d8220SZaibo Xu 845416d8220SZaibo Xu SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts, 846416d8220SZaibo Xu SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MIN_KEY_SIZE, 847416d8220SZaibo Xu AES_BLOCK_SIZE, AES_BLOCK_SIZE) 848416d8220SZaibo Xu 849416d8220SZaibo Xu SEC_SKCIPHER_ALG("cbc(sm4)", sec_setkey_sm4_cbc, 850416d8220SZaibo Xu AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE, 851416d8220SZaibo Xu AES_BLOCK_SIZE, AES_BLOCK_SIZE) 852416d8220SZaibo Xu }; 853416d8220SZaibo Xu 854416d8220SZaibo Xu int sec_register_to_crypto(void) 855416d8220SZaibo Xu { 856416d8220SZaibo Xu int ret = 0; 857416d8220SZaibo Xu 858416d8220SZaibo Xu /* To avoid repeat register */ 859416d8220SZaibo Xu mutex_lock(&sec_algs_lock); 860416d8220SZaibo Xu if (++sec_active_devs == 1) 861a181647cSZaibo Xu ret = crypto_register_skciphers(sec_skciphers, 862a181647cSZaibo Xu ARRAY_SIZE(sec_skciphers)); 863416d8220SZaibo Xu mutex_unlock(&sec_algs_lock); 864416d8220SZaibo Xu 865416d8220SZaibo Xu return ret; 866416d8220SZaibo Xu } 867416d8220SZaibo Xu 868416d8220SZaibo Xu void sec_unregister_from_crypto(void) 869416d8220SZaibo Xu { 870416d8220SZaibo Xu mutex_lock(&sec_algs_lock); 871416d8220SZaibo Xu if (--sec_active_devs == 0) 872a181647cSZaibo Xu crypto_unregister_skciphers(sec_skciphers, 873a181647cSZaibo Xu ARRAY_SIZE(sec_skciphers)); 874416d8220SZaibo Xu mutex_unlock(&sec_algs_lock); 875416d8220SZaibo Xu } 876