18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Cryptographic API. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Driver for EIP97 AES acceleration. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2016 Ryder Lee <ryder.lee@mediatek.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Some ideas are from atmel-aes.c drivers. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <crypto/aes.h> 138c2ecf20Sopenharmony_ci#include <crypto/gcm.h> 148c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h> 158c2ecf20Sopenharmony_ci#include "mtk-platform.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#define AES_QUEUE_SIZE 512 188c2ecf20Sopenharmony_ci#define AES_BUF_ORDER 2 198c2ecf20Sopenharmony_ci#define AES_BUF_SIZE ((PAGE_SIZE << AES_BUF_ORDER) \ 208c2ecf20Sopenharmony_ci & ~(AES_BLOCK_SIZE - 1)) 218c2ecf20Sopenharmony_ci#define AES_MAX_STATE_BUF_SIZE SIZE_IN_WORDS(AES_KEYSIZE_256 + \ 228c2ecf20Sopenharmony_ci AES_BLOCK_SIZE * 2) 238c2ecf20Sopenharmony_ci#define AES_MAX_CT_SIZE 6 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define AES_CT_CTRL_HDR cpu_to_le32(0x00220000) 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci/* AES-CBC/ECB/CTR/OFB/CFB command token */ 288c2ecf20Sopenharmony_ci#define AES_CMD0 cpu_to_le32(0x05000000) 298c2ecf20Sopenharmony_ci#define AES_CMD1 cpu_to_le32(0x2d060000) 308c2ecf20Sopenharmony_ci#define AES_CMD2 cpu_to_le32(0xe4a63806) 318c2ecf20Sopenharmony_ci/* AES-GCM command token */ 328c2ecf20Sopenharmony_ci#define AES_GCM_CMD0 cpu_to_le32(0x0b000000) 338c2ecf20Sopenharmony_ci#define AES_GCM_CMD1 cpu_to_le32(0xa0800000) 348c2ecf20Sopenharmony_ci#define AES_GCM_CMD2 cpu_to_le32(0x25000010) 358c2ecf20Sopenharmony_ci#define AES_GCM_CMD3 cpu_to_le32(0x0f020000) 368c2ecf20Sopenharmony_ci#define AES_GCM_CMD4 cpu_to_le32(0x21e60000) 378c2ecf20Sopenharmony_ci#define AES_GCM_CMD5 cpu_to_le32(0x40e60000) 388c2ecf20Sopenharmony_ci#define AES_GCM_CMD6 cpu_to_le32(0xd0070000) 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* AES transform information word 0 fields */ 418c2ecf20Sopenharmony_ci#define AES_TFM_BASIC_OUT cpu_to_le32(0x4 << 0) 428c2ecf20Sopenharmony_ci#define AES_TFM_BASIC_IN cpu_to_le32(0x5 << 0) 438c2ecf20Sopenharmony_ci#define AES_TFM_GCM_OUT cpu_to_le32(0x6 << 0) 448c2ecf20Sopenharmony_ci#define AES_TFM_GCM_IN cpu_to_le32(0xf << 0) 458c2ecf20Sopenharmony_ci#define AES_TFM_SIZE(x) cpu_to_le32((x) << 8) 468c2ecf20Sopenharmony_ci#define AES_TFM_128BITS cpu_to_le32(0xb << 16) 478c2ecf20Sopenharmony_ci#define AES_TFM_192BITS cpu_to_le32(0xd << 16) 488c2ecf20Sopenharmony_ci#define AES_TFM_256BITS cpu_to_le32(0xf << 16) 498c2ecf20Sopenharmony_ci#define AES_TFM_GHASH_DIGEST cpu_to_le32(0x2 << 21) 508c2ecf20Sopenharmony_ci#define AES_TFM_GHASH cpu_to_le32(0x4 << 23) 518c2ecf20Sopenharmony_ci/* AES transform information word 1 fields */ 528c2ecf20Sopenharmony_ci#define AES_TFM_ECB cpu_to_le32(0x0 << 0) 538c2ecf20Sopenharmony_ci#define AES_TFM_CBC cpu_to_le32(0x1 << 0) 548c2ecf20Sopenharmony_ci#define AES_TFM_OFB cpu_to_le32(0x4 << 0) 558c2ecf20Sopenharmony_ci#define AES_TFM_CFB128 cpu_to_le32(0x5 << 0) 568c2ecf20Sopenharmony_ci#define AES_TFM_CTR_INIT cpu_to_le32(0x2 << 0) /* init counter to 1 */ 578c2ecf20Sopenharmony_ci#define AES_TFM_CTR_LOAD cpu_to_le32(0x6 << 0) /* load/reuse counter */ 588c2ecf20Sopenharmony_ci#define AES_TFM_3IV cpu_to_le32(0x7 << 5) /* using IV 0-2 */ 598c2ecf20Sopenharmony_ci#define AES_TFM_FULL_IV cpu_to_le32(0xf << 5) /* using IV 0-3 */ 608c2ecf20Sopenharmony_ci#define AES_TFM_IV_CTR_MODE cpu_to_le32(0x1 << 10) 618c2ecf20Sopenharmony_ci#define AES_TFM_ENC_HASH cpu_to_le32(0x1 << 17) 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* AES flags */ 648c2ecf20Sopenharmony_ci#define AES_FLAGS_CIPHER_MSK GENMASK(4, 0) 658c2ecf20Sopenharmony_ci#define AES_FLAGS_ECB BIT(0) 668c2ecf20Sopenharmony_ci#define AES_FLAGS_CBC BIT(1) 678c2ecf20Sopenharmony_ci#define AES_FLAGS_CTR BIT(2) 688c2ecf20Sopenharmony_ci#define AES_FLAGS_OFB BIT(3) 698c2ecf20Sopenharmony_ci#define AES_FLAGS_CFB128 BIT(4) 708c2ecf20Sopenharmony_ci#define AES_FLAGS_GCM BIT(5) 718c2ecf20Sopenharmony_ci#define AES_FLAGS_ENCRYPT BIT(6) 728c2ecf20Sopenharmony_ci#define AES_FLAGS_BUSY BIT(7) 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci#define AES_AUTH_TAG_ERR cpu_to_le32(BIT(26)) 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/** 778c2ecf20Sopenharmony_ci * mtk_aes_info - hardware information of AES 788c2ecf20Sopenharmony_ci * @cmd: command token, hardware instruction 798c2ecf20Sopenharmony_ci * @tfm: transform state of cipher algorithm. 808c2ecf20Sopenharmony_ci * @state: contains keys and initial vectors. 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci * Memory layout of GCM buffer: 838c2ecf20Sopenharmony_ci * /-----------\ 848c2ecf20Sopenharmony_ci * | AES KEY | 128/196/256 bits 858c2ecf20Sopenharmony_ci * |-----------| 868c2ecf20Sopenharmony_ci * | HASH KEY | a string 128 zero bits encrypted using the block cipher 878c2ecf20Sopenharmony_ci * |-----------| 888c2ecf20Sopenharmony_ci * | IVs | 4 * 4 bytes 898c2ecf20Sopenharmony_ci * \-----------/ 908c2ecf20Sopenharmony_ci * 918c2ecf20Sopenharmony_ci * The engine requires all these info to do: 928c2ecf20Sopenharmony_ci * - Commands decoding and control of the engine's data path. 938c2ecf20Sopenharmony_ci * - Coordinating hardware data fetch and store operations. 948c2ecf20Sopenharmony_ci * - Result token construction and output. 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_cistruct mtk_aes_info { 978c2ecf20Sopenharmony_ci __le32 cmd[AES_MAX_CT_SIZE]; 988c2ecf20Sopenharmony_ci __le32 tfm[2]; 998c2ecf20Sopenharmony_ci __le32 state[AES_MAX_STATE_BUF_SIZE]; 1008c2ecf20Sopenharmony_ci}; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistruct mtk_aes_reqctx { 1038c2ecf20Sopenharmony_ci u64 mode; 1048c2ecf20Sopenharmony_ci}; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistruct mtk_aes_base_ctx { 1078c2ecf20Sopenharmony_ci struct mtk_cryp *cryp; 1088c2ecf20Sopenharmony_ci u32 keylen; 1098c2ecf20Sopenharmony_ci __le32 key[12]; 1108c2ecf20Sopenharmony_ci __le32 keymode; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci mtk_aes_fn start; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci struct mtk_aes_info info; 1158c2ecf20Sopenharmony_ci dma_addr_t ct_dma; 1168c2ecf20Sopenharmony_ci dma_addr_t tfm_dma; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci __le32 ct_hdr; 1198c2ecf20Sopenharmony_ci u32 ct_size; 1208c2ecf20Sopenharmony_ci}; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistruct mtk_aes_ctx { 1238c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx base; 1248c2ecf20Sopenharmony_ci}; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistruct mtk_aes_ctr_ctx { 1278c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx base; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci __be32 iv[AES_BLOCK_SIZE / sizeof(u32)]; 1308c2ecf20Sopenharmony_ci size_t offset; 1318c2ecf20Sopenharmony_ci struct scatterlist src[2]; 1328c2ecf20Sopenharmony_ci struct scatterlist dst[2]; 1338c2ecf20Sopenharmony_ci}; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistruct mtk_aes_gcm_ctx { 1368c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx base; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci u32 authsize; 1398c2ecf20Sopenharmony_ci size_t textlen; 1408c2ecf20Sopenharmony_ci}; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistruct mtk_aes_drv { 1438c2ecf20Sopenharmony_ci struct list_head dev_list; 1448c2ecf20Sopenharmony_ci /* Device list lock */ 1458c2ecf20Sopenharmony_ci spinlock_t lock; 1468c2ecf20Sopenharmony_ci}; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic struct mtk_aes_drv mtk_aes = { 1498c2ecf20Sopenharmony_ci .dev_list = LIST_HEAD_INIT(mtk_aes.dev_list), 1508c2ecf20Sopenharmony_ci .lock = __SPIN_LOCK_UNLOCKED(mtk_aes.lock), 1518c2ecf20Sopenharmony_ci}; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cistatic inline u32 mtk_aes_read(struct mtk_cryp *cryp, u32 offset) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci return readl_relaxed(cryp->base + offset); 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic inline void mtk_aes_write(struct mtk_cryp *cryp, 1598c2ecf20Sopenharmony_ci u32 offset, u32 value) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci writel_relaxed(value, cryp->base + offset); 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic struct mtk_cryp *mtk_aes_find_dev(struct mtk_aes_base_ctx *ctx) 1658c2ecf20Sopenharmony_ci{ 1668c2ecf20Sopenharmony_ci struct mtk_cryp *cryp = NULL; 1678c2ecf20Sopenharmony_ci struct mtk_cryp *tmp; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci spin_lock_bh(&mtk_aes.lock); 1708c2ecf20Sopenharmony_ci if (!ctx->cryp) { 1718c2ecf20Sopenharmony_ci list_for_each_entry(tmp, &mtk_aes.dev_list, aes_list) { 1728c2ecf20Sopenharmony_ci cryp = tmp; 1738c2ecf20Sopenharmony_ci break; 1748c2ecf20Sopenharmony_ci } 1758c2ecf20Sopenharmony_ci ctx->cryp = cryp; 1768c2ecf20Sopenharmony_ci } else { 1778c2ecf20Sopenharmony_ci cryp = ctx->cryp; 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci spin_unlock_bh(&mtk_aes.lock); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci return cryp; 1828c2ecf20Sopenharmony_ci} 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cistatic inline size_t mtk_aes_padlen(size_t len) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci len &= AES_BLOCK_SIZE - 1; 1878c2ecf20Sopenharmony_ci return len ? AES_BLOCK_SIZE - len : 0; 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_cistatic bool mtk_aes_check_aligned(struct scatterlist *sg, size_t len, 1918c2ecf20Sopenharmony_ci struct mtk_aes_dma *dma) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci int nents; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci if (!IS_ALIGNED(len, AES_BLOCK_SIZE)) 1968c2ecf20Sopenharmony_ci return false; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci for (nents = 0; sg; sg = sg_next(sg), ++nents) { 1998c2ecf20Sopenharmony_ci if (!IS_ALIGNED(sg->offset, sizeof(u32))) 2008c2ecf20Sopenharmony_ci return false; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci if (len <= sg->length) { 2038c2ecf20Sopenharmony_ci if (!IS_ALIGNED(len, AES_BLOCK_SIZE)) 2048c2ecf20Sopenharmony_ci return false; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci dma->nents = nents + 1; 2078c2ecf20Sopenharmony_ci dma->remainder = sg->length - len; 2088c2ecf20Sopenharmony_ci sg->length = len; 2098c2ecf20Sopenharmony_ci return true; 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci if (!IS_ALIGNED(sg->length, AES_BLOCK_SIZE)) 2138c2ecf20Sopenharmony_ci return false; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci len -= sg->length; 2168c2ecf20Sopenharmony_ci } 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci return false; 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic inline void mtk_aes_set_mode(struct mtk_aes_rec *aes, 2228c2ecf20Sopenharmony_ci const struct mtk_aes_reqctx *rctx) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci /* Clear all but persistent flags and set request flags. */ 2258c2ecf20Sopenharmony_ci aes->flags = (aes->flags & AES_FLAGS_BUSY) | rctx->mode; 2268c2ecf20Sopenharmony_ci} 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic inline void mtk_aes_restore_sg(const struct mtk_aes_dma *dma) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci struct scatterlist *sg = dma->sg; 2318c2ecf20Sopenharmony_ci int nents = dma->nents; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci if (!dma->remainder) 2348c2ecf20Sopenharmony_ci return; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci while (--nents > 0 && sg) 2378c2ecf20Sopenharmony_ci sg = sg_next(sg); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci if (!sg) 2408c2ecf20Sopenharmony_ci return; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci sg->length += dma->remainder; 2438c2ecf20Sopenharmony_ci} 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic inline int mtk_aes_complete(struct mtk_cryp *cryp, 2468c2ecf20Sopenharmony_ci struct mtk_aes_rec *aes, 2478c2ecf20Sopenharmony_ci int err) 2488c2ecf20Sopenharmony_ci{ 2498c2ecf20Sopenharmony_ci aes->flags &= ~AES_FLAGS_BUSY; 2508c2ecf20Sopenharmony_ci aes->areq->complete(aes->areq, err); 2518c2ecf20Sopenharmony_ci /* Handle new request */ 2528c2ecf20Sopenharmony_ci tasklet_schedule(&aes->queue_task); 2538c2ecf20Sopenharmony_ci return err; 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci/* 2578c2ecf20Sopenharmony_ci * Write descriptors for processing. This will configure the engine, load 2588c2ecf20Sopenharmony_ci * the transform information and then start the packet processing. 2598c2ecf20Sopenharmony_ci */ 2608c2ecf20Sopenharmony_cistatic int mtk_aes_xmit(struct mtk_cryp *cryp, struct mtk_aes_rec *aes) 2618c2ecf20Sopenharmony_ci{ 2628c2ecf20Sopenharmony_ci struct mtk_ring *ring = cryp->ring[aes->id]; 2638c2ecf20Sopenharmony_ci struct mtk_desc *cmd = NULL, *res = NULL; 2648c2ecf20Sopenharmony_ci struct scatterlist *ssg = aes->src.sg, *dsg = aes->dst.sg; 2658c2ecf20Sopenharmony_ci u32 slen = aes->src.sg_len, dlen = aes->dst.sg_len; 2668c2ecf20Sopenharmony_ci int nents; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /* Write command descriptors */ 2698c2ecf20Sopenharmony_ci for (nents = 0; nents < slen; ++nents, ssg = sg_next(ssg)) { 2708c2ecf20Sopenharmony_ci cmd = ring->cmd_next; 2718c2ecf20Sopenharmony_ci cmd->hdr = MTK_DESC_BUF_LEN(ssg->length); 2728c2ecf20Sopenharmony_ci cmd->buf = cpu_to_le32(sg_dma_address(ssg)); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci if (nents == 0) { 2758c2ecf20Sopenharmony_ci cmd->hdr |= MTK_DESC_FIRST | 2768c2ecf20Sopenharmony_ci MTK_DESC_CT_LEN(aes->ctx->ct_size); 2778c2ecf20Sopenharmony_ci cmd->ct = cpu_to_le32(aes->ctx->ct_dma); 2788c2ecf20Sopenharmony_ci cmd->ct_hdr = aes->ctx->ct_hdr; 2798c2ecf20Sopenharmony_ci cmd->tfm = cpu_to_le32(aes->ctx->tfm_dma); 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci /* Shift ring buffer and check boundary */ 2838c2ecf20Sopenharmony_ci if (++ring->cmd_next == ring->cmd_base + MTK_DESC_NUM) 2848c2ecf20Sopenharmony_ci ring->cmd_next = ring->cmd_base; 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci cmd->hdr |= MTK_DESC_LAST; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci /* Prepare result descriptors */ 2898c2ecf20Sopenharmony_ci for (nents = 0; nents < dlen; ++nents, dsg = sg_next(dsg)) { 2908c2ecf20Sopenharmony_ci res = ring->res_next; 2918c2ecf20Sopenharmony_ci res->hdr = MTK_DESC_BUF_LEN(dsg->length); 2928c2ecf20Sopenharmony_ci res->buf = cpu_to_le32(sg_dma_address(dsg)); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci if (nents == 0) 2958c2ecf20Sopenharmony_ci res->hdr |= MTK_DESC_FIRST; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci /* Shift ring buffer and check boundary */ 2988c2ecf20Sopenharmony_ci if (++ring->res_next == ring->res_base + MTK_DESC_NUM) 2998c2ecf20Sopenharmony_ci ring->res_next = ring->res_base; 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci res->hdr |= MTK_DESC_LAST; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci /* Pointer to current result descriptor */ 3048c2ecf20Sopenharmony_ci ring->res_prev = res; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci /* Prepare enough space for authenticated tag */ 3078c2ecf20Sopenharmony_ci if (aes->flags & AES_FLAGS_GCM) 3088c2ecf20Sopenharmony_ci le32_add_cpu(&res->hdr, AES_BLOCK_SIZE); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci /* 3118c2ecf20Sopenharmony_ci * Make sure that all changes to the DMA ring are done before we 3128c2ecf20Sopenharmony_ci * start engine. 3138c2ecf20Sopenharmony_ci */ 3148c2ecf20Sopenharmony_ci wmb(); 3158c2ecf20Sopenharmony_ci /* Start DMA transfer */ 3168c2ecf20Sopenharmony_ci mtk_aes_write(cryp, RDR_PREP_COUNT(aes->id), MTK_DESC_CNT(dlen)); 3178c2ecf20Sopenharmony_ci mtk_aes_write(cryp, CDR_PREP_COUNT(aes->id), MTK_DESC_CNT(slen)); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci return -EINPROGRESS; 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic void mtk_aes_unmap(struct mtk_cryp *cryp, struct mtk_aes_rec *aes) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx *ctx = aes->ctx; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci dma_unmap_single(cryp->dev, ctx->ct_dma, sizeof(ctx->info), 3278c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci if (aes->src.sg == aes->dst.sg) { 3308c2ecf20Sopenharmony_ci dma_unmap_sg(cryp->dev, aes->src.sg, aes->src.nents, 3318c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci if (aes->src.sg != &aes->aligned_sg) 3348c2ecf20Sopenharmony_ci mtk_aes_restore_sg(&aes->src); 3358c2ecf20Sopenharmony_ci } else { 3368c2ecf20Sopenharmony_ci dma_unmap_sg(cryp->dev, aes->dst.sg, aes->dst.nents, 3378c2ecf20Sopenharmony_ci DMA_FROM_DEVICE); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci if (aes->dst.sg != &aes->aligned_sg) 3408c2ecf20Sopenharmony_ci mtk_aes_restore_sg(&aes->dst); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci dma_unmap_sg(cryp->dev, aes->src.sg, aes->src.nents, 3438c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci if (aes->src.sg != &aes->aligned_sg) 3468c2ecf20Sopenharmony_ci mtk_aes_restore_sg(&aes->src); 3478c2ecf20Sopenharmony_ci } 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci if (aes->dst.sg == &aes->aligned_sg) 3508c2ecf20Sopenharmony_ci sg_copy_from_buffer(aes->real_dst, sg_nents(aes->real_dst), 3518c2ecf20Sopenharmony_ci aes->buf, aes->total); 3528c2ecf20Sopenharmony_ci} 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_cistatic int mtk_aes_map(struct mtk_cryp *cryp, struct mtk_aes_rec *aes) 3558c2ecf20Sopenharmony_ci{ 3568c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx *ctx = aes->ctx; 3578c2ecf20Sopenharmony_ci struct mtk_aes_info *info = &ctx->info; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci ctx->ct_dma = dma_map_single(cryp->dev, info, sizeof(*info), 3608c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 3618c2ecf20Sopenharmony_ci if (unlikely(dma_mapping_error(cryp->dev, ctx->ct_dma))) 3628c2ecf20Sopenharmony_ci goto exit; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci ctx->tfm_dma = ctx->ct_dma + sizeof(info->cmd); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci if (aes->src.sg == aes->dst.sg) { 3678c2ecf20Sopenharmony_ci aes->src.sg_len = dma_map_sg(cryp->dev, aes->src.sg, 3688c2ecf20Sopenharmony_ci aes->src.nents, 3698c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 3708c2ecf20Sopenharmony_ci aes->dst.sg_len = aes->src.sg_len; 3718c2ecf20Sopenharmony_ci if (unlikely(!aes->src.sg_len)) 3728c2ecf20Sopenharmony_ci goto sg_map_err; 3738c2ecf20Sopenharmony_ci } else { 3748c2ecf20Sopenharmony_ci aes->src.sg_len = dma_map_sg(cryp->dev, aes->src.sg, 3758c2ecf20Sopenharmony_ci aes->src.nents, DMA_TO_DEVICE); 3768c2ecf20Sopenharmony_ci if (unlikely(!aes->src.sg_len)) 3778c2ecf20Sopenharmony_ci goto sg_map_err; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci aes->dst.sg_len = dma_map_sg(cryp->dev, aes->dst.sg, 3808c2ecf20Sopenharmony_ci aes->dst.nents, DMA_FROM_DEVICE); 3818c2ecf20Sopenharmony_ci if (unlikely(!aes->dst.sg_len)) { 3828c2ecf20Sopenharmony_ci dma_unmap_sg(cryp->dev, aes->src.sg, aes->src.nents, 3838c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 3848c2ecf20Sopenharmony_ci goto sg_map_err; 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci return mtk_aes_xmit(cryp, aes); 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cisg_map_err: 3918c2ecf20Sopenharmony_ci dma_unmap_single(cryp->dev, ctx->ct_dma, sizeof(*info), DMA_TO_DEVICE); 3928c2ecf20Sopenharmony_ciexit: 3938c2ecf20Sopenharmony_ci return mtk_aes_complete(cryp, aes, -EINVAL); 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci/* Initialize transform information of CBC/ECB/CTR/OFB/CFB mode */ 3978c2ecf20Sopenharmony_cistatic void mtk_aes_info_init(struct mtk_cryp *cryp, struct mtk_aes_rec *aes, 3988c2ecf20Sopenharmony_ci size_t len) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci struct skcipher_request *req = skcipher_request_cast(aes->areq); 4018c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx *ctx = aes->ctx; 4028c2ecf20Sopenharmony_ci struct mtk_aes_info *info = &ctx->info; 4038c2ecf20Sopenharmony_ci u32 cnt = 0; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci ctx->ct_hdr = AES_CT_CTRL_HDR | cpu_to_le32(len); 4068c2ecf20Sopenharmony_ci info->cmd[cnt++] = AES_CMD0 | cpu_to_le32(len); 4078c2ecf20Sopenharmony_ci info->cmd[cnt++] = AES_CMD1; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci info->tfm[0] = AES_TFM_SIZE(ctx->keylen) | ctx->keymode; 4108c2ecf20Sopenharmony_ci if (aes->flags & AES_FLAGS_ENCRYPT) 4118c2ecf20Sopenharmony_ci info->tfm[0] |= AES_TFM_BASIC_OUT; 4128c2ecf20Sopenharmony_ci else 4138c2ecf20Sopenharmony_ci info->tfm[0] |= AES_TFM_BASIC_IN; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci switch (aes->flags & AES_FLAGS_CIPHER_MSK) { 4168c2ecf20Sopenharmony_ci case AES_FLAGS_CBC: 4178c2ecf20Sopenharmony_ci info->tfm[1] = AES_TFM_CBC; 4188c2ecf20Sopenharmony_ci break; 4198c2ecf20Sopenharmony_ci case AES_FLAGS_ECB: 4208c2ecf20Sopenharmony_ci info->tfm[1] = AES_TFM_ECB; 4218c2ecf20Sopenharmony_ci goto ecb; 4228c2ecf20Sopenharmony_ci case AES_FLAGS_CTR: 4238c2ecf20Sopenharmony_ci info->tfm[1] = AES_TFM_CTR_LOAD; 4248c2ecf20Sopenharmony_ci goto ctr; 4258c2ecf20Sopenharmony_ci case AES_FLAGS_OFB: 4268c2ecf20Sopenharmony_ci info->tfm[1] = AES_TFM_OFB; 4278c2ecf20Sopenharmony_ci break; 4288c2ecf20Sopenharmony_ci case AES_FLAGS_CFB128: 4298c2ecf20Sopenharmony_ci info->tfm[1] = AES_TFM_CFB128; 4308c2ecf20Sopenharmony_ci break; 4318c2ecf20Sopenharmony_ci default: 4328c2ecf20Sopenharmony_ci /* Should not happen... */ 4338c2ecf20Sopenharmony_ci return; 4348c2ecf20Sopenharmony_ci } 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci memcpy(info->state + ctx->keylen, req->iv, AES_BLOCK_SIZE); 4378c2ecf20Sopenharmony_cictr: 4388c2ecf20Sopenharmony_ci le32_add_cpu(&info->tfm[0], 4398c2ecf20Sopenharmony_ci le32_to_cpu(AES_TFM_SIZE(SIZE_IN_WORDS(AES_BLOCK_SIZE)))); 4408c2ecf20Sopenharmony_ci info->tfm[1] |= AES_TFM_FULL_IV; 4418c2ecf20Sopenharmony_ci info->cmd[cnt++] = AES_CMD2; 4428c2ecf20Sopenharmony_ciecb: 4438c2ecf20Sopenharmony_ci ctx->ct_size = cnt; 4448c2ecf20Sopenharmony_ci} 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic int mtk_aes_dma(struct mtk_cryp *cryp, struct mtk_aes_rec *aes, 4478c2ecf20Sopenharmony_ci struct scatterlist *src, struct scatterlist *dst, 4488c2ecf20Sopenharmony_ci size_t len) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci size_t padlen = 0; 4518c2ecf20Sopenharmony_ci bool src_aligned, dst_aligned; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci aes->total = len; 4548c2ecf20Sopenharmony_ci aes->src.sg = src; 4558c2ecf20Sopenharmony_ci aes->dst.sg = dst; 4568c2ecf20Sopenharmony_ci aes->real_dst = dst; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci src_aligned = mtk_aes_check_aligned(src, len, &aes->src); 4598c2ecf20Sopenharmony_ci if (src == dst) 4608c2ecf20Sopenharmony_ci dst_aligned = src_aligned; 4618c2ecf20Sopenharmony_ci else 4628c2ecf20Sopenharmony_ci dst_aligned = mtk_aes_check_aligned(dst, len, &aes->dst); 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci if (!src_aligned || !dst_aligned) { 4658c2ecf20Sopenharmony_ci padlen = mtk_aes_padlen(len); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci if (len + padlen > AES_BUF_SIZE) 4688c2ecf20Sopenharmony_ci return mtk_aes_complete(cryp, aes, -ENOMEM); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci if (!src_aligned) { 4718c2ecf20Sopenharmony_ci sg_copy_to_buffer(src, sg_nents(src), aes->buf, len); 4728c2ecf20Sopenharmony_ci aes->src.sg = &aes->aligned_sg; 4738c2ecf20Sopenharmony_ci aes->src.nents = 1; 4748c2ecf20Sopenharmony_ci aes->src.remainder = 0; 4758c2ecf20Sopenharmony_ci } 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci if (!dst_aligned) { 4788c2ecf20Sopenharmony_ci aes->dst.sg = &aes->aligned_sg; 4798c2ecf20Sopenharmony_ci aes->dst.nents = 1; 4808c2ecf20Sopenharmony_ci aes->dst.remainder = 0; 4818c2ecf20Sopenharmony_ci } 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci sg_init_table(&aes->aligned_sg, 1); 4848c2ecf20Sopenharmony_ci sg_set_buf(&aes->aligned_sg, aes->buf, len + padlen); 4858c2ecf20Sopenharmony_ci } 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci mtk_aes_info_init(cryp, aes, len + padlen); 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci return mtk_aes_map(cryp, aes); 4908c2ecf20Sopenharmony_ci} 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_cistatic int mtk_aes_handle_queue(struct mtk_cryp *cryp, u8 id, 4938c2ecf20Sopenharmony_ci struct crypto_async_request *new_areq) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci struct mtk_aes_rec *aes = cryp->aes[id]; 4968c2ecf20Sopenharmony_ci struct crypto_async_request *areq, *backlog; 4978c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx *ctx; 4988c2ecf20Sopenharmony_ci unsigned long flags; 4998c2ecf20Sopenharmony_ci int ret = 0; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci spin_lock_irqsave(&aes->lock, flags); 5028c2ecf20Sopenharmony_ci if (new_areq) 5038c2ecf20Sopenharmony_ci ret = crypto_enqueue_request(&aes->queue, new_areq); 5048c2ecf20Sopenharmony_ci if (aes->flags & AES_FLAGS_BUSY) { 5058c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&aes->lock, flags); 5068c2ecf20Sopenharmony_ci return ret; 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci backlog = crypto_get_backlog(&aes->queue); 5098c2ecf20Sopenharmony_ci areq = crypto_dequeue_request(&aes->queue); 5108c2ecf20Sopenharmony_ci if (areq) 5118c2ecf20Sopenharmony_ci aes->flags |= AES_FLAGS_BUSY; 5128c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&aes->lock, flags); 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci if (!areq) 5158c2ecf20Sopenharmony_ci return ret; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci if (backlog) 5188c2ecf20Sopenharmony_ci backlog->complete(backlog, -EINPROGRESS); 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci ctx = crypto_tfm_ctx(areq->tfm); 5218c2ecf20Sopenharmony_ci /* Write key into state buffer */ 5228c2ecf20Sopenharmony_ci memcpy(ctx->info.state, ctx->key, sizeof(ctx->key)); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci aes->areq = areq; 5258c2ecf20Sopenharmony_ci aes->ctx = ctx; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci return ctx->start(cryp, aes); 5288c2ecf20Sopenharmony_ci} 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_cistatic int mtk_aes_transfer_complete(struct mtk_cryp *cryp, 5318c2ecf20Sopenharmony_ci struct mtk_aes_rec *aes) 5328c2ecf20Sopenharmony_ci{ 5338c2ecf20Sopenharmony_ci return mtk_aes_complete(cryp, aes, 0); 5348c2ecf20Sopenharmony_ci} 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_cistatic int mtk_aes_start(struct mtk_cryp *cryp, struct mtk_aes_rec *aes) 5378c2ecf20Sopenharmony_ci{ 5388c2ecf20Sopenharmony_ci struct skcipher_request *req = skcipher_request_cast(aes->areq); 5398c2ecf20Sopenharmony_ci struct mtk_aes_reqctx *rctx = skcipher_request_ctx(req); 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci mtk_aes_set_mode(aes, rctx); 5428c2ecf20Sopenharmony_ci aes->resume = mtk_aes_transfer_complete; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci return mtk_aes_dma(cryp, aes, req->src, req->dst, req->cryptlen); 5458c2ecf20Sopenharmony_ci} 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_cistatic inline struct mtk_aes_ctr_ctx * 5488c2ecf20Sopenharmony_cimtk_aes_ctr_ctx_cast(struct mtk_aes_base_ctx *ctx) 5498c2ecf20Sopenharmony_ci{ 5508c2ecf20Sopenharmony_ci return container_of(ctx, struct mtk_aes_ctr_ctx, base); 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_cistatic int mtk_aes_ctr_transfer(struct mtk_cryp *cryp, struct mtk_aes_rec *aes) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx *ctx = aes->ctx; 5568c2ecf20Sopenharmony_ci struct mtk_aes_ctr_ctx *cctx = mtk_aes_ctr_ctx_cast(ctx); 5578c2ecf20Sopenharmony_ci struct skcipher_request *req = skcipher_request_cast(aes->areq); 5588c2ecf20Sopenharmony_ci struct scatterlist *src, *dst; 5598c2ecf20Sopenharmony_ci u32 start, end, ctr, blocks; 5608c2ecf20Sopenharmony_ci size_t datalen; 5618c2ecf20Sopenharmony_ci bool fragmented = false; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci /* Check for transfer completion. */ 5648c2ecf20Sopenharmony_ci cctx->offset += aes->total; 5658c2ecf20Sopenharmony_ci if (cctx->offset >= req->cryptlen) 5668c2ecf20Sopenharmony_ci return mtk_aes_transfer_complete(cryp, aes); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci /* Compute data length. */ 5698c2ecf20Sopenharmony_ci datalen = req->cryptlen - cctx->offset; 5708c2ecf20Sopenharmony_ci blocks = DIV_ROUND_UP(datalen, AES_BLOCK_SIZE); 5718c2ecf20Sopenharmony_ci ctr = be32_to_cpu(cctx->iv[3]); 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci /* Check 32bit counter overflow. */ 5748c2ecf20Sopenharmony_ci start = ctr; 5758c2ecf20Sopenharmony_ci end = start + blocks - 1; 5768c2ecf20Sopenharmony_ci if (end < start) { 5778c2ecf20Sopenharmony_ci ctr = 0xffffffff; 5788c2ecf20Sopenharmony_ci datalen = AES_BLOCK_SIZE * -start; 5798c2ecf20Sopenharmony_ci fragmented = true; 5808c2ecf20Sopenharmony_ci } 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci /* Jump to offset. */ 5838c2ecf20Sopenharmony_ci src = scatterwalk_ffwd(cctx->src, req->src, cctx->offset); 5848c2ecf20Sopenharmony_ci dst = ((req->src == req->dst) ? src : 5858c2ecf20Sopenharmony_ci scatterwalk_ffwd(cctx->dst, req->dst, cctx->offset)); 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci /* Write IVs into transform state buffer. */ 5888c2ecf20Sopenharmony_ci memcpy(ctx->info.state + ctx->keylen, cctx->iv, AES_BLOCK_SIZE); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci if (unlikely(fragmented)) { 5918c2ecf20Sopenharmony_ci /* 5928c2ecf20Sopenharmony_ci * Increment the counter manually to cope with the hardware 5938c2ecf20Sopenharmony_ci * counter overflow. 5948c2ecf20Sopenharmony_ci */ 5958c2ecf20Sopenharmony_ci cctx->iv[3] = cpu_to_be32(ctr); 5968c2ecf20Sopenharmony_ci crypto_inc((u8 *)cctx->iv, AES_BLOCK_SIZE); 5978c2ecf20Sopenharmony_ci } 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci return mtk_aes_dma(cryp, aes, src, dst, datalen); 6008c2ecf20Sopenharmony_ci} 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_cistatic int mtk_aes_ctr_start(struct mtk_cryp *cryp, struct mtk_aes_rec *aes) 6038c2ecf20Sopenharmony_ci{ 6048c2ecf20Sopenharmony_ci struct mtk_aes_ctr_ctx *cctx = mtk_aes_ctr_ctx_cast(aes->ctx); 6058c2ecf20Sopenharmony_ci struct skcipher_request *req = skcipher_request_cast(aes->areq); 6068c2ecf20Sopenharmony_ci struct mtk_aes_reqctx *rctx = skcipher_request_ctx(req); 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci mtk_aes_set_mode(aes, rctx); 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci memcpy(cctx->iv, req->iv, AES_BLOCK_SIZE); 6118c2ecf20Sopenharmony_ci cctx->offset = 0; 6128c2ecf20Sopenharmony_ci aes->total = 0; 6138c2ecf20Sopenharmony_ci aes->resume = mtk_aes_ctr_transfer; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci return mtk_aes_ctr_transfer(cryp, aes); 6168c2ecf20Sopenharmony_ci} 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci/* Check and set the AES key to transform state buffer */ 6198c2ecf20Sopenharmony_cistatic int mtk_aes_setkey(struct crypto_skcipher *tfm, 6208c2ecf20Sopenharmony_ci const u8 *key, u32 keylen) 6218c2ecf20Sopenharmony_ci{ 6228c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx *ctx = crypto_skcipher_ctx(tfm); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci switch (keylen) { 6258c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 6268c2ecf20Sopenharmony_ci ctx->keymode = AES_TFM_128BITS; 6278c2ecf20Sopenharmony_ci break; 6288c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 6298c2ecf20Sopenharmony_ci ctx->keymode = AES_TFM_192BITS; 6308c2ecf20Sopenharmony_ci break; 6318c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 6328c2ecf20Sopenharmony_ci ctx->keymode = AES_TFM_256BITS; 6338c2ecf20Sopenharmony_ci break; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci default: 6368c2ecf20Sopenharmony_ci return -EINVAL; 6378c2ecf20Sopenharmony_ci } 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci ctx->keylen = SIZE_IN_WORDS(keylen); 6408c2ecf20Sopenharmony_ci memcpy(ctx->key, key, keylen); 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci return 0; 6438c2ecf20Sopenharmony_ci} 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_cistatic int mtk_aes_crypt(struct skcipher_request *req, u64 mode) 6468c2ecf20Sopenharmony_ci{ 6478c2ecf20Sopenharmony_ci struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); 6488c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx *ctx = crypto_skcipher_ctx(skcipher); 6498c2ecf20Sopenharmony_ci struct mtk_aes_reqctx *rctx; 6508c2ecf20Sopenharmony_ci struct mtk_cryp *cryp; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci cryp = mtk_aes_find_dev(ctx); 6538c2ecf20Sopenharmony_ci if (!cryp) 6548c2ecf20Sopenharmony_ci return -ENODEV; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci rctx = skcipher_request_ctx(req); 6578c2ecf20Sopenharmony_ci rctx->mode = mode; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci return mtk_aes_handle_queue(cryp, !(mode & AES_FLAGS_ENCRYPT), 6608c2ecf20Sopenharmony_ci &req->base); 6618c2ecf20Sopenharmony_ci} 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_cistatic int mtk_aes_ecb_encrypt(struct skcipher_request *req) 6648c2ecf20Sopenharmony_ci{ 6658c2ecf20Sopenharmony_ci return mtk_aes_crypt(req, AES_FLAGS_ENCRYPT | AES_FLAGS_ECB); 6668c2ecf20Sopenharmony_ci} 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_cistatic int mtk_aes_ecb_decrypt(struct skcipher_request *req) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci return mtk_aes_crypt(req, AES_FLAGS_ECB); 6718c2ecf20Sopenharmony_ci} 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_cistatic int mtk_aes_cbc_encrypt(struct skcipher_request *req) 6748c2ecf20Sopenharmony_ci{ 6758c2ecf20Sopenharmony_ci return mtk_aes_crypt(req, AES_FLAGS_ENCRYPT | AES_FLAGS_CBC); 6768c2ecf20Sopenharmony_ci} 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_cistatic int mtk_aes_cbc_decrypt(struct skcipher_request *req) 6798c2ecf20Sopenharmony_ci{ 6808c2ecf20Sopenharmony_ci return mtk_aes_crypt(req, AES_FLAGS_CBC); 6818c2ecf20Sopenharmony_ci} 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_cistatic int mtk_aes_ctr_encrypt(struct skcipher_request *req) 6848c2ecf20Sopenharmony_ci{ 6858c2ecf20Sopenharmony_ci return mtk_aes_crypt(req, AES_FLAGS_ENCRYPT | AES_FLAGS_CTR); 6868c2ecf20Sopenharmony_ci} 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_cistatic int mtk_aes_ctr_decrypt(struct skcipher_request *req) 6898c2ecf20Sopenharmony_ci{ 6908c2ecf20Sopenharmony_ci return mtk_aes_crypt(req, AES_FLAGS_CTR); 6918c2ecf20Sopenharmony_ci} 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_cistatic int mtk_aes_ofb_encrypt(struct skcipher_request *req) 6948c2ecf20Sopenharmony_ci{ 6958c2ecf20Sopenharmony_ci return mtk_aes_crypt(req, AES_FLAGS_ENCRYPT | AES_FLAGS_OFB); 6968c2ecf20Sopenharmony_ci} 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_cistatic int mtk_aes_ofb_decrypt(struct skcipher_request *req) 6998c2ecf20Sopenharmony_ci{ 7008c2ecf20Sopenharmony_ci return mtk_aes_crypt(req, AES_FLAGS_OFB); 7018c2ecf20Sopenharmony_ci} 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_cistatic int mtk_aes_cfb_encrypt(struct skcipher_request *req) 7048c2ecf20Sopenharmony_ci{ 7058c2ecf20Sopenharmony_ci return mtk_aes_crypt(req, AES_FLAGS_ENCRYPT | AES_FLAGS_CFB128); 7068c2ecf20Sopenharmony_ci} 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_cistatic int mtk_aes_cfb_decrypt(struct skcipher_request *req) 7098c2ecf20Sopenharmony_ci{ 7108c2ecf20Sopenharmony_ci return mtk_aes_crypt(req, AES_FLAGS_CFB128); 7118c2ecf20Sopenharmony_ci} 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_cistatic int mtk_aes_init_tfm(struct crypto_skcipher *tfm) 7148c2ecf20Sopenharmony_ci{ 7158c2ecf20Sopenharmony_ci struct mtk_aes_ctx *ctx = crypto_skcipher_ctx(tfm); 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci crypto_skcipher_set_reqsize(tfm, sizeof(struct mtk_aes_reqctx)); 7188c2ecf20Sopenharmony_ci ctx->base.start = mtk_aes_start; 7198c2ecf20Sopenharmony_ci return 0; 7208c2ecf20Sopenharmony_ci} 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_cistatic int mtk_aes_ctr_init_tfm(struct crypto_skcipher *tfm) 7238c2ecf20Sopenharmony_ci{ 7248c2ecf20Sopenharmony_ci struct mtk_aes_ctx *ctx = crypto_skcipher_ctx(tfm); 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci crypto_skcipher_set_reqsize(tfm, sizeof(struct mtk_aes_reqctx)); 7278c2ecf20Sopenharmony_ci ctx->base.start = mtk_aes_ctr_start; 7288c2ecf20Sopenharmony_ci return 0; 7298c2ecf20Sopenharmony_ci} 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_cistatic struct skcipher_alg aes_algs[] = { 7328c2ecf20Sopenharmony_ci{ 7338c2ecf20Sopenharmony_ci .base.cra_name = "cbc(aes)", 7348c2ecf20Sopenharmony_ci .base.cra_driver_name = "cbc-aes-mtk", 7358c2ecf20Sopenharmony_ci .base.cra_priority = 400, 7368c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC, 7378c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 7388c2ecf20Sopenharmony_ci .base.cra_ctxsize = sizeof(struct mtk_aes_ctx), 7398c2ecf20Sopenharmony_ci .base.cra_alignmask = 0xf, 7408c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 7438c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 7448c2ecf20Sopenharmony_ci .setkey = mtk_aes_setkey, 7458c2ecf20Sopenharmony_ci .encrypt = mtk_aes_cbc_encrypt, 7468c2ecf20Sopenharmony_ci .decrypt = mtk_aes_cbc_decrypt, 7478c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 7488c2ecf20Sopenharmony_ci .init = mtk_aes_init_tfm, 7498c2ecf20Sopenharmony_ci}, 7508c2ecf20Sopenharmony_ci{ 7518c2ecf20Sopenharmony_ci .base.cra_name = "ecb(aes)", 7528c2ecf20Sopenharmony_ci .base.cra_driver_name = "ecb-aes-mtk", 7538c2ecf20Sopenharmony_ci .base.cra_priority = 400, 7548c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC, 7558c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 7568c2ecf20Sopenharmony_ci .base.cra_ctxsize = sizeof(struct mtk_aes_ctx), 7578c2ecf20Sopenharmony_ci .base.cra_alignmask = 0xf, 7588c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 7618c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 7628c2ecf20Sopenharmony_ci .setkey = mtk_aes_setkey, 7638c2ecf20Sopenharmony_ci .encrypt = mtk_aes_ecb_encrypt, 7648c2ecf20Sopenharmony_ci .decrypt = mtk_aes_ecb_decrypt, 7658c2ecf20Sopenharmony_ci .init = mtk_aes_init_tfm, 7668c2ecf20Sopenharmony_ci}, 7678c2ecf20Sopenharmony_ci{ 7688c2ecf20Sopenharmony_ci .base.cra_name = "ctr(aes)", 7698c2ecf20Sopenharmony_ci .base.cra_driver_name = "ctr-aes-mtk", 7708c2ecf20Sopenharmony_ci .base.cra_priority = 400, 7718c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC, 7728c2ecf20Sopenharmony_ci .base.cra_blocksize = 1, 7738c2ecf20Sopenharmony_ci .base.cra_ctxsize = sizeof(struct mtk_aes_ctx), 7748c2ecf20Sopenharmony_ci .base.cra_alignmask = 0xf, 7758c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 7788c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 7798c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 7808c2ecf20Sopenharmony_ci .setkey = mtk_aes_setkey, 7818c2ecf20Sopenharmony_ci .encrypt = mtk_aes_ctr_encrypt, 7828c2ecf20Sopenharmony_ci .decrypt = mtk_aes_ctr_decrypt, 7838c2ecf20Sopenharmony_ci .init = mtk_aes_ctr_init_tfm, 7848c2ecf20Sopenharmony_ci}, 7858c2ecf20Sopenharmony_ci{ 7868c2ecf20Sopenharmony_ci .base.cra_name = "ofb(aes)", 7878c2ecf20Sopenharmony_ci .base.cra_driver_name = "ofb-aes-mtk", 7888c2ecf20Sopenharmony_ci .base.cra_priority = 400, 7898c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC, 7908c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 7918c2ecf20Sopenharmony_ci .base.cra_ctxsize = sizeof(struct mtk_aes_ctx), 7928c2ecf20Sopenharmony_ci .base.cra_alignmask = 0xf, 7938c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 7968c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 7978c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 7988c2ecf20Sopenharmony_ci .setkey = mtk_aes_setkey, 7998c2ecf20Sopenharmony_ci .encrypt = mtk_aes_ofb_encrypt, 8008c2ecf20Sopenharmony_ci .decrypt = mtk_aes_ofb_decrypt, 8018c2ecf20Sopenharmony_ci}, 8028c2ecf20Sopenharmony_ci{ 8038c2ecf20Sopenharmony_ci .base.cra_name = "cfb(aes)", 8048c2ecf20Sopenharmony_ci .base.cra_driver_name = "cfb-aes-mtk", 8058c2ecf20Sopenharmony_ci .base.cra_priority = 400, 8068c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_ASYNC, 8078c2ecf20Sopenharmony_ci .base.cra_blocksize = 1, 8088c2ecf20Sopenharmony_ci .base.cra_ctxsize = sizeof(struct mtk_aes_ctx), 8098c2ecf20Sopenharmony_ci .base.cra_alignmask = 0xf, 8108c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 8138c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 8148c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 8158c2ecf20Sopenharmony_ci .setkey = mtk_aes_setkey, 8168c2ecf20Sopenharmony_ci .encrypt = mtk_aes_cfb_encrypt, 8178c2ecf20Sopenharmony_ci .decrypt = mtk_aes_cfb_decrypt, 8188c2ecf20Sopenharmony_ci}, 8198c2ecf20Sopenharmony_ci}; 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_cistatic inline struct mtk_aes_gcm_ctx * 8228c2ecf20Sopenharmony_cimtk_aes_gcm_ctx_cast(struct mtk_aes_base_ctx *ctx) 8238c2ecf20Sopenharmony_ci{ 8248c2ecf20Sopenharmony_ci return container_of(ctx, struct mtk_aes_gcm_ctx, base); 8258c2ecf20Sopenharmony_ci} 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci/* 8288c2ecf20Sopenharmony_ci * Engine will verify and compare tag automatically, so we just need 8298c2ecf20Sopenharmony_ci * to check returned status which stored in the result descriptor. 8308c2ecf20Sopenharmony_ci */ 8318c2ecf20Sopenharmony_cistatic int mtk_aes_gcm_tag_verify(struct mtk_cryp *cryp, 8328c2ecf20Sopenharmony_ci struct mtk_aes_rec *aes) 8338c2ecf20Sopenharmony_ci{ 8348c2ecf20Sopenharmony_ci __le32 status = cryp->ring[aes->id]->res_prev->ct; 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci return mtk_aes_complete(cryp, aes, (status & AES_AUTH_TAG_ERR) ? 8378c2ecf20Sopenharmony_ci -EBADMSG : 0); 8388c2ecf20Sopenharmony_ci} 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci/* Initialize transform information of GCM mode */ 8418c2ecf20Sopenharmony_cistatic void mtk_aes_gcm_info_init(struct mtk_cryp *cryp, 8428c2ecf20Sopenharmony_ci struct mtk_aes_rec *aes, 8438c2ecf20Sopenharmony_ci size_t len) 8448c2ecf20Sopenharmony_ci{ 8458c2ecf20Sopenharmony_ci struct aead_request *req = aead_request_cast(aes->areq); 8468c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx *ctx = aes->ctx; 8478c2ecf20Sopenharmony_ci struct mtk_aes_gcm_ctx *gctx = mtk_aes_gcm_ctx_cast(ctx); 8488c2ecf20Sopenharmony_ci struct mtk_aes_info *info = &ctx->info; 8498c2ecf20Sopenharmony_ci u32 ivsize = crypto_aead_ivsize(crypto_aead_reqtfm(req)); 8508c2ecf20Sopenharmony_ci u32 cnt = 0; 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci ctx->ct_hdr = AES_CT_CTRL_HDR | cpu_to_le32(len); 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci info->cmd[cnt++] = AES_GCM_CMD0 | cpu_to_le32(req->assoclen); 8558c2ecf20Sopenharmony_ci info->cmd[cnt++] = AES_GCM_CMD1 | cpu_to_le32(req->assoclen); 8568c2ecf20Sopenharmony_ci info->cmd[cnt++] = AES_GCM_CMD2; 8578c2ecf20Sopenharmony_ci info->cmd[cnt++] = AES_GCM_CMD3 | cpu_to_le32(gctx->textlen); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci if (aes->flags & AES_FLAGS_ENCRYPT) { 8608c2ecf20Sopenharmony_ci info->cmd[cnt++] = AES_GCM_CMD4 | cpu_to_le32(gctx->authsize); 8618c2ecf20Sopenharmony_ci info->tfm[0] = AES_TFM_GCM_OUT; 8628c2ecf20Sopenharmony_ci } else { 8638c2ecf20Sopenharmony_ci info->cmd[cnt++] = AES_GCM_CMD5 | cpu_to_le32(gctx->authsize); 8648c2ecf20Sopenharmony_ci info->cmd[cnt++] = AES_GCM_CMD6 | cpu_to_le32(gctx->authsize); 8658c2ecf20Sopenharmony_ci info->tfm[0] = AES_TFM_GCM_IN; 8668c2ecf20Sopenharmony_ci } 8678c2ecf20Sopenharmony_ci ctx->ct_size = cnt; 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci info->tfm[0] |= AES_TFM_GHASH_DIGEST | AES_TFM_GHASH | AES_TFM_SIZE( 8708c2ecf20Sopenharmony_ci ctx->keylen + SIZE_IN_WORDS(AES_BLOCK_SIZE + ivsize)) | 8718c2ecf20Sopenharmony_ci ctx->keymode; 8728c2ecf20Sopenharmony_ci info->tfm[1] = AES_TFM_CTR_INIT | AES_TFM_IV_CTR_MODE | AES_TFM_3IV | 8738c2ecf20Sopenharmony_ci AES_TFM_ENC_HASH; 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci memcpy(info->state + ctx->keylen + SIZE_IN_WORDS(AES_BLOCK_SIZE), 8768c2ecf20Sopenharmony_ci req->iv, ivsize); 8778c2ecf20Sopenharmony_ci} 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_cistatic int mtk_aes_gcm_dma(struct mtk_cryp *cryp, struct mtk_aes_rec *aes, 8808c2ecf20Sopenharmony_ci struct scatterlist *src, struct scatterlist *dst, 8818c2ecf20Sopenharmony_ci size_t len) 8828c2ecf20Sopenharmony_ci{ 8838c2ecf20Sopenharmony_ci bool src_aligned, dst_aligned; 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci aes->src.sg = src; 8868c2ecf20Sopenharmony_ci aes->dst.sg = dst; 8878c2ecf20Sopenharmony_ci aes->real_dst = dst; 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci src_aligned = mtk_aes_check_aligned(src, len, &aes->src); 8908c2ecf20Sopenharmony_ci if (src == dst) 8918c2ecf20Sopenharmony_ci dst_aligned = src_aligned; 8928c2ecf20Sopenharmony_ci else 8938c2ecf20Sopenharmony_ci dst_aligned = mtk_aes_check_aligned(dst, len, &aes->dst); 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci if (!src_aligned || !dst_aligned) { 8968c2ecf20Sopenharmony_ci if (aes->total > AES_BUF_SIZE) 8978c2ecf20Sopenharmony_ci return mtk_aes_complete(cryp, aes, -ENOMEM); 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci if (!src_aligned) { 9008c2ecf20Sopenharmony_ci sg_copy_to_buffer(src, sg_nents(src), aes->buf, len); 9018c2ecf20Sopenharmony_ci aes->src.sg = &aes->aligned_sg; 9028c2ecf20Sopenharmony_ci aes->src.nents = 1; 9038c2ecf20Sopenharmony_ci aes->src.remainder = 0; 9048c2ecf20Sopenharmony_ci } 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci if (!dst_aligned) { 9078c2ecf20Sopenharmony_ci aes->dst.sg = &aes->aligned_sg; 9088c2ecf20Sopenharmony_ci aes->dst.nents = 1; 9098c2ecf20Sopenharmony_ci aes->dst.remainder = 0; 9108c2ecf20Sopenharmony_ci } 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci sg_init_table(&aes->aligned_sg, 1); 9138c2ecf20Sopenharmony_ci sg_set_buf(&aes->aligned_sg, aes->buf, aes->total); 9148c2ecf20Sopenharmony_ci } 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci mtk_aes_gcm_info_init(cryp, aes, len); 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci return mtk_aes_map(cryp, aes); 9198c2ecf20Sopenharmony_ci} 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci/* Todo: GMAC */ 9228c2ecf20Sopenharmony_cistatic int mtk_aes_gcm_start(struct mtk_cryp *cryp, struct mtk_aes_rec *aes) 9238c2ecf20Sopenharmony_ci{ 9248c2ecf20Sopenharmony_ci struct mtk_aes_gcm_ctx *gctx = mtk_aes_gcm_ctx_cast(aes->ctx); 9258c2ecf20Sopenharmony_ci struct aead_request *req = aead_request_cast(aes->areq); 9268c2ecf20Sopenharmony_ci struct mtk_aes_reqctx *rctx = aead_request_ctx(req); 9278c2ecf20Sopenharmony_ci u32 len = req->assoclen + req->cryptlen; 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci mtk_aes_set_mode(aes, rctx); 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci if (aes->flags & AES_FLAGS_ENCRYPT) { 9328c2ecf20Sopenharmony_ci u32 tag[4]; 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci aes->resume = mtk_aes_transfer_complete; 9358c2ecf20Sopenharmony_ci /* Compute total process length. */ 9368c2ecf20Sopenharmony_ci aes->total = len + gctx->authsize; 9378c2ecf20Sopenharmony_ci /* Hardware will append authenticated tag to output buffer */ 9388c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(tag, req->dst, len, gctx->authsize, 1); 9398c2ecf20Sopenharmony_ci } else { 9408c2ecf20Sopenharmony_ci aes->resume = mtk_aes_gcm_tag_verify; 9418c2ecf20Sopenharmony_ci aes->total = len; 9428c2ecf20Sopenharmony_ci } 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci return mtk_aes_gcm_dma(cryp, aes, req->src, req->dst, len); 9458c2ecf20Sopenharmony_ci} 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_cistatic int mtk_aes_gcm_crypt(struct aead_request *req, u64 mode) 9488c2ecf20Sopenharmony_ci{ 9498c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); 9508c2ecf20Sopenharmony_ci struct mtk_aes_gcm_ctx *gctx = mtk_aes_gcm_ctx_cast(ctx); 9518c2ecf20Sopenharmony_ci struct mtk_aes_reqctx *rctx = aead_request_ctx(req); 9528c2ecf20Sopenharmony_ci struct mtk_cryp *cryp; 9538c2ecf20Sopenharmony_ci bool enc = !!(mode & AES_FLAGS_ENCRYPT); 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci cryp = mtk_aes_find_dev(ctx); 9568c2ecf20Sopenharmony_ci if (!cryp) 9578c2ecf20Sopenharmony_ci return -ENODEV; 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci /* Compute text length. */ 9608c2ecf20Sopenharmony_ci gctx->textlen = req->cryptlen - (enc ? 0 : gctx->authsize); 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ci /* Empty messages are not supported yet */ 9638c2ecf20Sopenharmony_ci if (!gctx->textlen && !req->assoclen) 9648c2ecf20Sopenharmony_ci return -EINVAL; 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci rctx->mode = AES_FLAGS_GCM | mode; 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci return mtk_aes_handle_queue(cryp, enc, &req->base); 9698c2ecf20Sopenharmony_ci} 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci/* 9728c2ecf20Sopenharmony_ci * Because of the hardware limitation, we need to pre-calculate key(H) 9738c2ecf20Sopenharmony_ci * for the GHASH operation. The result of the encryption operation 9748c2ecf20Sopenharmony_ci * need to be stored in the transform state buffer. 9758c2ecf20Sopenharmony_ci */ 9768c2ecf20Sopenharmony_cistatic int mtk_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key, 9778c2ecf20Sopenharmony_ci u32 keylen) 9788c2ecf20Sopenharmony_ci{ 9798c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx *ctx = crypto_aead_ctx(aead); 9808c2ecf20Sopenharmony_ci union { 9818c2ecf20Sopenharmony_ci u32 x32[SIZE_IN_WORDS(AES_BLOCK_SIZE)]; 9828c2ecf20Sopenharmony_ci u8 x8[AES_BLOCK_SIZE]; 9838c2ecf20Sopenharmony_ci } hash = {}; 9848c2ecf20Sopenharmony_ci struct crypto_aes_ctx aes_ctx; 9858c2ecf20Sopenharmony_ci int err; 9868c2ecf20Sopenharmony_ci int i; 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci switch (keylen) { 9898c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 9908c2ecf20Sopenharmony_ci ctx->keymode = AES_TFM_128BITS; 9918c2ecf20Sopenharmony_ci break; 9928c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 9938c2ecf20Sopenharmony_ci ctx->keymode = AES_TFM_192BITS; 9948c2ecf20Sopenharmony_ci break; 9958c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 9968c2ecf20Sopenharmony_ci ctx->keymode = AES_TFM_256BITS; 9978c2ecf20Sopenharmony_ci break; 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci default: 10008c2ecf20Sopenharmony_ci return -EINVAL; 10018c2ecf20Sopenharmony_ci } 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci ctx->keylen = SIZE_IN_WORDS(keylen); 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci err = aes_expandkey(&aes_ctx, key, keylen); 10068c2ecf20Sopenharmony_ci if (err) 10078c2ecf20Sopenharmony_ci return err; 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci aes_encrypt(&aes_ctx, hash.x8, hash.x8); 10108c2ecf20Sopenharmony_ci memzero_explicit(&aes_ctx, sizeof(aes_ctx)); 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci memcpy(ctx->key, key, keylen); 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci /* Why do we need to do this? */ 10158c2ecf20Sopenharmony_ci for (i = 0; i < SIZE_IN_WORDS(AES_BLOCK_SIZE); i++) 10168c2ecf20Sopenharmony_ci hash.x32[i] = swab32(hash.x32[i]); 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci memcpy(ctx->key + ctx->keylen, &hash, AES_BLOCK_SIZE); 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci return 0; 10218c2ecf20Sopenharmony_ci} 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_cistatic int mtk_aes_gcm_setauthsize(struct crypto_aead *aead, 10248c2ecf20Sopenharmony_ci u32 authsize) 10258c2ecf20Sopenharmony_ci{ 10268c2ecf20Sopenharmony_ci struct mtk_aes_base_ctx *ctx = crypto_aead_ctx(aead); 10278c2ecf20Sopenharmony_ci struct mtk_aes_gcm_ctx *gctx = mtk_aes_gcm_ctx_cast(ctx); 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci /* Same as crypto_gcm_authsize() from crypto/gcm.c */ 10308c2ecf20Sopenharmony_ci switch (authsize) { 10318c2ecf20Sopenharmony_ci case 8: 10328c2ecf20Sopenharmony_ci case 12: 10338c2ecf20Sopenharmony_ci case 16: 10348c2ecf20Sopenharmony_ci break; 10358c2ecf20Sopenharmony_ci default: 10368c2ecf20Sopenharmony_ci return -EINVAL; 10378c2ecf20Sopenharmony_ci } 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci gctx->authsize = authsize; 10408c2ecf20Sopenharmony_ci return 0; 10418c2ecf20Sopenharmony_ci} 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_cistatic int mtk_aes_gcm_encrypt(struct aead_request *req) 10448c2ecf20Sopenharmony_ci{ 10458c2ecf20Sopenharmony_ci return mtk_aes_gcm_crypt(req, AES_FLAGS_ENCRYPT); 10468c2ecf20Sopenharmony_ci} 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_cistatic int mtk_aes_gcm_decrypt(struct aead_request *req) 10498c2ecf20Sopenharmony_ci{ 10508c2ecf20Sopenharmony_ci return mtk_aes_gcm_crypt(req, 0); 10518c2ecf20Sopenharmony_ci} 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_cistatic int mtk_aes_gcm_init(struct crypto_aead *aead) 10548c2ecf20Sopenharmony_ci{ 10558c2ecf20Sopenharmony_ci struct mtk_aes_gcm_ctx *ctx = crypto_aead_ctx(aead); 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ci crypto_aead_set_reqsize(aead, sizeof(struct mtk_aes_reqctx)); 10588c2ecf20Sopenharmony_ci ctx->base.start = mtk_aes_gcm_start; 10598c2ecf20Sopenharmony_ci return 0; 10608c2ecf20Sopenharmony_ci} 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_cistatic struct aead_alg aes_gcm_alg = { 10638c2ecf20Sopenharmony_ci .setkey = mtk_aes_gcm_setkey, 10648c2ecf20Sopenharmony_ci .setauthsize = mtk_aes_gcm_setauthsize, 10658c2ecf20Sopenharmony_ci .encrypt = mtk_aes_gcm_encrypt, 10668c2ecf20Sopenharmony_ci .decrypt = mtk_aes_gcm_decrypt, 10678c2ecf20Sopenharmony_ci .init = mtk_aes_gcm_init, 10688c2ecf20Sopenharmony_ci .ivsize = GCM_AES_IV_SIZE, 10698c2ecf20Sopenharmony_ci .maxauthsize = AES_BLOCK_SIZE, 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci .base = { 10728c2ecf20Sopenharmony_ci .cra_name = "gcm(aes)", 10738c2ecf20Sopenharmony_ci .cra_driver_name = "gcm-aes-mtk", 10748c2ecf20Sopenharmony_ci .cra_priority = 400, 10758c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC, 10768c2ecf20Sopenharmony_ci .cra_blocksize = 1, 10778c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct mtk_aes_gcm_ctx), 10788c2ecf20Sopenharmony_ci .cra_alignmask = 0xf, 10798c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 10808c2ecf20Sopenharmony_ci }, 10818c2ecf20Sopenharmony_ci}; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_cistatic void mtk_aes_queue_task(unsigned long data) 10848c2ecf20Sopenharmony_ci{ 10858c2ecf20Sopenharmony_ci struct mtk_aes_rec *aes = (struct mtk_aes_rec *)data; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci mtk_aes_handle_queue(aes->cryp, aes->id, NULL); 10888c2ecf20Sopenharmony_ci} 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_cistatic void mtk_aes_done_task(unsigned long data) 10918c2ecf20Sopenharmony_ci{ 10928c2ecf20Sopenharmony_ci struct mtk_aes_rec *aes = (struct mtk_aes_rec *)data; 10938c2ecf20Sopenharmony_ci struct mtk_cryp *cryp = aes->cryp; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci mtk_aes_unmap(cryp, aes); 10968c2ecf20Sopenharmony_ci aes->resume(cryp, aes); 10978c2ecf20Sopenharmony_ci} 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_cistatic irqreturn_t mtk_aes_irq(int irq, void *dev_id) 11008c2ecf20Sopenharmony_ci{ 11018c2ecf20Sopenharmony_ci struct mtk_aes_rec *aes = (struct mtk_aes_rec *)dev_id; 11028c2ecf20Sopenharmony_ci struct mtk_cryp *cryp = aes->cryp; 11038c2ecf20Sopenharmony_ci u32 val = mtk_aes_read(cryp, RDR_STAT(aes->id)); 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci mtk_aes_write(cryp, RDR_STAT(aes->id), val); 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci if (likely(AES_FLAGS_BUSY & aes->flags)) { 11088c2ecf20Sopenharmony_ci mtk_aes_write(cryp, RDR_PROC_COUNT(aes->id), MTK_CNT_RST); 11098c2ecf20Sopenharmony_ci mtk_aes_write(cryp, RDR_THRESH(aes->id), 11108c2ecf20Sopenharmony_ci MTK_RDR_PROC_THRESH | MTK_RDR_PROC_MODE); 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci tasklet_schedule(&aes->done_task); 11138c2ecf20Sopenharmony_ci } else { 11148c2ecf20Sopenharmony_ci dev_warn(cryp->dev, "AES interrupt when no active requests.\n"); 11158c2ecf20Sopenharmony_ci } 11168c2ecf20Sopenharmony_ci return IRQ_HANDLED; 11178c2ecf20Sopenharmony_ci} 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci/* 11208c2ecf20Sopenharmony_ci * The purpose of creating encryption and decryption records is 11218c2ecf20Sopenharmony_ci * to process outbound/inbound data in parallel, it can improve 11228c2ecf20Sopenharmony_ci * performance in most use cases, such as IPSec VPN, especially 11238c2ecf20Sopenharmony_ci * under heavy network traffic. 11248c2ecf20Sopenharmony_ci */ 11258c2ecf20Sopenharmony_cistatic int mtk_aes_record_init(struct mtk_cryp *cryp) 11268c2ecf20Sopenharmony_ci{ 11278c2ecf20Sopenharmony_ci struct mtk_aes_rec **aes = cryp->aes; 11288c2ecf20Sopenharmony_ci int i, err = -ENOMEM; 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci for (i = 0; i < MTK_REC_NUM; i++) { 11318c2ecf20Sopenharmony_ci aes[i] = kzalloc(sizeof(**aes), GFP_KERNEL); 11328c2ecf20Sopenharmony_ci if (!aes[i]) 11338c2ecf20Sopenharmony_ci goto err_cleanup; 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci aes[i]->buf = (void *)__get_free_pages(GFP_KERNEL, 11368c2ecf20Sopenharmony_ci AES_BUF_ORDER); 11378c2ecf20Sopenharmony_ci if (!aes[i]->buf) 11388c2ecf20Sopenharmony_ci goto err_cleanup; 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci aes[i]->cryp = cryp; 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci spin_lock_init(&aes[i]->lock); 11438c2ecf20Sopenharmony_ci crypto_init_queue(&aes[i]->queue, AES_QUEUE_SIZE); 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci tasklet_init(&aes[i]->queue_task, mtk_aes_queue_task, 11468c2ecf20Sopenharmony_ci (unsigned long)aes[i]); 11478c2ecf20Sopenharmony_ci tasklet_init(&aes[i]->done_task, mtk_aes_done_task, 11488c2ecf20Sopenharmony_ci (unsigned long)aes[i]); 11498c2ecf20Sopenharmony_ci } 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci /* Link to ring0 and ring1 respectively */ 11528c2ecf20Sopenharmony_ci aes[0]->id = MTK_RING0; 11538c2ecf20Sopenharmony_ci aes[1]->id = MTK_RING1; 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci return 0; 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_cierr_cleanup: 11588c2ecf20Sopenharmony_ci for (; i--; ) { 11598c2ecf20Sopenharmony_ci free_page((unsigned long)aes[i]->buf); 11608c2ecf20Sopenharmony_ci kfree(aes[i]); 11618c2ecf20Sopenharmony_ci } 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci return err; 11648c2ecf20Sopenharmony_ci} 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_cistatic void mtk_aes_record_free(struct mtk_cryp *cryp) 11678c2ecf20Sopenharmony_ci{ 11688c2ecf20Sopenharmony_ci int i; 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci for (i = 0; i < MTK_REC_NUM; i++) { 11718c2ecf20Sopenharmony_ci tasklet_kill(&cryp->aes[i]->done_task); 11728c2ecf20Sopenharmony_ci tasklet_kill(&cryp->aes[i]->queue_task); 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci free_page((unsigned long)cryp->aes[i]->buf); 11758c2ecf20Sopenharmony_ci kfree(cryp->aes[i]); 11768c2ecf20Sopenharmony_ci } 11778c2ecf20Sopenharmony_ci} 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_cistatic void mtk_aes_unregister_algs(void) 11808c2ecf20Sopenharmony_ci{ 11818c2ecf20Sopenharmony_ci int i; 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci crypto_unregister_aead(&aes_gcm_alg); 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(aes_algs); i++) 11868c2ecf20Sopenharmony_ci crypto_unregister_skcipher(&aes_algs[i]); 11878c2ecf20Sopenharmony_ci} 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_cistatic int mtk_aes_register_algs(void) 11908c2ecf20Sopenharmony_ci{ 11918c2ecf20Sopenharmony_ci int err, i; 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(aes_algs); i++) { 11948c2ecf20Sopenharmony_ci err = crypto_register_skcipher(&aes_algs[i]); 11958c2ecf20Sopenharmony_ci if (err) 11968c2ecf20Sopenharmony_ci goto err_aes_algs; 11978c2ecf20Sopenharmony_ci } 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci err = crypto_register_aead(&aes_gcm_alg); 12008c2ecf20Sopenharmony_ci if (err) 12018c2ecf20Sopenharmony_ci goto err_aes_algs; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci return 0; 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_cierr_aes_algs: 12068c2ecf20Sopenharmony_ci for (; i--; ) 12078c2ecf20Sopenharmony_ci crypto_unregister_skcipher(&aes_algs[i]); 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci return err; 12108c2ecf20Sopenharmony_ci} 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ciint mtk_cipher_alg_register(struct mtk_cryp *cryp) 12138c2ecf20Sopenharmony_ci{ 12148c2ecf20Sopenharmony_ci int ret; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&cryp->aes_list); 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci /* Initialize two cipher records */ 12198c2ecf20Sopenharmony_ci ret = mtk_aes_record_init(cryp); 12208c2ecf20Sopenharmony_ci if (ret) 12218c2ecf20Sopenharmony_ci goto err_record; 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci ret = devm_request_irq(cryp->dev, cryp->irq[MTK_RING0], mtk_aes_irq, 12248c2ecf20Sopenharmony_ci 0, "mtk-aes", cryp->aes[0]); 12258c2ecf20Sopenharmony_ci if (ret) { 12268c2ecf20Sopenharmony_ci dev_err(cryp->dev, "unable to request AES irq.\n"); 12278c2ecf20Sopenharmony_ci goto err_res; 12288c2ecf20Sopenharmony_ci } 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci ret = devm_request_irq(cryp->dev, cryp->irq[MTK_RING1], mtk_aes_irq, 12318c2ecf20Sopenharmony_ci 0, "mtk-aes", cryp->aes[1]); 12328c2ecf20Sopenharmony_ci if (ret) { 12338c2ecf20Sopenharmony_ci dev_err(cryp->dev, "unable to request AES irq.\n"); 12348c2ecf20Sopenharmony_ci goto err_res; 12358c2ecf20Sopenharmony_ci } 12368c2ecf20Sopenharmony_ci 12378c2ecf20Sopenharmony_ci /* Enable ring0 and ring1 interrupt */ 12388c2ecf20Sopenharmony_ci mtk_aes_write(cryp, AIC_ENABLE_SET(MTK_RING0), MTK_IRQ_RDR0); 12398c2ecf20Sopenharmony_ci mtk_aes_write(cryp, AIC_ENABLE_SET(MTK_RING1), MTK_IRQ_RDR1); 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci spin_lock(&mtk_aes.lock); 12428c2ecf20Sopenharmony_ci list_add_tail(&cryp->aes_list, &mtk_aes.dev_list); 12438c2ecf20Sopenharmony_ci spin_unlock(&mtk_aes.lock); 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci ret = mtk_aes_register_algs(); 12468c2ecf20Sopenharmony_ci if (ret) 12478c2ecf20Sopenharmony_ci goto err_algs; 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci return 0; 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_cierr_algs: 12528c2ecf20Sopenharmony_ci spin_lock(&mtk_aes.lock); 12538c2ecf20Sopenharmony_ci list_del(&cryp->aes_list); 12548c2ecf20Sopenharmony_ci spin_unlock(&mtk_aes.lock); 12558c2ecf20Sopenharmony_cierr_res: 12568c2ecf20Sopenharmony_ci mtk_aes_record_free(cryp); 12578c2ecf20Sopenharmony_cierr_record: 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci dev_err(cryp->dev, "mtk-aes initialization failed.\n"); 12608c2ecf20Sopenharmony_ci return ret; 12618c2ecf20Sopenharmony_ci} 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_civoid mtk_cipher_alg_release(struct mtk_cryp *cryp) 12648c2ecf20Sopenharmony_ci{ 12658c2ecf20Sopenharmony_ci spin_lock(&mtk_aes.lock); 12668c2ecf20Sopenharmony_ci list_del(&cryp->aes_list); 12678c2ecf20Sopenharmony_ci spin_unlock(&mtk_aes.lock); 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci mtk_aes_unregister_algs(); 12708c2ecf20Sopenharmony_ci mtk_aes_record_free(cryp); 12718c2ecf20Sopenharmony_ci} 1272