18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright (c) 2019 HiSilicon Limited. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <crypto/aes.h> 58c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 68c2ecf20Sopenharmony_ci#include <crypto/authenc.h> 78c2ecf20Sopenharmony_ci#include <crypto/des.h> 88c2ecf20Sopenharmony_ci#include <crypto/hash.h> 98c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h> 108c2ecf20Sopenharmony_ci#include <crypto/sha.h> 118c2ecf20Sopenharmony_ci#include <crypto/skcipher.h> 128c2ecf20Sopenharmony_ci#include <crypto/xts.h> 138c2ecf20Sopenharmony_ci#include <linux/crypto.h> 148c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 158c2ecf20Sopenharmony_ci#include <linux/idr.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "sec.h" 188c2ecf20Sopenharmony_ci#include "sec_crypto.h" 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#define SEC_PRIORITY 4001 218c2ecf20Sopenharmony_ci#define SEC_XTS_MIN_KEY_SIZE (2 * AES_MIN_KEY_SIZE) 228c2ecf20Sopenharmony_ci#define SEC_XTS_MAX_KEY_SIZE (2 * AES_MAX_KEY_SIZE) 238c2ecf20Sopenharmony_ci#define SEC_DES3_2KEY_SIZE (2 * DES_KEY_SIZE) 248c2ecf20Sopenharmony_ci#define SEC_DES3_3KEY_SIZE (3 * DES_KEY_SIZE) 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* SEC sqe(bd) bit operational relative MACRO */ 278c2ecf20Sopenharmony_ci#define SEC_DE_OFFSET 1 288c2ecf20Sopenharmony_ci#define SEC_CIPHER_OFFSET 4 298c2ecf20Sopenharmony_ci#define SEC_SCENE_OFFSET 3 308c2ecf20Sopenharmony_ci#define SEC_DST_SGL_OFFSET 2 318c2ecf20Sopenharmony_ci#define SEC_SRC_SGL_OFFSET 7 328c2ecf20Sopenharmony_ci#define SEC_CKEY_OFFSET 9 338c2ecf20Sopenharmony_ci#define SEC_CMODE_OFFSET 12 348c2ecf20Sopenharmony_ci#define SEC_AKEY_OFFSET 5 358c2ecf20Sopenharmony_ci#define SEC_AEAD_ALG_OFFSET 11 368c2ecf20Sopenharmony_ci#define SEC_AUTH_OFFSET 6 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define SEC_FLAG_OFFSET 7 398c2ecf20Sopenharmony_ci#define SEC_FLAG_MASK 0x0780 408c2ecf20Sopenharmony_ci#define SEC_TYPE_MASK 0x0F 418c2ecf20Sopenharmony_ci#define SEC_DONE_MASK 0x0001 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define SEC_TOTAL_IV_SZ (SEC_IV_SIZE * QM_Q_DEPTH) 448c2ecf20Sopenharmony_ci#define SEC_SGL_SGE_NR 128 458c2ecf20Sopenharmony_ci#define SEC_CIPHER_AUTH 0xfe 468c2ecf20Sopenharmony_ci#define SEC_AUTH_CIPHER 0x1 478c2ecf20Sopenharmony_ci#define SEC_MAX_MAC_LEN 64 488c2ecf20Sopenharmony_ci#define SEC_MAX_AAD_LEN 65535 498c2ecf20Sopenharmony_ci#define SEC_TOTAL_MAC_SZ (SEC_MAX_MAC_LEN * QM_Q_DEPTH) 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define SEC_PBUF_SZ 512 528c2ecf20Sopenharmony_ci#define SEC_PBUF_IV_OFFSET SEC_PBUF_SZ 538c2ecf20Sopenharmony_ci#define SEC_PBUF_MAC_OFFSET (SEC_PBUF_SZ + SEC_IV_SIZE) 548c2ecf20Sopenharmony_ci#define SEC_PBUF_PKG (SEC_PBUF_SZ + SEC_IV_SIZE + \ 558c2ecf20Sopenharmony_ci SEC_MAX_MAC_LEN * 2) 568c2ecf20Sopenharmony_ci#define SEC_PBUF_NUM (PAGE_SIZE / SEC_PBUF_PKG) 578c2ecf20Sopenharmony_ci#define SEC_PBUF_PAGE_NUM (QM_Q_DEPTH / SEC_PBUF_NUM) 588c2ecf20Sopenharmony_ci#define SEC_PBUF_LEFT_SZ (SEC_PBUF_PKG * (QM_Q_DEPTH - \ 598c2ecf20Sopenharmony_ci SEC_PBUF_PAGE_NUM * SEC_PBUF_NUM)) 608c2ecf20Sopenharmony_ci#define SEC_TOTAL_PBUF_SZ (PAGE_SIZE * SEC_PBUF_PAGE_NUM + \ 618c2ecf20Sopenharmony_ci SEC_PBUF_LEFT_SZ) 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#define SEC_SQE_LEN_RATE 4 648c2ecf20Sopenharmony_ci#define SEC_SQE_CFLAG 2 658c2ecf20Sopenharmony_ci#define SEC_SQE_AEAD_FLAG 3 668c2ecf20Sopenharmony_ci#define SEC_SQE_DONE 0x1 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* Get an en/de-cipher queue cyclically to balance load over queues of TFM */ 698c2ecf20Sopenharmony_cistatic inline int sec_alloc_queue_id(struct sec_ctx *ctx, struct sec_req *req) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci if (req->c_req.encrypt) 728c2ecf20Sopenharmony_ci return (u32)atomic_inc_return(&ctx->enc_qcyclic) % 738c2ecf20Sopenharmony_ci ctx->hlf_q_num; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci return (u32)atomic_inc_return(&ctx->dec_qcyclic) % ctx->hlf_q_num + 768c2ecf20Sopenharmony_ci ctx->hlf_q_num; 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic inline void sec_free_queue_id(struct sec_ctx *ctx, struct sec_req *req) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci if (req->c_req.encrypt) 828c2ecf20Sopenharmony_ci atomic_dec(&ctx->enc_qcyclic); 838c2ecf20Sopenharmony_ci else 848c2ecf20Sopenharmony_ci atomic_dec(&ctx->dec_qcyclic); 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic int sec_alloc_req_id(struct sec_req *req, struct sec_qp_ctx *qp_ctx) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci int req_id; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci spin_lock_bh(&qp_ctx->req_lock); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci req_id = idr_alloc_cyclic(&qp_ctx->req_idr, NULL, 948c2ecf20Sopenharmony_ci 0, QM_Q_DEPTH, GFP_ATOMIC); 958c2ecf20Sopenharmony_ci spin_unlock_bh(&qp_ctx->req_lock); 968c2ecf20Sopenharmony_ci if (unlikely(req_id < 0)) { 978c2ecf20Sopenharmony_ci dev_err(req->ctx->dev, "alloc req id fail!\n"); 988c2ecf20Sopenharmony_ci return req_id; 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci req->qp_ctx = qp_ctx; 1028c2ecf20Sopenharmony_ci qp_ctx->req_list[req_id] = req; 1038c2ecf20Sopenharmony_ci return req_id; 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic void sec_free_req_id(struct sec_req *req) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx = req->qp_ctx; 1098c2ecf20Sopenharmony_ci int req_id = req->req_id; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci if (unlikely(req_id < 0 || req_id >= QM_Q_DEPTH)) { 1128c2ecf20Sopenharmony_ci dev_err(req->ctx->dev, "free request id invalid!\n"); 1138c2ecf20Sopenharmony_ci return; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci qp_ctx->req_list[req_id] = NULL; 1178c2ecf20Sopenharmony_ci req->qp_ctx = NULL; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci spin_lock_bh(&qp_ctx->req_lock); 1208c2ecf20Sopenharmony_ci idr_remove(&qp_ctx->req_idr, req_id); 1218c2ecf20Sopenharmony_ci spin_unlock_bh(&qp_ctx->req_lock); 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic int sec_aead_verify(struct sec_req *req) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci struct aead_request *aead_req = req->aead_req.aead_req; 1278c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(aead_req); 1288c2ecf20Sopenharmony_ci size_t authsize = crypto_aead_authsize(tfm); 1298c2ecf20Sopenharmony_ci u8 *mac_out = req->aead_req.out_mac; 1308c2ecf20Sopenharmony_ci u8 *mac = mac_out + SEC_MAX_MAC_LEN; 1318c2ecf20Sopenharmony_ci struct scatterlist *sgl = aead_req->src; 1328c2ecf20Sopenharmony_ci size_t sz; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), mac, authsize, 1358c2ecf20Sopenharmony_ci aead_req->cryptlen + aead_req->assoclen - 1368c2ecf20Sopenharmony_ci authsize); 1378c2ecf20Sopenharmony_ci if (unlikely(sz != authsize || memcmp(mac_out, mac, sz))) { 1388c2ecf20Sopenharmony_ci dev_err(req->ctx->dev, "aead verify failure!\n"); 1398c2ecf20Sopenharmony_ci return -EBADMSG; 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci return 0; 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic void sec_req_cb(struct hisi_qp *qp, void *resp) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx = qp->qp_ctx; 1488c2ecf20Sopenharmony_ci struct sec_dfx *dfx = &qp_ctx->ctx->sec->debug.dfx; 1498c2ecf20Sopenharmony_ci struct sec_sqe *bd = resp; 1508c2ecf20Sopenharmony_ci struct sec_ctx *ctx; 1518c2ecf20Sopenharmony_ci struct sec_req *req; 1528c2ecf20Sopenharmony_ci u16 done, flag; 1538c2ecf20Sopenharmony_ci int err = 0; 1548c2ecf20Sopenharmony_ci u8 type; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci type = bd->type_cipher_auth & SEC_TYPE_MASK; 1578c2ecf20Sopenharmony_ci if (unlikely(type != SEC_BD_TYPE2)) { 1588c2ecf20Sopenharmony_ci atomic64_inc(&dfx->err_bd_cnt); 1598c2ecf20Sopenharmony_ci pr_err("err bd type [%d]\n", type); 1608c2ecf20Sopenharmony_ci return; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci req = qp_ctx->req_list[le16_to_cpu(bd->type2.tag)]; 1648c2ecf20Sopenharmony_ci if (unlikely(!req)) { 1658c2ecf20Sopenharmony_ci atomic64_inc(&dfx->invalid_req_cnt); 1668c2ecf20Sopenharmony_ci atomic_inc(&qp->qp_status.used); 1678c2ecf20Sopenharmony_ci return; 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci req->err_type = bd->type2.error_type; 1708c2ecf20Sopenharmony_ci ctx = req->ctx; 1718c2ecf20Sopenharmony_ci done = le16_to_cpu(bd->type2.done_flag) & SEC_DONE_MASK; 1728c2ecf20Sopenharmony_ci flag = (le16_to_cpu(bd->type2.done_flag) & 1738c2ecf20Sopenharmony_ci SEC_FLAG_MASK) >> SEC_FLAG_OFFSET; 1748c2ecf20Sopenharmony_ci if (unlikely(req->err_type || done != SEC_SQE_DONE || 1758c2ecf20Sopenharmony_ci (ctx->alg_type == SEC_SKCIPHER && flag != SEC_SQE_CFLAG) || 1768c2ecf20Sopenharmony_ci (ctx->alg_type == SEC_AEAD && flag != SEC_SQE_AEAD_FLAG))) { 1778c2ecf20Sopenharmony_ci dev_err_ratelimited(ctx->dev, 1788c2ecf20Sopenharmony_ci "err_type[%d],done[%d],flag[%d]\n", 1798c2ecf20Sopenharmony_ci req->err_type, done, flag); 1808c2ecf20Sopenharmony_ci err = -EIO; 1818c2ecf20Sopenharmony_ci atomic64_inc(&dfx->done_flag_cnt); 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci if (ctx->alg_type == SEC_AEAD && !req->c_req.encrypt) 1858c2ecf20Sopenharmony_ci err = sec_aead_verify(req); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci atomic64_inc(&dfx->recv_cnt); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci ctx->req_op->buf_unmap(ctx, req); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci ctx->req_op->callback(ctx, req, err); 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx = req->qp_ctx; 1978c2ecf20Sopenharmony_ci int ret; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci if (ctx->fake_req_limit <= 2008c2ecf20Sopenharmony_ci atomic_read(&qp_ctx->qp->qp_status.used) && 2018c2ecf20Sopenharmony_ci !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG)) 2028c2ecf20Sopenharmony_ci return -EBUSY; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci spin_lock_bh(&qp_ctx->req_lock); 2058c2ecf20Sopenharmony_ci ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci if (ctx->fake_req_limit <= 2088c2ecf20Sopenharmony_ci atomic_read(&qp_ctx->qp->qp_status.used) && !ret) { 2098c2ecf20Sopenharmony_ci list_add_tail(&req->backlog_head, &qp_ctx->backlog); 2108c2ecf20Sopenharmony_ci atomic64_inc(&ctx->sec->debug.dfx.send_cnt); 2118c2ecf20Sopenharmony_ci atomic64_inc(&ctx->sec->debug.dfx.send_busy_cnt); 2128c2ecf20Sopenharmony_ci spin_unlock_bh(&qp_ctx->req_lock); 2138c2ecf20Sopenharmony_ci return -EBUSY; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci spin_unlock_bh(&qp_ctx->req_lock); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (unlikely(ret == -EBUSY)) 2188c2ecf20Sopenharmony_ci return -ENOBUFS; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (likely(!ret)) { 2218c2ecf20Sopenharmony_ci ret = -EINPROGRESS; 2228c2ecf20Sopenharmony_ci atomic64_inc(&ctx->sec->debug.dfx.send_cnt); 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci return ret; 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci/* Get DMA memory resources */ 2298c2ecf20Sopenharmony_cistatic int sec_alloc_civ_resource(struct device *dev, struct sec_alg_res *res) 2308c2ecf20Sopenharmony_ci{ 2318c2ecf20Sopenharmony_ci int i; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci res->c_ivin = dma_alloc_coherent(dev, SEC_TOTAL_IV_SZ, 2348c2ecf20Sopenharmony_ci &res->c_ivin_dma, GFP_KERNEL); 2358c2ecf20Sopenharmony_ci if (!res->c_ivin) 2368c2ecf20Sopenharmony_ci return -ENOMEM; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci for (i = 1; i < QM_Q_DEPTH; i++) { 2398c2ecf20Sopenharmony_ci res[i].c_ivin_dma = res->c_ivin_dma + i * SEC_IV_SIZE; 2408c2ecf20Sopenharmony_ci res[i].c_ivin = res->c_ivin + i * SEC_IV_SIZE; 2418c2ecf20Sopenharmony_ci } 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci return 0; 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic void sec_free_civ_resource(struct device *dev, struct sec_alg_res *res) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci if (res->c_ivin) 2498c2ecf20Sopenharmony_ci dma_free_coherent(dev, SEC_TOTAL_IV_SZ, 2508c2ecf20Sopenharmony_ci res->c_ivin, res->c_ivin_dma); 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic int sec_alloc_mac_resource(struct device *dev, struct sec_alg_res *res) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci int i; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci res->out_mac = dma_alloc_coherent(dev, SEC_TOTAL_MAC_SZ << 1, 2588c2ecf20Sopenharmony_ci &res->out_mac_dma, GFP_KERNEL); 2598c2ecf20Sopenharmony_ci if (!res->out_mac) 2608c2ecf20Sopenharmony_ci return -ENOMEM; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci for (i = 1; i < QM_Q_DEPTH; i++) { 2638c2ecf20Sopenharmony_ci res[i].out_mac_dma = res->out_mac_dma + 2648c2ecf20Sopenharmony_ci i * (SEC_MAX_MAC_LEN << 1); 2658c2ecf20Sopenharmony_ci res[i].out_mac = res->out_mac + i * (SEC_MAX_MAC_LEN << 1); 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci return 0; 2698c2ecf20Sopenharmony_ci} 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_cistatic void sec_free_mac_resource(struct device *dev, struct sec_alg_res *res) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci if (res->out_mac) 2748c2ecf20Sopenharmony_ci dma_free_coherent(dev, SEC_TOTAL_MAC_SZ << 1, 2758c2ecf20Sopenharmony_ci res->out_mac, res->out_mac_dma); 2768c2ecf20Sopenharmony_ci} 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_cistatic void sec_free_pbuf_resource(struct device *dev, struct sec_alg_res *res) 2798c2ecf20Sopenharmony_ci{ 2808c2ecf20Sopenharmony_ci if (res->pbuf) 2818c2ecf20Sopenharmony_ci dma_free_coherent(dev, SEC_TOTAL_PBUF_SZ, 2828c2ecf20Sopenharmony_ci res->pbuf, res->pbuf_dma); 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci/* 2868c2ecf20Sopenharmony_ci * To improve performance, pbuffer is used for 2878c2ecf20Sopenharmony_ci * small packets (< 512Bytes) as IOMMU translation using. 2888c2ecf20Sopenharmony_ci */ 2898c2ecf20Sopenharmony_cistatic int sec_alloc_pbuf_resource(struct device *dev, struct sec_alg_res *res) 2908c2ecf20Sopenharmony_ci{ 2918c2ecf20Sopenharmony_ci int pbuf_page_offset; 2928c2ecf20Sopenharmony_ci int i, j, k; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci res->pbuf = dma_alloc_coherent(dev, SEC_TOTAL_PBUF_SZ, 2958c2ecf20Sopenharmony_ci &res->pbuf_dma, GFP_KERNEL); 2968c2ecf20Sopenharmony_ci if (!res->pbuf) 2978c2ecf20Sopenharmony_ci return -ENOMEM; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci /* 3008c2ecf20Sopenharmony_ci * SEC_PBUF_PKG contains data pbuf, iv and 3018c2ecf20Sopenharmony_ci * out_mac : <SEC_PBUF|SEC_IV|SEC_MAC> 3028c2ecf20Sopenharmony_ci * Every PAGE contains six SEC_PBUF_PKG 3038c2ecf20Sopenharmony_ci * The sec_qp_ctx contains QM_Q_DEPTH numbers of SEC_PBUF_PKG 3048c2ecf20Sopenharmony_ci * So we need SEC_PBUF_PAGE_NUM numbers of PAGE 3058c2ecf20Sopenharmony_ci * for the SEC_TOTAL_PBUF_SZ 3068c2ecf20Sopenharmony_ci */ 3078c2ecf20Sopenharmony_ci for (i = 0; i <= SEC_PBUF_PAGE_NUM; i++) { 3088c2ecf20Sopenharmony_ci pbuf_page_offset = PAGE_SIZE * i; 3098c2ecf20Sopenharmony_ci for (j = 0; j < SEC_PBUF_NUM; j++) { 3108c2ecf20Sopenharmony_ci k = i * SEC_PBUF_NUM + j; 3118c2ecf20Sopenharmony_ci if (k == QM_Q_DEPTH) 3128c2ecf20Sopenharmony_ci break; 3138c2ecf20Sopenharmony_ci res[k].pbuf = res->pbuf + 3148c2ecf20Sopenharmony_ci j * SEC_PBUF_PKG + pbuf_page_offset; 3158c2ecf20Sopenharmony_ci res[k].pbuf_dma = res->pbuf_dma + 3168c2ecf20Sopenharmony_ci j * SEC_PBUF_PKG + pbuf_page_offset; 3178c2ecf20Sopenharmony_ci } 3188c2ecf20Sopenharmony_ci } 3198c2ecf20Sopenharmony_ci return 0; 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic int sec_alg_resource_alloc(struct sec_ctx *ctx, 3238c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci struct sec_alg_res *res = qp_ctx->res; 3268c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 3278c2ecf20Sopenharmony_ci int ret; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci ret = sec_alloc_civ_resource(dev, res); 3308c2ecf20Sopenharmony_ci if (ret) 3318c2ecf20Sopenharmony_ci return ret; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci if (ctx->alg_type == SEC_AEAD) { 3348c2ecf20Sopenharmony_ci ret = sec_alloc_mac_resource(dev, res); 3358c2ecf20Sopenharmony_ci if (ret) 3368c2ecf20Sopenharmony_ci goto alloc_fail; 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci if (ctx->pbuf_supported) { 3398c2ecf20Sopenharmony_ci ret = sec_alloc_pbuf_resource(dev, res); 3408c2ecf20Sopenharmony_ci if (ret) { 3418c2ecf20Sopenharmony_ci dev_err(dev, "fail to alloc pbuf dma resource!\n"); 3428c2ecf20Sopenharmony_ci goto alloc_pbuf_fail; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci return 0; 3478c2ecf20Sopenharmony_cialloc_pbuf_fail: 3488c2ecf20Sopenharmony_ci if (ctx->alg_type == SEC_AEAD) 3498c2ecf20Sopenharmony_ci sec_free_mac_resource(dev, qp_ctx->res); 3508c2ecf20Sopenharmony_cialloc_fail: 3518c2ecf20Sopenharmony_ci sec_free_civ_resource(dev, res); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci return ret; 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistatic void sec_alg_resource_free(struct sec_ctx *ctx, 3578c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx) 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci sec_free_civ_resource(dev, qp_ctx->res); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci if (ctx->pbuf_supported) 3648c2ecf20Sopenharmony_ci sec_free_pbuf_resource(dev, qp_ctx->res); 3658c2ecf20Sopenharmony_ci if (ctx->alg_type == SEC_AEAD) 3668c2ecf20Sopenharmony_ci sec_free_mac_resource(dev, qp_ctx->res); 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_cistatic int sec_create_qp_ctx(struct hisi_qm *qm, struct sec_ctx *ctx, 3708c2ecf20Sopenharmony_ci int qp_ctx_id, int alg_type) 3718c2ecf20Sopenharmony_ci{ 3728c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 3738c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx; 3748c2ecf20Sopenharmony_ci struct hisi_qp *qp; 3758c2ecf20Sopenharmony_ci int ret = -ENOMEM; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci qp_ctx = &ctx->qp_ctx[qp_ctx_id]; 3788c2ecf20Sopenharmony_ci qp = ctx->qps[qp_ctx_id]; 3798c2ecf20Sopenharmony_ci qp->req_type = 0; 3808c2ecf20Sopenharmony_ci qp->qp_ctx = qp_ctx; 3818c2ecf20Sopenharmony_ci qp->req_cb = sec_req_cb; 3828c2ecf20Sopenharmony_ci qp_ctx->qp = qp; 3838c2ecf20Sopenharmony_ci qp_ctx->ctx = ctx; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci spin_lock_init(&qp_ctx->req_lock); 3868c2ecf20Sopenharmony_ci idr_init(&qp_ctx->req_idr); 3878c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&qp_ctx->backlog); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci qp_ctx->c_in_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH, 3908c2ecf20Sopenharmony_ci SEC_SGL_SGE_NR); 3918c2ecf20Sopenharmony_ci if (IS_ERR(qp_ctx->c_in_pool)) { 3928c2ecf20Sopenharmony_ci dev_err(dev, "fail to create sgl pool for input!\n"); 3938c2ecf20Sopenharmony_ci goto err_destroy_idr; 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci qp_ctx->c_out_pool = hisi_acc_create_sgl_pool(dev, QM_Q_DEPTH, 3978c2ecf20Sopenharmony_ci SEC_SGL_SGE_NR); 3988c2ecf20Sopenharmony_ci if (IS_ERR(qp_ctx->c_out_pool)) { 3998c2ecf20Sopenharmony_ci dev_err(dev, "fail to create sgl pool for output!\n"); 4008c2ecf20Sopenharmony_ci goto err_free_c_in_pool; 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci ret = sec_alg_resource_alloc(ctx, qp_ctx); 4048c2ecf20Sopenharmony_ci if (ret) 4058c2ecf20Sopenharmony_ci goto err_free_c_out_pool; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci ret = hisi_qm_start_qp(qp, 0); 4088c2ecf20Sopenharmony_ci if (ret < 0) 4098c2ecf20Sopenharmony_ci goto err_queue_free; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci return 0; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_cierr_queue_free: 4148c2ecf20Sopenharmony_ci sec_alg_resource_free(ctx, qp_ctx); 4158c2ecf20Sopenharmony_cierr_free_c_out_pool: 4168c2ecf20Sopenharmony_ci hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool); 4178c2ecf20Sopenharmony_cierr_free_c_in_pool: 4188c2ecf20Sopenharmony_ci hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool); 4198c2ecf20Sopenharmony_cierr_destroy_idr: 4208c2ecf20Sopenharmony_ci idr_destroy(&qp_ctx->req_idr); 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci return ret; 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_cistatic void sec_release_qp_ctx(struct sec_ctx *ctx, 4268c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci hisi_qm_stop_qp(qp_ctx->qp); 4318c2ecf20Sopenharmony_ci sec_alg_resource_free(ctx, qp_ctx); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci hisi_acc_free_sgl_pool(dev, qp_ctx->c_out_pool); 4348c2ecf20Sopenharmony_ci hisi_acc_free_sgl_pool(dev, qp_ctx->c_in_pool); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci idr_destroy(&qp_ctx->req_idr); 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_cistatic int sec_ctx_base_init(struct sec_ctx *ctx) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci struct sec_dev *sec; 4428c2ecf20Sopenharmony_ci int i, ret; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci ctx->qps = sec_create_qps(); 4458c2ecf20Sopenharmony_ci if (!ctx->qps) { 4468c2ecf20Sopenharmony_ci pr_err("Can not create sec qps!\n"); 4478c2ecf20Sopenharmony_ci return -ENODEV; 4488c2ecf20Sopenharmony_ci } 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci sec = container_of(ctx->qps[0]->qm, struct sec_dev, qm); 4518c2ecf20Sopenharmony_ci ctx->sec = sec; 4528c2ecf20Sopenharmony_ci ctx->dev = &sec->qm.pdev->dev; 4538c2ecf20Sopenharmony_ci ctx->hlf_q_num = sec->ctx_q_num >> 1; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci ctx->pbuf_supported = ctx->sec->iommu_used; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci /* Half of queue depth is taken as fake requests limit in the queue. */ 4588c2ecf20Sopenharmony_ci ctx->fake_req_limit = QM_Q_DEPTH >> 1; 4598c2ecf20Sopenharmony_ci ctx->qp_ctx = kcalloc(sec->ctx_q_num, sizeof(struct sec_qp_ctx), 4608c2ecf20Sopenharmony_ci GFP_KERNEL); 4618c2ecf20Sopenharmony_ci if (!ctx->qp_ctx) { 4628c2ecf20Sopenharmony_ci ret = -ENOMEM; 4638c2ecf20Sopenharmony_ci goto err_destroy_qps; 4648c2ecf20Sopenharmony_ci } 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci for (i = 0; i < sec->ctx_q_num; i++) { 4678c2ecf20Sopenharmony_ci ret = sec_create_qp_ctx(&sec->qm, ctx, i, 0); 4688c2ecf20Sopenharmony_ci if (ret) 4698c2ecf20Sopenharmony_ci goto err_sec_release_qp_ctx; 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci return 0; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_cierr_sec_release_qp_ctx: 4758c2ecf20Sopenharmony_ci for (i = i - 1; i >= 0; i--) 4768c2ecf20Sopenharmony_ci sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]); 4778c2ecf20Sopenharmony_ci kfree(ctx->qp_ctx); 4788c2ecf20Sopenharmony_cierr_destroy_qps: 4798c2ecf20Sopenharmony_ci sec_destroy_qps(ctx->qps, sec->ctx_q_num); 4808c2ecf20Sopenharmony_ci return ret; 4818c2ecf20Sopenharmony_ci} 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_cistatic void sec_ctx_base_uninit(struct sec_ctx *ctx) 4848c2ecf20Sopenharmony_ci{ 4858c2ecf20Sopenharmony_ci int i; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci for (i = 0; i < ctx->sec->ctx_q_num; i++) 4888c2ecf20Sopenharmony_ci sec_release_qp_ctx(ctx, &ctx->qp_ctx[i]); 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci sec_destroy_qps(ctx->qps, ctx->sec->ctx_q_num); 4918c2ecf20Sopenharmony_ci kfree(ctx->qp_ctx); 4928c2ecf20Sopenharmony_ci} 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_cistatic int sec_cipher_init(struct sec_ctx *ctx) 4958c2ecf20Sopenharmony_ci{ 4968c2ecf20Sopenharmony_ci struct sec_cipher_ctx *c_ctx = &ctx->c_ctx; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci c_ctx->c_key = dma_alloc_coherent(ctx->dev, SEC_MAX_KEY_SIZE, 4998c2ecf20Sopenharmony_ci &c_ctx->c_key_dma, GFP_KERNEL); 5008c2ecf20Sopenharmony_ci if (!c_ctx->c_key) 5018c2ecf20Sopenharmony_ci return -ENOMEM; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci return 0; 5048c2ecf20Sopenharmony_ci} 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_cistatic void sec_cipher_uninit(struct sec_ctx *ctx) 5078c2ecf20Sopenharmony_ci{ 5088c2ecf20Sopenharmony_ci struct sec_cipher_ctx *c_ctx = &ctx->c_ctx; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci memzero_explicit(c_ctx->c_key, SEC_MAX_KEY_SIZE); 5118c2ecf20Sopenharmony_ci dma_free_coherent(ctx->dev, SEC_MAX_KEY_SIZE, 5128c2ecf20Sopenharmony_ci c_ctx->c_key, c_ctx->c_key_dma); 5138c2ecf20Sopenharmony_ci} 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_cistatic int sec_auth_init(struct sec_ctx *ctx) 5168c2ecf20Sopenharmony_ci{ 5178c2ecf20Sopenharmony_ci struct sec_auth_ctx *a_ctx = &ctx->a_ctx; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci a_ctx->a_key = dma_alloc_coherent(ctx->dev, SEC_MAX_AKEY_SIZE, 5208c2ecf20Sopenharmony_ci &a_ctx->a_key_dma, GFP_KERNEL); 5218c2ecf20Sopenharmony_ci if (!a_ctx->a_key) 5228c2ecf20Sopenharmony_ci return -ENOMEM; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci return 0; 5258c2ecf20Sopenharmony_ci} 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_cistatic void sec_auth_uninit(struct sec_ctx *ctx) 5288c2ecf20Sopenharmony_ci{ 5298c2ecf20Sopenharmony_ci struct sec_auth_ctx *a_ctx = &ctx->a_ctx; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci memzero_explicit(a_ctx->a_key, SEC_MAX_AKEY_SIZE); 5328c2ecf20Sopenharmony_ci dma_free_coherent(ctx->dev, SEC_MAX_AKEY_SIZE, 5338c2ecf20Sopenharmony_ci a_ctx->a_key, a_ctx->a_key_dma); 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_cistatic int sec_skcipher_init(struct crypto_skcipher *tfm) 5378c2ecf20Sopenharmony_ci{ 5388c2ecf20Sopenharmony_ci struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 5398c2ecf20Sopenharmony_ci int ret; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci ctx->alg_type = SEC_SKCIPHER; 5428c2ecf20Sopenharmony_ci crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_req)); 5438c2ecf20Sopenharmony_ci ctx->c_ctx.ivsize = crypto_skcipher_ivsize(tfm); 5448c2ecf20Sopenharmony_ci if (ctx->c_ctx.ivsize > SEC_IV_SIZE) { 5458c2ecf20Sopenharmony_ci pr_err("get error skcipher iv size!\n"); 5468c2ecf20Sopenharmony_ci return -EINVAL; 5478c2ecf20Sopenharmony_ci } 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_ci ret = sec_ctx_base_init(ctx); 5508c2ecf20Sopenharmony_ci if (ret) 5518c2ecf20Sopenharmony_ci return ret; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci ret = sec_cipher_init(ctx); 5548c2ecf20Sopenharmony_ci if (ret) 5558c2ecf20Sopenharmony_ci goto err_cipher_init; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci return 0; 5588c2ecf20Sopenharmony_cierr_cipher_init: 5598c2ecf20Sopenharmony_ci sec_ctx_base_uninit(ctx); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci return ret; 5628c2ecf20Sopenharmony_ci} 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_cistatic void sec_skcipher_uninit(struct crypto_skcipher *tfm) 5658c2ecf20Sopenharmony_ci{ 5668c2ecf20Sopenharmony_ci struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci sec_cipher_uninit(ctx); 5698c2ecf20Sopenharmony_ci sec_ctx_base_uninit(ctx); 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_cistatic int sec_skcipher_3des_setkey(struct sec_cipher_ctx *c_ctx, 5738c2ecf20Sopenharmony_ci const u32 keylen, 5748c2ecf20Sopenharmony_ci const enum sec_cmode c_mode) 5758c2ecf20Sopenharmony_ci{ 5768c2ecf20Sopenharmony_ci switch (keylen) { 5778c2ecf20Sopenharmony_ci case SEC_DES3_2KEY_SIZE: 5788c2ecf20Sopenharmony_ci c_ctx->c_key_len = SEC_CKEY_3DES_2KEY; 5798c2ecf20Sopenharmony_ci break; 5808c2ecf20Sopenharmony_ci case SEC_DES3_3KEY_SIZE: 5818c2ecf20Sopenharmony_ci c_ctx->c_key_len = SEC_CKEY_3DES_3KEY; 5828c2ecf20Sopenharmony_ci break; 5838c2ecf20Sopenharmony_ci default: 5848c2ecf20Sopenharmony_ci return -EINVAL; 5858c2ecf20Sopenharmony_ci } 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci return 0; 5888c2ecf20Sopenharmony_ci} 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_cistatic int sec_skcipher_aes_sm4_setkey(struct sec_cipher_ctx *c_ctx, 5918c2ecf20Sopenharmony_ci const u32 keylen, 5928c2ecf20Sopenharmony_ci const enum sec_cmode c_mode) 5938c2ecf20Sopenharmony_ci{ 5948c2ecf20Sopenharmony_ci if (c_mode == SEC_CMODE_XTS) { 5958c2ecf20Sopenharmony_ci switch (keylen) { 5968c2ecf20Sopenharmony_ci case SEC_XTS_MIN_KEY_SIZE: 5978c2ecf20Sopenharmony_ci c_ctx->c_key_len = SEC_CKEY_128BIT; 5988c2ecf20Sopenharmony_ci break; 5998c2ecf20Sopenharmony_ci case SEC_XTS_MAX_KEY_SIZE: 6008c2ecf20Sopenharmony_ci c_ctx->c_key_len = SEC_CKEY_256BIT; 6018c2ecf20Sopenharmony_ci break; 6028c2ecf20Sopenharmony_ci default: 6038c2ecf20Sopenharmony_ci pr_err("hisi_sec2: xts mode key error!\n"); 6048c2ecf20Sopenharmony_ci return -EINVAL; 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci } else { 6078c2ecf20Sopenharmony_ci switch (keylen) { 6088c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 6098c2ecf20Sopenharmony_ci c_ctx->c_key_len = SEC_CKEY_128BIT; 6108c2ecf20Sopenharmony_ci break; 6118c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 6128c2ecf20Sopenharmony_ci c_ctx->c_key_len = SEC_CKEY_192BIT; 6138c2ecf20Sopenharmony_ci break; 6148c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 6158c2ecf20Sopenharmony_ci c_ctx->c_key_len = SEC_CKEY_256BIT; 6168c2ecf20Sopenharmony_ci break; 6178c2ecf20Sopenharmony_ci default: 6188c2ecf20Sopenharmony_ci pr_err("hisi_sec2: aes key error!\n"); 6198c2ecf20Sopenharmony_ci return -EINVAL; 6208c2ecf20Sopenharmony_ci } 6218c2ecf20Sopenharmony_ci } 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci return 0; 6248c2ecf20Sopenharmony_ci} 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_cistatic int sec_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key, 6278c2ecf20Sopenharmony_ci const u32 keylen, const enum sec_calg c_alg, 6288c2ecf20Sopenharmony_ci const enum sec_cmode c_mode) 6298c2ecf20Sopenharmony_ci{ 6308c2ecf20Sopenharmony_ci struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 6318c2ecf20Sopenharmony_ci struct sec_cipher_ctx *c_ctx = &ctx->c_ctx; 6328c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 6338c2ecf20Sopenharmony_ci int ret; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci if (c_mode == SEC_CMODE_XTS) { 6368c2ecf20Sopenharmony_ci ret = xts_verify_key(tfm, key, keylen); 6378c2ecf20Sopenharmony_ci if (ret) { 6388c2ecf20Sopenharmony_ci dev_err(dev, "xts mode key err!\n"); 6398c2ecf20Sopenharmony_ci return ret; 6408c2ecf20Sopenharmony_ci } 6418c2ecf20Sopenharmony_ci } 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci c_ctx->c_alg = c_alg; 6448c2ecf20Sopenharmony_ci c_ctx->c_mode = c_mode; 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci switch (c_alg) { 6478c2ecf20Sopenharmony_ci case SEC_CALG_3DES: 6488c2ecf20Sopenharmony_ci ret = sec_skcipher_3des_setkey(c_ctx, keylen, c_mode); 6498c2ecf20Sopenharmony_ci break; 6508c2ecf20Sopenharmony_ci case SEC_CALG_AES: 6518c2ecf20Sopenharmony_ci case SEC_CALG_SM4: 6528c2ecf20Sopenharmony_ci ret = sec_skcipher_aes_sm4_setkey(c_ctx, keylen, c_mode); 6538c2ecf20Sopenharmony_ci break; 6548c2ecf20Sopenharmony_ci default: 6558c2ecf20Sopenharmony_ci return -EINVAL; 6568c2ecf20Sopenharmony_ci } 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci if (ret) { 6598c2ecf20Sopenharmony_ci dev_err(dev, "set sec key err!\n"); 6608c2ecf20Sopenharmony_ci return ret; 6618c2ecf20Sopenharmony_ci } 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci memcpy(c_ctx->c_key, key, keylen); 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci return 0; 6668c2ecf20Sopenharmony_ci} 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci#define GEN_SEC_SETKEY_FUNC(name, c_alg, c_mode) \ 6698c2ecf20Sopenharmony_cistatic int sec_setkey_##name(struct crypto_skcipher *tfm, const u8 *key,\ 6708c2ecf20Sopenharmony_ci u32 keylen) \ 6718c2ecf20Sopenharmony_ci{ \ 6728c2ecf20Sopenharmony_ci return sec_skcipher_setkey(tfm, key, keylen, c_alg, c_mode); \ 6738c2ecf20Sopenharmony_ci} 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(aes_ecb, SEC_CALG_AES, SEC_CMODE_ECB) 6768c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(aes_cbc, SEC_CALG_AES, SEC_CMODE_CBC) 6778c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(aes_xts, SEC_CALG_AES, SEC_CMODE_XTS) 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(3des_ecb, SEC_CALG_3DES, SEC_CMODE_ECB) 6808c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(3des_cbc, SEC_CALG_3DES, SEC_CMODE_CBC) 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(sm4_xts, SEC_CALG_SM4, SEC_CMODE_XTS) 6838c2ecf20Sopenharmony_ciGEN_SEC_SETKEY_FUNC(sm4_cbc, SEC_CALG_SM4, SEC_CMODE_CBC) 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_cistatic int sec_cipher_pbuf_map(struct sec_ctx *ctx, struct sec_req *req, 6868c2ecf20Sopenharmony_ci struct scatterlist *src) 6878c2ecf20Sopenharmony_ci{ 6888c2ecf20Sopenharmony_ci struct aead_request *aead_req = req->aead_req.aead_req; 6898c2ecf20Sopenharmony_ci struct sec_cipher_req *c_req = &req->c_req; 6908c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx = req->qp_ctx; 6918c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 6928c2ecf20Sopenharmony_ci int copy_size, pbuf_length; 6938c2ecf20Sopenharmony_ci int req_id = req->req_id; 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci if (ctx->alg_type == SEC_AEAD) 6968c2ecf20Sopenharmony_ci copy_size = aead_req->cryptlen + aead_req->assoclen; 6978c2ecf20Sopenharmony_ci else 6988c2ecf20Sopenharmony_ci copy_size = c_req->c_len; 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci pbuf_length = sg_copy_to_buffer(src, sg_nents(src), 7018c2ecf20Sopenharmony_ci qp_ctx->res[req_id].pbuf, 7028c2ecf20Sopenharmony_ci copy_size); 7038c2ecf20Sopenharmony_ci if (unlikely(pbuf_length != copy_size)) { 7048c2ecf20Sopenharmony_ci dev_err(dev, "copy src data to pbuf error!\n"); 7058c2ecf20Sopenharmony_ci return -EINVAL; 7068c2ecf20Sopenharmony_ci } 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci c_req->c_in_dma = qp_ctx->res[req_id].pbuf_dma; 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci if (!c_req->c_in_dma) { 7118c2ecf20Sopenharmony_ci dev_err(dev, "fail to set pbuffer address!\n"); 7128c2ecf20Sopenharmony_ci return -ENOMEM; 7138c2ecf20Sopenharmony_ci } 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci c_req->c_out_dma = c_req->c_in_dma; 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci return 0; 7188c2ecf20Sopenharmony_ci} 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_cistatic void sec_cipher_pbuf_unmap(struct sec_ctx *ctx, struct sec_req *req, 7218c2ecf20Sopenharmony_ci struct scatterlist *dst) 7228c2ecf20Sopenharmony_ci{ 7238c2ecf20Sopenharmony_ci struct aead_request *aead_req = req->aead_req.aead_req; 7248c2ecf20Sopenharmony_ci struct sec_cipher_req *c_req = &req->c_req; 7258c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx = req->qp_ctx; 7268c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 7278c2ecf20Sopenharmony_ci int copy_size, pbuf_length; 7288c2ecf20Sopenharmony_ci int req_id = req->req_id; 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci if (ctx->alg_type == SEC_AEAD) 7318c2ecf20Sopenharmony_ci copy_size = c_req->c_len + aead_req->assoclen; 7328c2ecf20Sopenharmony_ci else 7338c2ecf20Sopenharmony_ci copy_size = c_req->c_len; 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci pbuf_length = sg_copy_from_buffer(dst, sg_nents(dst), 7368c2ecf20Sopenharmony_ci qp_ctx->res[req_id].pbuf, 7378c2ecf20Sopenharmony_ci copy_size); 7388c2ecf20Sopenharmony_ci if (unlikely(pbuf_length != copy_size)) 7398c2ecf20Sopenharmony_ci dev_err(dev, "copy pbuf data to dst error!\n"); 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci} 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_cistatic int sec_cipher_map(struct sec_ctx *ctx, struct sec_req *req, 7448c2ecf20Sopenharmony_ci struct scatterlist *src, struct scatterlist *dst) 7458c2ecf20Sopenharmony_ci{ 7468c2ecf20Sopenharmony_ci struct sec_cipher_req *c_req = &req->c_req; 7478c2ecf20Sopenharmony_ci struct sec_aead_req *a_req = &req->aead_req; 7488c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx = req->qp_ctx; 7498c2ecf20Sopenharmony_ci struct sec_alg_res *res = &qp_ctx->res[req->req_id]; 7508c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 7518c2ecf20Sopenharmony_ci int ret; 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci if (req->use_pbuf) { 7548c2ecf20Sopenharmony_ci ret = sec_cipher_pbuf_map(ctx, req, src); 7558c2ecf20Sopenharmony_ci c_req->c_ivin = res->pbuf + SEC_PBUF_IV_OFFSET; 7568c2ecf20Sopenharmony_ci c_req->c_ivin_dma = res->pbuf_dma + SEC_PBUF_IV_OFFSET; 7578c2ecf20Sopenharmony_ci if (ctx->alg_type == SEC_AEAD) { 7588c2ecf20Sopenharmony_ci a_req->out_mac = res->pbuf + SEC_PBUF_MAC_OFFSET; 7598c2ecf20Sopenharmony_ci a_req->out_mac_dma = res->pbuf_dma + 7608c2ecf20Sopenharmony_ci SEC_PBUF_MAC_OFFSET; 7618c2ecf20Sopenharmony_ci } 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci return ret; 7648c2ecf20Sopenharmony_ci } 7658c2ecf20Sopenharmony_ci c_req->c_ivin = res->c_ivin; 7668c2ecf20Sopenharmony_ci c_req->c_ivin_dma = res->c_ivin_dma; 7678c2ecf20Sopenharmony_ci if (ctx->alg_type == SEC_AEAD) { 7688c2ecf20Sopenharmony_ci a_req->out_mac = res->out_mac; 7698c2ecf20Sopenharmony_ci a_req->out_mac_dma = res->out_mac_dma; 7708c2ecf20Sopenharmony_ci } 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci c_req->c_in = hisi_acc_sg_buf_map_to_hw_sgl(dev, src, 7738c2ecf20Sopenharmony_ci qp_ctx->c_in_pool, 7748c2ecf20Sopenharmony_ci req->req_id, 7758c2ecf20Sopenharmony_ci &c_req->c_in_dma); 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci if (IS_ERR(c_req->c_in)) { 7788c2ecf20Sopenharmony_ci dev_err(dev, "fail to dma map input sgl buffers!\n"); 7798c2ecf20Sopenharmony_ci return PTR_ERR(c_req->c_in); 7808c2ecf20Sopenharmony_ci } 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci if (dst == src) { 7838c2ecf20Sopenharmony_ci c_req->c_out = c_req->c_in; 7848c2ecf20Sopenharmony_ci c_req->c_out_dma = c_req->c_in_dma; 7858c2ecf20Sopenharmony_ci } else { 7868c2ecf20Sopenharmony_ci c_req->c_out = hisi_acc_sg_buf_map_to_hw_sgl(dev, dst, 7878c2ecf20Sopenharmony_ci qp_ctx->c_out_pool, 7888c2ecf20Sopenharmony_ci req->req_id, 7898c2ecf20Sopenharmony_ci &c_req->c_out_dma); 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci if (IS_ERR(c_req->c_out)) { 7928c2ecf20Sopenharmony_ci dev_err(dev, "fail to dma map output sgl buffers!\n"); 7938c2ecf20Sopenharmony_ci hisi_acc_sg_buf_unmap(dev, src, c_req->c_in); 7948c2ecf20Sopenharmony_ci return PTR_ERR(c_req->c_out); 7958c2ecf20Sopenharmony_ci } 7968c2ecf20Sopenharmony_ci } 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci return 0; 7998c2ecf20Sopenharmony_ci} 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_cistatic void sec_cipher_unmap(struct sec_ctx *ctx, struct sec_req *req, 8028c2ecf20Sopenharmony_ci struct scatterlist *src, struct scatterlist *dst) 8038c2ecf20Sopenharmony_ci{ 8048c2ecf20Sopenharmony_ci struct sec_cipher_req *c_req = &req->c_req; 8058c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci if (req->use_pbuf) { 8088c2ecf20Sopenharmony_ci sec_cipher_pbuf_unmap(ctx, req, dst); 8098c2ecf20Sopenharmony_ci } else { 8108c2ecf20Sopenharmony_ci if (dst != src) 8118c2ecf20Sopenharmony_ci hisi_acc_sg_buf_unmap(dev, src, c_req->c_in); 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci hisi_acc_sg_buf_unmap(dev, dst, c_req->c_out); 8148c2ecf20Sopenharmony_ci } 8158c2ecf20Sopenharmony_ci} 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_cistatic int sec_skcipher_sgl_map(struct sec_ctx *ctx, struct sec_req *req) 8188c2ecf20Sopenharmony_ci{ 8198c2ecf20Sopenharmony_ci struct skcipher_request *sq = req->c_req.sk_req; 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci return sec_cipher_map(ctx, req, sq->src, sq->dst); 8228c2ecf20Sopenharmony_ci} 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_cistatic void sec_skcipher_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req) 8258c2ecf20Sopenharmony_ci{ 8268c2ecf20Sopenharmony_ci struct skcipher_request *sq = req->c_req.sk_req; 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci sec_cipher_unmap(ctx, req, sq->src, sq->dst); 8298c2ecf20Sopenharmony_ci} 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_cistatic int sec_aead_aes_set_key(struct sec_cipher_ctx *c_ctx, 8328c2ecf20Sopenharmony_ci struct crypto_authenc_keys *keys) 8338c2ecf20Sopenharmony_ci{ 8348c2ecf20Sopenharmony_ci switch (keys->enckeylen) { 8358c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 8368c2ecf20Sopenharmony_ci c_ctx->c_key_len = SEC_CKEY_128BIT; 8378c2ecf20Sopenharmony_ci break; 8388c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 8398c2ecf20Sopenharmony_ci c_ctx->c_key_len = SEC_CKEY_192BIT; 8408c2ecf20Sopenharmony_ci break; 8418c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 8428c2ecf20Sopenharmony_ci c_ctx->c_key_len = SEC_CKEY_256BIT; 8438c2ecf20Sopenharmony_ci break; 8448c2ecf20Sopenharmony_ci default: 8458c2ecf20Sopenharmony_ci pr_err("hisi_sec2: aead aes key error!\n"); 8468c2ecf20Sopenharmony_ci return -EINVAL; 8478c2ecf20Sopenharmony_ci } 8488c2ecf20Sopenharmony_ci memcpy(c_ctx->c_key, keys->enckey, keys->enckeylen); 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci return 0; 8518c2ecf20Sopenharmony_ci} 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_cistatic int sec_aead_auth_set_key(struct sec_auth_ctx *ctx, 8548c2ecf20Sopenharmony_ci struct crypto_authenc_keys *keys) 8558c2ecf20Sopenharmony_ci{ 8568c2ecf20Sopenharmony_ci struct crypto_shash *hash_tfm = ctx->hash_tfm; 8578c2ecf20Sopenharmony_ci int blocksize, ret; 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci if (!keys->authkeylen) { 8608c2ecf20Sopenharmony_ci pr_err("hisi_sec2: aead auth key error!\n"); 8618c2ecf20Sopenharmony_ci return -EINVAL; 8628c2ecf20Sopenharmony_ci } 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci blocksize = crypto_shash_blocksize(hash_tfm); 8658c2ecf20Sopenharmony_ci if (keys->authkeylen > blocksize) { 8668c2ecf20Sopenharmony_ci ret = crypto_shash_tfm_digest(hash_tfm, keys->authkey, 8678c2ecf20Sopenharmony_ci keys->authkeylen, ctx->a_key); 8688c2ecf20Sopenharmony_ci if (ret) { 8698c2ecf20Sopenharmony_ci pr_err("hisi_sec2: aead auth digest error!\n"); 8708c2ecf20Sopenharmony_ci return -EINVAL; 8718c2ecf20Sopenharmony_ci } 8728c2ecf20Sopenharmony_ci ctx->a_key_len = blocksize; 8738c2ecf20Sopenharmony_ci } else { 8748c2ecf20Sopenharmony_ci memcpy(ctx->a_key, keys->authkey, keys->authkeylen); 8758c2ecf20Sopenharmony_ci ctx->a_key_len = keys->authkeylen; 8768c2ecf20Sopenharmony_ci } 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ci return 0; 8798c2ecf20Sopenharmony_ci} 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_cistatic int sec_aead_setkey(struct crypto_aead *tfm, const u8 *key, 8828c2ecf20Sopenharmony_ci const u32 keylen, const enum sec_hash_alg a_alg, 8838c2ecf20Sopenharmony_ci const enum sec_calg c_alg, 8848c2ecf20Sopenharmony_ci const enum sec_mac_len mac_len, 8858c2ecf20Sopenharmony_ci const enum sec_cmode c_mode) 8868c2ecf20Sopenharmony_ci{ 8878c2ecf20Sopenharmony_ci struct sec_ctx *ctx = crypto_aead_ctx(tfm); 8888c2ecf20Sopenharmony_ci struct sec_cipher_ctx *c_ctx = &ctx->c_ctx; 8898c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 8908c2ecf20Sopenharmony_ci struct crypto_authenc_keys keys; 8918c2ecf20Sopenharmony_ci int ret; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci ctx->a_ctx.a_alg = a_alg; 8948c2ecf20Sopenharmony_ci ctx->c_ctx.c_alg = c_alg; 8958c2ecf20Sopenharmony_ci ctx->a_ctx.mac_len = mac_len; 8968c2ecf20Sopenharmony_ci c_ctx->c_mode = c_mode; 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci if (crypto_authenc_extractkeys(&keys, key, keylen)) 8998c2ecf20Sopenharmony_ci goto bad_key; 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_ci ret = sec_aead_aes_set_key(c_ctx, &keys); 9028c2ecf20Sopenharmony_ci if (ret) { 9038c2ecf20Sopenharmony_ci dev_err(dev, "set sec cipher key err!\n"); 9048c2ecf20Sopenharmony_ci goto bad_key; 9058c2ecf20Sopenharmony_ci } 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci ret = sec_aead_auth_set_key(&ctx->a_ctx, &keys); 9088c2ecf20Sopenharmony_ci if (ret) { 9098c2ecf20Sopenharmony_ci dev_err(dev, "set sec auth key err!\n"); 9108c2ecf20Sopenharmony_ci goto bad_key; 9118c2ecf20Sopenharmony_ci } 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci return 0; 9148c2ecf20Sopenharmony_cibad_key: 9158c2ecf20Sopenharmony_ci memzero_explicit(&keys, sizeof(struct crypto_authenc_keys)); 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci return -EINVAL; 9188c2ecf20Sopenharmony_ci} 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci#define GEN_SEC_AEAD_SETKEY_FUNC(name, aalg, calg, maclen, cmode) \ 9228c2ecf20Sopenharmony_cistatic int sec_setkey_##name(struct crypto_aead *tfm, const u8 *key, \ 9238c2ecf20Sopenharmony_ci u32 keylen) \ 9248c2ecf20Sopenharmony_ci{ \ 9258c2ecf20Sopenharmony_ci return sec_aead_setkey(tfm, key, keylen, aalg, calg, maclen, cmode);\ 9268c2ecf20Sopenharmony_ci} 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ciGEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha1, SEC_A_HMAC_SHA1, 9298c2ecf20Sopenharmony_ci SEC_CALG_AES, SEC_HMAC_SHA1_MAC, SEC_CMODE_CBC) 9308c2ecf20Sopenharmony_ciGEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha256, SEC_A_HMAC_SHA256, 9318c2ecf20Sopenharmony_ci SEC_CALG_AES, SEC_HMAC_SHA256_MAC, SEC_CMODE_CBC) 9328c2ecf20Sopenharmony_ciGEN_SEC_AEAD_SETKEY_FUNC(aes_cbc_sha512, SEC_A_HMAC_SHA512, 9338c2ecf20Sopenharmony_ci SEC_CALG_AES, SEC_HMAC_SHA512_MAC, SEC_CMODE_CBC) 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_cistatic int sec_aead_sgl_map(struct sec_ctx *ctx, struct sec_req *req) 9368c2ecf20Sopenharmony_ci{ 9378c2ecf20Sopenharmony_ci struct aead_request *aq = req->aead_req.aead_req; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci return sec_cipher_map(ctx, req, aq->src, aq->dst); 9408c2ecf20Sopenharmony_ci} 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_cistatic void sec_aead_sgl_unmap(struct sec_ctx *ctx, struct sec_req *req) 9438c2ecf20Sopenharmony_ci{ 9448c2ecf20Sopenharmony_ci struct aead_request *aq = req->aead_req.aead_req; 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci sec_cipher_unmap(ctx, req, aq->src, aq->dst); 9478c2ecf20Sopenharmony_ci} 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_cistatic int sec_request_transfer(struct sec_ctx *ctx, struct sec_req *req) 9508c2ecf20Sopenharmony_ci{ 9518c2ecf20Sopenharmony_ci int ret; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci ret = ctx->req_op->buf_map(ctx, req); 9548c2ecf20Sopenharmony_ci if (unlikely(ret)) 9558c2ecf20Sopenharmony_ci return ret; 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci ctx->req_op->do_transfer(ctx, req); 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci ret = ctx->req_op->bd_fill(ctx, req); 9608c2ecf20Sopenharmony_ci if (unlikely(ret)) 9618c2ecf20Sopenharmony_ci goto unmap_req_buf; 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci return ret; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ciunmap_req_buf: 9668c2ecf20Sopenharmony_ci ctx->req_op->buf_unmap(ctx, req); 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci return ret; 9698c2ecf20Sopenharmony_ci} 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_cistatic void sec_request_untransfer(struct sec_ctx *ctx, struct sec_req *req) 9728c2ecf20Sopenharmony_ci{ 9738c2ecf20Sopenharmony_ci ctx->req_op->buf_unmap(ctx, req); 9748c2ecf20Sopenharmony_ci} 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_cistatic void sec_skcipher_copy_iv(struct sec_ctx *ctx, struct sec_req *req) 9778c2ecf20Sopenharmony_ci{ 9788c2ecf20Sopenharmony_ci struct skcipher_request *sk_req = req->c_req.sk_req; 9798c2ecf20Sopenharmony_ci struct sec_cipher_req *c_req = &req->c_req; 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci memcpy(c_req->c_ivin, sk_req->iv, ctx->c_ctx.ivsize); 9828c2ecf20Sopenharmony_ci} 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_cistatic int sec_skcipher_bd_fill(struct sec_ctx *ctx, struct sec_req *req) 9858c2ecf20Sopenharmony_ci{ 9868c2ecf20Sopenharmony_ci struct sec_cipher_ctx *c_ctx = &ctx->c_ctx; 9878c2ecf20Sopenharmony_ci struct sec_cipher_req *c_req = &req->c_req; 9888c2ecf20Sopenharmony_ci struct sec_sqe *sec_sqe = &req->sec_sqe; 9898c2ecf20Sopenharmony_ci u8 scene, sa_type, da_type; 9908c2ecf20Sopenharmony_ci u8 bd_type, cipher; 9918c2ecf20Sopenharmony_ci u8 de = 0; 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci memset(sec_sqe, 0, sizeof(struct sec_sqe)); 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci sec_sqe->type2.c_key_addr = cpu_to_le64(c_ctx->c_key_dma); 9968c2ecf20Sopenharmony_ci sec_sqe->type2.c_ivin_addr = cpu_to_le64(c_req->c_ivin_dma); 9978c2ecf20Sopenharmony_ci sec_sqe->type2.data_src_addr = cpu_to_le64(c_req->c_in_dma); 9988c2ecf20Sopenharmony_ci sec_sqe->type2.data_dst_addr = cpu_to_le64(c_req->c_out_dma); 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_mode) << 10018c2ecf20Sopenharmony_ci SEC_CMODE_OFFSET); 10028c2ecf20Sopenharmony_ci sec_sqe->type2.c_alg = c_ctx->c_alg; 10038c2ecf20Sopenharmony_ci sec_sqe->type2.icvw_kmode |= cpu_to_le16(((u16)c_ctx->c_key_len) << 10048c2ecf20Sopenharmony_ci SEC_CKEY_OFFSET); 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci bd_type = SEC_BD_TYPE2; 10078c2ecf20Sopenharmony_ci if (c_req->encrypt) 10088c2ecf20Sopenharmony_ci cipher = SEC_CIPHER_ENC << SEC_CIPHER_OFFSET; 10098c2ecf20Sopenharmony_ci else 10108c2ecf20Sopenharmony_ci cipher = SEC_CIPHER_DEC << SEC_CIPHER_OFFSET; 10118c2ecf20Sopenharmony_ci sec_sqe->type_cipher_auth = bd_type | cipher; 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci if (req->use_pbuf) 10148c2ecf20Sopenharmony_ci sa_type = SEC_PBUF << SEC_SRC_SGL_OFFSET; 10158c2ecf20Sopenharmony_ci else 10168c2ecf20Sopenharmony_ci sa_type = SEC_SGL << SEC_SRC_SGL_OFFSET; 10178c2ecf20Sopenharmony_ci scene = SEC_COMM_SCENE << SEC_SCENE_OFFSET; 10188c2ecf20Sopenharmony_ci if (c_req->c_in_dma != c_req->c_out_dma) 10198c2ecf20Sopenharmony_ci de = 0x1 << SEC_DE_OFFSET; 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci sec_sqe->sds_sa_type = (de | scene | sa_type); 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci /* Just set DST address type */ 10248c2ecf20Sopenharmony_ci if (req->use_pbuf) 10258c2ecf20Sopenharmony_ci da_type = SEC_PBUF << SEC_DST_SGL_OFFSET; 10268c2ecf20Sopenharmony_ci else 10278c2ecf20Sopenharmony_ci da_type = SEC_SGL << SEC_DST_SGL_OFFSET; 10288c2ecf20Sopenharmony_ci sec_sqe->sdm_addr_type |= da_type; 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci sec_sqe->type2.clen_ivhlen |= cpu_to_le32(c_req->c_len); 10318c2ecf20Sopenharmony_ci sec_sqe->type2.tag = cpu_to_le16((u16)req->req_id); 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci return 0; 10348c2ecf20Sopenharmony_ci} 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_cistatic void sec_update_iv(struct sec_req *req, enum sec_alg_type alg_type) 10378c2ecf20Sopenharmony_ci{ 10388c2ecf20Sopenharmony_ci struct aead_request *aead_req = req->aead_req.aead_req; 10398c2ecf20Sopenharmony_ci struct skcipher_request *sk_req = req->c_req.sk_req; 10408c2ecf20Sopenharmony_ci u32 iv_size = req->ctx->c_ctx.ivsize; 10418c2ecf20Sopenharmony_ci struct scatterlist *sgl; 10428c2ecf20Sopenharmony_ci unsigned int cryptlen; 10438c2ecf20Sopenharmony_ci size_t sz; 10448c2ecf20Sopenharmony_ci u8 *iv; 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci if (req->c_req.encrypt) 10478c2ecf20Sopenharmony_ci sgl = alg_type == SEC_SKCIPHER ? sk_req->dst : aead_req->dst; 10488c2ecf20Sopenharmony_ci else 10498c2ecf20Sopenharmony_ci sgl = alg_type == SEC_SKCIPHER ? sk_req->src : aead_req->src; 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci if (alg_type == SEC_SKCIPHER) { 10528c2ecf20Sopenharmony_ci iv = sk_req->iv; 10538c2ecf20Sopenharmony_ci cryptlen = sk_req->cryptlen; 10548c2ecf20Sopenharmony_ci } else { 10558c2ecf20Sopenharmony_ci iv = aead_req->iv; 10568c2ecf20Sopenharmony_ci cryptlen = aead_req->cryptlen; 10578c2ecf20Sopenharmony_ci } 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci sz = sg_pcopy_to_buffer(sgl, sg_nents(sgl), iv, iv_size, 10608c2ecf20Sopenharmony_ci cryptlen - iv_size); 10618c2ecf20Sopenharmony_ci if (unlikely(sz != iv_size)) 10628c2ecf20Sopenharmony_ci dev_err(req->ctx->dev, "copy output iv error!\n"); 10638c2ecf20Sopenharmony_ci} 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_cistatic struct sec_req *sec_back_req_clear(struct sec_ctx *ctx, 10668c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx) 10678c2ecf20Sopenharmony_ci{ 10688c2ecf20Sopenharmony_ci struct sec_req *backlog_req = NULL; 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci spin_lock_bh(&qp_ctx->req_lock); 10718c2ecf20Sopenharmony_ci if (ctx->fake_req_limit >= 10728c2ecf20Sopenharmony_ci atomic_read(&qp_ctx->qp->qp_status.used) && 10738c2ecf20Sopenharmony_ci !list_empty(&qp_ctx->backlog)) { 10748c2ecf20Sopenharmony_ci backlog_req = list_first_entry(&qp_ctx->backlog, 10758c2ecf20Sopenharmony_ci typeof(*backlog_req), backlog_head); 10768c2ecf20Sopenharmony_ci list_del(&backlog_req->backlog_head); 10778c2ecf20Sopenharmony_ci } 10788c2ecf20Sopenharmony_ci spin_unlock_bh(&qp_ctx->req_lock); 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci return backlog_req; 10818c2ecf20Sopenharmony_ci} 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_cistatic void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req, 10848c2ecf20Sopenharmony_ci int err) 10858c2ecf20Sopenharmony_ci{ 10868c2ecf20Sopenharmony_ci struct skcipher_request *sk_req = req->c_req.sk_req; 10878c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx = req->qp_ctx; 10888c2ecf20Sopenharmony_ci struct skcipher_request *backlog_sk_req; 10898c2ecf20Sopenharmony_ci struct sec_req *backlog_req; 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci sec_free_req_id(req); 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci /* IV output at encrypto of CBC mode */ 10948c2ecf20Sopenharmony_ci if (!err && ctx->c_ctx.c_mode == SEC_CMODE_CBC && req->c_req.encrypt) 10958c2ecf20Sopenharmony_ci sec_update_iv(req, SEC_SKCIPHER); 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci while (1) { 10988c2ecf20Sopenharmony_ci backlog_req = sec_back_req_clear(ctx, qp_ctx); 10998c2ecf20Sopenharmony_ci if (!backlog_req) 11008c2ecf20Sopenharmony_ci break; 11018c2ecf20Sopenharmony_ci 11028c2ecf20Sopenharmony_ci backlog_sk_req = backlog_req->c_req.sk_req; 11038c2ecf20Sopenharmony_ci backlog_sk_req->base.complete(&backlog_sk_req->base, 11048c2ecf20Sopenharmony_ci -EINPROGRESS); 11058c2ecf20Sopenharmony_ci atomic64_inc(&ctx->sec->debug.dfx.recv_busy_cnt); 11068c2ecf20Sopenharmony_ci } 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci sk_req->base.complete(&sk_req->base, err); 11108c2ecf20Sopenharmony_ci} 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_cistatic void sec_aead_copy_iv(struct sec_ctx *ctx, struct sec_req *req) 11138c2ecf20Sopenharmony_ci{ 11148c2ecf20Sopenharmony_ci struct aead_request *aead_req = req->aead_req.aead_req; 11158c2ecf20Sopenharmony_ci struct sec_cipher_req *c_req = &req->c_req; 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci memcpy(c_req->c_ivin, aead_req->iv, ctx->c_ctx.ivsize); 11188c2ecf20Sopenharmony_ci} 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_cistatic void sec_auth_bd_fill_ex(struct sec_auth_ctx *ctx, int dir, 11218c2ecf20Sopenharmony_ci struct sec_req *req, struct sec_sqe *sec_sqe) 11228c2ecf20Sopenharmony_ci{ 11238c2ecf20Sopenharmony_ci struct sec_aead_req *a_req = &req->aead_req; 11248c2ecf20Sopenharmony_ci struct sec_cipher_req *c_req = &req->c_req; 11258c2ecf20Sopenharmony_ci struct aead_request *aq = a_req->aead_req; 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci sec_sqe->type2.a_key_addr = cpu_to_le64(ctx->a_key_dma); 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci sec_sqe->type2.mac_key_alg = 11308c2ecf20Sopenharmony_ci cpu_to_le32(ctx->mac_len / SEC_SQE_LEN_RATE); 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci sec_sqe->type2.mac_key_alg |= 11338c2ecf20Sopenharmony_ci cpu_to_le32((u32)((ctx->a_key_len) / 11348c2ecf20Sopenharmony_ci SEC_SQE_LEN_RATE) << SEC_AKEY_OFFSET); 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci sec_sqe->type2.mac_key_alg |= 11378c2ecf20Sopenharmony_ci cpu_to_le32((u32)(ctx->a_alg) << SEC_AEAD_ALG_OFFSET); 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci sec_sqe->type_cipher_auth |= SEC_AUTH_TYPE1 << SEC_AUTH_OFFSET; 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci if (dir) 11428c2ecf20Sopenharmony_ci sec_sqe->sds_sa_type &= SEC_CIPHER_AUTH; 11438c2ecf20Sopenharmony_ci else 11448c2ecf20Sopenharmony_ci sec_sqe->sds_sa_type |= SEC_AUTH_CIPHER; 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci sec_sqe->type2.alen_ivllen = cpu_to_le32(c_req->c_len + aq->assoclen); 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci sec_sqe->type2.cipher_src_offset = cpu_to_le16((u16)aq->assoclen); 11498c2ecf20Sopenharmony_ci 11508c2ecf20Sopenharmony_ci sec_sqe->type2.mac_addr = cpu_to_le64(a_req->out_mac_dma); 11518c2ecf20Sopenharmony_ci} 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_cistatic int sec_aead_bd_fill(struct sec_ctx *ctx, struct sec_req *req) 11548c2ecf20Sopenharmony_ci{ 11558c2ecf20Sopenharmony_ci struct sec_auth_ctx *auth_ctx = &ctx->a_ctx; 11568c2ecf20Sopenharmony_ci struct sec_sqe *sec_sqe = &req->sec_sqe; 11578c2ecf20Sopenharmony_ci int ret; 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci ret = sec_skcipher_bd_fill(ctx, req); 11608c2ecf20Sopenharmony_ci if (unlikely(ret)) { 11618c2ecf20Sopenharmony_ci dev_err(ctx->dev, "skcipher bd fill is error!\n"); 11628c2ecf20Sopenharmony_ci return ret; 11638c2ecf20Sopenharmony_ci } 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci sec_auth_bd_fill_ex(auth_ctx, req->c_req.encrypt, req, sec_sqe); 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci return 0; 11688c2ecf20Sopenharmony_ci} 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_cistatic void sec_aead_callback(struct sec_ctx *c, struct sec_req *req, int err) 11718c2ecf20Sopenharmony_ci{ 11728c2ecf20Sopenharmony_ci struct aead_request *a_req = req->aead_req.aead_req; 11738c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(a_req); 11748c2ecf20Sopenharmony_ci struct sec_aead_req *aead_req = &req->aead_req; 11758c2ecf20Sopenharmony_ci struct sec_cipher_req *c_req = &req->c_req; 11768c2ecf20Sopenharmony_ci size_t authsize = crypto_aead_authsize(tfm); 11778c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx = req->qp_ctx; 11788c2ecf20Sopenharmony_ci struct aead_request *backlog_aead_req; 11798c2ecf20Sopenharmony_ci struct sec_req *backlog_req; 11808c2ecf20Sopenharmony_ci size_t sz; 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci if (!err && c->c_ctx.c_mode == SEC_CMODE_CBC && c_req->encrypt) 11838c2ecf20Sopenharmony_ci sec_update_iv(req, SEC_AEAD); 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci /* Copy output mac */ 11868c2ecf20Sopenharmony_ci if (!err && c_req->encrypt) { 11878c2ecf20Sopenharmony_ci struct scatterlist *sgl = a_req->dst; 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci sz = sg_pcopy_from_buffer(sgl, sg_nents(sgl), 11908c2ecf20Sopenharmony_ci aead_req->out_mac, 11918c2ecf20Sopenharmony_ci authsize, a_req->cryptlen + 11928c2ecf20Sopenharmony_ci a_req->assoclen); 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci if (unlikely(sz != authsize)) { 11958c2ecf20Sopenharmony_ci dev_err(c->dev, "copy out mac err!\n"); 11968c2ecf20Sopenharmony_ci err = -EINVAL; 11978c2ecf20Sopenharmony_ci } 11988c2ecf20Sopenharmony_ci } 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci sec_free_req_id(req); 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci while (1) { 12038c2ecf20Sopenharmony_ci backlog_req = sec_back_req_clear(c, qp_ctx); 12048c2ecf20Sopenharmony_ci if (!backlog_req) 12058c2ecf20Sopenharmony_ci break; 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci backlog_aead_req = backlog_req->aead_req.aead_req; 12088c2ecf20Sopenharmony_ci backlog_aead_req->base.complete(&backlog_aead_req->base, 12098c2ecf20Sopenharmony_ci -EINPROGRESS); 12108c2ecf20Sopenharmony_ci atomic64_inc(&c->sec->debug.dfx.recv_busy_cnt); 12118c2ecf20Sopenharmony_ci } 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci a_req->base.complete(&a_req->base, err); 12148c2ecf20Sopenharmony_ci} 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_cistatic void sec_request_uninit(struct sec_ctx *ctx, struct sec_req *req) 12178c2ecf20Sopenharmony_ci{ 12188c2ecf20Sopenharmony_ci sec_free_req_id(req); 12198c2ecf20Sopenharmony_ci sec_free_queue_id(ctx, req); 12208c2ecf20Sopenharmony_ci} 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_cistatic int sec_request_init(struct sec_ctx *ctx, struct sec_req *req) 12238c2ecf20Sopenharmony_ci{ 12248c2ecf20Sopenharmony_ci struct sec_qp_ctx *qp_ctx; 12258c2ecf20Sopenharmony_ci int queue_id; 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci /* To load balance */ 12288c2ecf20Sopenharmony_ci queue_id = sec_alloc_queue_id(ctx, req); 12298c2ecf20Sopenharmony_ci qp_ctx = &ctx->qp_ctx[queue_id]; 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci req->req_id = sec_alloc_req_id(req, qp_ctx); 12328c2ecf20Sopenharmony_ci if (unlikely(req->req_id < 0)) { 12338c2ecf20Sopenharmony_ci sec_free_queue_id(ctx, req); 12348c2ecf20Sopenharmony_ci return req->req_id; 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci return 0; 12388c2ecf20Sopenharmony_ci} 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_cistatic int sec_process(struct sec_ctx *ctx, struct sec_req *req) 12418c2ecf20Sopenharmony_ci{ 12428c2ecf20Sopenharmony_ci struct sec_cipher_req *c_req = &req->c_req; 12438c2ecf20Sopenharmony_ci int ret; 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci ret = sec_request_init(ctx, req); 12468c2ecf20Sopenharmony_ci if (unlikely(ret)) 12478c2ecf20Sopenharmony_ci return ret; 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci ret = sec_request_transfer(ctx, req); 12508c2ecf20Sopenharmony_ci if (unlikely(ret)) 12518c2ecf20Sopenharmony_ci goto err_uninit_req; 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci /* Output IV as decrypto */ 12548c2ecf20Sopenharmony_ci if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt) 12558c2ecf20Sopenharmony_ci sec_update_iv(req, ctx->alg_type); 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci ret = ctx->req_op->bd_send(ctx, req); 12588c2ecf20Sopenharmony_ci if (unlikely((ret != -EBUSY && ret != -EINPROGRESS) || 12598c2ecf20Sopenharmony_ci (ret == -EBUSY && !(req->flag & CRYPTO_TFM_REQ_MAY_BACKLOG)))) { 12608c2ecf20Sopenharmony_ci dev_err_ratelimited(ctx->dev, "send sec request failed!\n"); 12618c2ecf20Sopenharmony_ci goto err_send_req; 12628c2ecf20Sopenharmony_ci } 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci return ret; 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_cierr_send_req: 12678c2ecf20Sopenharmony_ci /* As failing, restore the IV from user */ 12688c2ecf20Sopenharmony_ci if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && !req->c_req.encrypt) { 12698c2ecf20Sopenharmony_ci if (ctx->alg_type == SEC_SKCIPHER) 12708c2ecf20Sopenharmony_ci memcpy(req->c_req.sk_req->iv, c_req->c_ivin, 12718c2ecf20Sopenharmony_ci ctx->c_ctx.ivsize); 12728c2ecf20Sopenharmony_ci else 12738c2ecf20Sopenharmony_ci memcpy(req->aead_req.aead_req->iv, c_req->c_ivin, 12748c2ecf20Sopenharmony_ci ctx->c_ctx.ivsize); 12758c2ecf20Sopenharmony_ci } 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci sec_request_untransfer(ctx, req); 12788c2ecf20Sopenharmony_cierr_uninit_req: 12798c2ecf20Sopenharmony_ci sec_request_uninit(ctx, req); 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci return ret; 12828c2ecf20Sopenharmony_ci} 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_cistatic const struct sec_req_op sec_skcipher_req_ops = { 12858c2ecf20Sopenharmony_ci .buf_map = sec_skcipher_sgl_map, 12868c2ecf20Sopenharmony_ci .buf_unmap = sec_skcipher_sgl_unmap, 12878c2ecf20Sopenharmony_ci .do_transfer = sec_skcipher_copy_iv, 12888c2ecf20Sopenharmony_ci .bd_fill = sec_skcipher_bd_fill, 12898c2ecf20Sopenharmony_ci .bd_send = sec_bd_send, 12908c2ecf20Sopenharmony_ci .callback = sec_skcipher_callback, 12918c2ecf20Sopenharmony_ci .process = sec_process, 12928c2ecf20Sopenharmony_ci}; 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_cistatic const struct sec_req_op sec_aead_req_ops = { 12958c2ecf20Sopenharmony_ci .buf_map = sec_aead_sgl_map, 12968c2ecf20Sopenharmony_ci .buf_unmap = sec_aead_sgl_unmap, 12978c2ecf20Sopenharmony_ci .do_transfer = sec_aead_copy_iv, 12988c2ecf20Sopenharmony_ci .bd_fill = sec_aead_bd_fill, 12998c2ecf20Sopenharmony_ci .bd_send = sec_bd_send, 13008c2ecf20Sopenharmony_ci .callback = sec_aead_callback, 13018c2ecf20Sopenharmony_ci .process = sec_process, 13028c2ecf20Sopenharmony_ci}; 13038c2ecf20Sopenharmony_ci 13048c2ecf20Sopenharmony_cistatic int sec_skcipher_ctx_init(struct crypto_skcipher *tfm) 13058c2ecf20Sopenharmony_ci{ 13068c2ecf20Sopenharmony_ci struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci ctx->req_op = &sec_skcipher_req_ops; 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci return sec_skcipher_init(tfm); 13118c2ecf20Sopenharmony_ci} 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_cistatic void sec_skcipher_ctx_exit(struct crypto_skcipher *tfm) 13148c2ecf20Sopenharmony_ci{ 13158c2ecf20Sopenharmony_ci sec_skcipher_uninit(tfm); 13168c2ecf20Sopenharmony_ci} 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_cistatic int sec_aead_init(struct crypto_aead *tfm) 13198c2ecf20Sopenharmony_ci{ 13208c2ecf20Sopenharmony_ci struct sec_ctx *ctx = crypto_aead_ctx(tfm); 13218c2ecf20Sopenharmony_ci int ret; 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci crypto_aead_set_reqsize(tfm, sizeof(struct sec_req)); 13248c2ecf20Sopenharmony_ci ctx->alg_type = SEC_AEAD; 13258c2ecf20Sopenharmony_ci ctx->c_ctx.ivsize = crypto_aead_ivsize(tfm); 13268c2ecf20Sopenharmony_ci if (ctx->c_ctx.ivsize > SEC_IV_SIZE) { 13278c2ecf20Sopenharmony_ci dev_err(ctx->dev, "get error aead iv size!\n"); 13288c2ecf20Sopenharmony_ci return -EINVAL; 13298c2ecf20Sopenharmony_ci } 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci ctx->req_op = &sec_aead_req_ops; 13328c2ecf20Sopenharmony_ci ret = sec_ctx_base_init(ctx); 13338c2ecf20Sopenharmony_ci if (ret) 13348c2ecf20Sopenharmony_ci return ret; 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci ret = sec_auth_init(ctx); 13378c2ecf20Sopenharmony_ci if (ret) 13388c2ecf20Sopenharmony_ci goto err_auth_init; 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci ret = sec_cipher_init(ctx); 13418c2ecf20Sopenharmony_ci if (ret) 13428c2ecf20Sopenharmony_ci goto err_cipher_init; 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci return ret; 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_cierr_cipher_init: 13478c2ecf20Sopenharmony_ci sec_auth_uninit(ctx); 13488c2ecf20Sopenharmony_cierr_auth_init: 13498c2ecf20Sopenharmony_ci sec_ctx_base_uninit(ctx); 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci return ret; 13528c2ecf20Sopenharmony_ci} 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_cistatic void sec_aead_exit(struct crypto_aead *tfm) 13558c2ecf20Sopenharmony_ci{ 13568c2ecf20Sopenharmony_ci struct sec_ctx *ctx = crypto_aead_ctx(tfm); 13578c2ecf20Sopenharmony_ci 13588c2ecf20Sopenharmony_ci sec_cipher_uninit(ctx); 13598c2ecf20Sopenharmony_ci sec_auth_uninit(ctx); 13608c2ecf20Sopenharmony_ci sec_ctx_base_uninit(ctx); 13618c2ecf20Sopenharmony_ci} 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_cistatic int sec_aead_ctx_init(struct crypto_aead *tfm, const char *hash_name) 13648c2ecf20Sopenharmony_ci{ 13658c2ecf20Sopenharmony_ci struct sec_ctx *ctx = crypto_aead_ctx(tfm); 13668c2ecf20Sopenharmony_ci struct sec_auth_ctx *auth_ctx = &ctx->a_ctx; 13678c2ecf20Sopenharmony_ci int ret; 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci ret = sec_aead_init(tfm); 13708c2ecf20Sopenharmony_ci if (ret) { 13718c2ecf20Sopenharmony_ci pr_err("hisi_sec2: aead init error!\n"); 13728c2ecf20Sopenharmony_ci return ret; 13738c2ecf20Sopenharmony_ci } 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci auth_ctx->hash_tfm = crypto_alloc_shash(hash_name, 0, 0); 13768c2ecf20Sopenharmony_ci if (IS_ERR(auth_ctx->hash_tfm)) { 13778c2ecf20Sopenharmony_ci dev_err(ctx->dev, "aead alloc shash error!\n"); 13788c2ecf20Sopenharmony_ci sec_aead_exit(tfm); 13798c2ecf20Sopenharmony_ci return PTR_ERR(auth_ctx->hash_tfm); 13808c2ecf20Sopenharmony_ci } 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci return 0; 13838c2ecf20Sopenharmony_ci} 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_cistatic void sec_aead_ctx_exit(struct crypto_aead *tfm) 13868c2ecf20Sopenharmony_ci{ 13878c2ecf20Sopenharmony_ci struct sec_ctx *ctx = crypto_aead_ctx(tfm); 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci crypto_free_shash(ctx->a_ctx.hash_tfm); 13908c2ecf20Sopenharmony_ci sec_aead_exit(tfm); 13918c2ecf20Sopenharmony_ci} 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_cistatic int sec_aead_sha1_ctx_init(struct crypto_aead *tfm) 13948c2ecf20Sopenharmony_ci{ 13958c2ecf20Sopenharmony_ci return sec_aead_ctx_init(tfm, "sha1"); 13968c2ecf20Sopenharmony_ci} 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_cistatic int sec_aead_sha256_ctx_init(struct crypto_aead *tfm) 13998c2ecf20Sopenharmony_ci{ 14008c2ecf20Sopenharmony_ci return sec_aead_ctx_init(tfm, "sha256"); 14018c2ecf20Sopenharmony_ci} 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_cistatic int sec_aead_sha512_ctx_init(struct crypto_aead *tfm) 14048c2ecf20Sopenharmony_ci{ 14058c2ecf20Sopenharmony_ci return sec_aead_ctx_init(tfm, "sha512"); 14068c2ecf20Sopenharmony_ci} 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_cistatic int sec_skcipher_param_check(struct sec_ctx *ctx, struct sec_req *sreq) 14098c2ecf20Sopenharmony_ci{ 14108c2ecf20Sopenharmony_ci struct skcipher_request *sk_req = sreq->c_req.sk_req; 14118c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 14128c2ecf20Sopenharmony_ci u8 c_alg = ctx->c_ctx.c_alg; 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci if (unlikely(!sk_req->src || !sk_req->dst)) { 14158c2ecf20Sopenharmony_ci dev_err(dev, "skcipher input param error!\n"); 14168c2ecf20Sopenharmony_ci return -EINVAL; 14178c2ecf20Sopenharmony_ci } 14188c2ecf20Sopenharmony_ci sreq->c_req.c_len = sk_req->cryptlen; 14198c2ecf20Sopenharmony_ci 14208c2ecf20Sopenharmony_ci if (ctx->pbuf_supported && sk_req->cryptlen <= SEC_PBUF_SZ) 14218c2ecf20Sopenharmony_ci sreq->use_pbuf = true; 14228c2ecf20Sopenharmony_ci else 14238c2ecf20Sopenharmony_ci sreq->use_pbuf = false; 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci if (c_alg == SEC_CALG_3DES) { 14268c2ecf20Sopenharmony_ci if (unlikely(sk_req->cryptlen & (DES3_EDE_BLOCK_SIZE - 1))) { 14278c2ecf20Sopenharmony_ci dev_err(dev, "skcipher 3des input length error!\n"); 14288c2ecf20Sopenharmony_ci return -EINVAL; 14298c2ecf20Sopenharmony_ci } 14308c2ecf20Sopenharmony_ci return 0; 14318c2ecf20Sopenharmony_ci } else if (c_alg == SEC_CALG_AES || c_alg == SEC_CALG_SM4) { 14328c2ecf20Sopenharmony_ci if (unlikely(sk_req->cryptlen & (AES_BLOCK_SIZE - 1))) { 14338c2ecf20Sopenharmony_ci dev_err(dev, "skcipher aes input length error!\n"); 14348c2ecf20Sopenharmony_ci return -EINVAL; 14358c2ecf20Sopenharmony_ci } 14368c2ecf20Sopenharmony_ci return 0; 14378c2ecf20Sopenharmony_ci } 14388c2ecf20Sopenharmony_ci 14398c2ecf20Sopenharmony_ci dev_err(dev, "skcipher algorithm error!\n"); 14408c2ecf20Sopenharmony_ci return -EINVAL; 14418c2ecf20Sopenharmony_ci} 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_cistatic int sec_skcipher_crypto(struct skcipher_request *sk_req, bool encrypt) 14448c2ecf20Sopenharmony_ci{ 14458c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(sk_req); 14468c2ecf20Sopenharmony_ci struct sec_req *req = skcipher_request_ctx(sk_req); 14478c2ecf20Sopenharmony_ci struct sec_ctx *ctx = crypto_skcipher_ctx(tfm); 14488c2ecf20Sopenharmony_ci int ret; 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci if (!sk_req->cryptlen) 14518c2ecf20Sopenharmony_ci return 0; 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci req->flag = sk_req->base.flags; 14548c2ecf20Sopenharmony_ci req->c_req.sk_req = sk_req; 14558c2ecf20Sopenharmony_ci req->c_req.encrypt = encrypt; 14568c2ecf20Sopenharmony_ci req->ctx = ctx; 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci ret = sec_skcipher_param_check(ctx, req); 14598c2ecf20Sopenharmony_ci if (unlikely(ret)) 14608c2ecf20Sopenharmony_ci return -EINVAL; 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ci return ctx->req_op->process(ctx, req); 14638c2ecf20Sopenharmony_ci} 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_cistatic int sec_skcipher_encrypt(struct skcipher_request *sk_req) 14668c2ecf20Sopenharmony_ci{ 14678c2ecf20Sopenharmony_ci return sec_skcipher_crypto(sk_req, true); 14688c2ecf20Sopenharmony_ci} 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_cistatic int sec_skcipher_decrypt(struct skcipher_request *sk_req) 14718c2ecf20Sopenharmony_ci{ 14728c2ecf20Sopenharmony_ci return sec_skcipher_crypto(sk_req, false); 14738c2ecf20Sopenharmony_ci} 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci#define SEC_SKCIPHER_GEN_ALG(sec_cra_name, sec_set_key, sec_min_key_size, \ 14768c2ecf20Sopenharmony_ci sec_max_key_size, ctx_init, ctx_exit, blk_size, iv_size)\ 14778c2ecf20Sopenharmony_ci{\ 14788c2ecf20Sopenharmony_ci .base = {\ 14798c2ecf20Sopenharmony_ci .cra_name = sec_cra_name,\ 14808c2ecf20Sopenharmony_ci .cra_driver_name = "hisi_sec_"sec_cra_name,\ 14818c2ecf20Sopenharmony_ci .cra_priority = SEC_PRIORITY,\ 14828c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,\ 14838c2ecf20Sopenharmony_ci .cra_blocksize = blk_size,\ 14848c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sec_ctx),\ 14858c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE,\ 14868c2ecf20Sopenharmony_ci },\ 14878c2ecf20Sopenharmony_ci .init = ctx_init,\ 14888c2ecf20Sopenharmony_ci .exit = ctx_exit,\ 14898c2ecf20Sopenharmony_ci .setkey = sec_set_key,\ 14908c2ecf20Sopenharmony_ci .decrypt = sec_skcipher_decrypt,\ 14918c2ecf20Sopenharmony_ci .encrypt = sec_skcipher_encrypt,\ 14928c2ecf20Sopenharmony_ci .min_keysize = sec_min_key_size,\ 14938c2ecf20Sopenharmony_ci .max_keysize = sec_max_key_size,\ 14948c2ecf20Sopenharmony_ci .ivsize = iv_size,\ 14958c2ecf20Sopenharmony_ci}, 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci#define SEC_SKCIPHER_ALG(name, key_func, min_key_size, \ 14988c2ecf20Sopenharmony_ci max_key_size, blk_size, iv_size) \ 14998c2ecf20Sopenharmony_ci SEC_SKCIPHER_GEN_ALG(name, key_func, min_key_size, max_key_size, \ 15008c2ecf20Sopenharmony_ci sec_skcipher_ctx_init, sec_skcipher_ctx_exit, blk_size, iv_size) 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_cistatic struct skcipher_alg sec_skciphers[] = { 15038c2ecf20Sopenharmony_ci SEC_SKCIPHER_ALG("ecb(aes)", sec_setkey_aes_ecb, 15048c2ecf20Sopenharmony_ci AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE, 15058c2ecf20Sopenharmony_ci AES_BLOCK_SIZE, 0) 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci SEC_SKCIPHER_ALG("cbc(aes)", sec_setkey_aes_cbc, 15088c2ecf20Sopenharmony_ci AES_MIN_KEY_SIZE, AES_MAX_KEY_SIZE, 15098c2ecf20Sopenharmony_ci AES_BLOCK_SIZE, AES_BLOCK_SIZE) 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci SEC_SKCIPHER_ALG("xts(aes)", sec_setkey_aes_xts, 15128c2ecf20Sopenharmony_ci SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MAX_KEY_SIZE, 15138c2ecf20Sopenharmony_ci AES_BLOCK_SIZE, AES_BLOCK_SIZE) 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb, 15168c2ecf20Sopenharmony_ci SEC_DES3_3KEY_SIZE, SEC_DES3_3KEY_SIZE, 15178c2ecf20Sopenharmony_ci DES3_EDE_BLOCK_SIZE, 0) 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc, 15208c2ecf20Sopenharmony_ci SEC_DES3_3KEY_SIZE, SEC_DES3_3KEY_SIZE, 15218c2ecf20Sopenharmony_ci DES3_EDE_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE) 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts, 15248c2ecf20Sopenharmony_ci SEC_XTS_MIN_KEY_SIZE, SEC_XTS_MIN_KEY_SIZE, 15258c2ecf20Sopenharmony_ci AES_BLOCK_SIZE, AES_BLOCK_SIZE) 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci SEC_SKCIPHER_ALG("cbc(sm4)", sec_setkey_sm4_cbc, 15288c2ecf20Sopenharmony_ci AES_MIN_KEY_SIZE, AES_MIN_KEY_SIZE, 15298c2ecf20Sopenharmony_ci AES_BLOCK_SIZE, AES_BLOCK_SIZE) 15308c2ecf20Sopenharmony_ci}; 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_cistatic int sec_aead_param_check(struct sec_ctx *ctx, struct sec_req *sreq) 15338c2ecf20Sopenharmony_ci{ 15348c2ecf20Sopenharmony_ci struct aead_request *req = sreq->aead_req.aead_req; 15358c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 15368c2ecf20Sopenharmony_ci size_t authsize = crypto_aead_authsize(tfm); 15378c2ecf20Sopenharmony_ci struct device *dev = ctx->dev; 15388c2ecf20Sopenharmony_ci u8 c_alg = ctx->c_ctx.c_alg; 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_ci if (unlikely(!req->src || !req->dst || !req->cryptlen || 15418c2ecf20Sopenharmony_ci req->assoclen > SEC_MAX_AAD_LEN)) { 15428c2ecf20Sopenharmony_ci dev_err(dev, "aead input param error!\n"); 15438c2ecf20Sopenharmony_ci return -EINVAL; 15448c2ecf20Sopenharmony_ci } 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_ci if (ctx->pbuf_supported && (req->cryptlen + req->assoclen) <= 15478c2ecf20Sopenharmony_ci SEC_PBUF_SZ) 15488c2ecf20Sopenharmony_ci sreq->use_pbuf = true; 15498c2ecf20Sopenharmony_ci else 15508c2ecf20Sopenharmony_ci sreq->use_pbuf = false; 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci /* Support AES only */ 15538c2ecf20Sopenharmony_ci if (unlikely(c_alg != SEC_CALG_AES)) { 15548c2ecf20Sopenharmony_ci dev_err(dev, "aead crypto alg error!\n"); 15558c2ecf20Sopenharmony_ci return -EINVAL; 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci } 15588c2ecf20Sopenharmony_ci if (sreq->c_req.encrypt) 15598c2ecf20Sopenharmony_ci sreq->c_req.c_len = req->cryptlen; 15608c2ecf20Sopenharmony_ci else 15618c2ecf20Sopenharmony_ci sreq->c_req.c_len = req->cryptlen - authsize; 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_ci if (unlikely(sreq->c_req.c_len & (AES_BLOCK_SIZE - 1))) { 15648c2ecf20Sopenharmony_ci dev_err(dev, "aead crypto length error!\n"); 15658c2ecf20Sopenharmony_ci return -EINVAL; 15668c2ecf20Sopenharmony_ci } 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_ci return 0; 15698c2ecf20Sopenharmony_ci} 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_cistatic int sec_aead_crypto(struct aead_request *a_req, bool encrypt) 15728c2ecf20Sopenharmony_ci{ 15738c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(a_req); 15748c2ecf20Sopenharmony_ci struct sec_req *req = aead_request_ctx(a_req); 15758c2ecf20Sopenharmony_ci struct sec_ctx *ctx = crypto_aead_ctx(tfm); 15768c2ecf20Sopenharmony_ci int ret; 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci req->flag = a_req->base.flags; 15798c2ecf20Sopenharmony_ci req->aead_req.aead_req = a_req; 15808c2ecf20Sopenharmony_ci req->c_req.encrypt = encrypt; 15818c2ecf20Sopenharmony_ci req->ctx = ctx; 15828c2ecf20Sopenharmony_ci 15838c2ecf20Sopenharmony_ci ret = sec_aead_param_check(ctx, req); 15848c2ecf20Sopenharmony_ci if (unlikely(ret)) 15858c2ecf20Sopenharmony_ci return -EINVAL; 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci return ctx->req_op->process(ctx, req); 15888c2ecf20Sopenharmony_ci} 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_cistatic int sec_aead_encrypt(struct aead_request *a_req) 15918c2ecf20Sopenharmony_ci{ 15928c2ecf20Sopenharmony_ci return sec_aead_crypto(a_req, true); 15938c2ecf20Sopenharmony_ci} 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_cistatic int sec_aead_decrypt(struct aead_request *a_req) 15968c2ecf20Sopenharmony_ci{ 15978c2ecf20Sopenharmony_ci return sec_aead_crypto(a_req, false); 15988c2ecf20Sopenharmony_ci} 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci#define SEC_AEAD_GEN_ALG(sec_cra_name, sec_set_key, ctx_init,\ 16018c2ecf20Sopenharmony_ci ctx_exit, blk_size, iv_size, max_authsize)\ 16028c2ecf20Sopenharmony_ci{\ 16038c2ecf20Sopenharmony_ci .base = {\ 16048c2ecf20Sopenharmony_ci .cra_name = sec_cra_name,\ 16058c2ecf20Sopenharmony_ci .cra_driver_name = "hisi_sec_"sec_cra_name,\ 16068c2ecf20Sopenharmony_ci .cra_priority = SEC_PRIORITY,\ 16078c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY,\ 16088c2ecf20Sopenharmony_ci .cra_blocksize = blk_size,\ 16098c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sec_ctx),\ 16108c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE,\ 16118c2ecf20Sopenharmony_ci },\ 16128c2ecf20Sopenharmony_ci .init = ctx_init,\ 16138c2ecf20Sopenharmony_ci .exit = ctx_exit,\ 16148c2ecf20Sopenharmony_ci .setkey = sec_set_key,\ 16158c2ecf20Sopenharmony_ci .decrypt = sec_aead_decrypt,\ 16168c2ecf20Sopenharmony_ci .encrypt = sec_aead_encrypt,\ 16178c2ecf20Sopenharmony_ci .ivsize = iv_size,\ 16188c2ecf20Sopenharmony_ci .maxauthsize = max_authsize,\ 16198c2ecf20Sopenharmony_ci} 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci#define SEC_AEAD_ALG(algname, keyfunc, aead_init, blksize, ivsize, authsize)\ 16228c2ecf20Sopenharmony_ci SEC_AEAD_GEN_ALG(algname, keyfunc, aead_init,\ 16238c2ecf20Sopenharmony_ci sec_aead_ctx_exit, blksize, ivsize, authsize) 16248c2ecf20Sopenharmony_ci 16258c2ecf20Sopenharmony_cistatic struct aead_alg sec_aeads[] = { 16268c2ecf20Sopenharmony_ci SEC_AEAD_ALG("authenc(hmac(sha1),cbc(aes))", 16278c2ecf20Sopenharmony_ci sec_setkey_aes_cbc_sha1, sec_aead_sha1_ctx_init, 16288c2ecf20Sopenharmony_ci AES_BLOCK_SIZE, AES_BLOCK_SIZE, SHA1_DIGEST_SIZE), 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_ci SEC_AEAD_ALG("authenc(hmac(sha256),cbc(aes))", 16318c2ecf20Sopenharmony_ci sec_setkey_aes_cbc_sha256, sec_aead_sha256_ctx_init, 16328c2ecf20Sopenharmony_ci AES_BLOCK_SIZE, AES_BLOCK_SIZE, SHA256_DIGEST_SIZE), 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci SEC_AEAD_ALG("authenc(hmac(sha512),cbc(aes))", 16358c2ecf20Sopenharmony_ci sec_setkey_aes_cbc_sha512, sec_aead_sha512_ctx_init, 16368c2ecf20Sopenharmony_ci AES_BLOCK_SIZE, AES_BLOCK_SIZE, SHA512_DIGEST_SIZE), 16378c2ecf20Sopenharmony_ci}; 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_ciint sec_register_to_crypto(void) 16408c2ecf20Sopenharmony_ci{ 16418c2ecf20Sopenharmony_ci int ret; 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci /* To avoid repeat register */ 16448c2ecf20Sopenharmony_ci ret = crypto_register_skciphers(sec_skciphers, 16458c2ecf20Sopenharmony_ci ARRAY_SIZE(sec_skciphers)); 16468c2ecf20Sopenharmony_ci if (ret) 16478c2ecf20Sopenharmony_ci return ret; 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci ret = crypto_register_aeads(sec_aeads, ARRAY_SIZE(sec_aeads)); 16508c2ecf20Sopenharmony_ci if (ret) 16518c2ecf20Sopenharmony_ci crypto_unregister_skciphers(sec_skciphers, 16528c2ecf20Sopenharmony_ci ARRAY_SIZE(sec_skciphers)); 16538c2ecf20Sopenharmony_ci return ret; 16548c2ecf20Sopenharmony_ci} 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_civoid sec_unregister_from_crypto(void) 16578c2ecf20Sopenharmony_ci{ 16588c2ecf20Sopenharmony_ci crypto_unregister_skciphers(sec_skciphers, 16598c2ecf20Sopenharmony_ci ARRAY_SIZE(sec_skciphers)); 16608c2ecf20Sopenharmony_ci crypto_unregister_aeads(sec_aeads, ARRAY_SIZE(sec_aeads)); 16618c2ecf20Sopenharmony_ci} 1662