18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include <linux/kernel.h> 58c2ecf20Sopenharmony_ci#include <linux/module.h> 68c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 78c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h> 88c2ecf20Sopenharmony_ci#include <crypto/internal/des.h> 98c2ecf20Sopenharmony_ci#include <crypto/xts.h> 108c2ecf20Sopenharmony_ci#include <crypto/sm4.h> 118c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "cc_driver.h" 148c2ecf20Sopenharmony_ci#include "cc_lli_defs.h" 158c2ecf20Sopenharmony_ci#include "cc_buffer_mgr.h" 168c2ecf20Sopenharmony_ci#include "cc_cipher.h" 178c2ecf20Sopenharmony_ci#include "cc_request_mgr.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define MAX_SKCIPHER_SEQ_LEN 6 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define template_skcipher template_u.skcipher 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistruct cc_user_key_info { 248c2ecf20Sopenharmony_ci u8 *key; 258c2ecf20Sopenharmony_ci dma_addr_t key_dma_addr; 268c2ecf20Sopenharmony_ci}; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistruct cc_hw_key_info { 298c2ecf20Sopenharmony_ci enum cc_hw_crypto_key key1_slot; 308c2ecf20Sopenharmony_ci enum cc_hw_crypto_key key2_slot; 318c2ecf20Sopenharmony_ci}; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistruct cc_cpp_key_info { 348c2ecf20Sopenharmony_ci u8 slot; 358c2ecf20Sopenharmony_ci enum cc_cpp_alg alg; 368c2ecf20Sopenharmony_ci}; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cienum cc_key_type { 398c2ecf20Sopenharmony_ci CC_UNPROTECTED_KEY, /* User key */ 408c2ecf20Sopenharmony_ci CC_HW_PROTECTED_KEY, /* HW (FDE) key */ 418c2ecf20Sopenharmony_ci CC_POLICY_PROTECTED_KEY, /* CPP key */ 428c2ecf20Sopenharmony_ci CC_INVALID_PROTECTED_KEY /* Invalid key */ 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistruct cc_cipher_ctx { 468c2ecf20Sopenharmony_ci struct cc_drvdata *drvdata; 478c2ecf20Sopenharmony_ci int keylen; 488c2ecf20Sopenharmony_ci int cipher_mode; 498c2ecf20Sopenharmony_ci int flow_mode; 508c2ecf20Sopenharmony_ci unsigned int flags; 518c2ecf20Sopenharmony_ci enum cc_key_type key_type; 528c2ecf20Sopenharmony_ci struct cc_user_key_info user; 538c2ecf20Sopenharmony_ci union { 548c2ecf20Sopenharmony_ci struct cc_hw_key_info hw; 558c2ecf20Sopenharmony_ci struct cc_cpp_key_info cpp; 568c2ecf20Sopenharmony_ci }; 578c2ecf20Sopenharmony_ci struct crypto_shash *shash_tfm; 588c2ecf20Sopenharmony_ci struct crypto_skcipher *fallback_tfm; 598c2ecf20Sopenharmony_ci bool fallback_on; 608c2ecf20Sopenharmony_ci}; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic void cc_cipher_complete(struct device *dev, void *cc_req, int err); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic inline enum cc_key_type cc_key_type(struct crypto_tfm *tfm) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci return ctx_p->key_type; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic int validate_keys_sizes(struct cc_cipher_ctx *ctx_p, u32 size) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci switch (ctx_p->flow_mode) { 748c2ecf20Sopenharmony_ci case S_DIN_to_AES: 758c2ecf20Sopenharmony_ci switch (size) { 768c2ecf20Sopenharmony_ci case CC_AES_128_BIT_KEY_SIZE: 778c2ecf20Sopenharmony_ci case CC_AES_192_BIT_KEY_SIZE: 788c2ecf20Sopenharmony_ci if (ctx_p->cipher_mode != DRV_CIPHER_XTS) 798c2ecf20Sopenharmony_ci return 0; 808c2ecf20Sopenharmony_ci break; 818c2ecf20Sopenharmony_ci case CC_AES_256_BIT_KEY_SIZE: 828c2ecf20Sopenharmony_ci return 0; 838c2ecf20Sopenharmony_ci case (CC_AES_192_BIT_KEY_SIZE * 2): 848c2ecf20Sopenharmony_ci case (CC_AES_256_BIT_KEY_SIZE * 2): 858c2ecf20Sopenharmony_ci if (ctx_p->cipher_mode == DRV_CIPHER_XTS || 868c2ecf20Sopenharmony_ci ctx_p->cipher_mode == DRV_CIPHER_ESSIV) 878c2ecf20Sopenharmony_ci return 0; 888c2ecf20Sopenharmony_ci break; 898c2ecf20Sopenharmony_ci default: 908c2ecf20Sopenharmony_ci break; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci break; 938c2ecf20Sopenharmony_ci case S_DIN_to_DES: 948c2ecf20Sopenharmony_ci if (size == DES3_EDE_KEY_SIZE || size == DES_KEY_SIZE) 958c2ecf20Sopenharmony_ci return 0; 968c2ecf20Sopenharmony_ci break; 978c2ecf20Sopenharmony_ci case S_DIN_to_SM4: 988c2ecf20Sopenharmony_ci if (size == SM4_KEY_SIZE) 998c2ecf20Sopenharmony_ci return 0; 1008c2ecf20Sopenharmony_ci default: 1018c2ecf20Sopenharmony_ci break; 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci return -EINVAL; 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cistatic int validate_data_size(struct cc_cipher_ctx *ctx_p, 1078c2ecf20Sopenharmony_ci unsigned int size) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci switch (ctx_p->flow_mode) { 1108c2ecf20Sopenharmony_ci case S_DIN_to_AES: 1118c2ecf20Sopenharmony_ci switch (ctx_p->cipher_mode) { 1128c2ecf20Sopenharmony_ci case DRV_CIPHER_XTS: 1138c2ecf20Sopenharmony_ci case DRV_CIPHER_CBC_CTS: 1148c2ecf20Sopenharmony_ci if (size >= AES_BLOCK_SIZE) 1158c2ecf20Sopenharmony_ci return 0; 1168c2ecf20Sopenharmony_ci break; 1178c2ecf20Sopenharmony_ci case DRV_CIPHER_OFB: 1188c2ecf20Sopenharmony_ci case DRV_CIPHER_CTR: 1198c2ecf20Sopenharmony_ci return 0; 1208c2ecf20Sopenharmony_ci case DRV_CIPHER_ECB: 1218c2ecf20Sopenharmony_ci case DRV_CIPHER_CBC: 1228c2ecf20Sopenharmony_ci case DRV_CIPHER_ESSIV: 1238c2ecf20Sopenharmony_ci if (IS_ALIGNED(size, AES_BLOCK_SIZE)) 1248c2ecf20Sopenharmony_ci return 0; 1258c2ecf20Sopenharmony_ci break; 1268c2ecf20Sopenharmony_ci default: 1278c2ecf20Sopenharmony_ci break; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci break; 1308c2ecf20Sopenharmony_ci case S_DIN_to_DES: 1318c2ecf20Sopenharmony_ci if (IS_ALIGNED(size, DES_BLOCK_SIZE)) 1328c2ecf20Sopenharmony_ci return 0; 1338c2ecf20Sopenharmony_ci break; 1348c2ecf20Sopenharmony_ci case S_DIN_to_SM4: 1358c2ecf20Sopenharmony_ci switch (ctx_p->cipher_mode) { 1368c2ecf20Sopenharmony_ci case DRV_CIPHER_CTR: 1378c2ecf20Sopenharmony_ci return 0; 1388c2ecf20Sopenharmony_ci case DRV_CIPHER_ECB: 1398c2ecf20Sopenharmony_ci case DRV_CIPHER_CBC: 1408c2ecf20Sopenharmony_ci if (IS_ALIGNED(size, SM4_BLOCK_SIZE)) 1418c2ecf20Sopenharmony_ci return 0; 1428c2ecf20Sopenharmony_ci default: 1438c2ecf20Sopenharmony_ci break; 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci default: 1468c2ecf20Sopenharmony_ci break; 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci return -EINVAL; 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic int cc_cipher_init(struct crypto_tfm *tfm) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); 1548c2ecf20Sopenharmony_ci struct cc_crypto_alg *cc_alg = 1558c2ecf20Sopenharmony_ci container_of(tfm->__crt_alg, struct cc_crypto_alg, 1568c2ecf20Sopenharmony_ci skcipher_alg.base); 1578c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(cc_alg->drvdata); 1588c2ecf20Sopenharmony_ci unsigned int max_key_buf_size = cc_alg->skcipher_alg.max_keysize; 1598c2ecf20Sopenharmony_ci unsigned int fallback_req_size = 0; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci dev_dbg(dev, "Initializing context @%p for %s\n", ctx_p, 1628c2ecf20Sopenharmony_ci crypto_tfm_alg_name(tfm)); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci ctx_p->cipher_mode = cc_alg->cipher_mode; 1658c2ecf20Sopenharmony_ci ctx_p->flow_mode = cc_alg->flow_mode; 1668c2ecf20Sopenharmony_ci ctx_p->drvdata = cc_alg->drvdata; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) { 1698c2ecf20Sopenharmony_ci const char *name = crypto_tfm_alg_name(tfm); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci /* Alloc hash tfm for essiv */ 1728c2ecf20Sopenharmony_ci ctx_p->shash_tfm = crypto_alloc_shash("sha256", 0, 0); 1738c2ecf20Sopenharmony_ci if (IS_ERR(ctx_p->shash_tfm)) { 1748c2ecf20Sopenharmony_ci dev_err(dev, "Error allocating hash tfm for ESSIV.\n"); 1758c2ecf20Sopenharmony_ci return PTR_ERR(ctx_p->shash_tfm); 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci max_key_buf_size <<= 1; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* Alloc fallabck tfm or essiv when key size != 256 bit */ 1808c2ecf20Sopenharmony_ci ctx_p->fallback_tfm = 1818c2ecf20Sopenharmony_ci crypto_alloc_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK | CRYPTO_ALG_ASYNC); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci if (IS_ERR(ctx_p->fallback_tfm)) { 1848c2ecf20Sopenharmony_ci /* Note we're still allowing registration with no fallback since it's 1858c2ecf20Sopenharmony_ci * better to have most modes supported than none at all. 1868c2ecf20Sopenharmony_ci */ 1878c2ecf20Sopenharmony_ci dev_warn(dev, "Error allocating fallback algo %s. Some modes may be available.\n", 1888c2ecf20Sopenharmony_ci name); 1898c2ecf20Sopenharmony_ci ctx_p->fallback_tfm = NULL; 1908c2ecf20Sopenharmony_ci } else { 1918c2ecf20Sopenharmony_ci fallback_req_size = crypto_skcipher_reqsize(ctx_p->fallback_tfm); 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci crypto_skcipher_set_reqsize(__crypto_skcipher_cast(tfm), 1968c2ecf20Sopenharmony_ci sizeof(struct cipher_req_ctx) + fallback_req_size); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci /* Allocate key buffer, cache line aligned */ 1998c2ecf20Sopenharmony_ci ctx_p->user.key = kzalloc(max_key_buf_size, GFP_KERNEL); 2008c2ecf20Sopenharmony_ci if (!ctx_p->user.key) 2018c2ecf20Sopenharmony_ci goto free_fallback; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci dev_dbg(dev, "Allocated key buffer in context. key=@%p\n", 2048c2ecf20Sopenharmony_ci ctx_p->user.key); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci /* Map key buffer */ 2078c2ecf20Sopenharmony_ci ctx_p->user.key_dma_addr = dma_map_single(dev, ctx_p->user.key, 2088c2ecf20Sopenharmony_ci max_key_buf_size, 2098c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 2108c2ecf20Sopenharmony_ci if (dma_mapping_error(dev, ctx_p->user.key_dma_addr)) { 2118c2ecf20Sopenharmony_ci dev_err(dev, "Mapping Key %u B at va=%pK for DMA failed\n", 2128c2ecf20Sopenharmony_ci max_key_buf_size, ctx_p->user.key); 2138c2ecf20Sopenharmony_ci goto free_key; 2148c2ecf20Sopenharmony_ci } 2158c2ecf20Sopenharmony_ci dev_dbg(dev, "Mapped key %u B at va=%pK to dma=%pad\n", 2168c2ecf20Sopenharmony_ci max_key_buf_size, ctx_p->user.key, &ctx_p->user.key_dma_addr); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci return 0; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cifree_key: 2218c2ecf20Sopenharmony_ci kfree(ctx_p->user.key); 2228c2ecf20Sopenharmony_cifree_fallback: 2238c2ecf20Sopenharmony_ci crypto_free_skcipher(ctx_p->fallback_tfm); 2248c2ecf20Sopenharmony_ci crypto_free_shash(ctx_p->shash_tfm); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci return -ENOMEM; 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_cistatic void cc_cipher_exit(struct crypto_tfm *tfm) 2308c2ecf20Sopenharmony_ci{ 2318c2ecf20Sopenharmony_ci struct crypto_alg *alg = tfm->__crt_alg; 2328c2ecf20Sopenharmony_ci struct cc_crypto_alg *cc_alg = 2338c2ecf20Sopenharmony_ci container_of(alg, struct cc_crypto_alg, 2348c2ecf20Sopenharmony_ci skcipher_alg.base); 2358c2ecf20Sopenharmony_ci unsigned int max_key_buf_size = cc_alg->skcipher_alg.max_keysize; 2368c2ecf20Sopenharmony_ci struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); 2378c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx_p->drvdata); 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci dev_dbg(dev, "Clearing context @%p for %s\n", 2408c2ecf20Sopenharmony_ci crypto_tfm_ctx(tfm), crypto_tfm_alg_name(tfm)); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) { 2438c2ecf20Sopenharmony_ci /* Free hash tfm for essiv */ 2448c2ecf20Sopenharmony_ci crypto_free_shash(ctx_p->shash_tfm); 2458c2ecf20Sopenharmony_ci ctx_p->shash_tfm = NULL; 2468c2ecf20Sopenharmony_ci crypto_free_skcipher(ctx_p->fallback_tfm); 2478c2ecf20Sopenharmony_ci ctx_p->fallback_tfm = NULL; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci /* Unmap key buffer */ 2518c2ecf20Sopenharmony_ci dma_unmap_single(dev, ctx_p->user.key_dma_addr, max_key_buf_size, 2528c2ecf20Sopenharmony_ci DMA_TO_DEVICE); 2538c2ecf20Sopenharmony_ci dev_dbg(dev, "Unmapped key buffer key_dma_addr=%pad\n", 2548c2ecf20Sopenharmony_ci &ctx_p->user.key_dma_addr); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci /* Free key buffer in context */ 2578c2ecf20Sopenharmony_ci dev_dbg(dev, "Free key buffer in context. key=@%p\n", ctx_p->user.key); 2588c2ecf20Sopenharmony_ci kfree_sensitive(ctx_p->user.key); 2598c2ecf20Sopenharmony_ci} 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistruct tdes_keys { 2628c2ecf20Sopenharmony_ci u8 key1[DES_KEY_SIZE]; 2638c2ecf20Sopenharmony_ci u8 key2[DES_KEY_SIZE]; 2648c2ecf20Sopenharmony_ci u8 key3[DES_KEY_SIZE]; 2658c2ecf20Sopenharmony_ci}; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_cistatic enum cc_hw_crypto_key cc_slot_to_hw_key(u8 slot_num) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci switch (slot_num) { 2708c2ecf20Sopenharmony_ci case 0: 2718c2ecf20Sopenharmony_ci return KFDE0_KEY; 2728c2ecf20Sopenharmony_ci case 1: 2738c2ecf20Sopenharmony_ci return KFDE1_KEY; 2748c2ecf20Sopenharmony_ci case 2: 2758c2ecf20Sopenharmony_ci return KFDE2_KEY; 2768c2ecf20Sopenharmony_ci case 3: 2778c2ecf20Sopenharmony_ci return KFDE3_KEY; 2788c2ecf20Sopenharmony_ci } 2798c2ecf20Sopenharmony_ci return END_OF_KEYS; 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cistatic u8 cc_slot_to_cpp_key(u8 slot_num) 2838c2ecf20Sopenharmony_ci{ 2848c2ecf20Sopenharmony_ci return (slot_num - CC_FIRST_CPP_KEY_SLOT); 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistatic inline enum cc_key_type cc_slot_to_key_type(u8 slot_num) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci if (slot_num >= CC_FIRST_HW_KEY_SLOT && slot_num <= CC_LAST_HW_KEY_SLOT) 2908c2ecf20Sopenharmony_ci return CC_HW_PROTECTED_KEY; 2918c2ecf20Sopenharmony_ci else if (slot_num >= CC_FIRST_CPP_KEY_SLOT && 2928c2ecf20Sopenharmony_ci slot_num <= CC_LAST_CPP_KEY_SLOT) 2938c2ecf20Sopenharmony_ci return CC_POLICY_PROTECTED_KEY; 2948c2ecf20Sopenharmony_ci else 2958c2ecf20Sopenharmony_ci return CC_INVALID_PROTECTED_KEY; 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic int cc_cipher_sethkey(struct crypto_skcipher *sktfm, const u8 *key, 2998c2ecf20Sopenharmony_ci unsigned int keylen) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_skcipher_tfm(sktfm); 3028c2ecf20Sopenharmony_ci struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); 3038c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx_p->drvdata); 3048c2ecf20Sopenharmony_ci struct cc_hkey_info hki; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci dev_dbg(dev, "Setting HW key in context @%p for %s. keylen=%u\n", 3078c2ecf20Sopenharmony_ci ctx_p, crypto_tfm_alg_name(tfm), keylen); 3088c2ecf20Sopenharmony_ci dump_byte_array("key", key, keylen); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci /* STAT_PHASE_0: Init and sanity checks */ 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci /* This check the size of the protected key token */ 3138c2ecf20Sopenharmony_ci if (keylen != sizeof(hki)) { 3148c2ecf20Sopenharmony_ci dev_err(dev, "Unsupported protected key size %d.\n", keylen); 3158c2ecf20Sopenharmony_ci return -EINVAL; 3168c2ecf20Sopenharmony_ci } 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci memcpy(&hki, key, keylen); 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci /* The real key len for crypto op is the size of the HW key 3218c2ecf20Sopenharmony_ci * referenced by the HW key slot, not the hardware key token 3228c2ecf20Sopenharmony_ci */ 3238c2ecf20Sopenharmony_ci keylen = hki.keylen; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci if (validate_keys_sizes(ctx_p, keylen)) { 3268c2ecf20Sopenharmony_ci dev_dbg(dev, "Unsupported key size %d.\n", keylen); 3278c2ecf20Sopenharmony_ci return -EINVAL; 3288c2ecf20Sopenharmony_ci } 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci ctx_p->keylen = keylen; 3318c2ecf20Sopenharmony_ci ctx_p->fallback_on = false; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci switch (cc_slot_to_key_type(hki.hw_key1)) { 3348c2ecf20Sopenharmony_ci case CC_HW_PROTECTED_KEY: 3358c2ecf20Sopenharmony_ci if (ctx_p->flow_mode == S_DIN_to_SM4) { 3368c2ecf20Sopenharmony_ci dev_err(dev, "Only AES HW protected keys are supported\n"); 3378c2ecf20Sopenharmony_ci return -EINVAL; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci ctx_p->hw.key1_slot = cc_slot_to_hw_key(hki.hw_key1); 3418c2ecf20Sopenharmony_ci if (ctx_p->hw.key1_slot == END_OF_KEYS) { 3428c2ecf20Sopenharmony_ci dev_err(dev, "Unsupported hw key1 number (%d)\n", 3438c2ecf20Sopenharmony_ci hki.hw_key1); 3448c2ecf20Sopenharmony_ci return -EINVAL; 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci if (ctx_p->cipher_mode == DRV_CIPHER_XTS || 3488c2ecf20Sopenharmony_ci ctx_p->cipher_mode == DRV_CIPHER_ESSIV) { 3498c2ecf20Sopenharmony_ci if (hki.hw_key1 == hki.hw_key2) { 3508c2ecf20Sopenharmony_ci dev_err(dev, "Illegal hw key numbers (%d,%d)\n", 3518c2ecf20Sopenharmony_ci hki.hw_key1, hki.hw_key2); 3528c2ecf20Sopenharmony_ci return -EINVAL; 3538c2ecf20Sopenharmony_ci } 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci ctx_p->hw.key2_slot = cc_slot_to_hw_key(hki.hw_key2); 3568c2ecf20Sopenharmony_ci if (ctx_p->hw.key2_slot == END_OF_KEYS) { 3578c2ecf20Sopenharmony_ci dev_err(dev, "Unsupported hw key2 number (%d)\n", 3588c2ecf20Sopenharmony_ci hki.hw_key2); 3598c2ecf20Sopenharmony_ci return -EINVAL; 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci ctx_p->key_type = CC_HW_PROTECTED_KEY; 3648c2ecf20Sopenharmony_ci dev_dbg(dev, "HW protected key %d/%d set\n.", 3658c2ecf20Sopenharmony_ci ctx_p->hw.key1_slot, ctx_p->hw.key2_slot); 3668c2ecf20Sopenharmony_ci break; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci case CC_POLICY_PROTECTED_KEY: 3698c2ecf20Sopenharmony_ci if (ctx_p->drvdata->hw_rev < CC_HW_REV_713) { 3708c2ecf20Sopenharmony_ci dev_err(dev, "CPP keys not supported in this hardware revision.\n"); 3718c2ecf20Sopenharmony_ci return -EINVAL; 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci if (ctx_p->cipher_mode != DRV_CIPHER_CBC && 3758c2ecf20Sopenharmony_ci ctx_p->cipher_mode != DRV_CIPHER_CTR) { 3768c2ecf20Sopenharmony_ci dev_err(dev, "CPP keys only supported in CBC or CTR modes.\n"); 3778c2ecf20Sopenharmony_ci return -EINVAL; 3788c2ecf20Sopenharmony_ci } 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci ctx_p->cpp.slot = cc_slot_to_cpp_key(hki.hw_key1); 3818c2ecf20Sopenharmony_ci if (ctx_p->flow_mode == S_DIN_to_AES) 3828c2ecf20Sopenharmony_ci ctx_p->cpp.alg = CC_CPP_AES; 3838c2ecf20Sopenharmony_ci else /* Must be SM4 since due to sethkey registration */ 3848c2ecf20Sopenharmony_ci ctx_p->cpp.alg = CC_CPP_SM4; 3858c2ecf20Sopenharmony_ci ctx_p->key_type = CC_POLICY_PROTECTED_KEY; 3868c2ecf20Sopenharmony_ci dev_dbg(dev, "policy protected key alg: %d slot: %d.\n", 3878c2ecf20Sopenharmony_ci ctx_p->cpp.alg, ctx_p->cpp.slot); 3888c2ecf20Sopenharmony_ci break; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci default: 3918c2ecf20Sopenharmony_ci dev_err(dev, "Unsupported protected key (%d)\n", hki.hw_key1); 3928c2ecf20Sopenharmony_ci return -EINVAL; 3938c2ecf20Sopenharmony_ci } 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci return 0; 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistatic int cc_cipher_setkey(struct crypto_skcipher *sktfm, const u8 *key, 3998c2ecf20Sopenharmony_ci unsigned int keylen) 4008c2ecf20Sopenharmony_ci{ 4018c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_skcipher_tfm(sktfm); 4028c2ecf20Sopenharmony_ci struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); 4038c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx_p->drvdata); 4048c2ecf20Sopenharmony_ci struct cc_crypto_alg *cc_alg = 4058c2ecf20Sopenharmony_ci container_of(tfm->__crt_alg, struct cc_crypto_alg, 4068c2ecf20Sopenharmony_ci skcipher_alg.base); 4078c2ecf20Sopenharmony_ci unsigned int max_key_buf_size = cc_alg->skcipher_alg.max_keysize; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci dev_dbg(dev, "Setting key in context @%p for %s. keylen=%u\n", 4108c2ecf20Sopenharmony_ci ctx_p, crypto_tfm_alg_name(tfm), keylen); 4118c2ecf20Sopenharmony_ci dump_byte_array("key", key, keylen); 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci /* STAT_PHASE_0: Init and sanity checks */ 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci if (validate_keys_sizes(ctx_p, keylen)) { 4168c2ecf20Sopenharmony_ci dev_dbg(dev, "Invalid key size %d.\n", keylen); 4178c2ecf20Sopenharmony_ci return -EINVAL; 4188c2ecf20Sopenharmony_ci } 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) { 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci /* We only support 256 bit ESSIV-CBC-AES keys */ 4238c2ecf20Sopenharmony_ci if (keylen != AES_KEYSIZE_256) { 4248c2ecf20Sopenharmony_ci unsigned int flags = crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_MASK; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci if (likely(ctx_p->fallback_tfm)) { 4278c2ecf20Sopenharmony_ci ctx_p->fallback_on = true; 4288c2ecf20Sopenharmony_ci crypto_skcipher_clear_flags(ctx_p->fallback_tfm, 4298c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 4308c2ecf20Sopenharmony_ci crypto_skcipher_clear_flags(ctx_p->fallback_tfm, flags); 4318c2ecf20Sopenharmony_ci return crypto_skcipher_setkey(ctx_p->fallback_tfm, key, keylen); 4328c2ecf20Sopenharmony_ci } 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci dev_dbg(dev, "Unsupported key size %d and no fallback.\n", keylen); 4358c2ecf20Sopenharmony_ci return -EINVAL; 4368c2ecf20Sopenharmony_ci } 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci /* Internal ESSIV key buffer is double sized */ 4398c2ecf20Sopenharmony_ci max_key_buf_size <<= 1; 4408c2ecf20Sopenharmony_ci } 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci ctx_p->fallback_on = false; 4438c2ecf20Sopenharmony_ci ctx_p->key_type = CC_UNPROTECTED_KEY; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci /* 4468c2ecf20Sopenharmony_ci * Verify DES weak keys 4478c2ecf20Sopenharmony_ci * Note that we're dropping the expanded key since the 4488c2ecf20Sopenharmony_ci * HW does the expansion on its own. 4498c2ecf20Sopenharmony_ci */ 4508c2ecf20Sopenharmony_ci if (ctx_p->flow_mode == S_DIN_to_DES) { 4518c2ecf20Sopenharmony_ci if ((keylen == DES3_EDE_KEY_SIZE && 4528c2ecf20Sopenharmony_ci verify_skcipher_des3_key(sktfm, key)) || 4538c2ecf20Sopenharmony_ci verify_skcipher_des_key(sktfm, key)) { 4548c2ecf20Sopenharmony_ci dev_dbg(dev, "weak DES key"); 4558c2ecf20Sopenharmony_ci return -EINVAL; 4568c2ecf20Sopenharmony_ci } 4578c2ecf20Sopenharmony_ci } 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci if (ctx_p->cipher_mode == DRV_CIPHER_XTS && 4608c2ecf20Sopenharmony_ci xts_check_key(tfm, key, keylen)) { 4618c2ecf20Sopenharmony_ci dev_dbg(dev, "weak XTS key"); 4628c2ecf20Sopenharmony_ci return -EINVAL; 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci /* STAT_PHASE_1: Copy key to ctx */ 4668c2ecf20Sopenharmony_ci dma_sync_single_for_cpu(dev, ctx_p->user.key_dma_addr, 4678c2ecf20Sopenharmony_ci max_key_buf_size, DMA_TO_DEVICE); 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci memcpy(ctx_p->user.key, key, keylen); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci if (ctx_p->cipher_mode == DRV_CIPHER_ESSIV) { 4728c2ecf20Sopenharmony_ci /* sha256 for key2 - use sw implementation */ 4738c2ecf20Sopenharmony_ci int err; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci err = crypto_shash_tfm_digest(ctx_p->shash_tfm, 4768c2ecf20Sopenharmony_ci ctx_p->user.key, keylen, 4778c2ecf20Sopenharmony_ci ctx_p->user.key + keylen); 4788c2ecf20Sopenharmony_ci if (err) { 4798c2ecf20Sopenharmony_ci dev_err(dev, "Failed to hash ESSIV key.\n"); 4808c2ecf20Sopenharmony_ci return err; 4818c2ecf20Sopenharmony_ci } 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci keylen <<= 1; 4848c2ecf20Sopenharmony_ci } 4858c2ecf20Sopenharmony_ci dma_sync_single_for_device(dev, ctx_p->user.key_dma_addr, 4868c2ecf20Sopenharmony_ci max_key_buf_size, DMA_TO_DEVICE); 4878c2ecf20Sopenharmony_ci ctx_p->keylen = keylen; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci dev_dbg(dev, "return safely"); 4908c2ecf20Sopenharmony_ci return 0; 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cistatic int cc_out_setup_mode(struct cc_cipher_ctx *ctx_p) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci switch (ctx_p->flow_mode) { 4968c2ecf20Sopenharmony_ci case S_DIN_to_AES: 4978c2ecf20Sopenharmony_ci return S_AES_to_DOUT; 4988c2ecf20Sopenharmony_ci case S_DIN_to_DES: 4998c2ecf20Sopenharmony_ci return S_DES_to_DOUT; 5008c2ecf20Sopenharmony_ci case S_DIN_to_SM4: 5018c2ecf20Sopenharmony_ci return S_SM4_to_DOUT; 5028c2ecf20Sopenharmony_ci default: 5038c2ecf20Sopenharmony_ci return ctx_p->flow_mode; 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci} 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_cistatic void cc_setup_readiv_desc(struct crypto_tfm *tfm, 5088c2ecf20Sopenharmony_ci struct cipher_req_ctx *req_ctx, 5098c2ecf20Sopenharmony_ci unsigned int ivsize, struct cc_hw_desc desc[], 5108c2ecf20Sopenharmony_ci unsigned int *seq_size) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); 5138c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx_p->drvdata); 5148c2ecf20Sopenharmony_ci int cipher_mode = ctx_p->cipher_mode; 5158c2ecf20Sopenharmony_ci int flow_mode = cc_out_setup_mode(ctx_p); 5168c2ecf20Sopenharmony_ci int direction = req_ctx->gen_ctx.op_type; 5178c2ecf20Sopenharmony_ci dma_addr_t iv_dma_addr = req_ctx->gen_ctx.iv_dma_addr; 5188c2ecf20Sopenharmony_ci 5198c2ecf20Sopenharmony_ci if (ctx_p->key_type == CC_POLICY_PROTECTED_KEY) 5208c2ecf20Sopenharmony_ci return; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci switch (cipher_mode) { 5238c2ecf20Sopenharmony_ci case DRV_CIPHER_ECB: 5248c2ecf20Sopenharmony_ci break; 5258c2ecf20Sopenharmony_ci case DRV_CIPHER_CBC: 5268c2ecf20Sopenharmony_ci case DRV_CIPHER_CBC_CTS: 5278c2ecf20Sopenharmony_ci case DRV_CIPHER_CTR: 5288c2ecf20Sopenharmony_ci case DRV_CIPHER_OFB: 5298c2ecf20Sopenharmony_ci /* Read next IV */ 5308c2ecf20Sopenharmony_ci hw_desc_init(&desc[*seq_size]); 5318c2ecf20Sopenharmony_ci set_dout_dlli(&desc[*seq_size], iv_dma_addr, ivsize, NS_BIT, 1); 5328c2ecf20Sopenharmony_ci set_cipher_config0(&desc[*seq_size], direction); 5338c2ecf20Sopenharmony_ci set_flow_mode(&desc[*seq_size], flow_mode); 5348c2ecf20Sopenharmony_ci set_cipher_mode(&desc[*seq_size], cipher_mode); 5358c2ecf20Sopenharmony_ci if (cipher_mode == DRV_CIPHER_CTR || 5368c2ecf20Sopenharmony_ci cipher_mode == DRV_CIPHER_OFB) { 5378c2ecf20Sopenharmony_ci set_setup_mode(&desc[*seq_size], SETUP_WRITE_STATE1); 5388c2ecf20Sopenharmony_ci } else { 5398c2ecf20Sopenharmony_ci set_setup_mode(&desc[*seq_size], SETUP_WRITE_STATE0); 5408c2ecf20Sopenharmony_ci } 5418c2ecf20Sopenharmony_ci set_queue_last_ind(ctx_p->drvdata, &desc[*seq_size]); 5428c2ecf20Sopenharmony_ci (*seq_size)++; 5438c2ecf20Sopenharmony_ci break; 5448c2ecf20Sopenharmony_ci case DRV_CIPHER_XTS: 5458c2ecf20Sopenharmony_ci case DRV_CIPHER_ESSIV: 5468c2ecf20Sopenharmony_ci /* IV */ 5478c2ecf20Sopenharmony_ci hw_desc_init(&desc[*seq_size]); 5488c2ecf20Sopenharmony_ci set_setup_mode(&desc[*seq_size], SETUP_WRITE_STATE1); 5498c2ecf20Sopenharmony_ci set_cipher_mode(&desc[*seq_size], cipher_mode); 5508c2ecf20Sopenharmony_ci set_cipher_config0(&desc[*seq_size], direction); 5518c2ecf20Sopenharmony_ci set_flow_mode(&desc[*seq_size], flow_mode); 5528c2ecf20Sopenharmony_ci set_dout_dlli(&desc[*seq_size], iv_dma_addr, CC_AES_BLOCK_SIZE, 5538c2ecf20Sopenharmony_ci NS_BIT, 1); 5548c2ecf20Sopenharmony_ci set_queue_last_ind(ctx_p->drvdata, &desc[*seq_size]); 5558c2ecf20Sopenharmony_ci (*seq_size)++; 5568c2ecf20Sopenharmony_ci break; 5578c2ecf20Sopenharmony_ci default: 5588c2ecf20Sopenharmony_ci dev_err(dev, "Unsupported cipher mode (%d)\n", cipher_mode); 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci} 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_cistatic void cc_setup_state_desc(struct crypto_tfm *tfm, 5648c2ecf20Sopenharmony_ci struct cipher_req_ctx *req_ctx, 5658c2ecf20Sopenharmony_ci unsigned int ivsize, unsigned int nbytes, 5668c2ecf20Sopenharmony_ci struct cc_hw_desc desc[], 5678c2ecf20Sopenharmony_ci unsigned int *seq_size) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); 5708c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx_p->drvdata); 5718c2ecf20Sopenharmony_ci int cipher_mode = ctx_p->cipher_mode; 5728c2ecf20Sopenharmony_ci int flow_mode = ctx_p->flow_mode; 5738c2ecf20Sopenharmony_ci int direction = req_ctx->gen_ctx.op_type; 5748c2ecf20Sopenharmony_ci dma_addr_t iv_dma_addr = req_ctx->gen_ctx.iv_dma_addr; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci switch (cipher_mode) { 5778c2ecf20Sopenharmony_ci case DRV_CIPHER_ECB: 5788c2ecf20Sopenharmony_ci break; 5798c2ecf20Sopenharmony_ci case DRV_CIPHER_CBC: 5808c2ecf20Sopenharmony_ci case DRV_CIPHER_CBC_CTS: 5818c2ecf20Sopenharmony_ci case DRV_CIPHER_CTR: 5828c2ecf20Sopenharmony_ci case DRV_CIPHER_OFB: 5838c2ecf20Sopenharmony_ci /* Load IV */ 5848c2ecf20Sopenharmony_ci hw_desc_init(&desc[*seq_size]); 5858c2ecf20Sopenharmony_ci set_din_type(&desc[*seq_size], DMA_DLLI, iv_dma_addr, ivsize, 5868c2ecf20Sopenharmony_ci NS_BIT); 5878c2ecf20Sopenharmony_ci set_cipher_config0(&desc[*seq_size], direction); 5888c2ecf20Sopenharmony_ci set_flow_mode(&desc[*seq_size], flow_mode); 5898c2ecf20Sopenharmony_ci set_cipher_mode(&desc[*seq_size], cipher_mode); 5908c2ecf20Sopenharmony_ci if (cipher_mode == DRV_CIPHER_CTR || 5918c2ecf20Sopenharmony_ci cipher_mode == DRV_CIPHER_OFB) { 5928c2ecf20Sopenharmony_ci set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE1); 5938c2ecf20Sopenharmony_ci } else { 5948c2ecf20Sopenharmony_ci set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE0); 5958c2ecf20Sopenharmony_ci } 5968c2ecf20Sopenharmony_ci (*seq_size)++; 5978c2ecf20Sopenharmony_ci break; 5988c2ecf20Sopenharmony_ci case DRV_CIPHER_XTS: 5998c2ecf20Sopenharmony_ci case DRV_CIPHER_ESSIV: 6008c2ecf20Sopenharmony_ci break; 6018c2ecf20Sopenharmony_ci default: 6028c2ecf20Sopenharmony_ci dev_err(dev, "Unsupported cipher mode (%d)\n", cipher_mode); 6038c2ecf20Sopenharmony_ci } 6048c2ecf20Sopenharmony_ci} 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_cistatic void cc_setup_xex_state_desc(struct crypto_tfm *tfm, 6088c2ecf20Sopenharmony_ci struct cipher_req_ctx *req_ctx, 6098c2ecf20Sopenharmony_ci unsigned int ivsize, unsigned int nbytes, 6108c2ecf20Sopenharmony_ci struct cc_hw_desc desc[], 6118c2ecf20Sopenharmony_ci unsigned int *seq_size) 6128c2ecf20Sopenharmony_ci{ 6138c2ecf20Sopenharmony_ci struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); 6148c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx_p->drvdata); 6158c2ecf20Sopenharmony_ci int cipher_mode = ctx_p->cipher_mode; 6168c2ecf20Sopenharmony_ci int flow_mode = ctx_p->flow_mode; 6178c2ecf20Sopenharmony_ci int direction = req_ctx->gen_ctx.op_type; 6188c2ecf20Sopenharmony_ci dma_addr_t key_dma_addr = ctx_p->user.key_dma_addr; 6198c2ecf20Sopenharmony_ci unsigned int key_len = (ctx_p->keylen / 2); 6208c2ecf20Sopenharmony_ci dma_addr_t iv_dma_addr = req_ctx->gen_ctx.iv_dma_addr; 6218c2ecf20Sopenharmony_ci unsigned int key_offset = key_len; 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci switch (cipher_mode) { 6248c2ecf20Sopenharmony_ci case DRV_CIPHER_ECB: 6258c2ecf20Sopenharmony_ci break; 6268c2ecf20Sopenharmony_ci case DRV_CIPHER_CBC: 6278c2ecf20Sopenharmony_ci case DRV_CIPHER_CBC_CTS: 6288c2ecf20Sopenharmony_ci case DRV_CIPHER_CTR: 6298c2ecf20Sopenharmony_ci case DRV_CIPHER_OFB: 6308c2ecf20Sopenharmony_ci break; 6318c2ecf20Sopenharmony_ci case DRV_CIPHER_XTS: 6328c2ecf20Sopenharmony_ci case DRV_CIPHER_ESSIV: 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci if (cipher_mode == DRV_CIPHER_ESSIV) 6358c2ecf20Sopenharmony_ci key_len = SHA256_DIGEST_SIZE; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci /* load XEX key */ 6388c2ecf20Sopenharmony_ci hw_desc_init(&desc[*seq_size]); 6398c2ecf20Sopenharmony_ci set_cipher_mode(&desc[*seq_size], cipher_mode); 6408c2ecf20Sopenharmony_ci set_cipher_config0(&desc[*seq_size], direction); 6418c2ecf20Sopenharmony_ci if (cc_key_type(tfm) == CC_HW_PROTECTED_KEY) { 6428c2ecf20Sopenharmony_ci set_hw_crypto_key(&desc[*seq_size], 6438c2ecf20Sopenharmony_ci ctx_p->hw.key2_slot); 6448c2ecf20Sopenharmony_ci } else { 6458c2ecf20Sopenharmony_ci set_din_type(&desc[*seq_size], DMA_DLLI, 6468c2ecf20Sopenharmony_ci (key_dma_addr + key_offset), 6478c2ecf20Sopenharmony_ci key_len, NS_BIT); 6488c2ecf20Sopenharmony_ci } 6498c2ecf20Sopenharmony_ci set_xex_data_unit_size(&desc[*seq_size], nbytes); 6508c2ecf20Sopenharmony_ci set_flow_mode(&desc[*seq_size], S_DIN_to_AES2); 6518c2ecf20Sopenharmony_ci set_key_size_aes(&desc[*seq_size], key_len); 6528c2ecf20Sopenharmony_ci set_setup_mode(&desc[*seq_size], SETUP_LOAD_XEX_KEY); 6538c2ecf20Sopenharmony_ci (*seq_size)++; 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci /* Load IV */ 6568c2ecf20Sopenharmony_ci hw_desc_init(&desc[*seq_size]); 6578c2ecf20Sopenharmony_ci set_setup_mode(&desc[*seq_size], SETUP_LOAD_STATE1); 6588c2ecf20Sopenharmony_ci set_cipher_mode(&desc[*seq_size], cipher_mode); 6598c2ecf20Sopenharmony_ci set_cipher_config0(&desc[*seq_size], direction); 6608c2ecf20Sopenharmony_ci set_key_size_aes(&desc[*seq_size], key_len); 6618c2ecf20Sopenharmony_ci set_flow_mode(&desc[*seq_size], flow_mode); 6628c2ecf20Sopenharmony_ci set_din_type(&desc[*seq_size], DMA_DLLI, iv_dma_addr, 6638c2ecf20Sopenharmony_ci CC_AES_BLOCK_SIZE, NS_BIT); 6648c2ecf20Sopenharmony_ci (*seq_size)++; 6658c2ecf20Sopenharmony_ci break; 6668c2ecf20Sopenharmony_ci default: 6678c2ecf20Sopenharmony_ci dev_err(dev, "Unsupported cipher mode (%d)\n", cipher_mode); 6688c2ecf20Sopenharmony_ci } 6698c2ecf20Sopenharmony_ci} 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_cistatic int cc_out_flow_mode(struct cc_cipher_ctx *ctx_p) 6728c2ecf20Sopenharmony_ci{ 6738c2ecf20Sopenharmony_ci switch (ctx_p->flow_mode) { 6748c2ecf20Sopenharmony_ci case S_DIN_to_AES: 6758c2ecf20Sopenharmony_ci return DIN_AES_DOUT; 6768c2ecf20Sopenharmony_ci case S_DIN_to_DES: 6778c2ecf20Sopenharmony_ci return DIN_DES_DOUT; 6788c2ecf20Sopenharmony_ci case S_DIN_to_SM4: 6798c2ecf20Sopenharmony_ci return DIN_SM4_DOUT; 6808c2ecf20Sopenharmony_ci default: 6818c2ecf20Sopenharmony_ci return ctx_p->flow_mode; 6828c2ecf20Sopenharmony_ci } 6838c2ecf20Sopenharmony_ci} 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_cistatic void cc_setup_key_desc(struct crypto_tfm *tfm, 6868c2ecf20Sopenharmony_ci struct cipher_req_ctx *req_ctx, 6878c2ecf20Sopenharmony_ci unsigned int nbytes, struct cc_hw_desc desc[], 6888c2ecf20Sopenharmony_ci unsigned int *seq_size) 6898c2ecf20Sopenharmony_ci{ 6908c2ecf20Sopenharmony_ci struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); 6918c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx_p->drvdata); 6928c2ecf20Sopenharmony_ci int cipher_mode = ctx_p->cipher_mode; 6938c2ecf20Sopenharmony_ci int flow_mode = ctx_p->flow_mode; 6948c2ecf20Sopenharmony_ci int direction = req_ctx->gen_ctx.op_type; 6958c2ecf20Sopenharmony_ci dma_addr_t key_dma_addr = ctx_p->user.key_dma_addr; 6968c2ecf20Sopenharmony_ci unsigned int key_len = ctx_p->keylen; 6978c2ecf20Sopenharmony_ci unsigned int din_size; 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci switch (cipher_mode) { 7008c2ecf20Sopenharmony_ci case DRV_CIPHER_CBC: 7018c2ecf20Sopenharmony_ci case DRV_CIPHER_CBC_CTS: 7028c2ecf20Sopenharmony_ci case DRV_CIPHER_CTR: 7038c2ecf20Sopenharmony_ci case DRV_CIPHER_OFB: 7048c2ecf20Sopenharmony_ci case DRV_CIPHER_ECB: 7058c2ecf20Sopenharmony_ci /* Load key */ 7068c2ecf20Sopenharmony_ci hw_desc_init(&desc[*seq_size]); 7078c2ecf20Sopenharmony_ci set_cipher_mode(&desc[*seq_size], cipher_mode); 7088c2ecf20Sopenharmony_ci set_cipher_config0(&desc[*seq_size], direction); 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci if (cc_key_type(tfm) == CC_POLICY_PROTECTED_KEY) { 7118c2ecf20Sopenharmony_ci /* We use the AES key size coding for all CPP algs */ 7128c2ecf20Sopenharmony_ci set_key_size_aes(&desc[*seq_size], key_len); 7138c2ecf20Sopenharmony_ci set_cpp_crypto_key(&desc[*seq_size], ctx_p->cpp.slot); 7148c2ecf20Sopenharmony_ci flow_mode = cc_out_flow_mode(ctx_p); 7158c2ecf20Sopenharmony_ci } else { 7168c2ecf20Sopenharmony_ci if (flow_mode == S_DIN_to_AES) { 7178c2ecf20Sopenharmony_ci if (cc_key_type(tfm) == CC_HW_PROTECTED_KEY) { 7188c2ecf20Sopenharmony_ci set_hw_crypto_key(&desc[*seq_size], 7198c2ecf20Sopenharmony_ci ctx_p->hw.key1_slot); 7208c2ecf20Sopenharmony_ci } else { 7218c2ecf20Sopenharmony_ci /* CC_POLICY_UNPROTECTED_KEY 7228c2ecf20Sopenharmony_ci * Invalid keys are filtered out in 7238c2ecf20Sopenharmony_ci * sethkey() 7248c2ecf20Sopenharmony_ci */ 7258c2ecf20Sopenharmony_ci din_size = (key_len == 24) ? 7268c2ecf20Sopenharmony_ci AES_MAX_KEY_SIZE : key_len; 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci set_din_type(&desc[*seq_size], DMA_DLLI, 7298c2ecf20Sopenharmony_ci key_dma_addr, din_size, 7308c2ecf20Sopenharmony_ci NS_BIT); 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci set_key_size_aes(&desc[*seq_size], key_len); 7338c2ecf20Sopenharmony_ci } else { 7348c2ecf20Sopenharmony_ci /*des*/ 7358c2ecf20Sopenharmony_ci set_din_type(&desc[*seq_size], DMA_DLLI, 7368c2ecf20Sopenharmony_ci key_dma_addr, key_len, NS_BIT); 7378c2ecf20Sopenharmony_ci set_key_size_des(&desc[*seq_size], key_len); 7388c2ecf20Sopenharmony_ci } 7398c2ecf20Sopenharmony_ci set_setup_mode(&desc[*seq_size], SETUP_LOAD_KEY0); 7408c2ecf20Sopenharmony_ci } 7418c2ecf20Sopenharmony_ci set_flow_mode(&desc[*seq_size], flow_mode); 7428c2ecf20Sopenharmony_ci (*seq_size)++; 7438c2ecf20Sopenharmony_ci break; 7448c2ecf20Sopenharmony_ci case DRV_CIPHER_XTS: 7458c2ecf20Sopenharmony_ci case DRV_CIPHER_ESSIV: 7468c2ecf20Sopenharmony_ci /* Load AES key */ 7478c2ecf20Sopenharmony_ci hw_desc_init(&desc[*seq_size]); 7488c2ecf20Sopenharmony_ci set_cipher_mode(&desc[*seq_size], cipher_mode); 7498c2ecf20Sopenharmony_ci set_cipher_config0(&desc[*seq_size], direction); 7508c2ecf20Sopenharmony_ci if (cc_key_type(tfm) == CC_HW_PROTECTED_KEY) { 7518c2ecf20Sopenharmony_ci set_hw_crypto_key(&desc[*seq_size], 7528c2ecf20Sopenharmony_ci ctx_p->hw.key1_slot); 7538c2ecf20Sopenharmony_ci } else { 7548c2ecf20Sopenharmony_ci set_din_type(&desc[*seq_size], DMA_DLLI, key_dma_addr, 7558c2ecf20Sopenharmony_ci (key_len / 2), NS_BIT); 7568c2ecf20Sopenharmony_ci } 7578c2ecf20Sopenharmony_ci set_key_size_aes(&desc[*seq_size], (key_len / 2)); 7588c2ecf20Sopenharmony_ci set_flow_mode(&desc[*seq_size], flow_mode); 7598c2ecf20Sopenharmony_ci set_setup_mode(&desc[*seq_size], SETUP_LOAD_KEY0); 7608c2ecf20Sopenharmony_ci (*seq_size)++; 7618c2ecf20Sopenharmony_ci break; 7628c2ecf20Sopenharmony_ci default: 7638c2ecf20Sopenharmony_ci dev_err(dev, "Unsupported cipher mode (%d)\n", cipher_mode); 7648c2ecf20Sopenharmony_ci } 7658c2ecf20Sopenharmony_ci} 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_cistatic void cc_setup_mlli_desc(struct crypto_tfm *tfm, 7688c2ecf20Sopenharmony_ci struct cipher_req_ctx *req_ctx, 7698c2ecf20Sopenharmony_ci struct scatterlist *dst, struct scatterlist *src, 7708c2ecf20Sopenharmony_ci unsigned int nbytes, void *areq, 7718c2ecf20Sopenharmony_ci struct cc_hw_desc desc[], unsigned int *seq_size) 7728c2ecf20Sopenharmony_ci{ 7738c2ecf20Sopenharmony_ci struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); 7748c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx_p->drvdata); 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci if (req_ctx->dma_buf_type == CC_DMA_BUF_MLLI) { 7778c2ecf20Sopenharmony_ci /* bypass */ 7788c2ecf20Sopenharmony_ci dev_dbg(dev, " bypass params addr %pad length 0x%X addr 0x%08X\n", 7798c2ecf20Sopenharmony_ci &req_ctx->mlli_params.mlli_dma_addr, 7808c2ecf20Sopenharmony_ci req_ctx->mlli_params.mlli_len, 7818c2ecf20Sopenharmony_ci ctx_p->drvdata->mlli_sram_addr); 7828c2ecf20Sopenharmony_ci hw_desc_init(&desc[*seq_size]); 7838c2ecf20Sopenharmony_ci set_din_type(&desc[*seq_size], DMA_DLLI, 7848c2ecf20Sopenharmony_ci req_ctx->mlli_params.mlli_dma_addr, 7858c2ecf20Sopenharmony_ci req_ctx->mlli_params.mlli_len, NS_BIT); 7868c2ecf20Sopenharmony_ci set_dout_sram(&desc[*seq_size], 7878c2ecf20Sopenharmony_ci ctx_p->drvdata->mlli_sram_addr, 7888c2ecf20Sopenharmony_ci req_ctx->mlli_params.mlli_len); 7898c2ecf20Sopenharmony_ci set_flow_mode(&desc[*seq_size], BYPASS); 7908c2ecf20Sopenharmony_ci (*seq_size)++; 7918c2ecf20Sopenharmony_ci } 7928c2ecf20Sopenharmony_ci} 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_cistatic void cc_setup_flow_desc(struct crypto_tfm *tfm, 7958c2ecf20Sopenharmony_ci struct cipher_req_ctx *req_ctx, 7968c2ecf20Sopenharmony_ci struct scatterlist *dst, struct scatterlist *src, 7978c2ecf20Sopenharmony_ci unsigned int nbytes, struct cc_hw_desc desc[], 7988c2ecf20Sopenharmony_ci unsigned int *seq_size) 7998c2ecf20Sopenharmony_ci{ 8008c2ecf20Sopenharmony_ci struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); 8018c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx_p->drvdata); 8028c2ecf20Sopenharmony_ci unsigned int flow_mode = cc_out_flow_mode(ctx_p); 8038c2ecf20Sopenharmony_ci bool last_desc = (ctx_p->key_type == CC_POLICY_PROTECTED_KEY || 8048c2ecf20Sopenharmony_ci ctx_p->cipher_mode == DRV_CIPHER_ECB); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci /* Process */ 8078c2ecf20Sopenharmony_ci if (req_ctx->dma_buf_type == CC_DMA_BUF_DLLI) { 8088c2ecf20Sopenharmony_ci dev_dbg(dev, " data params addr %pad length 0x%X\n", 8098c2ecf20Sopenharmony_ci &sg_dma_address(src), nbytes); 8108c2ecf20Sopenharmony_ci dev_dbg(dev, " data params addr %pad length 0x%X\n", 8118c2ecf20Sopenharmony_ci &sg_dma_address(dst), nbytes); 8128c2ecf20Sopenharmony_ci hw_desc_init(&desc[*seq_size]); 8138c2ecf20Sopenharmony_ci set_din_type(&desc[*seq_size], DMA_DLLI, sg_dma_address(src), 8148c2ecf20Sopenharmony_ci nbytes, NS_BIT); 8158c2ecf20Sopenharmony_ci set_dout_dlli(&desc[*seq_size], sg_dma_address(dst), 8168c2ecf20Sopenharmony_ci nbytes, NS_BIT, (!last_desc ? 0 : 1)); 8178c2ecf20Sopenharmony_ci if (last_desc) 8188c2ecf20Sopenharmony_ci set_queue_last_ind(ctx_p->drvdata, &desc[*seq_size]); 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci set_flow_mode(&desc[*seq_size], flow_mode); 8218c2ecf20Sopenharmony_ci (*seq_size)++; 8228c2ecf20Sopenharmony_ci } else { 8238c2ecf20Sopenharmony_ci hw_desc_init(&desc[*seq_size]); 8248c2ecf20Sopenharmony_ci set_din_type(&desc[*seq_size], DMA_MLLI, 8258c2ecf20Sopenharmony_ci ctx_p->drvdata->mlli_sram_addr, 8268c2ecf20Sopenharmony_ci req_ctx->in_mlli_nents, NS_BIT); 8278c2ecf20Sopenharmony_ci if (req_ctx->out_nents == 0) { 8288c2ecf20Sopenharmony_ci dev_dbg(dev, " din/dout params addr 0x%08X addr 0x%08X\n", 8298c2ecf20Sopenharmony_ci ctx_p->drvdata->mlli_sram_addr, 8308c2ecf20Sopenharmony_ci ctx_p->drvdata->mlli_sram_addr); 8318c2ecf20Sopenharmony_ci set_dout_mlli(&desc[*seq_size], 8328c2ecf20Sopenharmony_ci ctx_p->drvdata->mlli_sram_addr, 8338c2ecf20Sopenharmony_ci req_ctx->in_mlli_nents, NS_BIT, 8348c2ecf20Sopenharmony_ci (!last_desc ? 0 : 1)); 8358c2ecf20Sopenharmony_ci } else { 8368c2ecf20Sopenharmony_ci dev_dbg(dev, " din/dout params addr 0x%08X addr 0x%08X\n", 8378c2ecf20Sopenharmony_ci ctx_p->drvdata->mlli_sram_addr, 8388c2ecf20Sopenharmony_ci ctx_p->drvdata->mlli_sram_addr + 8398c2ecf20Sopenharmony_ci (u32)LLI_ENTRY_BYTE_SIZE * req_ctx->in_nents); 8408c2ecf20Sopenharmony_ci set_dout_mlli(&desc[*seq_size], 8418c2ecf20Sopenharmony_ci (ctx_p->drvdata->mlli_sram_addr + 8428c2ecf20Sopenharmony_ci (LLI_ENTRY_BYTE_SIZE * 8438c2ecf20Sopenharmony_ci req_ctx->in_mlli_nents)), 8448c2ecf20Sopenharmony_ci req_ctx->out_mlli_nents, NS_BIT, 8458c2ecf20Sopenharmony_ci (!last_desc ? 0 : 1)); 8468c2ecf20Sopenharmony_ci } 8478c2ecf20Sopenharmony_ci if (last_desc) 8488c2ecf20Sopenharmony_ci set_queue_last_ind(ctx_p->drvdata, &desc[*seq_size]); 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci set_flow_mode(&desc[*seq_size], flow_mode); 8518c2ecf20Sopenharmony_ci (*seq_size)++; 8528c2ecf20Sopenharmony_ci } 8538c2ecf20Sopenharmony_ci} 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_cistatic void cc_cipher_complete(struct device *dev, void *cc_req, int err) 8568c2ecf20Sopenharmony_ci{ 8578c2ecf20Sopenharmony_ci struct skcipher_request *req = (struct skcipher_request *)cc_req; 8588c2ecf20Sopenharmony_ci struct scatterlist *dst = req->dst; 8598c2ecf20Sopenharmony_ci struct scatterlist *src = req->src; 8608c2ecf20Sopenharmony_ci struct cipher_req_ctx *req_ctx = skcipher_request_ctx(req); 8618c2ecf20Sopenharmony_ci struct crypto_skcipher *sk_tfm = crypto_skcipher_reqtfm(req); 8628c2ecf20Sopenharmony_ci unsigned int ivsize = crypto_skcipher_ivsize(sk_tfm); 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci if (err != -EINPROGRESS) { 8658c2ecf20Sopenharmony_ci /* Not a BACKLOG notification */ 8668c2ecf20Sopenharmony_ci cc_unmap_cipher_request(dev, req_ctx, ivsize, src, dst); 8678c2ecf20Sopenharmony_ci memcpy(req->iv, req_ctx->iv, ivsize); 8688c2ecf20Sopenharmony_ci kfree_sensitive(req_ctx->iv); 8698c2ecf20Sopenharmony_ci } 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci skcipher_request_complete(req, err); 8728c2ecf20Sopenharmony_ci} 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_cistatic int cc_cipher_process(struct skcipher_request *req, 8758c2ecf20Sopenharmony_ci enum drv_crypto_direction direction) 8768c2ecf20Sopenharmony_ci{ 8778c2ecf20Sopenharmony_ci struct crypto_skcipher *sk_tfm = crypto_skcipher_reqtfm(req); 8788c2ecf20Sopenharmony_ci struct crypto_tfm *tfm = crypto_skcipher_tfm(sk_tfm); 8798c2ecf20Sopenharmony_ci struct cipher_req_ctx *req_ctx = skcipher_request_ctx(req); 8808c2ecf20Sopenharmony_ci unsigned int ivsize = crypto_skcipher_ivsize(sk_tfm); 8818c2ecf20Sopenharmony_ci struct scatterlist *dst = req->dst; 8828c2ecf20Sopenharmony_ci struct scatterlist *src = req->src; 8838c2ecf20Sopenharmony_ci unsigned int nbytes = req->cryptlen; 8848c2ecf20Sopenharmony_ci void *iv = req->iv; 8858c2ecf20Sopenharmony_ci struct cc_cipher_ctx *ctx_p = crypto_tfm_ctx(tfm); 8868c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(ctx_p->drvdata); 8878c2ecf20Sopenharmony_ci struct cc_hw_desc desc[MAX_SKCIPHER_SEQ_LEN]; 8888c2ecf20Sopenharmony_ci struct cc_crypto_req cc_req = {}; 8898c2ecf20Sopenharmony_ci int rc; 8908c2ecf20Sopenharmony_ci unsigned int seq_len = 0; 8918c2ecf20Sopenharmony_ci gfp_t flags = cc_gfp_flags(&req->base); 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci dev_dbg(dev, "%s req=%p iv=%p nbytes=%d\n", 8948c2ecf20Sopenharmony_ci ((direction == DRV_CRYPTO_DIRECTION_ENCRYPT) ? 8958c2ecf20Sopenharmony_ci "Encrypt" : "Decrypt"), req, iv, nbytes); 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci /* STAT_PHASE_0: Init and sanity checks */ 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci if (validate_data_size(ctx_p, nbytes)) { 9008c2ecf20Sopenharmony_ci dev_dbg(dev, "Unsupported data size %d.\n", nbytes); 9018c2ecf20Sopenharmony_ci rc = -EINVAL; 9028c2ecf20Sopenharmony_ci goto exit_process; 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci if (nbytes == 0) { 9058c2ecf20Sopenharmony_ci /* No data to process is valid */ 9068c2ecf20Sopenharmony_ci rc = 0; 9078c2ecf20Sopenharmony_ci goto exit_process; 9088c2ecf20Sopenharmony_ci } 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci if (ctx_p->fallback_on) { 9118c2ecf20Sopenharmony_ci struct skcipher_request *subreq = skcipher_request_ctx(req); 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci *subreq = *req; 9148c2ecf20Sopenharmony_ci skcipher_request_set_tfm(subreq, ctx_p->fallback_tfm); 9158c2ecf20Sopenharmony_ci if (direction == DRV_CRYPTO_DIRECTION_ENCRYPT) 9168c2ecf20Sopenharmony_ci return crypto_skcipher_encrypt(subreq); 9178c2ecf20Sopenharmony_ci else 9188c2ecf20Sopenharmony_ci return crypto_skcipher_decrypt(subreq); 9198c2ecf20Sopenharmony_ci } 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci /* The IV we are handed may be allocted from the stack so 9228c2ecf20Sopenharmony_ci * we must copy it to a DMAable buffer before use. 9238c2ecf20Sopenharmony_ci */ 9248c2ecf20Sopenharmony_ci req_ctx->iv = kmemdup(iv, ivsize, flags); 9258c2ecf20Sopenharmony_ci if (!req_ctx->iv) { 9268c2ecf20Sopenharmony_ci rc = -ENOMEM; 9278c2ecf20Sopenharmony_ci goto exit_process; 9288c2ecf20Sopenharmony_ci } 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci /* Setup request structure */ 9318c2ecf20Sopenharmony_ci cc_req.user_cb = cc_cipher_complete; 9328c2ecf20Sopenharmony_ci cc_req.user_arg = req; 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci /* Setup CPP operation details */ 9358c2ecf20Sopenharmony_ci if (ctx_p->key_type == CC_POLICY_PROTECTED_KEY) { 9368c2ecf20Sopenharmony_ci cc_req.cpp.is_cpp = true; 9378c2ecf20Sopenharmony_ci cc_req.cpp.alg = ctx_p->cpp.alg; 9388c2ecf20Sopenharmony_ci cc_req.cpp.slot = ctx_p->cpp.slot; 9398c2ecf20Sopenharmony_ci } 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci /* Setup request context */ 9428c2ecf20Sopenharmony_ci req_ctx->gen_ctx.op_type = direction; 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_ci /* STAT_PHASE_1: Map buffers */ 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci rc = cc_map_cipher_request(ctx_p->drvdata, req_ctx, ivsize, nbytes, 9478c2ecf20Sopenharmony_ci req_ctx->iv, src, dst, flags); 9488c2ecf20Sopenharmony_ci if (rc) { 9498c2ecf20Sopenharmony_ci dev_err(dev, "map_request() failed\n"); 9508c2ecf20Sopenharmony_ci goto exit_process; 9518c2ecf20Sopenharmony_ci } 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci /* STAT_PHASE_2: Create sequence */ 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci /* Setup state (IV) */ 9568c2ecf20Sopenharmony_ci cc_setup_state_desc(tfm, req_ctx, ivsize, nbytes, desc, &seq_len); 9578c2ecf20Sopenharmony_ci /* Setup MLLI line, if needed */ 9588c2ecf20Sopenharmony_ci cc_setup_mlli_desc(tfm, req_ctx, dst, src, nbytes, req, desc, &seq_len); 9598c2ecf20Sopenharmony_ci /* Setup key */ 9608c2ecf20Sopenharmony_ci cc_setup_key_desc(tfm, req_ctx, nbytes, desc, &seq_len); 9618c2ecf20Sopenharmony_ci /* Setup state (IV and XEX key) */ 9628c2ecf20Sopenharmony_ci cc_setup_xex_state_desc(tfm, req_ctx, ivsize, nbytes, desc, &seq_len); 9638c2ecf20Sopenharmony_ci /* Data processing */ 9648c2ecf20Sopenharmony_ci cc_setup_flow_desc(tfm, req_ctx, dst, src, nbytes, desc, &seq_len); 9658c2ecf20Sopenharmony_ci /* Read next IV */ 9668c2ecf20Sopenharmony_ci cc_setup_readiv_desc(tfm, req_ctx, ivsize, desc, &seq_len); 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci /* STAT_PHASE_3: Lock HW and push sequence */ 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci rc = cc_send_request(ctx_p->drvdata, &cc_req, desc, seq_len, 9718c2ecf20Sopenharmony_ci &req->base); 9728c2ecf20Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 9738c2ecf20Sopenharmony_ci /* Failed to send the request or request completed 9748c2ecf20Sopenharmony_ci * synchronously 9758c2ecf20Sopenharmony_ci */ 9768c2ecf20Sopenharmony_ci cc_unmap_cipher_request(dev, req_ctx, ivsize, src, dst); 9778c2ecf20Sopenharmony_ci } 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ciexit_process: 9808c2ecf20Sopenharmony_ci if (rc != -EINPROGRESS && rc != -EBUSY) { 9818c2ecf20Sopenharmony_ci kfree_sensitive(req_ctx->iv); 9828c2ecf20Sopenharmony_ci } 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci return rc; 9858c2ecf20Sopenharmony_ci} 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_cistatic int cc_cipher_encrypt(struct skcipher_request *req) 9888c2ecf20Sopenharmony_ci{ 9898c2ecf20Sopenharmony_ci struct cipher_req_ctx *req_ctx = skcipher_request_ctx(req); 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci memset(req_ctx, 0, sizeof(*req_ctx)); 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci return cc_cipher_process(req, DRV_CRYPTO_DIRECTION_ENCRYPT); 9948c2ecf20Sopenharmony_ci} 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_cistatic int cc_cipher_decrypt(struct skcipher_request *req) 9978c2ecf20Sopenharmony_ci{ 9988c2ecf20Sopenharmony_ci struct cipher_req_ctx *req_ctx = skcipher_request_ctx(req); 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci memset(req_ctx, 0, sizeof(*req_ctx)); 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci return cc_cipher_process(req, DRV_CRYPTO_DIRECTION_DECRYPT); 10038c2ecf20Sopenharmony_ci} 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci/* Block cipher alg */ 10068c2ecf20Sopenharmony_cistatic const struct cc_alg_template skcipher_algs[] = { 10078c2ecf20Sopenharmony_ci { 10088c2ecf20Sopenharmony_ci .name = "xts(paes)", 10098c2ecf20Sopenharmony_ci .driver_name = "xts-paes-ccree", 10108c2ecf20Sopenharmony_ci .blocksize = 1, 10118c2ecf20Sopenharmony_ci .template_skcipher = { 10128c2ecf20Sopenharmony_ci .setkey = cc_cipher_sethkey, 10138c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 10148c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 10158c2ecf20Sopenharmony_ci .min_keysize = CC_HW_KEY_SIZE, 10168c2ecf20Sopenharmony_ci .max_keysize = CC_HW_KEY_SIZE, 10178c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 10188c2ecf20Sopenharmony_ci }, 10198c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_XTS, 10208c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 10218c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 10228c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 10238c2ecf20Sopenharmony_ci .sec_func = true, 10248c2ecf20Sopenharmony_ci }, 10258c2ecf20Sopenharmony_ci { 10268c2ecf20Sopenharmony_ci .name = "essiv(cbc(paes),sha256)", 10278c2ecf20Sopenharmony_ci .driver_name = "essiv-paes-ccree", 10288c2ecf20Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 10298c2ecf20Sopenharmony_ci .template_skcipher = { 10308c2ecf20Sopenharmony_ci .setkey = cc_cipher_sethkey, 10318c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 10328c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 10338c2ecf20Sopenharmony_ci .min_keysize = CC_HW_KEY_SIZE, 10348c2ecf20Sopenharmony_ci .max_keysize = CC_HW_KEY_SIZE, 10358c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 10368c2ecf20Sopenharmony_ci }, 10378c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_ESSIV, 10388c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 10398c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_712, 10408c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 10418c2ecf20Sopenharmony_ci .sec_func = true, 10428c2ecf20Sopenharmony_ci }, 10438c2ecf20Sopenharmony_ci { 10448c2ecf20Sopenharmony_ci .name = "ecb(paes)", 10458c2ecf20Sopenharmony_ci .driver_name = "ecb-paes-ccree", 10468c2ecf20Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 10478c2ecf20Sopenharmony_ci .template_skcipher = { 10488c2ecf20Sopenharmony_ci .setkey = cc_cipher_sethkey, 10498c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 10508c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 10518c2ecf20Sopenharmony_ci .min_keysize = CC_HW_KEY_SIZE, 10528c2ecf20Sopenharmony_ci .max_keysize = CC_HW_KEY_SIZE, 10538c2ecf20Sopenharmony_ci .ivsize = 0, 10548c2ecf20Sopenharmony_ci }, 10558c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_ECB, 10568c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 10578c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_712, 10588c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 10598c2ecf20Sopenharmony_ci .sec_func = true, 10608c2ecf20Sopenharmony_ci }, 10618c2ecf20Sopenharmony_ci { 10628c2ecf20Sopenharmony_ci .name = "cbc(paes)", 10638c2ecf20Sopenharmony_ci .driver_name = "cbc-paes-ccree", 10648c2ecf20Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 10658c2ecf20Sopenharmony_ci .template_skcipher = { 10668c2ecf20Sopenharmony_ci .setkey = cc_cipher_sethkey, 10678c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 10688c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 10698c2ecf20Sopenharmony_ci .min_keysize = CC_HW_KEY_SIZE, 10708c2ecf20Sopenharmony_ci .max_keysize = CC_HW_KEY_SIZE, 10718c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 10728c2ecf20Sopenharmony_ci }, 10738c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_CBC, 10748c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 10758c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_712, 10768c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 10778c2ecf20Sopenharmony_ci .sec_func = true, 10788c2ecf20Sopenharmony_ci }, 10798c2ecf20Sopenharmony_ci { 10808c2ecf20Sopenharmony_ci .name = "ofb(paes)", 10818c2ecf20Sopenharmony_ci .driver_name = "ofb-paes-ccree", 10828c2ecf20Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 10838c2ecf20Sopenharmony_ci .template_skcipher = { 10848c2ecf20Sopenharmony_ci .setkey = cc_cipher_sethkey, 10858c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 10868c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 10878c2ecf20Sopenharmony_ci .min_keysize = CC_HW_KEY_SIZE, 10888c2ecf20Sopenharmony_ci .max_keysize = CC_HW_KEY_SIZE, 10898c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 10908c2ecf20Sopenharmony_ci }, 10918c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_OFB, 10928c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 10938c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_712, 10948c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 10958c2ecf20Sopenharmony_ci .sec_func = true, 10968c2ecf20Sopenharmony_ci }, 10978c2ecf20Sopenharmony_ci { 10988c2ecf20Sopenharmony_ci .name = "cts(cbc(paes))", 10998c2ecf20Sopenharmony_ci .driver_name = "cts-cbc-paes-ccree", 11008c2ecf20Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 11018c2ecf20Sopenharmony_ci .template_skcipher = { 11028c2ecf20Sopenharmony_ci .setkey = cc_cipher_sethkey, 11038c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 11048c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 11058c2ecf20Sopenharmony_ci .min_keysize = CC_HW_KEY_SIZE, 11068c2ecf20Sopenharmony_ci .max_keysize = CC_HW_KEY_SIZE, 11078c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 11088c2ecf20Sopenharmony_ci }, 11098c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_CBC_CTS, 11108c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 11118c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_712, 11128c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 11138c2ecf20Sopenharmony_ci .sec_func = true, 11148c2ecf20Sopenharmony_ci }, 11158c2ecf20Sopenharmony_ci { 11168c2ecf20Sopenharmony_ci .name = "ctr(paes)", 11178c2ecf20Sopenharmony_ci .driver_name = "ctr-paes-ccree", 11188c2ecf20Sopenharmony_ci .blocksize = 1, 11198c2ecf20Sopenharmony_ci .template_skcipher = { 11208c2ecf20Sopenharmony_ci .setkey = cc_cipher_sethkey, 11218c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 11228c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 11238c2ecf20Sopenharmony_ci .min_keysize = CC_HW_KEY_SIZE, 11248c2ecf20Sopenharmony_ci .max_keysize = CC_HW_KEY_SIZE, 11258c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 11268c2ecf20Sopenharmony_ci }, 11278c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_CTR, 11288c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 11298c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_712, 11308c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 11318c2ecf20Sopenharmony_ci .sec_func = true, 11328c2ecf20Sopenharmony_ci }, 11338c2ecf20Sopenharmony_ci { 11348c2ecf20Sopenharmony_ci /* See https://www.mail-archive.com/linux-crypto@vger.kernel.org/msg40576.html 11358c2ecf20Sopenharmony_ci * for the reason why this differs from the generic 11368c2ecf20Sopenharmony_ci * implementation. 11378c2ecf20Sopenharmony_ci */ 11388c2ecf20Sopenharmony_ci .name = "xts(aes)", 11398c2ecf20Sopenharmony_ci .driver_name = "xts-aes-ccree", 11408c2ecf20Sopenharmony_ci .blocksize = 1, 11418c2ecf20Sopenharmony_ci .template_skcipher = { 11428c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 11438c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 11448c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 11458c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE * 2, 11468c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE * 2, 11478c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 11488c2ecf20Sopenharmony_ci }, 11498c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_XTS, 11508c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 11518c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 11528c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 11538c2ecf20Sopenharmony_ci }, 11548c2ecf20Sopenharmony_ci { 11558c2ecf20Sopenharmony_ci .name = "essiv(cbc(aes),sha256)", 11568c2ecf20Sopenharmony_ci .driver_name = "essiv-aes-ccree", 11578c2ecf20Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 11588c2ecf20Sopenharmony_ci .template_skcipher = { 11598c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 11608c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 11618c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 11628c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 11638c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 11648c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 11658c2ecf20Sopenharmony_ci }, 11668c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_ESSIV, 11678c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 11688c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_712, 11698c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 11708c2ecf20Sopenharmony_ci }, 11718c2ecf20Sopenharmony_ci { 11728c2ecf20Sopenharmony_ci .name = "ecb(aes)", 11738c2ecf20Sopenharmony_ci .driver_name = "ecb-aes-ccree", 11748c2ecf20Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 11758c2ecf20Sopenharmony_ci .template_skcipher = { 11768c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 11778c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 11788c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 11798c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 11808c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 11818c2ecf20Sopenharmony_ci .ivsize = 0, 11828c2ecf20Sopenharmony_ci }, 11838c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_ECB, 11848c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 11858c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 11868c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 11878c2ecf20Sopenharmony_ci }, 11888c2ecf20Sopenharmony_ci { 11898c2ecf20Sopenharmony_ci .name = "cbc(aes)", 11908c2ecf20Sopenharmony_ci .driver_name = "cbc-aes-ccree", 11918c2ecf20Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 11928c2ecf20Sopenharmony_ci .template_skcipher = { 11938c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 11948c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 11958c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 11968c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 11978c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 11988c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 11998c2ecf20Sopenharmony_ci }, 12008c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_CBC, 12018c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 12028c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 12038c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 12048c2ecf20Sopenharmony_ci }, 12058c2ecf20Sopenharmony_ci { 12068c2ecf20Sopenharmony_ci .name = "ofb(aes)", 12078c2ecf20Sopenharmony_ci .driver_name = "ofb-aes-ccree", 12088c2ecf20Sopenharmony_ci .blocksize = 1, 12098c2ecf20Sopenharmony_ci .template_skcipher = { 12108c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 12118c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 12128c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 12138c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 12148c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 12158c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 12168c2ecf20Sopenharmony_ci }, 12178c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_OFB, 12188c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 12198c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 12208c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 12218c2ecf20Sopenharmony_ci }, 12228c2ecf20Sopenharmony_ci { 12238c2ecf20Sopenharmony_ci .name = "cts(cbc(aes))", 12248c2ecf20Sopenharmony_ci .driver_name = "cts-cbc-aes-ccree", 12258c2ecf20Sopenharmony_ci .blocksize = AES_BLOCK_SIZE, 12268c2ecf20Sopenharmony_ci .template_skcipher = { 12278c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 12288c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 12298c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 12308c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 12318c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 12328c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 12338c2ecf20Sopenharmony_ci }, 12348c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_CBC_CTS, 12358c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 12368c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 12378c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 12388c2ecf20Sopenharmony_ci }, 12398c2ecf20Sopenharmony_ci { 12408c2ecf20Sopenharmony_ci .name = "ctr(aes)", 12418c2ecf20Sopenharmony_ci .driver_name = "ctr-aes-ccree", 12428c2ecf20Sopenharmony_ci .blocksize = 1, 12438c2ecf20Sopenharmony_ci .template_skcipher = { 12448c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 12458c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 12468c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 12478c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 12488c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 12498c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 12508c2ecf20Sopenharmony_ci }, 12518c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_CTR, 12528c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_AES, 12538c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 12548c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 12558c2ecf20Sopenharmony_ci }, 12568c2ecf20Sopenharmony_ci { 12578c2ecf20Sopenharmony_ci .name = "cbc(des3_ede)", 12588c2ecf20Sopenharmony_ci .driver_name = "cbc-3des-ccree", 12598c2ecf20Sopenharmony_ci .blocksize = DES3_EDE_BLOCK_SIZE, 12608c2ecf20Sopenharmony_ci .template_skcipher = { 12618c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 12628c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 12638c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 12648c2ecf20Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 12658c2ecf20Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 12668c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 12678c2ecf20Sopenharmony_ci }, 12688c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_CBC, 12698c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_DES, 12708c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 12718c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 12728c2ecf20Sopenharmony_ci }, 12738c2ecf20Sopenharmony_ci { 12748c2ecf20Sopenharmony_ci .name = "ecb(des3_ede)", 12758c2ecf20Sopenharmony_ci .driver_name = "ecb-3des-ccree", 12768c2ecf20Sopenharmony_ci .blocksize = DES3_EDE_BLOCK_SIZE, 12778c2ecf20Sopenharmony_ci .template_skcipher = { 12788c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 12798c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 12808c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 12818c2ecf20Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 12828c2ecf20Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 12838c2ecf20Sopenharmony_ci .ivsize = 0, 12848c2ecf20Sopenharmony_ci }, 12858c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_ECB, 12868c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_DES, 12878c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 12888c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 12898c2ecf20Sopenharmony_ci }, 12908c2ecf20Sopenharmony_ci { 12918c2ecf20Sopenharmony_ci .name = "cbc(des)", 12928c2ecf20Sopenharmony_ci .driver_name = "cbc-des-ccree", 12938c2ecf20Sopenharmony_ci .blocksize = DES_BLOCK_SIZE, 12948c2ecf20Sopenharmony_ci .template_skcipher = { 12958c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 12968c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 12978c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 12988c2ecf20Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 12998c2ecf20Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 13008c2ecf20Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 13018c2ecf20Sopenharmony_ci }, 13028c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_CBC, 13038c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_DES, 13048c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 13058c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 13068c2ecf20Sopenharmony_ci }, 13078c2ecf20Sopenharmony_ci { 13088c2ecf20Sopenharmony_ci .name = "ecb(des)", 13098c2ecf20Sopenharmony_ci .driver_name = "ecb-des-ccree", 13108c2ecf20Sopenharmony_ci .blocksize = DES_BLOCK_SIZE, 13118c2ecf20Sopenharmony_ci .template_skcipher = { 13128c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 13138c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 13148c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 13158c2ecf20Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 13168c2ecf20Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 13178c2ecf20Sopenharmony_ci .ivsize = 0, 13188c2ecf20Sopenharmony_ci }, 13198c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_ECB, 13208c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_DES, 13218c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_630, 13228c2ecf20Sopenharmony_ci .std_body = CC_STD_NIST, 13238c2ecf20Sopenharmony_ci }, 13248c2ecf20Sopenharmony_ci { 13258c2ecf20Sopenharmony_ci .name = "cbc(sm4)", 13268c2ecf20Sopenharmony_ci .driver_name = "cbc-sm4-ccree", 13278c2ecf20Sopenharmony_ci .blocksize = SM4_BLOCK_SIZE, 13288c2ecf20Sopenharmony_ci .template_skcipher = { 13298c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 13308c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 13318c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 13328c2ecf20Sopenharmony_ci .min_keysize = SM4_KEY_SIZE, 13338c2ecf20Sopenharmony_ci .max_keysize = SM4_KEY_SIZE, 13348c2ecf20Sopenharmony_ci .ivsize = SM4_BLOCK_SIZE, 13358c2ecf20Sopenharmony_ci }, 13368c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_CBC, 13378c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_SM4, 13388c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_713, 13398c2ecf20Sopenharmony_ci .std_body = CC_STD_OSCCA, 13408c2ecf20Sopenharmony_ci }, 13418c2ecf20Sopenharmony_ci { 13428c2ecf20Sopenharmony_ci .name = "ecb(sm4)", 13438c2ecf20Sopenharmony_ci .driver_name = "ecb-sm4-ccree", 13448c2ecf20Sopenharmony_ci .blocksize = SM4_BLOCK_SIZE, 13458c2ecf20Sopenharmony_ci .template_skcipher = { 13468c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 13478c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 13488c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 13498c2ecf20Sopenharmony_ci .min_keysize = SM4_KEY_SIZE, 13508c2ecf20Sopenharmony_ci .max_keysize = SM4_KEY_SIZE, 13518c2ecf20Sopenharmony_ci .ivsize = 0, 13528c2ecf20Sopenharmony_ci }, 13538c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_ECB, 13548c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_SM4, 13558c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_713, 13568c2ecf20Sopenharmony_ci .std_body = CC_STD_OSCCA, 13578c2ecf20Sopenharmony_ci }, 13588c2ecf20Sopenharmony_ci { 13598c2ecf20Sopenharmony_ci .name = "ctr(sm4)", 13608c2ecf20Sopenharmony_ci .driver_name = "ctr-sm4-ccree", 13618c2ecf20Sopenharmony_ci .blocksize = 1, 13628c2ecf20Sopenharmony_ci .template_skcipher = { 13638c2ecf20Sopenharmony_ci .setkey = cc_cipher_setkey, 13648c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 13658c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 13668c2ecf20Sopenharmony_ci .min_keysize = SM4_KEY_SIZE, 13678c2ecf20Sopenharmony_ci .max_keysize = SM4_KEY_SIZE, 13688c2ecf20Sopenharmony_ci .ivsize = SM4_BLOCK_SIZE, 13698c2ecf20Sopenharmony_ci }, 13708c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_CTR, 13718c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_SM4, 13728c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_713, 13738c2ecf20Sopenharmony_ci .std_body = CC_STD_OSCCA, 13748c2ecf20Sopenharmony_ci }, 13758c2ecf20Sopenharmony_ci { 13768c2ecf20Sopenharmony_ci .name = "cbc(psm4)", 13778c2ecf20Sopenharmony_ci .driver_name = "cbc-psm4-ccree", 13788c2ecf20Sopenharmony_ci .blocksize = SM4_BLOCK_SIZE, 13798c2ecf20Sopenharmony_ci .template_skcipher = { 13808c2ecf20Sopenharmony_ci .setkey = cc_cipher_sethkey, 13818c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 13828c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 13838c2ecf20Sopenharmony_ci .min_keysize = CC_HW_KEY_SIZE, 13848c2ecf20Sopenharmony_ci .max_keysize = CC_HW_KEY_SIZE, 13858c2ecf20Sopenharmony_ci .ivsize = SM4_BLOCK_SIZE, 13868c2ecf20Sopenharmony_ci }, 13878c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_CBC, 13888c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_SM4, 13898c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_713, 13908c2ecf20Sopenharmony_ci .std_body = CC_STD_OSCCA, 13918c2ecf20Sopenharmony_ci .sec_func = true, 13928c2ecf20Sopenharmony_ci }, 13938c2ecf20Sopenharmony_ci { 13948c2ecf20Sopenharmony_ci .name = "ctr(psm4)", 13958c2ecf20Sopenharmony_ci .driver_name = "ctr-psm4-ccree", 13968c2ecf20Sopenharmony_ci .blocksize = SM4_BLOCK_SIZE, 13978c2ecf20Sopenharmony_ci .template_skcipher = { 13988c2ecf20Sopenharmony_ci .setkey = cc_cipher_sethkey, 13998c2ecf20Sopenharmony_ci .encrypt = cc_cipher_encrypt, 14008c2ecf20Sopenharmony_ci .decrypt = cc_cipher_decrypt, 14018c2ecf20Sopenharmony_ci .min_keysize = CC_HW_KEY_SIZE, 14028c2ecf20Sopenharmony_ci .max_keysize = CC_HW_KEY_SIZE, 14038c2ecf20Sopenharmony_ci .ivsize = SM4_BLOCK_SIZE, 14048c2ecf20Sopenharmony_ci }, 14058c2ecf20Sopenharmony_ci .cipher_mode = DRV_CIPHER_CTR, 14068c2ecf20Sopenharmony_ci .flow_mode = S_DIN_to_SM4, 14078c2ecf20Sopenharmony_ci .min_hw_rev = CC_HW_REV_713, 14088c2ecf20Sopenharmony_ci .std_body = CC_STD_OSCCA, 14098c2ecf20Sopenharmony_ci .sec_func = true, 14108c2ecf20Sopenharmony_ci }, 14118c2ecf20Sopenharmony_ci}; 14128c2ecf20Sopenharmony_ci 14138c2ecf20Sopenharmony_cistatic struct cc_crypto_alg *cc_create_alg(const struct cc_alg_template *tmpl, 14148c2ecf20Sopenharmony_ci struct device *dev) 14158c2ecf20Sopenharmony_ci{ 14168c2ecf20Sopenharmony_ci struct cc_crypto_alg *t_alg; 14178c2ecf20Sopenharmony_ci struct skcipher_alg *alg; 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci t_alg = devm_kzalloc(dev, sizeof(*t_alg), GFP_KERNEL); 14208c2ecf20Sopenharmony_ci if (!t_alg) 14218c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci alg = &t_alg->skcipher_alg; 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci memcpy(alg, &tmpl->template_skcipher, sizeof(*alg)); 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", tmpl->name); 14288c2ecf20Sopenharmony_ci snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", 14298c2ecf20Sopenharmony_ci tmpl->driver_name); 14308c2ecf20Sopenharmony_ci alg->base.cra_module = THIS_MODULE; 14318c2ecf20Sopenharmony_ci alg->base.cra_priority = CC_CRA_PRIO; 14328c2ecf20Sopenharmony_ci alg->base.cra_blocksize = tmpl->blocksize; 14338c2ecf20Sopenharmony_ci alg->base.cra_alignmask = 0; 14348c2ecf20Sopenharmony_ci alg->base.cra_ctxsize = sizeof(struct cc_cipher_ctx); 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci alg->base.cra_init = cc_cipher_init; 14378c2ecf20Sopenharmony_ci alg->base.cra_exit = cc_cipher_exit; 14388c2ecf20Sopenharmony_ci alg->base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY; 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci t_alg->cipher_mode = tmpl->cipher_mode; 14418c2ecf20Sopenharmony_ci t_alg->flow_mode = tmpl->flow_mode; 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci return t_alg; 14448c2ecf20Sopenharmony_ci} 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_ciint cc_cipher_free(struct cc_drvdata *drvdata) 14478c2ecf20Sopenharmony_ci{ 14488c2ecf20Sopenharmony_ci struct cc_crypto_alg *t_alg, *n; 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci /* Remove registered algs */ 14518c2ecf20Sopenharmony_ci list_for_each_entry_safe(t_alg, n, &drvdata->alg_list, entry) { 14528c2ecf20Sopenharmony_ci crypto_unregister_skcipher(&t_alg->skcipher_alg); 14538c2ecf20Sopenharmony_ci list_del(&t_alg->entry); 14548c2ecf20Sopenharmony_ci } 14558c2ecf20Sopenharmony_ci return 0; 14568c2ecf20Sopenharmony_ci} 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ciint cc_cipher_alloc(struct cc_drvdata *drvdata) 14598c2ecf20Sopenharmony_ci{ 14608c2ecf20Sopenharmony_ci struct cc_crypto_alg *t_alg; 14618c2ecf20Sopenharmony_ci struct device *dev = drvdata_to_dev(drvdata); 14628c2ecf20Sopenharmony_ci int rc = -ENOMEM; 14638c2ecf20Sopenharmony_ci int alg; 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&drvdata->alg_list); 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci /* Linux crypto */ 14688c2ecf20Sopenharmony_ci dev_dbg(dev, "Number of algorithms = %zu\n", 14698c2ecf20Sopenharmony_ci ARRAY_SIZE(skcipher_algs)); 14708c2ecf20Sopenharmony_ci for (alg = 0; alg < ARRAY_SIZE(skcipher_algs); alg++) { 14718c2ecf20Sopenharmony_ci if ((skcipher_algs[alg].min_hw_rev > drvdata->hw_rev) || 14728c2ecf20Sopenharmony_ci !(drvdata->std_bodies & skcipher_algs[alg].std_body) || 14738c2ecf20Sopenharmony_ci (drvdata->sec_disabled && skcipher_algs[alg].sec_func)) 14748c2ecf20Sopenharmony_ci continue; 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci dev_dbg(dev, "creating %s\n", skcipher_algs[alg].driver_name); 14778c2ecf20Sopenharmony_ci t_alg = cc_create_alg(&skcipher_algs[alg], dev); 14788c2ecf20Sopenharmony_ci if (IS_ERR(t_alg)) { 14798c2ecf20Sopenharmony_ci rc = PTR_ERR(t_alg); 14808c2ecf20Sopenharmony_ci dev_err(dev, "%s alg allocation failed\n", 14818c2ecf20Sopenharmony_ci skcipher_algs[alg].driver_name); 14828c2ecf20Sopenharmony_ci goto fail0; 14838c2ecf20Sopenharmony_ci } 14848c2ecf20Sopenharmony_ci t_alg->drvdata = drvdata; 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci dev_dbg(dev, "registering %s\n", 14878c2ecf20Sopenharmony_ci skcipher_algs[alg].driver_name); 14888c2ecf20Sopenharmony_ci rc = crypto_register_skcipher(&t_alg->skcipher_alg); 14898c2ecf20Sopenharmony_ci dev_dbg(dev, "%s alg registration rc = %x\n", 14908c2ecf20Sopenharmony_ci t_alg->skcipher_alg.base.cra_driver_name, rc); 14918c2ecf20Sopenharmony_ci if (rc) { 14928c2ecf20Sopenharmony_ci dev_err(dev, "%s alg registration failed\n", 14938c2ecf20Sopenharmony_ci t_alg->skcipher_alg.base.cra_driver_name); 14948c2ecf20Sopenharmony_ci goto fail0; 14958c2ecf20Sopenharmony_ci } 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci list_add_tail(&t_alg->entry, &drvdata->alg_list); 14988c2ecf20Sopenharmony_ci dev_dbg(dev, "Registered %s\n", 14998c2ecf20Sopenharmony_ci t_alg->skcipher_alg.base.cra_driver_name); 15008c2ecf20Sopenharmony_ci } 15018c2ecf20Sopenharmony_ci return 0; 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_cifail0: 15048c2ecf20Sopenharmony_ci cc_cipher_free(drvdata); 15058c2ecf20Sopenharmony_ci return rc; 15068c2ecf20Sopenharmony_ci} 1507