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) 38416d8220SZaibo Xu 39416d8220SZaibo Xu static DEFINE_MUTEX(sec_algs_lock); 40416d8220SZaibo Xu static unsigned int sec_active_devs; 41416d8220SZaibo Xu 42416d8220SZaibo Xu /* Get an en/de-cipher queue cyclically to balance load over queues of TFM */ 43416d8220SZaibo Xu static inline int sec_get_queue_id(struct sec_ctx *ctx, struct sec_req *req) 44416d8220SZaibo Xu { 45416d8220SZaibo Xu if (req->c_req.encrypt) 46416d8220SZaibo Xu return (u32)atomic_inc_return(&ctx->enc_qcyclic) % 47416d8220SZaibo Xu ctx->hlf_q_num; 48416d8220SZaibo Xu 49416d8220SZaibo Xu return (u32)atomic_inc_return(&ctx->dec_qcyclic) % ctx->hlf_q_num + 50416d8220SZaibo Xu ctx->hlf_q_num; 51416d8220SZaibo Xu } 52416d8220SZaibo Xu 53416d8220SZaibo Xu static inline void sec_put_queue_id(struct sec_ctx *ctx, struct sec_req *req) 54416d8220SZaibo Xu { 55416d8220SZaibo Xu if (req->c_req.encrypt) 56416d8220SZaibo Xu atomic_dec(&ctx->enc_qcyclic); 57416d8220SZaibo Xu else 58416d8220SZaibo Xu atomic_dec(&ctx->dec_qcyclic); 59416d8220SZaibo Xu } 60416d8220SZaibo Xu 61416d8220SZaibo Xu static int sec_alloc_req_id(struct sec_req *req, struct sec_qp_ctx *qp_ctx) 62416d8220SZaibo Xu { 63416d8220SZaibo Xu int req_id; 64416d8220SZaibo Xu 65416d8220SZaibo Xu mutex_lock(&qp_ctx->req_lock); 66416d8220SZaibo Xu 67416d8220SZaibo Xu req_id = idr_alloc_cyclic(&qp_ctx->req_idr, NULL, 68416d8220SZaibo Xu 0, QM_Q_DEPTH, GFP_ATOMIC); 69416d8220SZaibo Xu mutex_unlock(&qp_ctx->req_lock); 70416d8220SZaibo Xu if (req_id < 0) { 71416d8220SZaibo Xu dev_err(SEC_CTX_DEV(req->ctx), "alloc req id fail!\n"); 72416d8220SZaibo Xu return req_id; 73416d8220SZaibo Xu } 74416d8220SZaibo Xu 75416d8220SZaibo Xu req->qp_ctx = qp_ctx; 76416d8220SZaibo Xu qp_ctx->req_list[req_id] = req; 77416d8220SZaibo Xu return req_id; 78416d8220SZaibo Xu } 79416d8220SZaibo Xu 80416d8220SZaibo Xu static void sec_free_req_id(struct sec_req *req) 81416d8220SZaibo Xu { 82416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx = req->qp_ctx; 83416d8220SZaibo Xu int req_id = req->req_id; 84416d8220SZaibo Xu 85416d8220SZaibo Xu if (req_id < 0 || req_id >= QM_Q_DEPTH) { 86416d8220SZaibo Xu dev_err(SEC_CTX_DEV(req->ctx), "free request id invalid!\n"); 87416d8220SZaibo Xu return; 88416d8220SZaibo Xu } 89416d8220SZaibo Xu 90416d8220SZaibo Xu qp_ctx->req_list[req_id] = NULL; 91416d8220SZaibo Xu req->qp_ctx = NULL; 92416d8220SZaibo Xu 93416d8220SZaibo Xu mutex_lock(&qp_ctx->req_lock); 94416d8220SZaibo Xu idr_remove(&qp_ctx->req_idr, req_id); 95416d8220SZaibo Xu mutex_unlock(&qp_ctx->req_lock); 96416d8220SZaibo Xu } 97416d8220SZaibo Xu 98416d8220SZaibo Xu static void sec_req_cb(struct hisi_qp *qp, void *resp) 99416d8220SZaibo Xu { 100416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx = qp->qp_ctx; 101416d8220SZaibo Xu struct sec_sqe *bd = resp; 102416d8220SZaibo Xu u16 done, flag; 103416d8220SZaibo Xu u8 type; 104416d8220SZaibo Xu struct sec_req *req; 105416d8220SZaibo Xu 106416d8220SZaibo Xu type = bd->type_cipher_auth & SEC_TYPE_MASK; 107416d8220SZaibo Xu if (type == SEC_BD_TYPE2) { 108416d8220SZaibo Xu req = qp_ctx->req_list[le16_to_cpu(bd->type2.tag)]; 109416d8220SZaibo Xu req->err_type = bd->type2.error_type; 110416d8220SZaibo Xu 111416d8220SZaibo Xu done = le16_to_cpu(bd->type2.done_flag) & SEC_DONE_MASK; 112416d8220SZaibo Xu flag = (le16_to_cpu(bd->type2.done_flag) & 113416d8220SZaibo Xu SEC_FLAG_MASK) >> SEC_FLAG_OFFSET; 114416d8220SZaibo Xu if (req->err_type || done != 0x1 || flag != 0x2) 115416d8220SZaibo Xu dev_err(SEC_CTX_DEV(req->ctx), 116416d8220SZaibo Xu "err_type[%d],done[%d],flag[%d]\n", 117416d8220SZaibo Xu req->err_type, done, flag); 118416d8220SZaibo Xu } else { 119416d8220SZaibo Xu pr_err("err bd type [%d]\n", type); 120416d8220SZaibo Xu return; 121416d8220SZaibo Xu } 122416d8220SZaibo Xu 123*1e9bc276SZaibo Xu __sync_add_and_fetch(&req->ctx->sec->debug.dfx.recv_cnt, 1); 124*1e9bc276SZaibo Xu 125416d8220SZaibo Xu req->ctx->req_op->buf_unmap(req->ctx, req); 126416d8220SZaibo Xu 127416d8220SZaibo Xu req->ctx->req_op->callback(req->ctx, req); 128416d8220SZaibo Xu } 129416d8220SZaibo Xu 130416d8220SZaibo Xu static int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req) 131416d8220SZaibo Xu { 132416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx = req->qp_ctx; 133416d8220SZaibo Xu int ret; 134416d8220SZaibo Xu 135416d8220SZaibo Xu mutex_lock(&qp_ctx->req_lock); 136416d8220SZaibo Xu ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe); 137416d8220SZaibo Xu mutex_unlock(&qp_ctx->req_lock); 138*1e9bc276SZaibo Xu __sync_add_and_fetch(&ctx->sec->debug.dfx.send_cnt, 1); 139416d8220SZaibo Xu 140416d8220SZaibo Xu if (ret == -EBUSY) 141416d8220SZaibo Xu return -ENOBUFS; 142416d8220SZaibo Xu 143416d8220SZaibo Xu if (!ret) { 144416d8220SZaibo Xu if (req->fake_busy) 145416d8220SZaibo Xu ret = -EBUSY; 146416d8220SZaibo Xu else 147416d8220SZaibo Xu ret = -EINPROGRESS; 148416d8220SZaibo Xu } 149416d8220SZaibo Xu 150416d8220SZaibo Xu return ret; 151416d8220SZaibo Xu } 152416d8220SZaibo Xu 153416d8220SZaibo Xu static int sec_create_qp_ctx(struct hisi_qm *qm, struct sec_ctx *ctx, 154416d8220SZaibo Xu int qp_ctx_id, int alg_type) 155416d8220SZaibo Xu { 156416d8220SZaibo Xu struct device *dev = SEC_CTX_DEV(ctx); 157416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx; 158416d8220SZaibo Xu struct hisi_qp *qp; 159416d8220SZaibo Xu int ret = -ENOMEM; 160416d8220SZaibo Xu 161416d8220SZaibo Xu qp = hisi_qm_create_qp(qm, alg_type); 162416d8220SZaibo Xu if (IS_ERR(qp)) 163416d8220SZaibo Xu return PTR_ERR(qp); 164416d8220SZaibo Xu 165416d8220SZaibo Xu qp_ctx = &ctx->qp_ctx[qp_ctx_id]; 166416d8220SZaibo Xu qp->req_type = 0; 167416d8220SZaibo Xu qp->qp_ctx = qp_ctx; 168416d8220SZaibo Xu qp->req_cb = sec_req_cb; 169416d8220SZaibo Xu qp_ctx->qp = qp; 170416d8220SZaibo Xu qp_ctx->ctx = ctx; 171416d8220SZaibo Xu 172416d8220SZaibo Xu mutex_init(&qp_ctx->req_lock); 173416d8220SZaibo Xu atomic_set(&qp_ctx->pending_reqs, 0); 174416d8220SZaibo Xu idr_init(&qp_ctx->req_idr); 175416d8220SZaibo Xu 176416d8220SZaibo Xu qp_ctx->req_list = kcalloc(QM_Q_DEPTH, sizeof(void *), GFP_ATOMIC); 177416d8220SZaibo Xu if (!qp_ctx->req_list) 178416d8220SZaibo Xu goto err_destroy_idr; 179416d8220SZaibo Xu 180416d8220SZaibo Xu qp_ctx->c_in_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH, 181416d8220SZaibo Xu SEC_SGL_SGE_NR); 182416d8220SZaibo Xu if (!qp_ctx->c_in_pool) { 183416d8220SZaibo Xu dev_err(dev, "fail to create sgl pool for input!\n"); 184416d8220SZaibo Xu goto err_free_req_list; 185416d8220SZaibo Xu } 186416d8220SZaibo Xu 187416d8220SZaibo Xu qp_ctx->c_out_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH, 188416d8220SZaibo Xu SEC_SGL_SGE_NR); 189416d8220SZaibo Xu if (!qp_ctx->c_out_pool) { 190416d8220SZaibo Xu dev_err(dev, "fail to create sgl pool for output!\n"); 191416d8220SZaibo Xu goto err_free_c_in_pool; 192416d8220SZaibo Xu } 193416d8220SZaibo Xu 194416d8220SZaibo Xu ret = ctx->req_op->resource_alloc(ctx, qp_ctx); 195416d8220SZaibo Xu if (ret) 196416d8220SZaibo Xu goto err_free_c_out_pool; 197416d8220SZaibo Xu 198416d8220SZaibo Xu ret = hisi_qm_start_qp(qp, 0); 199416d8220SZaibo Xu if (ret < 0) 200416d8220SZaibo Xu goto err_queue_free; 201416d8220SZaibo Xu 202416d8220SZaibo Xu return 0; 203416d8220SZaibo Xu 204416d8220SZaibo Xu err_queue_free: 205416d8220SZaibo Xu ctx->req_op->resource_free(ctx, qp_ctx); 206416d8220SZaibo Xu err_free_c_out_pool: 207416d8220SZaibo Xu hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool); 208416d8220SZaibo Xu err_free_c_in_pool: 209416d8220SZaibo Xu hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool); 210416d8220SZaibo Xu err_free_req_list: 211416d8220SZaibo Xu kfree(qp_ctx->req_list); 212416d8220SZaibo Xu err_destroy_idr: 213416d8220SZaibo Xu idr_destroy(&qp_ctx->req_idr); 214416d8220SZaibo Xu hisi_qm_release_qp(qp); 215416d8220SZaibo Xu 216416d8220SZaibo Xu return ret; 217416d8220SZaibo Xu } 218416d8220SZaibo Xu 219416d8220SZaibo Xu static void sec_release_qp_ctx(struct sec_ctx *ctx, 220416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx) 221416d8220SZaibo Xu { 222416d8220SZaibo Xu struct device *dev = SEC_CTX_DEV(ctx); 223416d8220SZaibo Xu 224416d8220SZaibo Xu hisi_qm_stop_qp(qp_ctx->qp); 225416d8220SZaibo Xu ctx->req_op->resource_free(ctx, qp_ctx); 226416d8220SZaibo Xu 227416d8220SZaibo Xu hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool); 228416d8220SZaibo Xu hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool); 229416d8220SZaibo Xu 230416d8220SZaibo Xu idr_destroy(&qp_ctx->req_idr); 231416d8220SZaibo Xu kfree(qp_ctx->req_list); 232416d8220SZaibo Xu hisi_qm_release_qp(qp_ctx->qp); 233416d8220SZaibo Xu } 234416d8220SZaibo Xu 235416d8220SZaibo Xu static int sec_skcipher_init(struct crypto_skcipher *tfm) 236416d8220SZaibo Xu { 237416d8220SZaibo Xu struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 238416d8220SZaibo Xu struct sec_cipher_ctx *c_ctx; 239416d8220SZaibo Xu struct sec_dev *sec; 240416d8220SZaibo Xu struct device *dev; 241416d8220SZaibo Xu struct hisi_qm *qm; 242416d8220SZaibo Xu int i, ret; 243416d8220SZaibo Xu 244416d8220SZaibo Xu crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_req)); 245416d8220SZaibo Xu 246416d8220SZaibo Xu sec = sec_find_device(cpu_to_node(smp_processor_id())); 247416d8220SZaibo Xu if (!sec) { 248416d8220SZaibo Xu pr_err("find no Hisilicon SEC device!\n"); 249416d8220SZaibo Xu return -ENODEV; 250416d8220SZaibo Xu } 251416d8220SZaibo Xu ctx->sec = sec; 252416d8220SZaibo Xu qm = &sec->qm; 253416d8220SZaibo Xu dev = &qm->pdev->dev; 254416d8220SZaibo Xu ctx->hlf_q_num = sec->ctx_q_num >> 0x1; 255416d8220SZaibo Xu 256416d8220SZaibo Xu /* Half of queue depth is taken as fake requests limit in the queue. */ 257416d8220SZaibo Xu ctx->fake_req_limit = QM_Q_DEPTH >> 0x1; 258416d8220SZaibo Xu ctx->qp_ctx = kcalloc(sec->ctx_q_num, sizeof(struct sec_qp_ctx), 259416d8220SZaibo Xu GFP_KERNEL); 260416d8220SZaibo Xu if (!ctx->qp_ctx) 261416d8220SZaibo Xu return -ENOMEM; 262416d8220SZaibo Xu 263416d8220SZaibo Xu for (i = 0; i < sec->ctx_q_num; i++) { 264416d8220SZaibo Xu ret = sec_create_qp_ctx(qm, ctx, i, 0); 265416d8220SZaibo Xu if (ret) 266416d8220SZaibo Xu goto err_sec_release_qp_ctx; 267416d8220SZaibo Xu } 268416d8220SZaibo Xu 269416d8220SZaibo Xu c_ctx = &ctx->c_ctx; 270416d8220SZaibo Xu c_ctx->ivsize = crypto_skcipher_ivsize(tfm); 271416d8220SZaibo Xu if (c_ctx->ivsize > SEC_IV_SIZE) { 272416d8220SZaibo Xu dev_err(dev, "get error iv size!\n"); 273416d8220SZaibo Xu ret = -EINVAL; 274416d8220SZaibo Xu goto err_sec_release_qp_ctx; 275416d8220SZaibo Xu } 276416d8220SZaibo Xu c_ctx->c_key = dma_alloc_coherent(dev, SEC_MAX_KEY_SIZE, 277416d8220SZaibo Xu &c_ctx->c_key_dma, GFP_KERNEL); 278416d8220SZaibo Xu if (!c_ctx->c_key) { 279416d8220SZaibo Xu ret = -ENOMEM; 280416d8220SZaibo Xu goto err_sec_release_qp_ctx; 281416d8220SZaibo Xu } 282416d8220SZaibo Xu 283416d8220SZaibo Xu return 0; 284416d8220SZaibo Xu 285416d8220SZaibo Xu err_sec_release_qp_ctx: 286416d8220SZaibo Xu for (i = i - 1; i >= 0; i--) 287416d8220SZaibo Xu sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]); 288416d8220SZaibo Xu 289416d8220SZaibo Xu kfree(ctx->qp_ctx); 290416d8220SZaibo Xu return ret; 291416d8220SZaibo Xu } 292416d8220SZaibo Xu 293416d8220SZaibo Xu static void sec_skcipher_exit(struct crypto_skcipher *tfm) 294416d8220SZaibo Xu { 295416d8220SZaibo Xu struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 296416d8220SZaibo Xu struct sec_cipher_ctx *c_ctx = &ctx->c_ctx; 297416d8220SZaibo Xu int i = 0; 298416d8220SZaibo Xu 299416d8220SZaibo Xu if (c_ctx->c_key) { 300416d8220SZaibo Xu dma_free_coherent(SEC_CTX_DEV(ctx), SEC_MAX_KEY_SIZE, 301416d8220SZaibo Xu c_ctx->c_key, c_ctx->c_key_dma); 302416d8220SZaibo Xu c_ctx->c_key = NULL; 303416d8220SZaibo Xu } 304416d8220SZaibo Xu 305416d8220SZaibo Xu for (i = 0; i < ctx->sec->ctx_q_num; i++) 306416d8220SZaibo Xu sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]); 307416d8220SZaibo Xu 308416d8220SZaibo Xu kfree(ctx->qp_ctx); 309416d8220SZaibo Xu } 310416d8220SZaibo Xu 311416d8220SZaibo Xu static int sec_skcipher_3des_setkey(struct sec_cipher_ctx *c_ctx, 312416d8220SZaibo Xu const u32 keylen, 313416d8220SZaibo Xu const enum sec_cmode c_mode) 314416d8220SZaibo Xu { 315416d8220SZaibo Xu switch (keylen) { 316416d8220SZaibo Xu case SEC_DES3_2KEY_SIZE: 317416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_3DES_2KEY; 318416d8220SZaibo Xu break; 319416d8220SZaibo Xu case SEC_DES3_3KEY_SIZE: 320416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_3DES_3KEY; 321416d8220SZaibo Xu break; 322416d8220SZaibo Xu default: 323416d8220SZaibo Xu return -EINVAL; 324416d8220SZaibo Xu } 325416d8220SZaibo Xu 326416d8220SZaibo Xu return 0; 327416d8220SZaibo Xu } 328416d8220SZaibo Xu 329416d8220SZaibo Xu static int sec_skcipher_aes_sm4_setkey(struct sec_cipher_ctx *c_ctx, 330416d8220SZaibo Xu const u32 keylen, 331416d8220SZaibo Xu const enum sec_cmode c_mode) 332416d8220SZaibo Xu { 333416d8220SZaibo Xu if (c_mode == SEC_CMODE_XTS) { 334416d8220SZaibo Xu switch (keylen) { 335416d8220SZaibo Xu case SEC_XTS_MIN_KEY_SIZE: 336416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_128BIT; 337416d8220SZaibo Xu break; 338416d8220SZaibo Xu case SEC_XTS_MAX_KEY_SIZE: 339416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_256BIT; 340416d8220SZaibo Xu break; 341416d8220SZaibo Xu default: 342416d8220SZaibo Xu pr_err("hisi_sec2: xts mode key error!\n"); 343416d8220SZaibo Xu return -EINVAL; 344416d8220SZaibo Xu } 345416d8220SZaibo Xu } else { 346416d8220SZaibo Xu switch (keylen) { 347416d8220SZaibo Xu case AES_KEYSIZE_128: 348416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_128BIT; 349416d8220SZaibo Xu break; 350416d8220SZaibo Xu case AES_KEYSIZE_192: 351416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_192BIT; 352416d8220SZaibo Xu break; 353416d8220SZaibo Xu case AES_KEYSIZE_256: 354416d8220SZaibo Xu c_ctx->c_key_len = SEC_CKEY_256BIT; 355416d8220SZaibo Xu break; 356416d8220SZaibo Xu default: 357416d8220SZaibo Xu pr_err("hisi_sec2: aes key error!\n"); 358416d8220SZaibo Xu return -EINVAL; 359416d8220SZaibo Xu } 360416d8220SZaibo Xu } 361416d8220SZaibo Xu 362416d8220SZaibo Xu return 0; 363416d8220SZaibo Xu } 364416d8220SZaibo Xu 365416d8220SZaibo Xu static int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, 366416d8220SZaibo Xu const u32 keylen, const enum sec_calg c_alg, 367416d8220SZaibo Xu const enum sec_cmode c_mode) 368416d8220SZaibo Xu { 369416d8220SZaibo Xu struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 370416d8220SZaibo Xu struct sec_cipher_ctx *c_ctx = &ctx->c_ctx; 371416d8220SZaibo Xu int ret; 372416d8220SZaibo Xu 373416d8220SZaibo Xu if (c_mode == SEC_CMODE_XTS) { 374416d8220SZaibo Xu ret = xts_verify_key(tfm, key, keylen); 375416d8220SZaibo Xu if (ret) { 376416d8220SZaibo Xu dev_err(SEC_CTX_DEV(ctx), "xts mode key err!\n"); 377416d8220SZaibo Xu return ret; 378416d8220SZaibo Xu } 379416d8220SZaibo Xu } 380416d8220SZaibo Xu 381416d8220SZaibo Xu c_ctx->c_alg = c_alg; 382416d8220SZaibo Xu c_ctx->c_mode = c_mode; 383416d8220SZaibo Xu 384416d8220SZaibo Xu switch (c_alg) { 385416d8220SZaibo Xu case SEC_CALG_3DES: 386416d8220SZaibo Xu ret = sec_skcipher_3des_setkey(c_ctx, keylen, c_mode); 387416d8220SZaibo Xu break; 388416d8220SZaibo Xu case SEC_CALG_AES: 389416d8220SZaibo Xu case SEC_CALG_SM4: 390416d8220SZaibo Xu ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode); 391416d8220SZaibo Xu break; 392416d8220SZaibo Xu default: 393416d8220SZaibo Xu return -EINVAL; 394416d8220SZaibo Xu } 395416d8220SZaibo Xu 396416d8220SZaibo Xu if (ret) { 397416d8220SZaibo Xu dev_err(SEC_CTX_DEV(ctx), "set sec key err!\n"); 398416d8220SZaibo Xu return ret; 399416d8220SZaibo Xu } 400416d8220SZaibo Xu 401416d8220SZaibo Xu memcpy(c_ctx->c_key, key, keylen); 402416d8220SZaibo Xu 403416d8220SZaibo Xu return 0; 404416d8220SZaibo Xu } 405416d8220SZaibo Xu 406416d8220SZaibo Xu #define GEN_SEC_SETKEY_FUNC(name, c_alg, c_mode) \ 407416d8220SZaibo Xu static int sec_setkey_##name(struct crypto_skcipher *tfm, const u8 *key,\ 408416d8220SZaibo Xu u32 keylen) \ 409416d8220SZaibo Xu { \ 410416d8220SZaibo Xu return sec_skcipher_setkey(tfm, key, keylen, c_alg, c_mode); \ 411416d8220SZaibo Xu } 412416d8220SZaibo Xu 413416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_ecb, SEC_CALG_AES, SEC_CMODE_ECB) 414416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_cbc, SEC_CALG_AES, SEC_CMODE_CBC) 415416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(aes_xts, SEC_CALG_AES, SEC_CMODE_XTS) 416416d8220SZaibo Xu 417416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_ecb, SEC_CALG_3DES, SEC_CMODE_ECB) 418416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(3des_cbc, SEC_CALG_3DES, SEC_CMODE_CBC) 419416d8220SZaibo Xu 420416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_xts, SEC_CALG_SM4, SEC_CMODE_XTS) 421416d8220SZaibo Xu GEN_SEC_SETKEY_FUNC(sm4_cbc, SEC_CALG_SM4, SEC_CMODE_CBC) 422416d8220SZaibo Xu 423416d8220SZaibo Xu static int sec_skcipher_get_res(struct sec_ctx *ctx, 424416d8220SZaibo Xu struct sec_req *req) 425416d8220SZaibo Xu { 426416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx = req->qp_ctx; 427416d8220SZaibo Xu struct sec_cipher_res *c_res = qp_ctx->alg_meta_data; 428416d8220SZaibo Xu struct sec_cipher_req *c_req = &req->c_req; 429416d8220SZaibo Xu int req_id = req->req_id; 430416d8220SZaibo Xu 431416d8220SZaibo Xu c_req->c_ivin = c_res[req_id].c_ivin; 432416d8220SZaibo Xu c_req->c_ivin_dma = c_res[req_id].c_ivin_dma; 433416d8220SZaibo Xu 434416d8220SZaibo Xu return 0; 435416d8220SZaibo Xu } 436416d8220SZaibo Xu 437416d8220SZaibo Xu static int sec_skcipher_resource_alloc(struct sec_ctx *ctx, 438416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx) 439416d8220SZaibo Xu { 440416d8220SZaibo Xu struct device *dev = SEC_CTX_DEV(ctx); 441416d8220SZaibo Xu struct sec_cipher_res *res; 442416d8220SZaibo Xu int i; 443416d8220SZaibo Xu 444416d8220SZaibo Xu res = kcalloc(QM_Q_DEPTH, sizeof(struct sec_cipher_res), GFP_KERNEL); 445416d8220SZaibo Xu if (!res) 446416d8220SZaibo Xu return -ENOMEM; 447416d8220SZaibo Xu 448416d8220SZaibo Xu res->c_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ, 449416d8220SZaibo Xu &res->c_ivin_dma, GFP_KERNEL); 450416d8220SZaibo Xu if (!res->c_ivin) { 451416d8220SZaibo Xu kfree(res); 452416d8220SZaibo Xu return -ENOMEM; 453416d8220SZaibo Xu } 454416d8220SZaibo Xu 455416d8220SZaibo Xu for (i = 1; i < QM_Q_DEPTH; i++) { 456416d8220SZaibo Xu res[i].c_ivin_dma = res->c_ivin_dma + i * SEC_IV_SIZE; 457416d8220SZaibo Xu res[i].c_ivin = res->c_ivin + i * SEC_IV_SIZE; 458416d8220SZaibo Xu } 459416d8220SZaibo Xu qp_ctx->alg_meta_data = res; 460416d8220SZaibo Xu 461416d8220SZaibo Xu return 0; 462416d8220SZaibo Xu } 463416d8220SZaibo Xu 464416d8220SZaibo Xu static void sec_skcipher_resource_free(struct sec_ctx *ctx, 465416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx) 466416d8220SZaibo Xu { 467416d8220SZaibo Xu struct sec_cipher_res *res = qp_ctx->alg_meta_data; 468416d8220SZaibo Xu struct device *dev = SEC_CTX_DEV(ctx); 469416d8220SZaibo Xu 470416d8220SZaibo Xu if (!res) 471416d8220SZaibo Xu return; 472416d8220SZaibo Xu 473416d8220SZaibo Xu dma_free_coherent(dev, SEC_TOTAL_IV_SZ, res->c_ivin, res->c_ivin_dma); 474416d8220SZaibo Xu kfree(res); 475416d8220SZaibo Xu } 476416d8220SZaibo Xu 477416d8220SZaibo Xu static int sec_skcipher_map(struct device *dev, struct sec_req *req, 478416d8220SZaibo Xu struct scatterlist *src, struct scatterlist *dst) 479416d8220SZaibo Xu { 480416d8220SZaibo Xu struct sec_cipher_req *c_req = &req->c_req; 481416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx = req->qp_ctx; 482416d8220SZaibo Xu 483416d8220SZaibo Xu c_req->c_in = hisi_acc_sg_buf_map_to_hw_sgl(dev, src, 484416d8220SZaibo Xu qp_ctx->c_in_pool, 485416d8220SZaibo Xu req->req_id, 486416d8220SZaibo Xu &c_req->c_in_dma); 487416d8220SZaibo Xu 488416d8220SZaibo Xu if (IS_ERR(c_req->c_in)) { 489416d8220SZaibo Xu dev_err(dev, "fail to dma map input sgl buffers!\n"); 490416d8220SZaibo Xu return PTR_ERR(c_req->c_in); 491416d8220SZaibo Xu } 492416d8220SZaibo Xu 493416d8220SZaibo Xu if (dst == src) { 494416d8220SZaibo Xu c_req->c_out = c_req->c_in; 495416d8220SZaibo Xu c_req->c_out_dma = c_req->c_in_dma; 496416d8220SZaibo Xu } else { 497416d8220SZaibo Xu c_req->c_out = hisi_acc_sg_buf_map_to_hw_sgl(dev, dst, 498416d8220SZaibo Xu qp_ctx->c_out_pool, 499416d8220SZaibo Xu req->req_id, 500416d8220SZaibo Xu &c_req->c_out_dma); 501416d8220SZaibo Xu 502416d8220SZaibo Xu if (IS_ERR(c_req->c_out)) { 503416d8220SZaibo Xu dev_err(dev, "fail to dma map output sgl buffers!\n"); 504416d8220SZaibo Xu hisi_acc_sg_buf_unmap(dev, src, c_req->c_in); 505416d8220SZaibo Xu return PTR_ERR(c_req->c_out); 506416d8220SZaibo Xu } 507416d8220SZaibo Xu } 508416d8220SZaibo Xu 509416d8220SZaibo Xu return 0; 510416d8220SZaibo Xu } 511416d8220SZaibo Xu 512416d8220SZaibo Xu static int sec_skcipher_sgl_map(struct sec_ctx *ctx, struct sec_req *req) 513416d8220SZaibo Xu { 514416d8220SZaibo Xu struct sec_cipher_req *c_req = &req->c_req; 515416d8220SZaibo Xu 516416d8220SZaibo Xu return sec_skcipher_map(SEC_CTX_DEV(ctx), req, 517416d8220SZaibo Xu c_req->sk_req->src, c_req->sk_req->dst); 518416d8220SZaibo Xu } 519416d8220SZaibo Xu 520416d8220SZaibo Xu static void sec_skcipher_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req) 521416d8220SZaibo Xu { 522416d8220SZaibo Xu struct device *dev = SEC_CTX_DEV(ctx); 523416d8220SZaibo Xu struct sec_cipher_req *c_req = &req->c_req; 524416d8220SZaibo Xu struct skcipher_request *sk_req = c_req->sk_req; 525416d8220SZaibo Xu 526416d8220SZaibo Xu if (sk_req->dst != sk_req->src) 527416d8220SZaibo Xu hisi_acc_sg_buf_unmap(dev, sk_req->src, c_req->c_in); 528416d8220SZaibo Xu 529416d8220SZaibo Xu hisi_acc_sg_buf_unmap(dev, sk_req->dst, c_req->c_out); 530416d8220SZaibo Xu } 531416d8220SZaibo Xu 532416d8220SZaibo Xu static int sec_request_transfer(struct sec_ctx *ctx, struct sec_req *req) 533416d8220SZaibo Xu { 534416d8220SZaibo Xu int ret; 535416d8220SZaibo Xu 536416d8220SZaibo Xu ret = ctx->req_op->buf_map(ctx, req); 537416d8220SZaibo Xu if (ret) 538416d8220SZaibo Xu return ret; 539416d8220SZaibo Xu 540416d8220SZaibo Xu ctx->req_op->do_transfer(ctx, req); 541416d8220SZaibo Xu 542416d8220SZaibo Xu ret = ctx->req_op->bd_fill(ctx, req); 543416d8220SZaibo Xu if (ret) 544416d8220SZaibo Xu goto unmap_req_buf; 545416d8220SZaibo Xu 546416d8220SZaibo Xu return ret; 547416d8220SZaibo Xu 548416d8220SZaibo Xu unmap_req_buf: 549416d8220SZaibo Xu ctx->req_op->buf_unmap(ctx, req); 550416d8220SZaibo Xu 551416d8220SZaibo Xu return ret; 552416d8220SZaibo Xu } 553416d8220SZaibo Xu 554416d8220SZaibo Xu static void sec_request_untransfer(struct sec_ctx *ctx, struct sec_req *req) 555416d8220SZaibo Xu { 556416d8220SZaibo Xu ctx->req_op->buf_unmap(ctx, req); 557416d8220SZaibo Xu } 558416d8220SZaibo Xu 559416d8220SZaibo Xu static void sec_skcipher_copy_iv(struct sec_ctx *ctx, struct sec_req *req) 560416d8220SZaibo Xu { 561416d8220SZaibo Xu struct skcipher_request *sk_req = req->c_req.sk_req; 562416d8220SZaibo Xu struct sec_cipher_req *c_req = &req->c_req; 563416d8220SZaibo Xu 564416d8220SZaibo Xu c_req->c_len = sk_req->cryptlen; 565416d8220SZaibo Xu memcpy(c_req->c_ivin, sk_req->iv, ctx->c_ctx.ivsize); 566416d8220SZaibo Xu } 567416d8220SZaibo Xu 568416d8220SZaibo Xu static int sec_skcipher_bd_fill(struct sec_ctx *ctx, struct sec_req *req) 569416d8220SZaibo Xu { 570416d8220SZaibo Xu struct sec_cipher_ctx *c_ctx = &ctx->c_ctx; 571416d8220SZaibo Xu struct sec_cipher_req *c_req = &req->c_req; 572416d8220SZaibo Xu struct sec_sqe *sec_sqe = &req->sec_sqe; 573416d8220SZaibo Xu u8 de = 0; 574416d8220SZaibo Xu u8 scene, sa_type, da_type; 575416d8220SZaibo Xu u8 bd_type, cipher; 576416d8220SZaibo Xu 577416d8220SZaibo Xu memset(sec_sqe, 0, sizeof(struct sec_sqe)); 578416d8220SZaibo Xu 579416d8220SZaibo Xu sec_sqe->type2.c_key_addr = cpu_to_le64(c_ctx->c_key_dma); 580416d8220SZaibo Xu sec_sqe->type2.c_ivin_addr = cpu_to_le64(c_req->c_ivin_dma); 581416d8220SZaibo Xu sec_sqe->type2.data_src_addr = cpu_to_le64(c_req->c_in_dma); 582416d8220SZaibo Xu sec_sqe->type2.data_dst_addr = cpu_to_le64(c_req->c_out_dma); 583416d8220SZaibo Xu 584416d8220SZaibo Xu sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_mode) << 585416d8220SZaibo Xu SEC_CMODE_OFFSET); 586416d8220SZaibo Xu sec_sqe->type2.c_alg = c_ctx->c_alg; 587416d8220SZaibo Xu sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_key_len) << 588416d8220SZaibo Xu SEC_CKEY_OFFSET); 589416d8220SZaibo Xu 590416d8220SZaibo Xu bd_type = SEC_BD_TYPE2; 591416d8220SZaibo Xu if (c_req->encrypt) 592416d8220SZaibo Xu cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET; 593416d8220SZaibo Xu else 594416d8220SZaibo Xu cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET; 595416d8220SZaibo Xu sec_sqe->type_cipher_auth = bd_type | cipher; 596416d8220SZaibo Xu 597416d8220SZaibo Xu sa_type = SEC_SGL << SEC_SRC_SGL_OFFSET; 598416d8220SZaibo Xu scene = SEC_COMM_SCENE << SEC_SCENE_OFFSET; 599416d8220SZaibo Xu if (c_req->c_in_dma != c_req->c_out_dma) 600416d8220SZaibo Xu de = 0x1 << SEC_DE_OFFSET; 601416d8220SZaibo Xu 602416d8220SZaibo Xu sec_sqe->sds_sa_type = (de | scene | sa_type); 603416d8220SZaibo Xu 604416d8220SZaibo Xu /* Just set DST address type */ 605416d8220SZaibo Xu da_type = SEC_SGL << SEC_DST_SGL_OFFSET; 606416d8220SZaibo Xu sec_sqe->sdm_addr_type |= da_type; 607416d8220SZaibo Xu 608416d8220SZaibo Xu sec_sqe->type2.clen_ivhlen |= cpu_to_le32(c_req->c_len); 609416d8220SZaibo Xu sec_sqe->type2.tag = cpu_to_le16((u16)req->req_id); 610416d8220SZaibo Xu 611416d8220SZaibo Xu return 0; 612416d8220SZaibo Xu } 613416d8220SZaibo Xu 614416d8220SZaibo Xu static void sec_update_iv(struct sec_req *req) 615416d8220SZaibo Xu { 616416d8220SZaibo Xu struct skcipher_request *sk_req = req->c_req.sk_req; 617416d8220SZaibo Xu u32 iv_size = req->ctx->c_ctx.ivsize; 618416d8220SZaibo Xu struct scatterlist *sgl; 619416d8220SZaibo Xu size_t sz; 620416d8220SZaibo Xu 621416d8220SZaibo Xu if (req->c_req.encrypt) 622416d8220SZaibo Xu sgl = sk_req->dst; 623416d8220SZaibo Xu else 624416d8220SZaibo Xu sgl = sk_req->src; 625416d8220SZaibo Xu 626416d8220SZaibo Xu sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), sk_req->iv, 627416d8220SZaibo Xu iv_size, sk_req->cryptlen - iv_size); 628416d8220SZaibo Xu if (sz != iv_size) 629416d8220SZaibo Xu dev_err(SEC_CTX_DEV(req->ctx), "copy output iv error!\n"); 630416d8220SZaibo Xu } 631416d8220SZaibo Xu 632416d8220SZaibo Xu static void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req) 633416d8220SZaibo Xu { 634416d8220SZaibo Xu struct skcipher_request *sk_req = req->c_req.sk_req; 635416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx = req->qp_ctx; 636416d8220SZaibo Xu 637416d8220SZaibo Xu atomic_dec(&qp_ctx->pending_reqs); 638416d8220SZaibo Xu sec_free_req_id(req); 639416d8220SZaibo Xu 640416d8220SZaibo Xu /* IV output at encrypto of CBC mode */ 641416d8220SZaibo Xu if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && req->c_req.encrypt) 642416d8220SZaibo Xu sec_update_iv(req); 643416d8220SZaibo Xu 644416d8220SZaibo Xu if (__sync_bool_compare_and_swap(&req->fake_busy, 1, 0)) 645416d8220SZaibo Xu sk_req->base.complete(&sk_req->base, -EINPROGRESS); 646416d8220SZaibo Xu 647416d8220SZaibo Xu sk_req->base.complete(&sk_req->base, req->err_type); 648416d8220SZaibo Xu } 649416d8220SZaibo Xu 650416d8220SZaibo Xu static void sec_request_uninit(struct sec_ctx *ctx, struct sec_req *req) 651416d8220SZaibo Xu { 652416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx = req->qp_ctx; 653416d8220SZaibo Xu 654416d8220SZaibo Xu atomic_dec(&qp_ctx->pending_reqs); 655416d8220SZaibo Xu sec_free_req_id(req); 656416d8220SZaibo Xu sec_put_queue_id(ctx, req); 657416d8220SZaibo Xu } 658416d8220SZaibo Xu 659416d8220SZaibo Xu static int sec_request_init(struct sec_ctx *ctx, struct sec_req *req) 660416d8220SZaibo Xu { 661416d8220SZaibo Xu struct sec_qp_ctx *qp_ctx; 662416d8220SZaibo Xu int issue_id, ret; 663416d8220SZaibo Xu 664416d8220SZaibo Xu /* To load balance */ 665416d8220SZaibo Xu issue_id = sec_get_queue_id(ctx, req); 666416d8220SZaibo Xu qp_ctx = &ctx->qp_ctx[issue_id]; 667416d8220SZaibo Xu 668416d8220SZaibo Xu req->req_id = sec_alloc_req_id(req, qp_ctx); 669416d8220SZaibo Xu if (req->req_id < 0) { 670416d8220SZaibo Xu sec_put_queue_id(ctx, req); 671416d8220SZaibo Xu return req->req_id; 672416d8220SZaibo Xu } 673416d8220SZaibo Xu 674416d8220SZaibo Xu if (ctx->fake_req_limit <= atomic_inc_return(&qp_ctx->pending_reqs)) 675416d8220SZaibo Xu req->fake_busy = 1; 676416d8220SZaibo Xu else 677416d8220SZaibo Xu req->fake_busy = 0; 678416d8220SZaibo Xu 679416d8220SZaibo Xu ret = ctx->req_op->get_res(ctx, req); 680416d8220SZaibo Xu if (ret) { 681416d8220SZaibo Xu atomic_dec(&qp_ctx->pending_reqs); 682416d8220SZaibo Xu sec_request_uninit(ctx, req); 683416d8220SZaibo Xu dev_err(SEC_CTX_DEV(ctx), "get resources failed!\n"); 684416d8220SZaibo Xu } 685416d8220SZaibo Xu 686416d8220SZaibo Xu return ret; 687416d8220SZaibo Xu } 688416d8220SZaibo Xu 689416d8220SZaibo Xu static int sec_process(struct sec_ctx *ctx, struct sec_req *req) 690416d8220SZaibo Xu { 691416d8220SZaibo Xu int ret; 692416d8220SZaibo Xu 693416d8220SZaibo Xu ret = sec_request_init(ctx, req); 694416d8220SZaibo Xu if (ret) 695416d8220SZaibo Xu return ret; 696416d8220SZaibo Xu 697416d8220SZaibo Xu ret = sec_request_transfer(ctx, req); 698416d8220SZaibo Xu if (ret) 699416d8220SZaibo Xu goto err_uninit_req; 700416d8220SZaibo Xu 701416d8220SZaibo Xu /* Output IV as decrypto */ 702416d8220SZaibo Xu if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt) 703416d8220SZaibo Xu sec_update_iv(req); 704416d8220SZaibo Xu 705416d8220SZaibo Xu ret = ctx->req_op->bd_send(ctx, req); 706416d8220SZaibo Xu if (ret != -EBUSY && ret != -EINPROGRESS) { 707416d8220SZaibo Xu dev_err(SEC_CTX_DEV(ctx), "send sec request failed!\n"); 708416d8220SZaibo Xu goto err_send_req; 709416d8220SZaibo Xu } 710416d8220SZaibo Xu 711416d8220SZaibo Xu return ret; 712416d8220SZaibo Xu 713416d8220SZaibo Xu err_send_req: 714416d8220SZaibo Xu /* As failing, restore the IV from user */ 715416d8220SZaibo Xu if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt) 716416d8220SZaibo Xu memcpy(req->c_req.sk_req->iv, req->c_req.c_ivin, 717416d8220SZaibo Xu ctx->c_ctx.ivsize); 718416d8220SZaibo Xu 719416d8220SZaibo Xu sec_request_untransfer(ctx, req); 720416d8220SZaibo Xu err_uninit_req: 721416d8220SZaibo Xu sec_request_uninit(ctx, req); 722416d8220SZaibo Xu 723416d8220SZaibo Xu return ret; 724416d8220SZaibo Xu } 725416d8220SZaibo Xu 726416d8220SZaibo Xu static struct sec_req_op sec_req_ops_tbl = { 727416d8220SZaibo Xu .get_res = sec_skcipher_get_res, 728416d8220SZaibo Xu .resource_alloc = sec_skcipher_resource_alloc, 729416d8220SZaibo Xu .resource_free = sec_skcipher_resource_free, 730416d8220SZaibo Xu .buf_map = sec_skcipher_sgl_map, 731416d8220SZaibo Xu .buf_unmap = sec_skcipher_sgl_unmap, 732416d8220SZaibo Xu .do_transfer = sec_skcipher_copy_iv, 733416d8220SZaibo Xu .bd_fill = sec_skcipher_bd_fill, 734416d8220SZaibo Xu .bd_send = sec_bd_send, 735416d8220SZaibo Xu .callback = sec_skcipher_callback, 736416d8220SZaibo Xu .process = sec_process, 737416d8220SZaibo Xu }; 738416d8220SZaibo Xu 739416d8220SZaibo Xu static int sec_skcipher_ctx_init(struct crypto_skcipher *tfm) 740416d8220SZaibo Xu { 741416d8220SZaibo Xu struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 742416d8220SZaibo Xu 743416d8220SZaibo Xu ctx->req_op = &sec_req_ops_tbl; 744416d8220SZaibo Xu 745416d8220SZaibo Xu return sec_skcipher_init(tfm); 746416d8220SZaibo Xu } 747416d8220SZaibo Xu 748416d8220SZaibo Xu static void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm) 749416d8220SZaibo Xu { 750416d8220SZaibo Xu sec_skcipher_exit(tfm); 751416d8220SZaibo Xu } 752416d8220SZaibo Xu 753416d8220SZaibo Xu static int sec_skcipher_param_check(struct sec_ctx *ctx, 754416d8220SZaibo Xu struct skcipher_request *sk_req) 755416d8220SZaibo Xu { 756416d8220SZaibo Xu u8 c_alg = ctx->c_ctx.c_alg; 757416d8220SZaibo Xu struct device *dev = SEC_CTX_DEV(ctx); 758416d8220SZaibo Xu 759416d8220SZaibo Xu if (!sk_req->src || !sk_req->dst) { 760416d8220SZaibo Xu dev_err(dev, "skcipher input param error!\n"); 761416d8220SZaibo Xu return -EINVAL; 762416d8220SZaibo Xu } 763416d8220SZaibo Xu 764416d8220SZaibo Xu if (c_alg == SEC_CALG_3DES) { 765416d8220SZaibo Xu if (sk_req->cryptlen & (DES3_EDE_BLOCK_SIZE - 1)) { 766416d8220SZaibo Xu dev_err(dev, "skcipher 3des input length error!\n"); 767416d8220SZaibo Xu return -EINVAL; 768416d8220SZaibo Xu } 769416d8220SZaibo Xu return 0; 770416d8220SZaibo Xu } else if (c_alg == SEC_CALG_AES || c_alg == SEC_CALG_SM4) { 771416d8220SZaibo Xu if (sk_req->cryptlen & (AES_BLOCK_SIZE - 1)) { 772416d8220SZaibo Xu dev_err(dev, "skcipher aes input length error!\n"); 773416d8220SZaibo Xu return -EINVAL; 774416d8220SZaibo Xu } 775416d8220SZaibo Xu return 0; 776416d8220SZaibo Xu } 777416d8220SZaibo Xu 778416d8220SZaibo Xu dev_err(dev, "skcipher algorithm error!\n"); 779416d8220SZaibo Xu return -EINVAL; 780416d8220SZaibo Xu } 781416d8220SZaibo Xu 782416d8220SZaibo Xu static int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt) 783416d8220SZaibo Xu { 784416d8220SZaibo Xu struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req); 785416d8220SZaibo Xu struct sec_req *req = skcipher_request_ctx(sk_req); 786416d8220SZaibo Xu struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 787416d8220SZaibo Xu int ret; 788416d8220SZaibo Xu 789416d8220SZaibo Xu if (!sk_req->cryptlen) 790416d8220SZaibo Xu return 0; 791416d8220SZaibo Xu 792416d8220SZaibo Xu ret = sec_skcipher_param_check(ctx, sk_req); 793416d8220SZaibo Xu if (ret) 794416d8220SZaibo Xu return ret; 795416d8220SZaibo Xu 796416d8220SZaibo Xu req->c_req.sk_req = sk_req; 797416d8220SZaibo Xu req->c_req.encrypt = encrypt; 798416d8220SZaibo Xu req->ctx = ctx; 799416d8220SZaibo Xu 800416d8220SZaibo Xu return ctx->req_op->process(ctx, req); 801416d8220SZaibo Xu } 802416d8220SZaibo Xu 803416d8220SZaibo Xu static int sec_skcipher_encrypt(struct skcipher_request *sk_req) 804416d8220SZaibo Xu { 805416d8220SZaibo Xu return sec_skcipher_crypto(sk_req, true); 806416d8220SZaibo Xu } 807416d8220SZaibo Xu 808416d8220SZaibo Xu static int sec_skcipher_decrypt(struct skcipher_request *sk_req) 809416d8220SZaibo Xu { 810416d8220SZaibo Xu return sec_skcipher_crypto(sk_req, false); 811416d8220SZaibo Xu } 812416d8220SZaibo Xu 813416d8220SZaibo Xu #define SEC_SKCIPHER_GEN_ALG(sec_cra_name, sec_set_key, sec_min_key_size, \ 814416d8220SZaibo Xu sec_max_key_size, ctx_init, ctx_exit, blk_size, iv_size)\ 815416d8220SZaibo Xu {\ 816416d8220SZaibo Xu .base = {\ 817416d8220SZaibo Xu .cra_name = sec_cra_name,\ 818416d8220SZaibo Xu .cra_driver_name = "hisi_sec_"sec_cra_name,\ 819416d8220SZaibo Xu .cra_priority = SEC_PRIORITY,\ 820416d8220SZaibo Xu .cra_flags = CRYPTO_ALG_ASYNC,\ 821416d8220SZaibo Xu .cra_blocksize = blk_size,\ 822416d8220SZaibo Xu .cra_ctxsize = sizeof(struct sec_ctx),\ 823416d8220SZaibo Xu .cra_module = THIS_MODULE,\ 824416d8220SZaibo Xu },\ 825416d8220SZaibo Xu .init = ctx_init,\ 826416d8220SZaibo Xu .exit = ctx_exit,\ 827416d8220SZaibo Xu .setkey = sec_set_key,\ 828416d8220SZaibo Xu .decrypt = sec_skcipher_decrypt,\ 829416d8220SZaibo Xu .encrypt = sec_skcipher_encrypt,\ 830416d8220SZaibo Xu .min_keysize = sec_min_key_size,\ 831416d8220SZaibo Xu .max_keysize = sec_max_key_size,\ 832416d8220SZaibo Xu .ivsize = iv_size,\ 833416d8220SZaibo Xu }, 834416d8220SZaibo Xu 835416d8220SZaibo Xu #define SEC_SKCIPHER_ALG(name, key_func, min_key_size, \ 836416d8220SZaibo Xu max_key_size, blk_size, iv_size) \ 837416d8220SZaibo Xu SEC_SKCIPHER_GEN_ALG(name, key_func, min_key_size, max_key_size, \ 838416d8220SZaibo Xu sec_skcipher_ctx_init, sec_skcipher_ctx_exit, blk_size, iv_size) 839416d8220SZaibo Xu 840416d8220SZaibo Xu static struct skcipher_alg sec_algs[] = { 841416d8220SZaibo Xu SEC_SKCIPHER_ALG("ecb(aes)", sec_setkey_aes_ecb, 842416d8220SZaibo Xu AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE, 843416d8220SZaibo Xu AES_BLOCK_SIZE, 0) 844416d8220SZaibo Xu 845416d8220SZaibo Xu SEC_SKCIPHER_ALG("cbc(aes)", sec_setkey_aes_cbc, 846416d8220SZaibo Xu AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE, 847416d8220SZaibo Xu AES_BLOCK_SIZE, AES_BLOCK_SIZE) 848416d8220SZaibo Xu 849416d8220SZaibo Xu SEC_SKCIPHER_ALG("xts(aes)", sec_setkey_aes_xts, 850416d8220SZaibo Xu SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MAX_KEY_SIZE, 851416d8220SZaibo Xu AES_BLOCK_SIZE, AES_BLOCK_SIZE) 852416d8220SZaibo Xu 853416d8220SZaibo Xu SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb, 854416d8220SZaibo Xu SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE, 855416d8220SZaibo Xu DES3_EDE_BLOCK_SIZE, 0) 856416d8220SZaibo Xu 857416d8220SZaibo Xu SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc, 858416d8220SZaibo Xu SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE, 859416d8220SZaibo Xu DES3_EDE_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE) 860416d8220SZaibo Xu 861416d8220SZaibo Xu SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts, 862416d8220SZaibo Xu SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MIN_KEY_SIZE, 863416d8220SZaibo Xu AES_BLOCK_SIZE, AES_BLOCK_SIZE) 864416d8220SZaibo Xu 865416d8220SZaibo Xu SEC_SKCIPHER_ALG("cbc(sm4)", sec_setkey_sm4_cbc, 866416d8220SZaibo Xu AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE, 867416d8220SZaibo Xu AES_BLOCK_SIZE, AES_BLOCK_SIZE) 868416d8220SZaibo Xu }; 869416d8220SZaibo Xu 870416d8220SZaibo Xu int sec_register_to_crypto(void) 871416d8220SZaibo Xu { 872416d8220SZaibo Xu int ret = 0; 873416d8220SZaibo Xu 874416d8220SZaibo Xu /* To avoid repeat register */ 875416d8220SZaibo Xu mutex_lock(&sec_algs_lock); 876416d8220SZaibo Xu if (++sec_active_devs == 1) 877416d8220SZaibo Xu ret = crypto_register_skciphers(sec_algs, ARRAY_SIZE(sec_algs)); 878416d8220SZaibo Xu mutex_unlock(&sec_algs_lock); 879416d8220SZaibo Xu 880416d8220SZaibo Xu return ret; 881416d8220SZaibo Xu } 882416d8220SZaibo Xu 883416d8220SZaibo Xu void sec_unregister_from_crypto(void) 884416d8220SZaibo Xu { 885416d8220SZaibo Xu mutex_lock(&sec_algs_lock); 886416d8220SZaibo Xu if (--sec_active_devs == 0) 887416d8220SZaibo Xu crypto_unregister_skciphers(sec_algs, ARRAY_SIZE(sec_algs)); 888416d8220SZaibo Xu mutex_unlock(&sec_algs_lock); 889416d8220SZaibo Xu } 890