18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright (c) 2016-2017 Hisilicon Limited. */ 38c2ecf20Sopenharmony_ci#include <linux/crypto.h> 48c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 58c2ecf20Sopenharmony_ci#include <linux/dmapool.h> 68c2ecf20Sopenharmony_ci#include <linux/module.h> 78c2ecf20Sopenharmony_ci#include <linux/mutex.h> 88c2ecf20Sopenharmony_ci#include <linux/slab.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <crypto/aes.h> 118c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 128c2ecf20Sopenharmony_ci#include <crypto/internal/des.h> 138c2ecf20Sopenharmony_ci#include <crypto/skcipher.h> 148c2ecf20Sopenharmony_ci#include <crypto/xts.h> 158c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "sec_drv.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define SEC_MAX_CIPHER_KEY 64 208c2ecf20Sopenharmony_ci#define SEC_REQ_LIMIT SZ_32M 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistruct sec_c_alg_cfg { 238c2ecf20Sopenharmony_ci unsigned c_alg : 3; 248c2ecf20Sopenharmony_ci unsigned c_mode : 3; 258c2ecf20Sopenharmony_ci unsigned key_len : 2; 268c2ecf20Sopenharmony_ci unsigned c_width : 2; 278c2ecf20Sopenharmony_ci}; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic const struct sec_c_alg_cfg sec_c_alg_cfgs[] = { 308c2ecf20Sopenharmony_ci [SEC_C_DES_ECB_64] = { 318c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_DES, 328c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_ECB, 338c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_DES, 348c2ecf20Sopenharmony_ci }, 358c2ecf20Sopenharmony_ci [SEC_C_DES_CBC_64] = { 368c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_DES, 378c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_CBC, 388c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_DES, 398c2ecf20Sopenharmony_ci }, 408c2ecf20Sopenharmony_ci [SEC_C_3DES_ECB_192_3KEY] = { 418c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_3DES, 428c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_ECB, 438c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_3DES_3_KEY, 448c2ecf20Sopenharmony_ci }, 458c2ecf20Sopenharmony_ci [SEC_C_3DES_ECB_192_2KEY] = { 468c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_3DES, 478c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_ECB, 488c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_3DES_2_KEY, 498c2ecf20Sopenharmony_ci }, 508c2ecf20Sopenharmony_ci [SEC_C_3DES_CBC_192_3KEY] = { 518c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_3DES, 528c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_CBC, 538c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_3DES_3_KEY, 548c2ecf20Sopenharmony_ci }, 558c2ecf20Sopenharmony_ci [SEC_C_3DES_CBC_192_2KEY] = { 568c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_3DES, 578c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_CBC, 588c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_3DES_2_KEY, 598c2ecf20Sopenharmony_ci }, 608c2ecf20Sopenharmony_ci [SEC_C_AES_ECB_128] = { 618c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_AES, 628c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_ECB, 638c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_AES_128, 648c2ecf20Sopenharmony_ci }, 658c2ecf20Sopenharmony_ci [SEC_C_AES_ECB_192] = { 668c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_AES, 678c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_ECB, 688c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_AES_192, 698c2ecf20Sopenharmony_ci }, 708c2ecf20Sopenharmony_ci [SEC_C_AES_ECB_256] = { 718c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_AES, 728c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_ECB, 738c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_AES_256, 748c2ecf20Sopenharmony_ci }, 758c2ecf20Sopenharmony_ci [SEC_C_AES_CBC_128] = { 768c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_AES, 778c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_CBC, 788c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_AES_128, 798c2ecf20Sopenharmony_ci }, 808c2ecf20Sopenharmony_ci [SEC_C_AES_CBC_192] = { 818c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_AES, 828c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_CBC, 838c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_AES_192, 848c2ecf20Sopenharmony_ci }, 858c2ecf20Sopenharmony_ci [SEC_C_AES_CBC_256] = { 868c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_AES, 878c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_CBC, 888c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_AES_256, 898c2ecf20Sopenharmony_ci }, 908c2ecf20Sopenharmony_ci [SEC_C_AES_CTR_128] = { 918c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_AES, 928c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_CTR, 938c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_AES_128, 948c2ecf20Sopenharmony_ci }, 958c2ecf20Sopenharmony_ci [SEC_C_AES_CTR_192] = { 968c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_AES, 978c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_CTR, 988c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_AES_192, 998c2ecf20Sopenharmony_ci }, 1008c2ecf20Sopenharmony_ci [SEC_C_AES_CTR_256] = { 1018c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_AES, 1028c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_CTR, 1038c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_AES_256, 1048c2ecf20Sopenharmony_ci }, 1058c2ecf20Sopenharmony_ci [SEC_C_AES_XTS_128] = { 1068c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_AES, 1078c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_XTS, 1088c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_AES_128, 1098c2ecf20Sopenharmony_ci }, 1108c2ecf20Sopenharmony_ci [SEC_C_AES_XTS_256] = { 1118c2ecf20Sopenharmony_ci .c_alg = SEC_C_ALG_AES, 1128c2ecf20Sopenharmony_ci .c_mode = SEC_C_MODE_XTS, 1138c2ecf20Sopenharmony_ci .key_len = SEC_KEY_LEN_AES_256, 1148c2ecf20Sopenharmony_ci }, 1158c2ecf20Sopenharmony_ci [SEC_C_NULL] = { 1168c2ecf20Sopenharmony_ci }, 1178c2ecf20Sopenharmony_ci}; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/* 1208c2ecf20Sopenharmony_ci * Mutex used to ensure safe operation of reference count of 1218c2ecf20Sopenharmony_ci * alg providers 1228c2ecf20Sopenharmony_ci */ 1238c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(algs_lock); 1248c2ecf20Sopenharmony_cistatic unsigned int active_devs; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistatic void sec_alg_skcipher_init_template(struct sec_alg_tfm_ctx *ctx, 1278c2ecf20Sopenharmony_ci struct sec_bd_info *req, 1288c2ecf20Sopenharmony_ci enum sec_cipher_alg alg) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci const struct sec_c_alg_cfg *cfg = &sec_c_alg_cfgs[alg]; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci memset(req, 0, sizeof(*req)); 1338c2ecf20Sopenharmony_ci req->w0 |= cfg->c_mode << SEC_BD_W0_C_MODE_S; 1348c2ecf20Sopenharmony_ci req->w1 |= cfg->c_alg << SEC_BD_W1_C_ALG_S; 1358c2ecf20Sopenharmony_ci req->w3 |= cfg->key_len << SEC_BD_W3_C_KEY_LEN_S; 1368c2ecf20Sopenharmony_ci req->w0 |= cfg->c_width << SEC_BD_W0_C_WIDTH_S; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci req->cipher_key_addr_lo = lower_32_bits(ctx->pkey); 1398c2ecf20Sopenharmony_ci req->cipher_key_addr_hi = upper_32_bits(ctx->pkey); 1408c2ecf20Sopenharmony_ci} 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic void sec_alg_skcipher_init_context(struct crypto_skcipher *atfm, 1438c2ecf20Sopenharmony_ci const u8 *key, 1448c2ecf20Sopenharmony_ci unsigned int keylen, 1458c2ecf20Sopenharmony_ci enum sec_cipher_alg alg) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_skcipher_tfm(atfm); 1488c2ecf20Sopenharmony_ci struct sec_alg_tfm_ctx *ctx = crypto_tfm_ctx(tfm); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci ctx->cipher_alg = alg; 1518c2ecf20Sopenharmony_ci memcpy(ctx->key, key, keylen); 1528c2ecf20Sopenharmony_ci sec_alg_skcipher_init_template(ctx, &ctx->req_template, 1538c2ecf20Sopenharmony_ci ctx->cipher_alg); 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic void sec_free_hw_sgl(struct sec_hw_sgl *hw_sgl, 1578c2ecf20Sopenharmony_ci dma_addr_t psec_sgl, struct sec_dev_info *info) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci struct sec_hw_sgl *sgl_current, *sgl_next; 1608c2ecf20Sopenharmony_ci dma_addr_t sgl_next_dma; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci sgl_current = hw_sgl; 1638c2ecf20Sopenharmony_ci while (sgl_current) { 1648c2ecf20Sopenharmony_ci sgl_next = sgl_current->next; 1658c2ecf20Sopenharmony_ci sgl_next_dma = sgl_current->next_sgl; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci dma_pool_free(info->hw_sgl_pool, sgl_current, psec_sgl); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci sgl_current = sgl_next; 1708c2ecf20Sopenharmony_ci psec_sgl = sgl_next_dma; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic int sec_alloc_and_fill_hw_sgl(struct sec_hw_sgl **sec_sgl, 1758c2ecf20Sopenharmony_ci dma_addr_t *psec_sgl, 1768c2ecf20Sopenharmony_ci struct scatterlist *sgl, 1778c2ecf20Sopenharmony_ci int count, 1788c2ecf20Sopenharmony_ci struct sec_dev_info *info, 1798c2ecf20Sopenharmony_ci gfp_t gfp) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci struct sec_hw_sgl *sgl_current = NULL; 1828c2ecf20Sopenharmony_ci struct sec_hw_sgl *sgl_next; 1838c2ecf20Sopenharmony_ci dma_addr_t sgl_next_dma; 1848c2ecf20Sopenharmony_ci struct scatterlist *sg; 1858c2ecf20Sopenharmony_ci int ret, sge_index, i; 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci if (!count) 1888c2ecf20Sopenharmony_ci return -EINVAL; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci for_each_sg(sgl, sg, count, i) { 1918c2ecf20Sopenharmony_ci sge_index = i % SEC_MAX_SGE_NUM; 1928c2ecf20Sopenharmony_ci if (sge_index == 0) { 1938c2ecf20Sopenharmony_ci sgl_next = dma_pool_zalloc(info->hw_sgl_pool, 1948c2ecf20Sopenharmony_ci gfp, &sgl_next_dma); 1958c2ecf20Sopenharmony_ci if (!sgl_next) { 1968c2ecf20Sopenharmony_ci ret = -ENOMEM; 1978c2ecf20Sopenharmony_ci goto err_free_hw_sgls; 1988c2ecf20Sopenharmony_ci } 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci if (!sgl_current) { /* First one */ 2018c2ecf20Sopenharmony_ci *psec_sgl = sgl_next_dma; 2028c2ecf20Sopenharmony_ci *sec_sgl = sgl_next; 2038c2ecf20Sopenharmony_ci } else { /* Chained */ 2048c2ecf20Sopenharmony_ci sgl_current->entry_sum_in_sgl = SEC_MAX_SGE_NUM; 2058c2ecf20Sopenharmony_ci sgl_current->next_sgl = sgl_next_dma; 2068c2ecf20Sopenharmony_ci sgl_current->next = sgl_next; 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci sgl_current = sgl_next; 2098c2ecf20Sopenharmony_ci } 2108c2ecf20Sopenharmony_ci sgl_current->sge_entries[sge_index].buf = sg_dma_address(sg); 2118c2ecf20Sopenharmony_ci sgl_current->sge_entries[sge_index].len = sg_dma_len(sg); 2128c2ecf20Sopenharmony_ci sgl_current->data_bytes_in_sgl += sg_dma_len(sg); 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci sgl_current->entry_sum_in_sgl = count % SEC_MAX_SGE_NUM; 2158c2ecf20Sopenharmony_ci sgl_current->next_sgl = 0; 2168c2ecf20Sopenharmony_ci (*sec_sgl)->entry_sum_in_chain = count; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci return 0; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cierr_free_hw_sgls: 2218c2ecf20Sopenharmony_ci sec_free_hw_sgl(*sec_sgl, *psec_sgl, info); 2228c2ecf20Sopenharmony_ci *psec_sgl = 0; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci return ret; 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_setkey(struct crypto_skcipher *tfm, 2288c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen, 2298c2ecf20Sopenharmony_ci enum sec_cipher_alg alg) 2308c2ecf20Sopenharmony_ci{ 2318c2ecf20Sopenharmony_ci struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); 2328c2ecf20Sopenharmony_ci struct device *dev = ctx->queue->dev_info->dev; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci mutex_lock(&ctx->lock); 2358c2ecf20Sopenharmony_ci if (ctx->key) { 2368c2ecf20Sopenharmony_ci /* rekeying */ 2378c2ecf20Sopenharmony_ci memset(ctx->key, 0, SEC_MAX_CIPHER_KEY); 2388c2ecf20Sopenharmony_ci } else { 2398c2ecf20Sopenharmony_ci /* new key */ 2408c2ecf20Sopenharmony_ci ctx->key = dma_alloc_coherent(dev, SEC_MAX_CIPHER_KEY, 2418c2ecf20Sopenharmony_ci &ctx->pkey, GFP_KERNEL); 2428c2ecf20Sopenharmony_ci if (!ctx->key) { 2438c2ecf20Sopenharmony_ci mutex_unlock(&ctx->lock); 2448c2ecf20Sopenharmony_ci return -ENOMEM; 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci } 2478c2ecf20Sopenharmony_ci mutex_unlock(&ctx->lock); 2488c2ecf20Sopenharmony_ci sec_alg_skcipher_init_context(tfm, key, keylen, alg); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci return 0; 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_setkey_aes_ecb(struct crypto_skcipher *tfm, 2548c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci enum sec_cipher_alg alg; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci switch (keylen) { 2598c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 2608c2ecf20Sopenharmony_ci alg = SEC_C_AES_ECB_128; 2618c2ecf20Sopenharmony_ci break; 2628c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 2638c2ecf20Sopenharmony_ci alg = SEC_C_AES_ECB_192; 2648c2ecf20Sopenharmony_ci break; 2658c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 2668c2ecf20Sopenharmony_ci alg = SEC_C_AES_ECB_256; 2678c2ecf20Sopenharmony_ci break; 2688c2ecf20Sopenharmony_ci default: 2698c2ecf20Sopenharmony_ci return -EINVAL; 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci return sec_alg_skcipher_setkey(tfm, key, keylen, alg); 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_setkey_aes_cbc(struct crypto_skcipher *tfm, 2768c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 2778c2ecf20Sopenharmony_ci{ 2788c2ecf20Sopenharmony_ci enum sec_cipher_alg alg; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci switch (keylen) { 2818c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 2828c2ecf20Sopenharmony_ci alg = SEC_C_AES_CBC_128; 2838c2ecf20Sopenharmony_ci break; 2848c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 2858c2ecf20Sopenharmony_ci alg = SEC_C_AES_CBC_192; 2868c2ecf20Sopenharmony_ci break; 2878c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 2888c2ecf20Sopenharmony_ci alg = SEC_C_AES_CBC_256; 2898c2ecf20Sopenharmony_ci break; 2908c2ecf20Sopenharmony_ci default: 2918c2ecf20Sopenharmony_ci return -EINVAL; 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci return sec_alg_skcipher_setkey(tfm, key, keylen, alg); 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_setkey_aes_ctr(struct crypto_skcipher *tfm, 2988c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci enum sec_cipher_alg alg; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci switch (keylen) { 3038c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 3048c2ecf20Sopenharmony_ci alg = SEC_C_AES_CTR_128; 3058c2ecf20Sopenharmony_ci break; 3068c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 3078c2ecf20Sopenharmony_ci alg = SEC_C_AES_CTR_192; 3088c2ecf20Sopenharmony_ci break; 3098c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 3108c2ecf20Sopenharmony_ci alg = SEC_C_AES_CTR_256; 3118c2ecf20Sopenharmony_ci break; 3128c2ecf20Sopenharmony_ci default: 3138c2ecf20Sopenharmony_ci return -EINVAL; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci return sec_alg_skcipher_setkey(tfm, key, keylen, alg); 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_setkey_aes_xts(struct crypto_skcipher *tfm, 3208c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci enum sec_cipher_alg alg; 3238c2ecf20Sopenharmony_ci int ret; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci ret = xts_verify_key(tfm, key, keylen); 3268c2ecf20Sopenharmony_ci if (ret) 3278c2ecf20Sopenharmony_ci return ret; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci switch (keylen) { 3308c2ecf20Sopenharmony_ci case AES_KEYSIZE_128 * 2: 3318c2ecf20Sopenharmony_ci alg = SEC_C_AES_XTS_128; 3328c2ecf20Sopenharmony_ci break; 3338c2ecf20Sopenharmony_ci case AES_KEYSIZE_256 * 2: 3348c2ecf20Sopenharmony_ci alg = SEC_C_AES_XTS_256; 3358c2ecf20Sopenharmony_ci break; 3368c2ecf20Sopenharmony_ci default: 3378c2ecf20Sopenharmony_ci return -EINVAL; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci return sec_alg_skcipher_setkey(tfm, key, keylen, alg); 3418c2ecf20Sopenharmony_ci} 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_setkey_des_ecb(struct crypto_skcipher *tfm, 3448c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci return verify_skcipher_des_key(tfm, key) ?: 3478c2ecf20Sopenharmony_ci sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_DES_ECB_64); 3488c2ecf20Sopenharmony_ci} 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_setkey_des_cbc(struct crypto_skcipher *tfm, 3518c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci return verify_skcipher_des_key(tfm, key) ?: 3548c2ecf20Sopenharmony_ci sec_alg_skcipher_setkey(tfm, key, keylen, SEC_C_DES_CBC_64); 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_setkey_3des_ecb(struct crypto_skcipher *tfm, 3588c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci return verify_skcipher_des3_key(tfm, key) ?: 3618c2ecf20Sopenharmony_ci sec_alg_skcipher_setkey(tfm, key, keylen, 3628c2ecf20Sopenharmony_ci SEC_C_3DES_ECB_192_3KEY); 3638c2ecf20Sopenharmony_ci} 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_setkey_3des_cbc(struct crypto_skcipher *tfm, 3668c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 3678c2ecf20Sopenharmony_ci{ 3688c2ecf20Sopenharmony_ci return verify_skcipher_des3_key(tfm, key) ?: 3698c2ecf20Sopenharmony_ci sec_alg_skcipher_setkey(tfm, key, keylen, 3708c2ecf20Sopenharmony_ci SEC_C_3DES_CBC_192_3KEY); 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cistatic void sec_alg_free_el(struct sec_request_el *el, 3748c2ecf20Sopenharmony_ci struct sec_dev_info *info) 3758c2ecf20Sopenharmony_ci{ 3768c2ecf20Sopenharmony_ci sec_free_hw_sgl(el->out, el->dma_out, info); 3778c2ecf20Sopenharmony_ci sec_free_hw_sgl(el->in, el->dma_in, info); 3788c2ecf20Sopenharmony_ci kfree(el->sgl_in); 3798c2ecf20Sopenharmony_ci kfree(el->sgl_out); 3808c2ecf20Sopenharmony_ci kfree(el); 3818c2ecf20Sopenharmony_ci} 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci/* queuelock must be held */ 3848c2ecf20Sopenharmony_cistatic int sec_send_request(struct sec_request *sec_req, struct sec_queue *queue) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci struct sec_request_el *el, *temp; 3878c2ecf20Sopenharmony_ci int ret = 0; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci mutex_lock(&sec_req->lock); 3908c2ecf20Sopenharmony_ci list_for_each_entry_safe(el, temp, &sec_req->elements, head) { 3918c2ecf20Sopenharmony_ci /* 3928c2ecf20Sopenharmony_ci * Add to hardware queue only under following circumstances 3938c2ecf20Sopenharmony_ci * 1) Software and hardware queue empty so no chain dependencies 3948c2ecf20Sopenharmony_ci * 2) No dependencies as new IV - (check software queue empty 3958c2ecf20Sopenharmony_ci * to maintain order) 3968c2ecf20Sopenharmony_ci * 3) No dependencies because the mode does no chaining. 3978c2ecf20Sopenharmony_ci * 3988c2ecf20Sopenharmony_ci * In other cases first insert onto the software queue which 3998c2ecf20Sopenharmony_ci * is then emptied as requests complete 4008c2ecf20Sopenharmony_ci */ 4018c2ecf20Sopenharmony_ci if (!queue->havesoftqueue || 4028c2ecf20Sopenharmony_ci (kfifo_is_empty(&queue->softqueue) && 4038c2ecf20Sopenharmony_ci sec_queue_empty(queue))) { 4048c2ecf20Sopenharmony_ci ret = sec_queue_send(queue, &el->req, sec_req); 4058c2ecf20Sopenharmony_ci if (ret == -EAGAIN) { 4068c2ecf20Sopenharmony_ci /* Wait unti we can send then try again */ 4078c2ecf20Sopenharmony_ci /* DEAD if here - should not happen */ 4088c2ecf20Sopenharmony_ci ret = -EBUSY; 4098c2ecf20Sopenharmony_ci goto err_unlock; 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci } else { 4128c2ecf20Sopenharmony_ci kfifo_put(&queue->softqueue, el); 4138c2ecf20Sopenharmony_ci } 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_cierr_unlock: 4168c2ecf20Sopenharmony_ci mutex_unlock(&sec_req->lock); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci return ret; 4198c2ecf20Sopenharmony_ci} 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cistatic void sec_skcipher_alg_callback(struct sec_bd_info *sec_resp, 4228c2ecf20Sopenharmony_ci struct crypto_async_request *req_base) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci struct skcipher_request *skreq = container_of(req_base, 4258c2ecf20Sopenharmony_ci struct skcipher_request, 4268c2ecf20Sopenharmony_ci base); 4278c2ecf20Sopenharmony_ci struct sec_request *sec_req = skcipher_request_ctx(skreq); 4288c2ecf20Sopenharmony_ci struct sec_request *backlog_req; 4298c2ecf20Sopenharmony_ci struct sec_request_el *sec_req_el, *nextrequest; 4308c2ecf20Sopenharmony_ci struct sec_alg_tfm_ctx *ctx = sec_req->tfm_ctx; 4318c2ecf20Sopenharmony_ci struct crypto_skcipher *atfm = crypto_skcipher_reqtfm(skreq); 4328c2ecf20Sopenharmony_ci struct device *dev = ctx->queue->dev_info->dev; 4338c2ecf20Sopenharmony_ci int icv_or_skey_en, ret; 4348c2ecf20Sopenharmony_ci bool done; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci sec_req_el = list_first_entry(&sec_req->elements, struct sec_request_el, 4378c2ecf20Sopenharmony_ci head); 4388c2ecf20Sopenharmony_ci icv_or_skey_en = (sec_resp->w0 & SEC_BD_W0_ICV_OR_SKEY_EN_M) >> 4398c2ecf20Sopenharmony_ci SEC_BD_W0_ICV_OR_SKEY_EN_S; 4408c2ecf20Sopenharmony_ci if (sec_resp->w1 & SEC_BD_W1_BD_INVALID || icv_or_skey_en == 3) { 4418c2ecf20Sopenharmony_ci dev_err(dev, "Got an invalid answer %lu %d\n", 4428c2ecf20Sopenharmony_ci sec_resp->w1 & SEC_BD_W1_BD_INVALID, 4438c2ecf20Sopenharmony_ci icv_or_skey_en); 4448c2ecf20Sopenharmony_ci sec_req->err = -EINVAL; 4458c2ecf20Sopenharmony_ci /* 4468c2ecf20Sopenharmony_ci * We need to muddle on to avoid getting stuck with elements 4478c2ecf20Sopenharmony_ci * on the queue. Error will be reported so requester so 4488c2ecf20Sopenharmony_ci * it should be able to handle appropriately. 4498c2ecf20Sopenharmony_ci */ 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci spin_lock_bh(&ctx->queue->queuelock); 4538c2ecf20Sopenharmony_ci /* Put the IV in place for chained cases */ 4548c2ecf20Sopenharmony_ci switch (ctx->cipher_alg) { 4558c2ecf20Sopenharmony_ci case SEC_C_AES_CBC_128: 4568c2ecf20Sopenharmony_ci case SEC_C_AES_CBC_192: 4578c2ecf20Sopenharmony_ci case SEC_C_AES_CBC_256: 4588c2ecf20Sopenharmony_ci if (sec_req_el->req.w0 & SEC_BD_W0_DE) 4598c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(sec_req_el->sgl_out, 4608c2ecf20Sopenharmony_ci sg_nents(sec_req_el->sgl_out), 4618c2ecf20Sopenharmony_ci skreq->iv, 4628c2ecf20Sopenharmony_ci crypto_skcipher_ivsize(atfm), 4638c2ecf20Sopenharmony_ci sec_req_el->el_length - 4648c2ecf20Sopenharmony_ci crypto_skcipher_ivsize(atfm)); 4658c2ecf20Sopenharmony_ci else 4668c2ecf20Sopenharmony_ci sg_pcopy_to_buffer(sec_req_el->sgl_in, 4678c2ecf20Sopenharmony_ci sg_nents(sec_req_el->sgl_in), 4688c2ecf20Sopenharmony_ci skreq->iv, 4698c2ecf20Sopenharmony_ci crypto_skcipher_ivsize(atfm), 4708c2ecf20Sopenharmony_ci sec_req_el->el_length - 4718c2ecf20Sopenharmony_ci crypto_skcipher_ivsize(atfm)); 4728c2ecf20Sopenharmony_ci /* No need to sync to the device as coherent DMA */ 4738c2ecf20Sopenharmony_ci break; 4748c2ecf20Sopenharmony_ci case SEC_C_AES_CTR_128: 4758c2ecf20Sopenharmony_ci case SEC_C_AES_CTR_192: 4768c2ecf20Sopenharmony_ci case SEC_C_AES_CTR_256: 4778c2ecf20Sopenharmony_ci crypto_inc(skreq->iv, 16); 4788c2ecf20Sopenharmony_ci break; 4798c2ecf20Sopenharmony_ci default: 4808c2ecf20Sopenharmony_ci /* Do not update */ 4818c2ecf20Sopenharmony_ci break; 4828c2ecf20Sopenharmony_ci } 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci if (ctx->queue->havesoftqueue && 4858c2ecf20Sopenharmony_ci !kfifo_is_empty(&ctx->queue->softqueue) && 4868c2ecf20Sopenharmony_ci sec_queue_empty(ctx->queue)) { 4878c2ecf20Sopenharmony_ci ret = kfifo_get(&ctx->queue->softqueue, &nextrequest); 4888c2ecf20Sopenharmony_ci if (ret <= 0) 4898c2ecf20Sopenharmony_ci dev_err(dev, 4908c2ecf20Sopenharmony_ci "Error getting next element from kfifo %d\n", 4918c2ecf20Sopenharmony_ci ret); 4928c2ecf20Sopenharmony_ci else 4938c2ecf20Sopenharmony_ci /* We know there is space so this cannot fail */ 4948c2ecf20Sopenharmony_ci sec_queue_send(ctx->queue, &nextrequest->req, 4958c2ecf20Sopenharmony_ci nextrequest->sec_req); 4968c2ecf20Sopenharmony_ci } else if (!list_empty(&ctx->backlog)) { 4978c2ecf20Sopenharmony_ci /* Need to verify there is room first */ 4988c2ecf20Sopenharmony_ci backlog_req = list_first_entry(&ctx->backlog, 4998c2ecf20Sopenharmony_ci typeof(*backlog_req), 5008c2ecf20Sopenharmony_ci backlog_head); 5018c2ecf20Sopenharmony_ci if (sec_queue_can_enqueue(ctx->queue, 5028c2ecf20Sopenharmony_ci backlog_req->num_elements) || 5038c2ecf20Sopenharmony_ci (ctx->queue->havesoftqueue && 5048c2ecf20Sopenharmony_ci kfifo_avail(&ctx->queue->softqueue) > 5058c2ecf20Sopenharmony_ci backlog_req->num_elements)) { 5068c2ecf20Sopenharmony_ci sec_send_request(backlog_req, ctx->queue); 5078c2ecf20Sopenharmony_ci backlog_req->req_base->complete(backlog_req->req_base, 5088c2ecf20Sopenharmony_ci -EINPROGRESS); 5098c2ecf20Sopenharmony_ci list_del(&backlog_req->backlog_head); 5108c2ecf20Sopenharmony_ci } 5118c2ecf20Sopenharmony_ci } 5128c2ecf20Sopenharmony_ci spin_unlock_bh(&ctx->queue->queuelock); 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci mutex_lock(&sec_req->lock); 5158c2ecf20Sopenharmony_ci list_del(&sec_req_el->head); 5168c2ecf20Sopenharmony_ci mutex_unlock(&sec_req->lock); 5178c2ecf20Sopenharmony_ci sec_alg_free_el(sec_req_el, ctx->queue->dev_info); 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci /* 5208c2ecf20Sopenharmony_ci * Request is done. 5218c2ecf20Sopenharmony_ci * The dance is needed as the lock is freed in the completion 5228c2ecf20Sopenharmony_ci */ 5238c2ecf20Sopenharmony_ci mutex_lock(&sec_req->lock); 5248c2ecf20Sopenharmony_ci done = list_empty(&sec_req->elements); 5258c2ecf20Sopenharmony_ci mutex_unlock(&sec_req->lock); 5268c2ecf20Sopenharmony_ci if (done) { 5278c2ecf20Sopenharmony_ci if (crypto_skcipher_ivsize(atfm)) { 5288c2ecf20Sopenharmony_ci dma_unmap_single(dev, sec_req->dma_iv, 5298c2ecf20Sopenharmony_ci crypto_skcipher_ivsize(atfm), 5308c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci dma_unmap_sg(dev, skreq->src, sec_req->len_in, 5338c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 5348c2ecf20Sopenharmony_ci if (skreq->src != skreq->dst) 5358c2ecf20Sopenharmony_ci dma_unmap_sg(dev, skreq->dst, sec_req->len_out, 5368c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 5378c2ecf20Sopenharmony_ci skreq->base.complete(&skreq->base, sec_req->err); 5388c2ecf20Sopenharmony_ci } 5398c2ecf20Sopenharmony_ci} 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_civoid sec_alg_callback(struct sec_bd_info *resp, void *shadow) 5428c2ecf20Sopenharmony_ci{ 5438c2ecf20Sopenharmony_ci struct sec_request *sec_req = shadow; 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci sec_req->cb(resp, sec_req->req_base); 5468c2ecf20Sopenharmony_ci} 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_cistatic int sec_alg_alloc_and_calc_split_sizes(int length, size_t **split_sizes, 5498c2ecf20Sopenharmony_ci int *steps, gfp_t gfp) 5508c2ecf20Sopenharmony_ci{ 5518c2ecf20Sopenharmony_ci size_t *sizes; 5528c2ecf20Sopenharmony_ci int i; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci /* Split into suitable sized blocks */ 5558c2ecf20Sopenharmony_ci *steps = roundup(length, SEC_REQ_LIMIT) / SEC_REQ_LIMIT; 5568c2ecf20Sopenharmony_ci sizes = kcalloc(*steps, sizeof(*sizes), gfp); 5578c2ecf20Sopenharmony_ci if (!sizes) 5588c2ecf20Sopenharmony_ci return -ENOMEM; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci for (i = 0; i < *steps - 1; i++) 5618c2ecf20Sopenharmony_ci sizes[i] = SEC_REQ_LIMIT; 5628c2ecf20Sopenharmony_ci sizes[*steps - 1] = length - SEC_REQ_LIMIT * (*steps - 1); 5638c2ecf20Sopenharmony_ci *split_sizes = sizes; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci return 0; 5668c2ecf20Sopenharmony_ci} 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_cistatic int sec_map_and_split_sg(struct scatterlist *sgl, size_t *split_sizes, 5698c2ecf20Sopenharmony_ci int steps, struct scatterlist ***splits, 5708c2ecf20Sopenharmony_ci int **splits_nents, 5718c2ecf20Sopenharmony_ci int sgl_len_in, 5728c2ecf20Sopenharmony_ci struct device *dev, gfp_t gfp) 5738c2ecf20Sopenharmony_ci{ 5748c2ecf20Sopenharmony_ci int ret, count; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci count = dma_map_sg(dev, sgl, sgl_len_in, DMA_BIDIRECTIONAL); 5778c2ecf20Sopenharmony_ci if (!count) 5788c2ecf20Sopenharmony_ci return -EINVAL; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci *splits = kcalloc(steps, sizeof(struct scatterlist *), gfp); 5818c2ecf20Sopenharmony_ci if (!*splits) { 5828c2ecf20Sopenharmony_ci ret = -ENOMEM; 5838c2ecf20Sopenharmony_ci goto err_unmap_sg; 5848c2ecf20Sopenharmony_ci } 5858c2ecf20Sopenharmony_ci *splits_nents = kcalloc(steps, sizeof(int), gfp); 5868c2ecf20Sopenharmony_ci if (!*splits_nents) { 5878c2ecf20Sopenharmony_ci ret = -ENOMEM; 5888c2ecf20Sopenharmony_ci goto err_free_splits; 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci /* output the scatter list before and after this */ 5928c2ecf20Sopenharmony_ci ret = sg_split(sgl, count, 0, steps, split_sizes, 5938c2ecf20Sopenharmony_ci *splits, *splits_nents, gfp); 5948c2ecf20Sopenharmony_ci if (ret) { 5958c2ecf20Sopenharmony_ci ret = -ENOMEM; 5968c2ecf20Sopenharmony_ci goto err_free_splits_nents; 5978c2ecf20Sopenharmony_ci } 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci return 0; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_cierr_free_splits_nents: 6028c2ecf20Sopenharmony_ci kfree(*splits_nents); 6038c2ecf20Sopenharmony_cierr_free_splits: 6048c2ecf20Sopenharmony_ci kfree(*splits); 6058c2ecf20Sopenharmony_cierr_unmap_sg: 6068c2ecf20Sopenharmony_ci dma_unmap_sg(dev, sgl, sgl_len_in, DMA_BIDIRECTIONAL); 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci return ret; 6098c2ecf20Sopenharmony_ci} 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci/* 6128c2ecf20Sopenharmony_ci * Reverses the sec_map_and_split_sg call for messages not yet added to 6138c2ecf20Sopenharmony_ci * the queues. 6148c2ecf20Sopenharmony_ci */ 6158c2ecf20Sopenharmony_cistatic void sec_unmap_sg_on_err(struct scatterlist *sgl, int steps, 6168c2ecf20Sopenharmony_ci struct scatterlist **splits, int *splits_nents, 6178c2ecf20Sopenharmony_ci int sgl_len_in, struct device *dev) 6188c2ecf20Sopenharmony_ci{ 6198c2ecf20Sopenharmony_ci int i; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci for (i = 0; i < steps; i++) 6228c2ecf20Sopenharmony_ci kfree(splits[i]); 6238c2ecf20Sopenharmony_ci kfree(splits_nents); 6248c2ecf20Sopenharmony_ci kfree(splits); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci dma_unmap_sg(dev, sgl, sgl_len_in, DMA_BIDIRECTIONAL); 6278c2ecf20Sopenharmony_ci} 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_cistatic struct sec_request_el 6308c2ecf20Sopenharmony_ci*sec_alg_alloc_and_fill_el(struct sec_bd_info *template, int encrypt, 6318c2ecf20Sopenharmony_ci int el_size, bool different_dest, 6328c2ecf20Sopenharmony_ci struct scatterlist *sgl_in, int n_ents_in, 6338c2ecf20Sopenharmony_ci struct scatterlist *sgl_out, int n_ents_out, 6348c2ecf20Sopenharmony_ci struct sec_dev_info *info, gfp_t gfp) 6358c2ecf20Sopenharmony_ci{ 6368c2ecf20Sopenharmony_ci struct sec_request_el *el; 6378c2ecf20Sopenharmony_ci struct sec_bd_info *req; 6388c2ecf20Sopenharmony_ci int ret; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci el = kzalloc(sizeof(*el), gfp); 6418c2ecf20Sopenharmony_ci if (!el) 6428c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 6438c2ecf20Sopenharmony_ci el->el_length = el_size; 6448c2ecf20Sopenharmony_ci req = &el->req; 6458c2ecf20Sopenharmony_ci memcpy(req, template, sizeof(*req)); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci req->w0 &= ~SEC_BD_W0_CIPHER_M; 6488c2ecf20Sopenharmony_ci if (encrypt) 6498c2ecf20Sopenharmony_ci req->w0 |= SEC_CIPHER_ENCRYPT << SEC_BD_W0_CIPHER_S; 6508c2ecf20Sopenharmony_ci else 6518c2ecf20Sopenharmony_ci req->w0 |= SEC_CIPHER_DECRYPT << SEC_BD_W0_CIPHER_S; 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci req->w0 &= ~SEC_BD_W0_C_GRAN_SIZE_19_16_M; 6548c2ecf20Sopenharmony_ci req->w0 |= ((el_size >> 16) << SEC_BD_W0_C_GRAN_SIZE_19_16_S) & 6558c2ecf20Sopenharmony_ci SEC_BD_W0_C_GRAN_SIZE_19_16_M; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci req->w0 &= ~SEC_BD_W0_C_GRAN_SIZE_21_20_M; 6588c2ecf20Sopenharmony_ci req->w0 |= ((el_size >> 20) << SEC_BD_W0_C_GRAN_SIZE_21_20_S) & 6598c2ecf20Sopenharmony_ci SEC_BD_W0_C_GRAN_SIZE_21_20_M; 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci /* Writing whole u32 so no need to take care of masking */ 6628c2ecf20Sopenharmony_ci req->w2 = ((1 << SEC_BD_W2_GRAN_NUM_S) & SEC_BD_W2_GRAN_NUM_M) | 6638c2ecf20Sopenharmony_ci ((el_size << SEC_BD_W2_C_GRAN_SIZE_15_0_S) & 6648c2ecf20Sopenharmony_ci SEC_BD_W2_C_GRAN_SIZE_15_0_M); 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci req->w3 &= ~SEC_BD_W3_CIPHER_LEN_OFFSET_M; 6678c2ecf20Sopenharmony_ci req->w1 |= SEC_BD_W1_ADDR_TYPE; 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci el->sgl_in = sgl_in; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci ret = sec_alloc_and_fill_hw_sgl(&el->in, &el->dma_in, el->sgl_in, 6728c2ecf20Sopenharmony_ci n_ents_in, info, gfp); 6738c2ecf20Sopenharmony_ci if (ret) 6748c2ecf20Sopenharmony_ci goto err_free_el; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci req->data_addr_lo = lower_32_bits(el->dma_in); 6778c2ecf20Sopenharmony_ci req->data_addr_hi = upper_32_bits(el->dma_in); 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci if (different_dest) { 6808c2ecf20Sopenharmony_ci el->sgl_out = sgl_out; 6818c2ecf20Sopenharmony_ci ret = sec_alloc_and_fill_hw_sgl(&el->out, &el->dma_out, 6828c2ecf20Sopenharmony_ci el->sgl_out, 6838c2ecf20Sopenharmony_ci n_ents_out, info, gfp); 6848c2ecf20Sopenharmony_ci if (ret) 6858c2ecf20Sopenharmony_ci goto err_free_hw_sgl_in; 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci req->w0 |= SEC_BD_W0_DE; 6888c2ecf20Sopenharmony_ci req->cipher_destin_addr_lo = lower_32_bits(el->dma_out); 6898c2ecf20Sopenharmony_ci req->cipher_destin_addr_hi = upper_32_bits(el->dma_out); 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci } else { 6928c2ecf20Sopenharmony_ci req->w0 &= ~SEC_BD_W0_DE; 6938c2ecf20Sopenharmony_ci req->cipher_destin_addr_lo = lower_32_bits(el->dma_in); 6948c2ecf20Sopenharmony_ci req->cipher_destin_addr_hi = upper_32_bits(el->dma_in); 6958c2ecf20Sopenharmony_ci } 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci return el; 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_cierr_free_hw_sgl_in: 7008c2ecf20Sopenharmony_ci sec_free_hw_sgl(el->in, el->dma_in, info); 7018c2ecf20Sopenharmony_cierr_free_el: 7028c2ecf20Sopenharmony_ci kfree(el); 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci return ERR_PTR(ret); 7058c2ecf20Sopenharmony_ci} 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_crypto(struct skcipher_request *skreq, 7088c2ecf20Sopenharmony_ci bool encrypt) 7098c2ecf20Sopenharmony_ci{ 7108c2ecf20Sopenharmony_ci struct crypto_skcipher *atfm = crypto_skcipher_reqtfm(skreq); 7118c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_skcipher_tfm(atfm); 7128c2ecf20Sopenharmony_ci struct sec_alg_tfm_ctx *ctx = crypto_tfm_ctx(tfm); 7138c2ecf20Sopenharmony_ci struct sec_queue *queue = ctx->queue; 7148c2ecf20Sopenharmony_ci struct sec_request *sec_req = skcipher_request_ctx(skreq); 7158c2ecf20Sopenharmony_ci struct sec_dev_info *info = queue->dev_info; 7168c2ecf20Sopenharmony_ci int i, ret, steps; 7178c2ecf20Sopenharmony_ci size_t *split_sizes; 7188c2ecf20Sopenharmony_ci struct scatterlist **splits_in; 7198c2ecf20Sopenharmony_ci struct scatterlist **splits_out = NULL; 7208c2ecf20Sopenharmony_ci int *splits_in_nents; 7218c2ecf20Sopenharmony_ci int *splits_out_nents = NULL; 7228c2ecf20Sopenharmony_ci struct sec_request_el *el, *temp; 7238c2ecf20Sopenharmony_ci bool split = skreq->src != skreq->dst; 7248c2ecf20Sopenharmony_ci gfp_t gfp = skreq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC; 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci mutex_init(&sec_req->lock); 7278c2ecf20Sopenharmony_ci sec_req->req_base = &skreq->base; 7288c2ecf20Sopenharmony_ci sec_req->err = 0; 7298c2ecf20Sopenharmony_ci /* SGL mapping out here to allow us to break it up as necessary */ 7308c2ecf20Sopenharmony_ci sec_req->len_in = sg_nents(skreq->src); 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci ret = sec_alg_alloc_and_calc_split_sizes(skreq->cryptlen, &split_sizes, 7338c2ecf20Sopenharmony_ci &steps, gfp); 7348c2ecf20Sopenharmony_ci if (ret) 7358c2ecf20Sopenharmony_ci return ret; 7368c2ecf20Sopenharmony_ci sec_req->num_elements = steps; 7378c2ecf20Sopenharmony_ci ret = sec_map_and_split_sg(skreq->src, split_sizes, steps, &splits_in, 7388c2ecf20Sopenharmony_ci &splits_in_nents, sec_req->len_in, 7398c2ecf20Sopenharmony_ci info->dev, gfp); 7408c2ecf20Sopenharmony_ci if (ret) 7418c2ecf20Sopenharmony_ci goto err_free_split_sizes; 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ci if (split) { 7448c2ecf20Sopenharmony_ci sec_req->len_out = sg_nents(skreq->dst); 7458c2ecf20Sopenharmony_ci ret = sec_map_and_split_sg(skreq->dst, split_sizes, steps, 7468c2ecf20Sopenharmony_ci &splits_out, &splits_out_nents, 7478c2ecf20Sopenharmony_ci sec_req->len_out, info->dev, gfp); 7488c2ecf20Sopenharmony_ci if (ret) 7498c2ecf20Sopenharmony_ci goto err_unmap_in_sg; 7508c2ecf20Sopenharmony_ci } 7518c2ecf20Sopenharmony_ci /* Shared info stored in seq_req - applies to all BDs */ 7528c2ecf20Sopenharmony_ci sec_req->tfm_ctx = ctx; 7538c2ecf20Sopenharmony_ci sec_req->cb = sec_skcipher_alg_callback; 7548c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&sec_req->elements); 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci /* 7578c2ecf20Sopenharmony_ci * Future optimization. 7588c2ecf20Sopenharmony_ci * In the chaining case we can't use a dma pool bounce buffer 7598c2ecf20Sopenharmony_ci * but in the case where we know there is no chaining we can 7608c2ecf20Sopenharmony_ci */ 7618c2ecf20Sopenharmony_ci if (crypto_skcipher_ivsize(atfm)) { 7628c2ecf20Sopenharmony_ci sec_req->dma_iv = dma_map_single(info->dev, skreq->iv, 7638c2ecf20Sopenharmony_ci crypto_skcipher_ivsize(atfm), 7648c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 7658c2ecf20Sopenharmony_ci if (dma_mapping_error(info->dev, sec_req->dma_iv)) { 7668c2ecf20Sopenharmony_ci ret = -ENOMEM; 7678c2ecf20Sopenharmony_ci goto err_unmap_out_sg; 7688c2ecf20Sopenharmony_ci } 7698c2ecf20Sopenharmony_ci } 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci /* Set them all up then queue - cleaner error handling. */ 7728c2ecf20Sopenharmony_ci for (i = 0; i < steps; i++) { 7738c2ecf20Sopenharmony_ci el = sec_alg_alloc_and_fill_el(&ctx->req_template, 7748c2ecf20Sopenharmony_ci encrypt ? 1 : 0, 7758c2ecf20Sopenharmony_ci split_sizes[i], 7768c2ecf20Sopenharmony_ci skreq->src != skreq->dst, 7778c2ecf20Sopenharmony_ci splits_in[i], splits_in_nents[i], 7788c2ecf20Sopenharmony_ci split ? splits_out[i] : NULL, 7798c2ecf20Sopenharmony_ci split ? splits_out_nents[i] : 0, 7808c2ecf20Sopenharmony_ci info, gfp); 7818c2ecf20Sopenharmony_ci if (IS_ERR(el)) { 7828c2ecf20Sopenharmony_ci ret = PTR_ERR(el); 7838c2ecf20Sopenharmony_ci goto err_free_elements; 7848c2ecf20Sopenharmony_ci } 7858c2ecf20Sopenharmony_ci el->req.cipher_iv_addr_lo = lower_32_bits(sec_req->dma_iv); 7868c2ecf20Sopenharmony_ci el->req.cipher_iv_addr_hi = upper_32_bits(sec_req->dma_iv); 7878c2ecf20Sopenharmony_ci el->sec_req = sec_req; 7888c2ecf20Sopenharmony_ci list_add_tail(&el->head, &sec_req->elements); 7898c2ecf20Sopenharmony_ci } 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci /* 7928c2ecf20Sopenharmony_ci * Only attempt to queue if the whole lot can fit in the queue - 7938c2ecf20Sopenharmony_ci * we can't successfully cleanup after a partial queing so this 7948c2ecf20Sopenharmony_ci * must succeed or fail atomically. 7958c2ecf20Sopenharmony_ci * 7968c2ecf20Sopenharmony_ci * Big hammer test of both software and hardware queues - could be 7978c2ecf20Sopenharmony_ci * more refined but this is unlikely to happen so no need. 7988c2ecf20Sopenharmony_ci */ 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci /* Grab a big lock for a long time to avoid concurrency issues */ 8018c2ecf20Sopenharmony_ci spin_lock_bh(&queue->queuelock); 8028c2ecf20Sopenharmony_ci 8038c2ecf20Sopenharmony_ci /* 8048c2ecf20Sopenharmony_ci * Can go on to queue if we have space in either: 8058c2ecf20Sopenharmony_ci * 1) The hardware queue and no software queue 8068c2ecf20Sopenharmony_ci * 2) The software queue 8078c2ecf20Sopenharmony_ci * AND there is nothing in the backlog. If there is backlog we 8088c2ecf20Sopenharmony_ci * have to only queue to the backlog queue and return busy. 8098c2ecf20Sopenharmony_ci */ 8108c2ecf20Sopenharmony_ci if ((!sec_queue_can_enqueue(queue, steps) && 8118c2ecf20Sopenharmony_ci (!queue->havesoftqueue || 8128c2ecf20Sopenharmony_ci kfifo_avail(&queue->softqueue) > steps)) || 8138c2ecf20Sopenharmony_ci !list_empty(&ctx->backlog)) { 8148c2ecf20Sopenharmony_ci ret = -EBUSY; 8158c2ecf20Sopenharmony_ci if ((skreq->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) { 8168c2ecf20Sopenharmony_ci list_add_tail(&sec_req->backlog_head, &ctx->backlog); 8178c2ecf20Sopenharmony_ci spin_unlock_bh(&queue->queuelock); 8188c2ecf20Sopenharmony_ci goto out; 8198c2ecf20Sopenharmony_ci } 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci spin_unlock_bh(&queue->queuelock); 8228c2ecf20Sopenharmony_ci goto err_free_elements; 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci ret = sec_send_request(sec_req, queue); 8258c2ecf20Sopenharmony_ci spin_unlock_bh(&queue->queuelock); 8268c2ecf20Sopenharmony_ci if (ret) 8278c2ecf20Sopenharmony_ci goto err_free_elements; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci ret = -EINPROGRESS; 8308c2ecf20Sopenharmony_ciout: 8318c2ecf20Sopenharmony_ci /* Cleanup - all elements in pointer arrays have been copied */ 8328c2ecf20Sopenharmony_ci kfree(splits_in_nents); 8338c2ecf20Sopenharmony_ci kfree(splits_in); 8348c2ecf20Sopenharmony_ci kfree(splits_out_nents); 8358c2ecf20Sopenharmony_ci kfree(splits_out); 8368c2ecf20Sopenharmony_ci kfree(split_sizes); 8378c2ecf20Sopenharmony_ci return ret; 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_cierr_free_elements: 8408c2ecf20Sopenharmony_ci list_for_each_entry_safe(el, temp, &sec_req->elements, head) { 8418c2ecf20Sopenharmony_ci list_del(&el->head); 8428c2ecf20Sopenharmony_ci sec_alg_free_el(el, info); 8438c2ecf20Sopenharmony_ci } 8448c2ecf20Sopenharmony_ci if (crypto_skcipher_ivsize(atfm)) 8458c2ecf20Sopenharmony_ci dma_unmap_single(info->dev, sec_req->dma_iv, 8468c2ecf20Sopenharmony_ci crypto_skcipher_ivsize(atfm), 8478c2ecf20Sopenharmony_ci DMA_BIDIRECTIONAL); 8488c2ecf20Sopenharmony_cierr_unmap_out_sg: 8498c2ecf20Sopenharmony_ci if (split) 8508c2ecf20Sopenharmony_ci sec_unmap_sg_on_err(skreq->dst, steps, splits_out, 8518c2ecf20Sopenharmony_ci splits_out_nents, sec_req->len_out, 8528c2ecf20Sopenharmony_ci info->dev); 8538c2ecf20Sopenharmony_cierr_unmap_in_sg: 8548c2ecf20Sopenharmony_ci sec_unmap_sg_on_err(skreq->src, steps, splits_in, splits_in_nents, 8558c2ecf20Sopenharmony_ci sec_req->len_in, info->dev); 8568c2ecf20Sopenharmony_cierr_free_split_sizes: 8578c2ecf20Sopenharmony_ci kfree(split_sizes); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci return ret; 8608c2ecf20Sopenharmony_ci} 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_encrypt(struct skcipher_request *req) 8638c2ecf20Sopenharmony_ci{ 8648c2ecf20Sopenharmony_ci return sec_alg_skcipher_crypto(req, true); 8658c2ecf20Sopenharmony_ci} 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_decrypt(struct skcipher_request *req) 8688c2ecf20Sopenharmony_ci{ 8698c2ecf20Sopenharmony_ci return sec_alg_skcipher_crypto(req, false); 8708c2ecf20Sopenharmony_ci} 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_init(struct crypto_skcipher *tfm) 8738c2ecf20Sopenharmony_ci{ 8748c2ecf20Sopenharmony_ci struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci mutex_init(&ctx->lock); 8778c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ctx->backlog); 8788c2ecf20Sopenharmony_ci crypto_skcipher_set_reqsize(tfm, sizeof(struct sec_request)); 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci ctx->queue = sec_queue_alloc_start_safe(); 8818c2ecf20Sopenharmony_ci if (IS_ERR(ctx->queue)) 8828c2ecf20Sopenharmony_ci return PTR_ERR(ctx->queue); 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci spin_lock_init(&ctx->queue->queuelock); 8858c2ecf20Sopenharmony_ci ctx->queue->havesoftqueue = false; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci return 0; 8888c2ecf20Sopenharmony_ci} 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_cistatic void sec_alg_skcipher_exit(struct crypto_skcipher *tfm) 8918c2ecf20Sopenharmony_ci{ 8928c2ecf20Sopenharmony_ci struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); 8938c2ecf20Sopenharmony_ci struct device *dev = ctx->queue->dev_info->dev; 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci if (ctx->key) { 8968c2ecf20Sopenharmony_ci memzero_explicit(ctx->key, SEC_MAX_CIPHER_KEY); 8978c2ecf20Sopenharmony_ci dma_free_coherent(dev, SEC_MAX_CIPHER_KEY, ctx->key, 8988c2ecf20Sopenharmony_ci ctx->pkey); 8998c2ecf20Sopenharmony_ci } 9008c2ecf20Sopenharmony_ci sec_queue_stop_release(ctx->queue); 9018c2ecf20Sopenharmony_ci} 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_cistatic int sec_alg_skcipher_init_with_queue(struct crypto_skcipher *tfm) 9048c2ecf20Sopenharmony_ci{ 9058c2ecf20Sopenharmony_ci struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); 9068c2ecf20Sopenharmony_ci int ret; 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci ret = sec_alg_skcipher_init(tfm); 9098c2ecf20Sopenharmony_ci if (ret) 9108c2ecf20Sopenharmony_ci return ret; 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci INIT_KFIFO(ctx->queue->softqueue); 9138c2ecf20Sopenharmony_ci ret = kfifo_alloc(&ctx->queue->softqueue, 512, GFP_KERNEL); 9148c2ecf20Sopenharmony_ci if (ret) { 9158c2ecf20Sopenharmony_ci sec_alg_skcipher_exit(tfm); 9168c2ecf20Sopenharmony_ci return ret; 9178c2ecf20Sopenharmony_ci } 9188c2ecf20Sopenharmony_ci ctx->queue->havesoftqueue = true; 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_ci return 0; 9218c2ecf20Sopenharmony_ci} 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_cistatic void sec_alg_skcipher_exit_with_queue(struct crypto_skcipher *tfm) 9248c2ecf20Sopenharmony_ci{ 9258c2ecf20Sopenharmony_ci struct sec_alg_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci kfifo_free(&ctx->queue->softqueue); 9288c2ecf20Sopenharmony_ci sec_alg_skcipher_exit(tfm); 9298c2ecf20Sopenharmony_ci} 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_cistatic struct skcipher_alg sec_algs[] = { 9328c2ecf20Sopenharmony_ci { 9338c2ecf20Sopenharmony_ci .base = { 9348c2ecf20Sopenharmony_ci .cra_name = "ecb(aes)", 9358c2ecf20Sopenharmony_ci .cra_driver_name = "hisi_sec_aes_ecb", 9368c2ecf20Sopenharmony_ci .cra_priority = 4001, 9378c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 9388c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 9398c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 9408c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), 9418c2ecf20Sopenharmony_ci .cra_alignmask = 0, 9428c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 9438c2ecf20Sopenharmony_ci }, 9448c2ecf20Sopenharmony_ci .init = sec_alg_skcipher_init, 9458c2ecf20Sopenharmony_ci .exit = sec_alg_skcipher_exit, 9468c2ecf20Sopenharmony_ci .setkey = sec_alg_skcipher_setkey_aes_ecb, 9478c2ecf20Sopenharmony_ci .decrypt = sec_alg_skcipher_decrypt, 9488c2ecf20Sopenharmony_ci .encrypt = sec_alg_skcipher_encrypt, 9498c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 9508c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 9518c2ecf20Sopenharmony_ci .ivsize = 0, 9528c2ecf20Sopenharmony_ci }, { 9538c2ecf20Sopenharmony_ci .base = { 9548c2ecf20Sopenharmony_ci .cra_name = "cbc(aes)", 9558c2ecf20Sopenharmony_ci .cra_driver_name = "hisi_sec_aes_cbc", 9568c2ecf20Sopenharmony_ci .cra_priority = 4001, 9578c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 9588c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 9598c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 9608c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), 9618c2ecf20Sopenharmony_ci .cra_alignmask = 0, 9628c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 9638c2ecf20Sopenharmony_ci }, 9648c2ecf20Sopenharmony_ci .init = sec_alg_skcipher_init_with_queue, 9658c2ecf20Sopenharmony_ci .exit = sec_alg_skcipher_exit_with_queue, 9668c2ecf20Sopenharmony_ci .setkey = sec_alg_skcipher_setkey_aes_cbc, 9678c2ecf20Sopenharmony_ci .decrypt = sec_alg_skcipher_decrypt, 9688c2ecf20Sopenharmony_ci .encrypt = sec_alg_skcipher_encrypt, 9698c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 9708c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 9718c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 9728c2ecf20Sopenharmony_ci }, { 9738c2ecf20Sopenharmony_ci .base = { 9748c2ecf20Sopenharmony_ci .cra_name = "ctr(aes)", 9758c2ecf20Sopenharmony_ci .cra_driver_name = "hisi_sec_aes_ctr", 9768c2ecf20Sopenharmony_ci .cra_priority = 4001, 9778c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 9788c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 9798c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 9808c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), 9818c2ecf20Sopenharmony_ci .cra_alignmask = 0, 9828c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 9838c2ecf20Sopenharmony_ci }, 9848c2ecf20Sopenharmony_ci .init = sec_alg_skcipher_init_with_queue, 9858c2ecf20Sopenharmony_ci .exit = sec_alg_skcipher_exit_with_queue, 9868c2ecf20Sopenharmony_ci .setkey = sec_alg_skcipher_setkey_aes_ctr, 9878c2ecf20Sopenharmony_ci .decrypt = sec_alg_skcipher_decrypt, 9888c2ecf20Sopenharmony_ci .encrypt = sec_alg_skcipher_encrypt, 9898c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 9908c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 9918c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 9928c2ecf20Sopenharmony_ci }, { 9938c2ecf20Sopenharmony_ci .base = { 9948c2ecf20Sopenharmony_ci .cra_name = "xts(aes)", 9958c2ecf20Sopenharmony_ci .cra_driver_name = "hisi_sec_aes_xts", 9968c2ecf20Sopenharmony_ci .cra_priority = 4001, 9978c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 9988c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 9998c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 10008c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), 10018c2ecf20Sopenharmony_ci .cra_alignmask = 0, 10028c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 10038c2ecf20Sopenharmony_ci }, 10048c2ecf20Sopenharmony_ci .init = sec_alg_skcipher_init, 10058c2ecf20Sopenharmony_ci .exit = sec_alg_skcipher_exit, 10068c2ecf20Sopenharmony_ci .setkey = sec_alg_skcipher_setkey_aes_xts, 10078c2ecf20Sopenharmony_ci .decrypt = sec_alg_skcipher_decrypt, 10088c2ecf20Sopenharmony_ci .encrypt = sec_alg_skcipher_encrypt, 10098c2ecf20Sopenharmony_ci .min_keysize = 2 * AES_MIN_KEY_SIZE, 10108c2ecf20Sopenharmony_ci .max_keysize = 2 * AES_MAX_KEY_SIZE, 10118c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 10128c2ecf20Sopenharmony_ci }, { 10138c2ecf20Sopenharmony_ci /* Unable to find any test vectors so untested */ 10148c2ecf20Sopenharmony_ci .base = { 10158c2ecf20Sopenharmony_ci .cra_name = "ecb(des)", 10168c2ecf20Sopenharmony_ci .cra_driver_name = "hisi_sec_des_ecb", 10178c2ecf20Sopenharmony_ci .cra_priority = 4001, 10188c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 10198c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 10208c2ecf20Sopenharmony_ci .cra_blocksize = DES_BLOCK_SIZE, 10218c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), 10228c2ecf20Sopenharmony_ci .cra_alignmask = 0, 10238c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 10248c2ecf20Sopenharmony_ci }, 10258c2ecf20Sopenharmony_ci .init = sec_alg_skcipher_init, 10268c2ecf20Sopenharmony_ci .exit = sec_alg_skcipher_exit, 10278c2ecf20Sopenharmony_ci .setkey = sec_alg_skcipher_setkey_des_ecb, 10288c2ecf20Sopenharmony_ci .decrypt = sec_alg_skcipher_decrypt, 10298c2ecf20Sopenharmony_ci .encrypt = sec_alg_skcipher_encrypt, 10308c2ecf20Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 10318c2ecf20Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 10328c2ecf20Sopenharmony_ci .ivsize = 0, 10338c2ecf20Sopenharmony_ci }, { 10348c2ecf20Sopenharmony_ci .base = { 10358c2ecf20Sopenharmony_ci .cra_name = "cbc(des)", 10368c2ecf20Sopenharmony_ci .cra_driver_name = "hisi_sec_des_cbc", 10378c2ecf20Sopenharmony_ci .cra_priority = 4001, 10388c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 10398c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 10408c2ecf20Sopenharmony_ci .cra_blocksize = DES_BLOCK_SIZE, 10418c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), 10428c2ecf20Sopenharmony_ci .cra_alignmask = 0, 10438c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 10448c2ecf20Sopenharmony_ci }, 10458c2ecf20Sopenharmony_ci .init = sec_alg_skcipher_init_with_queue, 10468c2ecf20Sopenharmony_ci .exit = sec_alg_skcipher_exit_with_queue, 10478c2ecf20Sopenharmony_ci .setkey = sec_alg_skcipher_setkey_des_cbc, 10488c2ecf20Sopenharmony_ci .decrypt = sec_alg_skcipher_decrypt, 10498c2ecf20Sopenharmony_ci .encrypt = sec_alg_skcipher_encrypt, 10508c2ecf20Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 10518c2ecf20Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 10528c2ecf20Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 10538c2ecf20Sopenharmony_ci }, { 10548c2ecf20Sopenharmony_ci .base = { 10558c2ecf20Sopenharmony_ci .cra_name = "cbc(des3_ede)", 10568c2ecf20Sopenharmony_ci .cra_driver_name = "hisi_sec_3des_cbc", 10578c2ecf20Sopenharmony_ci .cra_priority = 4001, 10588c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 10598c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 10608c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 10618c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), 10628c2ecf20Sopenharmony_ci .cra_alignmask = 0, 10638c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 10648c2ecf20Sopenharmony_ci }, 10658c2ecf20Sopenharmony_ci .init = sec_alg_skcipher_init_with_queue, 10668c2ecf20Sopenharmony_ci .exit = sec_alg_skcipher_exit_with_queue, 10678c2ecf20Sopenharmony_ci .setkey = sec_alg_skcipher_setkey_3des_cbc, 10688c2ecf20Sopenharmony_ci .decrypt = sec_alg_skcipher_decrypt, 10698c2ecf20Sopenharmony_ci .encrypt = sec_alg_skcipher_encrypt, 10708c2ecf20Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 10718c2ecf20Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 10728c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 10738c2ecf20Sopenharmony_ci }, { 10748c2ecf20Sopenharmony_ci .base = { 10758c2ecf20Sopenharmony_ci .cra_name = "ecb(des3_ede)", 10768c2ecf20Sopenharmony_ci .cra_driver_name = "hisi_sec_3des_ecb", 10778c2ecf20Sopenharmony_ci .cra_priority = 4001, 10788c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_ASYNC | 10798c2ecf20Sopenharmony_ci CRYPTO_ALG_ALLOCATES_MEMORY, 10808c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 10818c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sec_alg_tfm_ctx), 10828c2ecf20Sopenharmony_ci .cra_alignmask = 0, 10838c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 10848c2ecf20Sopenharmony_ci }, 10858c2ecf20Sopenharmony_ci .init = sec_alg_skcipher_init, 10868c2ecf20Sopenharmony_ci .exit = sec_alg_skcipher_exit, 10878c2ecf20Sopenharmony_ci .setkey = sec_alg_skcipher_setkey_3des_ecb, 10888c2ecf20Sopenharmony_ci .decrypt = sec_alg_skcipher_decrypt, 10898c2ecf20Sopenharmony_ci .encrypt = sec_alg_skcipher_encrypt, 10908c2ecf20Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 10918c2ecf20Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 10928c2ecf20Sopenharmony_ci .ivsize = 0, 10938c2ecf20Sopenharmony_ci } 10948c2ecf20Sopenharmony_ci}; 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ciint sec_algs_register(void) 10978c2ecf20Sopenharmony_ci{ 10988c2ecf20Sopenharmony_ci int ret = 0; 10998c2ecf20Sopenharmony_ci 11008c2ecf20Sopenharmony_ci mutex_lock(&algs_lock); 11018c2ecf20Sopenharmony_ci if (++active_devs != 1) 11028c2ecf20Sopenharmony_ci goto unlock; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci ret = crypto_register_skciphers(sec_algs, ARRAY_SIZE(sec_algs)); 11058c2ecf20Sopenharmony_ci if (ret) 11068c2ecf20Sopenharmony_ci --active_devs; 11078c2ecf20Sopenharmony_ciunlock: 11088c2ecf20Sopenharmony_ci mutex_unlock(&algs_lock); 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci return ret; 11118c2ecf20Sopenharmony_ci} 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_civoid sec_algs_unregister(void) 11148c2ecf20Sopenharmony_ci{ 11158c2ecf20Sopenharmony_ci mutex_lock(&algs_lock); 11168c2ecf20Sopenharmony_ci if (--active_devs != 0) 11178c2ecf20Sopenharmony_ci goto unlock; 11188c2ecf20Sopenharmony_ci crypto_unregister_skciphers(sec_algs, ARRAY_SIZE(sec_algs)); 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ciunlock: 11218c2ecf20Sopenharmony_ci mutex_unlock(&algs_lock); 11228c2ecf20Sopenharmony_ci} 1123