18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * K3 SA2UL crypto accelerator driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2018-2020 Texas Instruments Incorporated - http://www.ti.com 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Authors: Keerthy 88c2ecf20Sopenharmony_ci * Vitaly Andrianov 98c2ecf20Sopenharmony_ci * Tero Kristo 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci#include <linux/clk.h> 128c2ecf20Sopenharmony_ci#include <linux/dmaengine.h> 138c2ecf20Sopenharmony_ci#include <linux/dmapool.h> 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <linux/of_device.h> 168c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 178c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <crypto/aes.h> 208c2ecf20Sopenharmony_ci#include <crypto/authenc.h> 218c2ecf20Sopenharmony_ci#include <crypto/des.h> 228c2ecf20Sopenharmony_ci#include <crypto/internal/aead.h> 238c2ecf20Sopenharmony_ci#include <crypto/internal/hash.h> 248c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h> 258c2ecf20Sopenharmony_ci#include <crypto/scatterwalk.h> 268c2ecf20Sopenharmony_ci#include <crypto/sha.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include "sa2ul.h" 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* Byte offset for key in encryption security context */ 318c2ecf20Sopenharmony_ci#define SC_ENC_KEY_OFFSET (1 + 27 + 4) 328c2ecf20Sopenharmony_ci/* Byte offset for Aux-1 in encryption security context */ 338c2ecf20Sopenharmony_ci#define SC_ENC_AUX1_OFFSET (1 + 27 + 4 + 32) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define SA_CMDL_UPD_ENC 0x0001 368c2ecf20Sopenharmony_ci#define SA_CMDL_UPD_AUTH 0x0002 378c2ecf20Sopenharmony_ci#define SA_CMDL_UPD_ENC_IV 0x0004 388c2ecf20Sopenharmony_ci#define SA_CMDL_UPD_AUTH_IV 0x0008 398c2ecf20Sopenharmony_ci#define SA_CMDL_UPD_AUX_KEY 0x0010 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define SA_AUTH_SUBKEY_LEN 16 428c2ecf20Sopenharmony_ci#define SA_CMDL_PAYLOAD_LENGTH_MASK 0xFFFF 438c2ecf20Sopenharmony_ci#define SA_CMDL_SOP_BYPASS_LEN_MASK 0xFF000000 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define MODE_CONTROL_BYTES 27 468c2ecf20Sopenharmony_ci#define SA_HASH_PROCESSING 0 478c2ecf20Sopenharmony_ci#define SA_CRYPTO_PROCESSING 0 488c2ecf20Sopenharmony_ci#define SA_UPLOAD_HASH_TO_TLR BIT(6) 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#define SA_SW0_FLAGS_MASK 0xF0000 518c2ecf20Sopenharmony_ci#define SA_SW0_CMDL_INFO_MASK 0x1F00000 528c2ecf20Sopenharmony_ci#define SA_SW0_CMDL_PRESENT BIT(4) 538c2ecf20Sopenharmony_ci#define SA_SW0_ENG_ID_MASK 0x3E000000 548c2ecf20Sopenharmony_ci#define SA_SW0_DEST_INFO_PRESENT BIT(30) 558c2ecf20Sopenharmony_ci#define SA_SW2_EGRESS_LENGTH 0xFF000000 568c2ecf20Sopenharmony_ci#define SA_BASIC_HASH 0x10 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci#define SHA256_DIGEST_WORDS 8 598c2ecf20Sopenharmony_ci/* Make 32-bit word from 4 bytes */ 608c2ecf20Sopenharmony_ci#define SA_MK_U32(b0, b1, b2, b3) (((b0) << 24) | ((b1) << 16) | \ 618c2ecf20Sopenharmony_ci ((b2) << 8) | (b3)) 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* size of SCCTL structure in bytes */ 648c2ecf20Sopenharmony_ci#define SA_SCCTL_SZ 16 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/* Max Authentication tag size */ 678c2ecf20Sopenharmony_ci#define SA_MAX_AUTH_TAG_SZ 64 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci#define PRIV_ID 0x1 708c2ecf20Sopenharmony_ci#define PRIV 0x1 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic struct device *sa_k3_dev; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/** 758c2ecf20Sopenharmony_ci * struct sa_cmdl_cfg - Command label configuration descriptor 768c2ecf20Sopenharmony_ci * @aalg: authentication algorithm ID 778c2ecf20Sopenharmony_ci * @enc_eng_id: Encryption Engine ID supported by the SA hardware 788c2ecf20Sopenharmony_ci * @auth_eng_id: Authentication Engine ID 798c2ecf20Sopenharmony_ci * @iv_size: Initialization Vector size 808c2ecf20Sopenharmony_ci * @akey: Authentication key 818c2ecf20Sopenharmony_ci * @akey_len: Authentication key length 828c2ecf20Sopenharmony_ci * @enc: True, if this is an encode request 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_cistruct sa_cmdl_cfg { 858c2ecf20Sopenharmony_ci int aalg; 868c2ecf20Sopenharmony_ci u8 enc_eng_id; 878c2ecf20Sopenharmony_ci u8 auth_eng_id; 888c2ecf20Sopenharmony_ci u8 iv_size; 898c2ecf20Sopenharmony_ci const u8 *akey; 908c2ecf20Sopenharmony_ci u16 akey_len; 918c2ecf20Sopenharmony_ci bool enc; 928c2ecf20Sopenharmony_ci}; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/** 958c2ecf20Sopenharmony_ci * struct algo_data - Crypto algorithm specific data 968c2ecf20Sopenharmony_ci * @enc_eng: Encryption engine info structure 978c2ecf20Sopenharmony_ci * @auth_eng: Authentication engine info structure 988c2ecf20Sopenharmony_ci * @auth_ctrl: Authentication control word 998c2ecf20Sopenharmony_ci * @hash_size: Size of digest 1008c2ecf20Sopenharmony_ci * @iv_idx: iv index in psdata 1018c2ecf20Sopenharmony_ci * @iv_out_size: iv out size 1028c2ecf20Sopenharmony_ci * @ealg_id: Encryption Algorithm ID 1038c2ecf20Sopenharmony_ci * @aalg_id: Authentication algorithm ID 1048c2ecf20Sopenharmony_ci * @mci_enc: Mode Control Instruction for Encryption algorithm 1058c2ecf20Sopenharmony_ci * @mci_dec: Mode Control Instruction for Decryption 1068c2ecf20Sopenharmony_ci * @inv_key: Whether the encryption algorithm demands key inversion 1078c2ecf20Sopenharmony_ci * @ctx: Pointer to the algorithm context 1088c2ecf20Sopenharmony_ci * @keyed_mac: Whether the authentication algorithm has key 1098c2ecf20Sopenharmony_ci * @prep_iopad: Function pointer to generate intermediate ipad/opad 1108c2ecf20Sopenharmony_ci */ 1118c2ecf20Sopenharmony_cistruct algo_data { 1128c2ecf20Sopenharmony_ci struct sa_eng_info enc_eng; 1138c2ecf20Sopenharmony_ci struct sa_eng_info auth_eng; 1148c2ecf20Sopenharmony_ci u8 auth_ctrl; 1158c2ecf20Sopenharmony_ci u8 hash_size; 1168c2ecf20Sopenharmony_ci u8 iv_idx; 1178c2ecf20Sopenharmony_ci u8 iv_out_size; 1188c2ecf20Sopenharmony_ci u8 ealg_id; 1198c2ecf20Sopenharmony_ci u8 aalg_id; 1208c2ecf20Sopenharmony_ci u8 *mci_enc; 1218c2ecf20Sopenharmony_ci u8 *mci_dec; 1228c2ecf20Sopenharmony_ci bool inv_key; 1238c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx; 1248c2ecf20Sopenharmony_ci bool keyed_mac; 1258c2ecf20Sopenharmony_ci void (*prep_iopad)(struct algo_data *algo, const u8 *key, 1268c2ecf20Sopenharmony_ci u16 key_sz, __be32 *ipad, __be32 *opad); 1278c2ecf20Sopenharmony_ci}; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci/** 1308c2ecf20Sopenharmony_ci * struct sa_alg_tmpl: A generic template encompassing crypto/aead algorithms 1318c2ecf20Sopenharmony_ci * @type: Type of the crypto algorithm. 1328c2ecf20Sopenharmony_ci * @alg: Union of crypto algorithm definitions. 1338c2ecf20Sopenharmony_ci * @registered: Flag indicating if the crypto algorithm is already registered 1348c2ecf20Sopenharmony_ci */ 1358c2ecf20Sopenharmony_cistruct sa_alg_tmpl { 1368c2ecf20Sopenharmony_ci u32 type; /* CRYPTO_ALG_TYPE from <linux/crypto.h> */ 1378c2ecf20Sopenharmony_ci union { 1388c2ecf20Sopenharmony_ci struct skcipher_alg skcipher; 1398c2ecf20Sopenharmony_ci struct ahash_alg ahash; 1408c2ecf20Sopenharmony_ci struct aead_alg aead; 1418c2ecf20Sopenharmony_ci } alg; 1428c2ecf20Sopenharmony_ci bool registered; 1438c2ecf20Sopenharmony_ci}; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci/** 1468c2ecf20Sopenharmony_ci * struct sa_mapped_sg: scatterlist information for tx and rx 1478c2ecf20Sopenharmony_ci * @mapped: Set to true if the @sgt is mapped 1488c2ecf20Sopenharmony_ci * @dir: mapping direction used for @sgt 1498c2ecf20Sopenharmony_ci * @split_sg: Set if the sg is split and needs to be freed up 1508c2ecf20Sopenharmony_ci * @static_sg: Static scatterlist entry for overriding data 1518c2ecf20Sopenharmony_ci * @sgt: scatterlist table for DMA API use 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_cistruct sa_mapped_sg { 1548c2ecf20Sopenharmony_ci bool mapped; 1558c2ecf20Sopenharmony_ci enum dma_data_direction dir; 1568c2ecf20Sopenharmony_ci struct scatterlist static_sg; 1578c2ecf20Sopenharmony_ci struct scatterlist *split_sg; 1588c2ecf20Sopenharmony_ci struct sg_table sgt; 1598c2ecf20Sopenharmony_ci}; 1608c2ecf20Sopenharmony_ci/** 1618c2ecf20Sopenharmony_ci * struct sa_rx_data: RX Packet miscellaneous data place holder 1628c2ecf20Sopenharmony_ci * @req: crypto request data pointer 1638c2ecf20Sopenharmony_ci * @ddev: pointer to the DMA device 1648c2ecf20Sopenharmony_ci * @tx_in: dma_async_tx_descriptor pointer for rx channel 1658c2ecf20Sopenharmony_ci * @mapped_sg: Information on tx (0) and rx (1) scatterlist DMA mapping 1668c2ecf20Sopenharmony_ci * @enc: Flag indicating either encryption or decryption 1678c2ecf20Sopenharmony_ci * @enc_iv_size: Initialisation vector size 1688c2ecf20Sopenharmony_ci * @iv_idx: Initialisation vector index 1698c2ecf20Sopenharmony_ci */ 1708c2ecf20Sopenharmony_cistruct sa_rx_data { 1718c2ecf20Sopenharmony_ci void *req; 1728c2ecf20Sopenharmony_ci struct device *ddev; 1738c2ecf20Sopenharmony_ci struct dma_async_tx_descriptor *tx_in; 1748c2ecf20Sopenharmony_ci struct sa_mapped_sg mapped_sg[2]; 1758c2ecf20Sopenharmony_ci u8 enc; 1768c2ecf20Sopenharmony_ci u8 enc_iv_size; 1778c2ecf20Sopenharmony_ci u8 iv_idx; 1788c2ecf20Sopenharmony_ci}; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci/** 1818c2ecf20Sopenharmony_ci * struct sa_req: SA request definition 1828c2ecf20Sopenharmony_ci * @dev: device for the request 1838c2ecf20Sopenharmony_ci * @size: total data to the xmitted via DMA 1848c2ecf20Sopenharmony_ci * @enc_offset: offset of cipher data 1858c2ecf20Sopenharmony_ci * @enc_size: data to be passed to cipher engine 1868c2ecf20Sopenharmony_ci * @enc_iv: cipher IV 1878c2ecf20Sopenharmony_ci * @auth_offset: offset of the authentication data 1888c2ecf20Sopenharmony_ci * @auth_size: size of the authentication data 1898c2ecf20Sopenharmony_ci * @auth_iv: authentication IV 1908c2ecf20Sopenharmony_ci * @type: algorithm type for the request 1918c2ecf20Sopenharmony_ci * @cmdl: command label pointer 1928c2ecf20Sopenharmony_ci * @base: pointer to the base request 1938c2ecf20Sopenharmony_ci * @ctx: pointer to the algorithm context data 1948c2ecf20Sopenharmony_ci * @enc: true if this is an encode request 1958c2ecf20Sopenharmony_ci * @src: source data 1968c2ecf20Sopenharmony_ci * @dst: destination data 1978c2ecf20Sopenharmony_ci * @callback: DMA callback for the request 1988c2ecf20Sopenharmony_ci * @mdata_size: metadata size passed to DMA 1998c2ecf20Sopenharmony_ci */ 2008c2ecf20Sopenharmony_cistruct sa_req { 2018c2ecf20Sopenharmony_ci struct device *dev; 2028c2ecf20Sopenharmony_ci u16 size; 2038c2ecf20Sopenharmony_ci u8 enc_offset; 2048c2ecf20Sopenharmony_ci u16 enc_size; 2058c2ecf20Sopenharmony_ci u8 *enc_iv; 2068c2ecf20Sopenharmony_ci u8 auth_offset; 2078c2ecf20Sopenharmony_ci u16 auth_size; 2088c2ecf20Sopenharmony_ci u8 *auth_iv; 2098c2ecf20Sopenharmony_ci u32 type; 2108c2ecf20Sopenharmony_ci u32 *cmdl; 2118c2ecf20Sopenharmony_ci struct crypto_async_request *base; 2128c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx; 2138c2ecf20Sopenharmony_ci bool enc; 2148c2ecf20Sopenharmony_ci struct scatterlist *src; 2158c2ecf20Sopenharmony_ci struct scatterlist *dst; 2168c2ecf20Sopenharmony_ci dma_async_tx_callback callback; 2178c2ecf20Sopenharmony_ci u16 mdata_size; 2188c2ecf20Sopenharmony_ci}; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci/* 2218c2ecf20Sopenharmony_ci * Mode Control Instructions for various Key lengths 128, 192, 256 2228c2ecf20Sopenharmony_ci * For CBC (Cipher Block Chaining) mode for encryption 2238c2ecf20Sopenharmony_ci */ 2248c2ecf20Sopenharmony_cistatic u8 mci_cbc_enc_array[3][MODE_CONTROL_BYTES] = { 2258c2ecf20Sopenharmony_ci { 0x61, 0x00, 0x00, 0x18, 0x88, 0x0a, 0xaa, 0x4b, 0x7e, 0x00, 2268c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2278c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2288c2ecf20Sopenharmony_ci { 0x61, 0x00, 0x00, 0x18, 0x88, 0x4a, 0xaa, 0x4b, 0x7e, 0x00, 2298c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2308c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2318c2ecf20Sopenharmony_ci { 0x61, 0x00, 0x00, 0x18, 0x88, 0x8a, 0xaa, 0x4b, 0x7e, 0x00, 2328c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2338c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2348c2ecf20Sopenharmony_ci}; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci/* 2378c2ecf20Sopenharmony_ci * Mode Control Instructions for various Key lengths 128, 192, 256 2388c2ecf20Sopenharmony_ci * For CBC (Cipher Block Chaining) mode for decryption 2398c2ecf20Sopenharmony_ci */ 2408c2ecf20Sopenharmony_cistatic u8 mci_cbc_dec_array[3][MODE_CONTROL_BYTES] = { 2418c2ecf20Sopenharmony_ci { 0x71, 0x00, 0x00, 0x80, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 2428c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2438c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2448c2ecf20Sopenharmony_ci { 0x71, 0x00, 0x00, 0x84, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 2458c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2468c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2478c2ecf20Sopenharmony_ci { 0x71, 0x00, 0x00, 0x88, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 2488c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2498c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2508c2ecf20Sopenharmony_ci}; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci/* 2538c2ecf20Sopenharmony_ci * Mode Control Instructions for various Key lengths 128, 192, 256 2548c2ecf20Sopenharmony_ci * For CBC (Cipher Block Chaining) mode for encryption 2558c2ecf20Sopenharmony_ci */ 2568c2ecf20Sopenharmony_cistatic u8 mci_cbc_enc_no_iv_array[3][MODE_CONTROL_BYTES] = { 2578c2ecf20Sopenharmony_ci { 0x21, 0x00, 0x00, 0x18, 0x88, 0x0a, 0xaa, 0x4b, 0x7e, 0x00, 2588c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2598c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2608c2ecf20Sopenharmony_ci { 0x21, 0x00, 0x00, 0x18, 0x88, 0x4a, 0xaa, 0x4b, 0x7e, 0x00, 2618c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2628c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2638c2ecf20Sopenharmony_ci { 0x21, 0x00, 0x00, 0x18, 0x88, 0x8a, 0xaa, 0x4b, 0x7e, 0x00, 2648c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2658c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2668c2ecf20Sopenharmony_ci}; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci/* 2698c2ecf20Sopenharmony_ci * Mode Control Instructions for various Key lengths 128, 192, 256 2708c2ecf20Sopenharmony_ci * For CBC (Cipher Block Chaining) mode for decryption 2718c2ecf20Sopenharmony_ci */ 2728c2ecf20Sopenharmony_cistatic u8 mci_cbc_dec_no_iv_array[3][MODE_CONTROL_BYTES] = { 2738c2ecf20Sopenharmony_ci { 0x31, 0x00, 0x00, 0x80, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 2748c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2758c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2768c2ecf20Sopenharmony_ci { 0x31, 0x00, 0x00, 0x84, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 2778c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2788c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2798c2ecf20Sopenharmony_ci { 0x31, 0x00, 0x00, 0x88, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 2808c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2818c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2828c2ecf20Sopenharmony_ci}; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci/* 2858c2ecf20Sopenharmony_ci * Mode Control Instructions for various Key lengths 128, 192, 256 2868c2ecf20Sopenharmony_ci * For ECB (Electronic Code Book) mode for encryption 2878c2ecf20Sopenharmony_ci */ 2888c2ecf20Sopenharmony_cistatic u8 mci_ecb_enc_array[3][27] = { 2898c2ecf20Sopenharmony_ci { 0x21, 0x00, 0x00, 0x80, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 2908c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2918c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2928c2ecf20Sopenharmony_ci { 0x21, 0x00, 0x00, 0x84, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 2938c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2948c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2958c2ecf20Sopenharmony_ci { 0x21, 0x00, 0x00, 0x88, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 2968c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 2978c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 2988c2ecf20Sopenharmony_ci}; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci/* 3018c2ecf20Sopenharmony_ci * Mode Control Instructions for various Key lengths 128, 192, 256 3028c2ecf20Sopenharmony_ci * For ECB (Electronic Code Book) mode for decryption 3038c2ecf20Sopenharmony_ci */ 3048c2ecf20Sopenharmony_cistatic u8 mci_ecb_dec_array[3][27] = { 3058c2ecf20Sopenharmony_ci { 0x31, 0x00, 0x00, 0x80, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 3068c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3078c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 3088c2ecf20Sopenharmony_ci { 0x31, 0x00, 0x00, 0x84, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 3098c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3108c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 3118c2ecf20Sopenharmony_ci { 0x31, 0x00, 0x00, 0x88, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 3128c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3138c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 3148c2ecf20Sopenharmony_ci}; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci/* 3178c2ecf20Sopenharmony_ci * Mode Control Instructions for DES algorithm 3188c2ecf20Sopenharmony_ci * For CBC (Cipher Block Chaining) mode and ECB mode 3198c2ecf20Sopenharmony_ci * encryption and for decryption respectively 3208c2ecf20Sopenharmony_ci */ 3218c2ecf20Sopenharmony_cistatic u8 mci_cbc_3des_enc_array[MODE_CONTROL_BYTES] = { 3228c2ecf20Sopenharmony_ci 0x60, 0x00, 0x00, 0x18, 0x88, 0x52, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 3238c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3248c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 3258c2ecf20Sopenharmony_ci}; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic u8 mci_cbc_3des_dec_array[MODE_CONTROL_BYTES] = { 3288c2ecf20Sopenharmony_ci 0x70, 0x00, 0x00, 0x85, 0x0a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 3298c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3308c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 3318c2ecf20Sopenharmony_ci}; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistatic u8 mci_ecb_3des_enc_array[MODE_CONTROL_BYTES] = { 3348c2ecf20Sopenharmony_ci 0x20, 0x00, 0x00, 0x85, 0x0a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 3358c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3368c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 3378c2ecf20Sopenharmony_ci}; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_cistatic u8 mci_ecb_3des_dec_array[MODE_CONTROL_BYTES] = { 3408c2ecf20Sopenharmony_ci 0x30, 0x00, 0x00, 0x85, 0x0a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 3418c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 3428c2ecf20Sopenharmony_ci 0x00, 0x00, 0x00, 3438c2ecf20Sopenharmony_ci}; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci/* 3468c2ecf20Sopenharmony_ci * Perform 16 byte or 128 bit swizzling 3478c2ecf20Sopenharmony_ci * The SA2UL Expects the security context to 3488c2ecf20Sopenharmony_ci * be in little Endian and the bus width is 128 bits or 16 bytes 3498c2ecf20Sopenharmony_ci * Hence swap 16 bytes at a time from higher to lower address 3508c2ecf20Sopenharmony_ci */ 3518c2ecf20Sopenharmony_cistatic void sa_swiz_128(u8 *in, u16 len) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci u8 data[16]; 3548c2ecf20Sopenharmony_ci int i, j; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci for (i = 0; i < len; i += 16) { 3578c2ecf20Sopenharmony_ci memcpy(data, &in[i], 16); 3588c2ecf20Sopenharmony_ci for (j = 0; j < 16; j++) 3598c2ecf20Sopenharmony_ci in[i + j] = data[15 - j]; 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci} 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci/* Prepare the ipad and opad from key as per SHA algorithm step 1*/ 3648c2ecf20Sopenharmony_cistatic void prepare_kiopad(u8 *k_ipad, u8 *k_opad, const u8 *key, u16 key_sz) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci int i; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci for (i = 0; i < key_sz; i++) { 3698c2ecf20Sopenharmony_ci k_ipad[i] = key[i] ^ 0x36; 3708c2ecf20Sopenharmony_ci k_opad[i] = key[i] ^ 0x5c; 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci /* Instead of XOR with 0 */ 3748c2ecf20Sopenharmony_ci for (; i < SHA1_BLOCK_SIZE; i++) { 3758c2ecf20Sopenharmony_ci k_ipad[i] = 0x36; 3768c2ecf20Sopenharmony_ci k_opad[i] = 0x5c; 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic void sa_export_shash(struct shash_desc *hash, int block_size, 3818c2ecf20Sopenharmony_ci int digest_size, __be32 *out) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci union { 3848c2ecf20Sopenharmony_ci struct sha1_state sha1; 3858c2ecf20Sopenharmony_ci struct sha256_state sha256; 3868c2ecf20Sopenharmony_ci struct sha512_state sha512; 3878c2ecf20Sopenharmony_ci } sha; 3888c2ecf20Sopenharmony_ci void *state; 3898c2ecf20Sopenharmony_ci u32 *result; 3908c2ecf20Sopenharmony_ci int i; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci switch (digest_size) { 3938c2ecf20Sopenharmony_ci case SHA1_DIGEST_SIZE: 3948c2ecf20Sopenharmony_ci state = &sha.sha1; 3958c2ecf20Sopenharmony_ci result = sha.sha1.state; 3968c2ecf20Sopenharmony_ci break; 3978c2ecf20Sopenharmony_ci case SHA256_DIGEST_SIZE: 3988c2ecf20Sopenharmony_ci state = &sha.sha256; 3998c2ecf20Sopenharmony_ci result = sha.sha256.state; 4008c2ecf20Sopenharmony_ci break; 4018c2ecf20Sopenharmony_ci default: 4028c2ecf20Sopenharmony_ci dev_err(sa_k3_dev, "%s: bad digest_size=%d\n", __func__, 4038c2ecf20Sopenharmony_ci digest_size); 4048c2ecf20Sopenharmony_ci return; 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci crypto_shash_export(hash, state); 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci for (i = 0; i < digest_size >> 2; i++) 4108c2ecf20Sopenharmony_ci out[i] = cpu_to_be32(result[i]); 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_cistatic void sa_prepare_iopads(struct algo_data *data, const u8 *key, 4148c2ecf20Sopenharmony_ci u16 key_sz, __be32 *ipad, __be32 *opad) 4158c2ecf20Sopenharmony_ci{ 4168c2ecf20Sopenharmony_ci SHASH_DESC_ON_STACK(shash, data->ctx->shash); 4178c2ecf20Sopenharmony_ci int block_size = crypto_shash_blocksize(data->ctx->shash); 4188c2ecf20Sopenharmony_ci int digest_size = crypto_shash_digestsize(data->ctx->shash); 4198c2ecf20Sopenharmony_ci u8 k_ipad[SHA1_BLOCK_SIZE]; 4208c2ecf20Sopenharmony_ci u8 k_opad[SHA1_BLOCK_SIZE]; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci shash->tfm = data->ctx->shash; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci prepare_kiopad(k_ipad, k_opad, key, key_sz); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci memzero_explicit(ipad, block_size); 4278c2ecf20Sopenharmony_ci memzero_explicit(opad, block_size); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci crypto_shash_init(shash); 4308c2ecf20Sopenharmony_ci crypto_shash_update(shash, k_ipad, block_size); 4318c2ecf20Sopenharmony_ci sa_export_shash(shash, block_size, digest_size, ipad); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci crypto_shash_init(shash); 4348c2ecf20Sopenharmony_ci crypto_shash_update(shash, k_opad, block_size); 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci sa_export_shash(shash, block_size, digest_size, opad); 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci/* Derive the inverse key used in AES-CBC decryption operation */ 4408c2ecf20Sopenharmony_cistatic inline int sa_aes_inv_key(u8 *inv_key, const u8 *key, u16 key_sz) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci struct crypto_aes_ctx ctx; 4438c2ecf20Sopenharmony_ci int key_pos; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci if (aes_expandkey(&ctx, key, key_sz)) { 4468c2ecf20Sopenharmony_ci dev_err(sa_k3_dev, "%s: bad key len(%d)\n", __func__, key_sz); 4478c2ecf20Sopenharmony_ci return -EINVAL; 4488c2ecf20Sopenharmony_ci } 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci /* work around to get the right inverse for AES_KEYSIZE_192 size keys */ 4518c2ecf20Sopenharmony_ci if (key_sz == AES_KEYSIZE_192) { 4528c2ecf20Sopenharmony_ci ctx.key_enc[52] = ctx.key_enc[51] ^ ctx.key_enc[46]; 4538c2ecf20Sopenharmony_ci ctx.key_enc[53] = ctx.key_enc[52] ^ ctx.key_enc[47]; 4548c2ecf20Sopenharmony_ci } 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci /* Based crypto_aes_expand_key logic */ 4578c2ecf20Sopenharmony_ci switch (key_sz) { 4588c2ecf20Sopenharmony_ci case AES_KEYSIZE_128: 4598c2ecf20Sopenharmony_ci case AES_KEYSIZE_192: 4608c2ecf20Sopenharmony_ci key_pos = key_sz + 24; 4618c2ecf20Sopenharmony_ci break; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci case AES_KEYSIZE_256: 4648c2ecf20Sopenharmony_ci key_pos = key_sz + 24 - 4; 4658c2ecf20Sopenharmony_ci break; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci default: 4688c2ecf20Sopenharmony_ci dev_err(sa_k3_dev, "%s: bad key len(%d)\n", __func__, key_sz); 4698c2ecf20Sopenharmony_ci return -EINVAL; 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci memcpy(inv_key, &ctx.key_enc[key_pos], key_sz); 4738c2ecf20Sopenharmony_ci return 0; 4748c2ecf20Sopenharmony_ci} 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci/* Set Security context for the encryption engine */ 4778c2ecf20Sopenharmony_cistatic int sa_set_sc_enc(struct algo_data *ad, const u8 *key, u16 key_sz, 4788c2ecf20Sopenharmony_ci u8 enc, u8 *sc_buf) 4798c2ecf20Sopenharmony_ci{ 4808c2ecf20Sopenharmony_ci const u8 *mci = NULL; 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci /* Set Encryption mode selector to crypto processing */ 4838c2ecf20Sopenharmony_ci sc_buf[0] = SA_CRYPTO_PROCESSING; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci if (enc) 4868c2ecf20Sopenharmony_ci mci = ad->mci_enc; 4878c2ecf20Sopenharmony_ci else 4888c2ecf20Sopenharmony_ci mci = ad->mci_dec; 4898c2ecf20Sopenharmony_ci /* Set the mode control instructions in security context */ 4908c2ecf20Sopenharmony_ci if (mci) 4918c2ecf20Sopenharmony_ci memcpy(&sc_buf[1], mci, MODE_CONTROL_BYTES); 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci /* For AES-CBC decryption get the inverse key */ 4948c2ecf20Sopenharmony_ci if (ad->inv_key && !enc) { 4958c2ecf20Sopenharmony_ci if (sa_aes_inv_key(&sc_buf[SC_ENC_KEY_OFFSET], key, key_sz)) 4968c2ecf20Sopenharmony_ci return -EINVAL; 4978c2ecf20Sopenharmony_ci /* For all other cases: key is used */ 4988c2ecf20Sopenharmony_ci } else { 4998c2ecf20Sopenharmony_ci memcpy(&sc_buf[SC_ENC_KEY_OFFSET], key, key_sz); 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci return 0; 5038c2ecf20Sopenharmony_ci} 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci/* Set Security context for the authentication engine */ 5068c2ecf20Sopenharmony_cistatic void sa_set_sc_auth(struct algo_data *ad, const u8 *key, u16 key_sz, 5078c2ecf20Sopenharmony_ci u8 *sc_buf) 5088c2ecf20Sopenharmony_ci{ 5098c2ecf20Sopenharmony_ci __be32 ipad[64], opad[64]; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci /* Set Authentication mode selector to hash processing */ 5128c2ecf20Sopenharmony_ci sc_buf[0] = SA_HASH_PROCESSING; 5138c2ecf20Sopenharmony_ci /* Auth SW ctrl word: bit[6]=1 (upload computed hash to TLR section) */ 5148c2ecf20Sopenharmony_ci sc_buf[1] = SA_UPLOAD_HASH_TO_TLR; 5158c2ecf20Sopenharmony_ci sc_buf[1] |= ad->auth_ctrl; 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci /* Copy the keys or ipad/opad */ 5188c2ecf20Sopenharmony_ci if (ad->keyed_mac) { 5198c2ecf20Sopenharmony_ci ad->prep_iopad(ad, key, key_sz, ipad, opad); 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci /* Copy ipad to AuthKey */ 5228c2ecf20Sopenharmony_ci memcpy(&sc_buf[32], ipad, ad->hash_size); 5238c2ecf20Sopenharmony_ci /* Copy opad to Aux-1 */ 5248c2ecf20Sopenharmony_ci memcpy(&sc_buf[64], opad, ad->hash_size); 5258c2ecf20Sopenharmony_ci } else { 5268c2ecf20Sopenharmony_ci /* basic hash */ 5278c2ecf20Sopenharmony_ci sc_buf[1] |= SA_BASIC_HASH; 5288c2ecf20Sopenharmony_ci } 5298c2ecf20Sopenharmony_ci} 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_cistatic inline void sa_copy_iv(__be32 *out, const u8 *iv, bool size16) 5328c2ecf20Sopenharmony_ci{ 5338c2ecf20Sopenharmony_ci int j; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci for (j = 0; j < ((size16) ? 4 : 2); j++) { 5368c2ecf20Sopenharmony_ci *out = cpu_to_be32(*((u32 *)iv)); 5378c2ecf20Sopenharmony_ci iv += 4; 5388c2ecf20Sopenharmony_ci out++; 5398c2ecf20Sopenharmony_ci } 5408c2ecf20Sopenharmony_ci} 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci/* Format general command label */ 5438c2ecf20Sopenharmony_cistatic int sa_format_cmdl_gen(struct sa_cmdl_cfg *cfg, u8 *cmdl, 5448c2ecf20Sopenharmony_ci struct sa_cmdl_upd_info *upd_info) 5458c2ecf20Sopenharmony_ci{ 5468c2ecf20Sopenharmony_ci u8 enc_offset = 0, auth_offset = 0, total = 0; 5478c2ecf20Sopenharmony_ci u8 enc_next_eng = SA_ENG_ID_OUTPORT2; 5488c2ecf20Sopenharmony_ci u8 auth_next_eng = SA_ENG_ID_OUTPORT2; 5498c2ecf20Sopenharmony_ci u32 *word_ptr = (u32 *)cmdl; 5508c2ecf20Sopenharmony_ci int i; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci /* Clear the command label */ 5538c2ecf20Sopenharmony_ci memzero_explicit(cmdl, (SA_MAX_CMDL_WORDS * sizeof(u32))); 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci /* Iniialize the command update structure */ 5568c2ecf20Sopenharmony_ci memzero_explicit(upd_info, sizeof(*upd_info)); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci if (cfg->enc_eng_id && cfg->auth_eng_id) { 5598c2ecf20Sopenharmony_ci if (cfg->enc) { 5608c2ecf20Sopenharmony_ci auth_offset = SA_CMDL_HEADER_SIZE_BYTES; 5618c2ecf20Sopenharmony_ci enc_next_eng = cfg->auth_eng_id; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci if (cfg->iv_size) 5648c2ecf20Sopenharmony_ci auth_offset += cfg->iv_size; 5658c2ecf20Sopenharmony_ci } else { 5668c2ecf20Sopenharmony_ci enc_offset = SA_CMDL_HEADER_SIZE_BYTES; 5678c2ecf20Sopenharmony_ci auth_next_eng = cfg->enc_eng_id; 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci } 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci if (cfg->enc_eng_id) { 5728c2ecf20Sopenharmony_ci upd_info->flags |= SA_CMDL_UPD_ENC; 5738c2ecf20Sopenharmony_ci upd_info->enc_size.index = enc_offset >> 2; 5748c2ecf20Sopenharmony_ci upd_info->enc_offset.index = upd_info->enc_size.index + 1; 5758c2ecf20Sopenharmony_ci /* Encryption command label */ 5768c2ecf20Sopenharmony_ci cmdl[enc_offset + SA_CMDL_OFFSET_NESC] = enc_next_eng; 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci /* Encryption modes requiring IV */ 5798c2ecf20Sopenharmony_ci if (cfg->iv_size) { 5808c2ecf20Sopenharmony_ci upd_info->flags |= SA_CMDL_UPD_ENC_IV; 5818c2ecf20Sopenharmony_ci upd_info->enc_iv.index = 5828c2ecf20Sopenharmony_ci (enc_offset + SA_CMDL_HEADER_SIZE_BYTES) >> 2; 5838c2ecf20Sopenharmony_ci upd_info->enc_iv.size = cfg->iv_size; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci cmdl[enc_offset + SA_CMDL_OFFSET_LABEL_LEN] = 5868c2ecf20Sopenharmony_ci SA_CMDL_HEADER_SIZE_BYTES + cfg->iv_size; 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci cmdl[enc_offset + SA_CMDL_OFFSET_OPTION_CTRL1] = 5898c2ecf20Sopenharmony_ci (SA_CTX_ENC_AUX2_OFFSET | (cfg->iv_size >> 3)); 5908c2ecf20Sopenharmony_ci total += SA_CMDL_HEADER_SIZE_BYTES + cfg->iv_size; 5918c2ecf20Sopenharmony_ci } else { 5928c2ecf20Sopenharmony_ci cmdl[enc_offset + SA_CMDL_OFFSET_LABEL_LEN] = 5938c2ecf20Sopenharmony_ci SA_CMDL_HEADER_SIZE_BYTES; 5948c2ecf20Sopenharmony_ci total += SA_CMDL_HEADER_SIZE_BYTES; 5958c2ecf20Sopenharmony_ci } 5968c2ecf20Sopenharmony_ci } 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci if (cfg->auth_eng_id) { 5998c2ecf20Sopenharmony_ci upd_info->flags |= SA_CMDL_UPD_AUTH; 6008c2ecf20Sopenharmony_ci upd_info->auth_size.index = auth_offset >> 2; 6018c2ecf20Sopenharmony_ci upd_info->auth_offset.index = upd_info->auth_size.index + 1; 6028c2ecf20Sopenharmony_ci cmdl[auth_offset + SA_CMDL_OFFSET_NESC] = auth_next_eng; 6038c2ecf20Sopenharmony_ci cmdl[auth_offset + SA_CMDL_OFFSET_LABEL_LEN] = 6048c2ecf20Sopenharmony_ci SA_CMDL_HEADER_SIZE_BYTES; 6058c2ecf20Sopenharmony_ci total += SA_CMDL_HEADER_SIZE_BYTES; 6068c2ecf20Sopenharmony_ci } 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci total = roundup(total, 8); 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci for (i = 0; i < total / 4; i++) 6118c2ecf20Sopenharmony_ci word_ptr[i] = swab32(word_ptr[i]); 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci return total; 6148c2ecf20Sopenharmony_ci} 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci/* Update Command label */ 6178c2ecf20Sopenharmony_cistatic inline void sa_update_cmdl(struct sa_req *req, u32 *cmdl, 6188c2ecf20Sopenharmony_ci struct sa_cmdl_upd_info *upd_info) 6198c2ecf20Sopenharmony_ci{ 6208c2ecf20Sopenharmony_ci int i = 0, j; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci if (likely(upd_info->flags & SA_CMDL_UPD_ENC)) { 6238c2ecf20Sopenharmony_ci cmdl[upd_info->enc_size.index] &= ~SA_CMDL_PAYLOAD_LENGTH_MASK; 6248c2ecf20Sopenharmony_ci cmdl[upd_info->enc_size.index] |= req->enc_size; 6258c2ecf20Sopenharmony_ci cmdl[upd_info->enc_offset.index] &= 6268c2ecf20Sopenharmony_ci ~SA_CMDL_SOP_BYPASS_LEN_MASK; 6278c2ecf20Sopenharmony_ci cmdl[upd_info->enc_offset.index] |= 6288c2ecf20Sopenharmony_ci ((u32)req->enc_offset << 6298c2ecf20Sopenharmony_ci __ffs(SA_CMDL_SOP_BYPASS_LEN_MASK)); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci if (likely(upd_info->flags & SA_CMDL_UPD_ENC_IV)) { 6328c2ecf20Sopenharmony_ci __be32 *data = (__be32 *)&cmdl[upd_info->enc_iv.index]; 6338c2ecf20Sopenharmony_ci u32 *enc_iv = (u32 *)req->enc_iv; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci for (j = 0; i < upd_info->enc_iv.size; i += 4, j++) { 6368c2ecf20Sopenharmony_ci data[j] = cpu_to_be32(*enc_iv); 6378c2ecf20Sopenharmony_ci enc_iv++; 6388c2ecf20Sopenharmony_ci } 6398c2ecf20Sopenharmony_ci } 6408c2ecf20Sopenharmony_ci } 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci if (likely(upd_info->flags & SA_CMDL_UPD_AUTH)) { 6438c2ecf20Sopenharmony_ci cmdl[upd_info->auth_size.index] &= ~SA_CMDL_PAYLOAD_LENGTH_MASK; 6448c2ecf20Sopenharmony_ci cmdl[upd_info->auth_size.index] |= req->auth_size; 6458c2ecf20Sopenharmony_ci cmdl[upd_info->auth_offset.index] &= 6468c2ecf20Sopenharmony_ci ~SA_CMDL_SOP_BYPASS_LEN_MASK; 6478c2ecf20Sopenharmony_ci cmdl[upd_info->auth_offset.index] |= 6488c2ecf20Sopenharmony_ci ((u32)req->auth_offset << 6498c2ecf20Sopenharmony_ci __ffs(SA_CMDL_SOP_BYPASS_LEN_MASK)); 6508c2ecf20Sopenharmony_ci if (upd_info->flags & SA_CMDL_UPD_AUTH_IV) { 6518c2ecf20Sopenharmony_ci sa_copy_iv((void *)&cmdl[upd_info->auth_iv.index], 6528c2ecf20Sopenharmony_ci req->auth_iv, 6538c2ecf20Sopenharmony_ci (upd_info->auth_iv.size > 8)); 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci if (upd_info->flags & SA_CMDL_UPD_AUX_KEY) { 6568c2ecf20Sopenharmony_ci int offset = (req->auth_size & 0xF) ? 4 : 0; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci memcpy(&cmdl[upd_info->aux_key_info.index], 6598c2ecf20Sopenharmony_ci &upd_info->aux_key[offset], 16); 6608c2ecf20Sopenharmony_ci } 6618c2ecf20Sopenharmony_ci } 6628c2ecf20Sopenharmony_ci} 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci/* Format SWINFO words to be sent to SA */ 6658c2ecf20Sopenharmony_cistatic 6668c2ecf20Sopenharmony_civoid sa_set_swinfo(u8 eng_id, u16 sc_id, dma_addr_t sc_phys, 6678c2ecf20Sopenharmony_ci u8 cmdl_present, u8 cmdl_offset, u8 flags, 6688c2ecf20Sopenharmony_ci u8 hash_size, u32 *swinfo) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci swinfo[0] = sc_id; 6718c2ecf20Sopenharmony_ci swinfo[0] |= (flags << __ffs(SA_SW0_FLAGS_MASK)); 6728c2ecf20Sopenharmony_ci if (likely(cmdl_present)) 6738c2ecf20Sopenharmony_ci swinfo[0] |= ((cmdl_offset | SA_SW0_CMDL_PRESENT) << 6748c2ecf20Sopenharmony_ci __ffs(SA_SW0_CMDL_INFO_MASK)); 6758c2ecf20Sopenharmony_ci swinfo[0] |= (eng_id << __ffs(SA_SW0_ENG_ID_MASK)); 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci swinfo[0] |= SA_SW0_DEST_INFO_PRESENT; 6788c2ecf20Sopenharmony_ci swinfo[1] = (u32)(sc_phys & 0xFFFFFFFFULL); 6798c2ecf20Sopenharmony_ci swinfo[2] = (u32)((sc_phys & 0xFFFFFFFF00000000ULL) >> 32); 6808c2ecf20Sopenharmony_ci swinfo[2] |= (hash_size << __ffs(SA_SW2_EGRESS_LENGTH)); 6818c2ecf20Sopenharmony_ci} 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci/* Dump the security context */ 6848c2ecf20Sopenharmony_cistatic void sa_dump_sc(u8 *buf, dma_addr_t dma_addr) 6858c2ecf20Sopenharmony_ci{ 6868c2ecf20Sopenharmony_ci#ifdef DEBUG 6878c2ecf20Sopenharmony_ci dev_info(sa_k3_dev, "Security context dump:: 0x%pad\n", &dma_addr); 6888c2ecf20Sopenharmony_ci print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET, 6898c2ecf20Sopenharmony_ci 16, 1, buf, SA_CTX_MAX_SZ, false); 6908c2ecf20Sopenharmony_ci#endif 6918c2ecf20Sopenharmony_ci} 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_cistatic 6948c2ecf20Sopenharmony_ciint sa_init_sc(struct sa_ctx_info *ctx, const u8 *enc_key, 6958c2ecf20Sopenharmony_ci u16 enc_key_sz, const u8 *auth_key, u16 auth_key_sz, 6968c2ecf20Sopenharmony_ci struct algo_data *ad, u8 enc, u32 *swinfo) 6978c2ecf20Sopenharmony_ci{ 6988c2ecf20Sopenharmony_ci int enc_sc_offset = 0; 6998c2ecf20Sopenharmony_ci int auth_sc_offset = 0; 7008c2ecf20Sopenharmony_ci u8 *sc_buf = ctx->sc; 7018c2ecf20Sopenharmony_ci u16 sc_id = ctx->sc_id; 7028c2ecf20Sopenharmony_ci u8 first_engine = 0; 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci memzero_explicit(sc_buf, SA_CTX_MAX_SZ); 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci if (ad->auth_eng.eng_id) { 7078c2ecf20Sopenharmony_ci if (enc) 7088c2ecf20Sopenharmony_ci first_engine = ad->enc_eng.eng_id; 7098c2ecf20Sopenharmony_ci else 7108c2ecf20Sopenharmony_ci first_engine = ad->auth_eng.eng_id; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci enc_sc_offset = SA_CTX_PHP_PE_CTX_SZ; 7138c2ecf20Sopenharmony_ci auth_sc_offset = enc_sc_offset + ad->enc_eng.sc_size; 7148c2ecf20Sopenharmony_ci sc_buf[1] = SA_SCCTL_FE_AUTH_ENC; 7158c2ecf20Sopenharmony_ci if (!ad->hash_size) 7168c2ecf20Sopenharmony_ci return -EINVAL; 7178c2ecf20Sopenharmony_ci ad->hash_size = roundup(ad->hash_size, 8); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci } else if (ad->enc_eng.eng_id && !ad->auth_eng.eng_id) { 7208c2ecf20Sopenharmony_ci enc_sc_offset = SA_CTX_PHP_PE_CTX_SZ; 7218c2ecf20Sopenharmony_ci first_engine = ad->enc_eng.eng_id; 7228c2ecf20Sopenharmony_ci sc_buf[1] = SA_SCCTL_FE_ENC; 7238c2ecf20Sopenharmony_ci ad->hash_size = ad->iv_out_size; 7248c2ecf20Sopenharmony_ci } 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci /* SCCTL Owner info: 0=host, 1=CP_ACE */ 7278c2ecf20Sopenharmony_ci sc_buf[SA_CTX_SCCTL_OWNER_OFFSET] = 0; 7288c2ecf20Sopenharmony_ci memcpy(&sc_buf[2], &sc_id, 2); 7298c2ecf20Sopenharmony_ci sc_buf[4] = 0x0; 7308c2ecf20Sopenharmony_ci sc_buf[5] = PRIV_ID; 7318c2ecf20Sopenharmony_ci sc_buf[6] = PRIV; 7328c2ecf20Sopenharmony_ci sc_buf[7] = 0x0; 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci /* Prepare context for encryption engine */ 7358c2ecf20Sopenharmony_ci if (ad->enc_eng.sc_size) { 7368c2ecf20Sopenharmony_ci if (sa_set_sc_enc(ad, enc_key, enc_key_sz, enc, 7378c2ecf20Sopenharmony_ci &sc_buf[enc_sc_offset])) 7388c2ecf20Sopenharmony_ci return -EINVAL; 7398c2ecf20Sopenharmony_ci } 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci /* Prepare context for authentication engine */ 7428c2ecf20Sopenharmony_ci if (ad->auth_eng.sc_size) 7438c2ecf20Sopenharmony_ci sa_set_sc_auth(ad, auth_key, auth_key_sz, 7448c2ecf20Sopenharmony_ci &sc_buf[auth_sc_offset]); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci /* Set the ownership of context to CP_ACE */ 7478c2ecf20Sopenharmony_ci sc_buf[SA_CTX_SCCTL_OWNER_OFFSET] = 0x80; 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci /* swizzle the security context */ 7508c2ecf20Sopenharmony_ci sa_swiz_128(sc_buf, SA_CTX_MAX_SZ); 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci sa_set_swinfo(first_engine, ctx->sc_id, ctx->sc_phys, 1, 0, 7538c2ecf20Sopenharmony_ci SA_SW_INFO_FLAG_EVICT, ad->hash_size, swinfo); 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci sa_dump_sc(sc_buf, ctx->sc_phys); 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci return 0; 7588c2ecf20Sopenharmony_ci} 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci/* Free the per direction context memory */ 7618c2ecf20Sopenharmony_cistatic void sa_free_ctx_info(struct sa_ctx_info *ctx, 7628c2ecf20Sopenharmony_ci struct sa_crypto_data *data) 7638c2ecf20Sopenharmony_ci{ 7648c2ecf20Sopenharmony_ci unsigned long bn; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci bn = ctx->sc_id - data->sc_id_start; 7678c2ecf20Sopenharmony_ci spin_lock(&data->scid_lock); 7688c2ecf20Sopenharmony_ci __clear_bit(bn, data->ctx_bm); 7698c2ecf20Sopenharmony_ci data->sc_id--; 7708c2ecf20Sopenharmony_ci spin_unlock(&data->scid_lock); 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci if (ctx->sc) { 7738c2ecf20Sopenharmony_ci dma_pool_free(data->sc_pool, ctx->sc, ctx->sc_phys); 7748c2ecf20Sopenharmony_ci ctx->sc = NULL; 7758c2ecf20Sopenharmony_ci } 7768c2ecf20Sopenharmony_ci} 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_cistatic int sa_init_ctx_info(struct sa_ctx_info *ctx, 7798c2ecf20Sopenharmony_ci struct sa_crypto_data *data) 7808c2ecf20Sopenharmony_ci{ 7818c2ecf20Sopenharmony_ci unsigned long bn; 7828c2ecf20Sopenharmony_ci int err; 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci spin_lock(&data->scid_lock); 7858c2ecf20Sopenharmony_ci bn = find_first_zero_bit(data->ctx_bm, SA_MAX_NUM_CTX); 7868c2ecf20Sopenharmony_ci __set_bit(bn, data->ctx_bm); 7878c2ecf20Sopenharmony_ci data->sc_id++; 7888c2ecf20Sopenharmony_ci spin_unlock(&data->scid_lock); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci ctx->sc_id = (u16)(data->sc_id_start + bn); 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci ctx->sc = dma_pool_alloc(data->sc_pool, GFP_KERNEL, &ctx->sc_phys); 7938c2ecf20Sopenharmony_ci if (!ctx->sc) { 7948c2ecf20Sopenharmony_ci dev_err(&data->pdev->dev, "Failed to allocate SC memory\n"); 7958c2ecf20Sopenharmony_ci err = -ENOMEM; 7968c2ecf20Sopenharmony_ci goto scid_rollback; 7978c2ecf20Sopenharmony_ci } 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci return 0; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ciscid_rollback: 8028c2ecf20Sopenharmony_ci spin_lock(&data->scid_lock); 8038c2ecf20Sopenharmony_ci __clear_bit(bn, data->ctx_bm); 8048c2ecf20Sopenharmony_ci data->sc_id--; 8058c2ecf20Sopenharmony_ci spin_unlock(&data->scid_lock); 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci return err; 8088c2ecf20Sopenharmony_ci} 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_cistatic void sa_cipher_cra_exit(struct crypto_skcipher *tfm) 8118c2ecf20Sopenharmony_ci{ 8128c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); 8138c2ecf20Sopenharmony_ci struct sa_crypto_data *data = dev_get_drvdata(sa_k3_dev); 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci dev_dbg(sa_k3_dev, "%s(0x%p) sc-ids(0x%x(0x%pad), 0x%x(0x%pad))\n", 8168c2ecf20Sopenharmony_ci __func__, tfm, ctx->enc.sc_id, &ctx->enc.sc_phys, 8178c2ecf20Sopenharmony_ci ctx->dec.sc_id, &ctx->dec.sc_phys); 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci sa_free_ctx_info(&ctx->enc, data); 8208c2ecf20Sopenharmony_ci sa_free_ctx_info(&ctx->dec, data); 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci crypto_free_sync_skcipher(ctx->fallback.skcipher); 8238c2ecf20Sopenharmony_ci} 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_cistatic int sa_cipher_cra_init(struct crypto_skcipher *tfm) 8268c2ecf20Sopenharmony_ci{ 8278c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); 8288c2ecf20Sopenharmony_ci struct sa_crypto_data *data = dev_get_drvdata(sa_k3_dev); 8298c2ecf20Sopenharmony_ci const char *name = crypto_tfm_alg_name(&tfm->base); 8308c2ecf20Sopenharmony_ci int ret; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci memzero_explicit(ctx, sizeof(*ctx)); 8338c2ecf20Sopenharmony_ci ctx->dev_data = data; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci ret = sa_init_ctx_info(&ctx->enc, data); 8368c2ecf20Sopenharmony_ci if (ret) 8378c2ecf20Sopenharmony_ci return ret; 8388c2ecf20Sopenharmony_ci ret = sa_init_ctx_info(&ctx->dec, data); 8398c2ecf20Sopenharmony_ci if (ret) { 8408c2ecf20Sopenharmony_ci sa_free_ctx_info(&ctx->enc, data); 8418c2ecf20Sopenharmony_ci return ret; 8428c2ecf20Sopenharmony_ci } 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci ctx->fallback.skcipher = 8458c2ecf20Sopenharmony_ci crypto_alloc_sync_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci if (IS_ERR(ctx->fallback.skcipher)) { 8488c2ecf20Sopenharmony_ci dev_err(sa_k3_dev, "Error allocating fallback algo %s\n", name); 8498c2ecf20Sopenharmony_ci return PTR_ERR(ctx->fallback.skcipher); 8508c2ecf20Sopenharmony_ci } 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci dev_dbg(sa_k3_dev, "%s(0x%p) sc-ids(0x%x(0x%pad), 0x%x(0x%pad))\n", 8538c2ecf20Sopenharmony_ci __func__, tfm, ctx->enc.sc_id, &ctx->enc.sc_phys, 8548c2ecf20Sopenharmony_ci ctx->dec.sc_id, &ctx->dec.sc_phys); 8558c2ecf20Sopenharmony_ci return 0; 8568c2ecf20Sopenharmony_ci} 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_cistatic int sa_cipher_setkey(struct crypto_skcipher *tfm, const u8 *key, 8598c2ecf20Sopenharmony_ci unsigned int keylen, struct algo_data *ad) 8608c2ecf20Sopenharmony_ci{ 8618c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_skcipher_ctx(tfm); 8628c2ecf20Sopenharmony_ci int cmdl_len; 8638c2ecf20Sopenharmony_ci struct sa_cmdl_cfg cfg; 8648c2ecf20Sopenharmony_ci int ret; 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_192 && 8678c2ecf20Sopenharmony_ci keylen != AES_KEYSIZE_256) 8688c2ecf20Sopenharmony_ci return -EINVAL; 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci ad->enc_eng.eng_id = SA_ENG_ID_EM1; 8718c2ecf20Sopenharmony_ci ad->enc_eng.sc_size = SA_CTX_ENC_TYPE1_SZ; 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci memzero_explicit(&cfg, sizeof(cfg)); 8748c2ecf20Sopenharmony_ci cfg.enc_eng_id = ad->enc_eng.eng_id; 8758c2ecf20Sopenharmony_ci cfg.iv_size = crypto_skcipher_ivsize(tfm); 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci crypto_sync_skcipher_clear_flags(ctx->fallback.skcipher, 8788c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 8798c2ecf20Sopenharmony_ci crypto_sync_skcipher_set_flags(ctx->fallback.skcipher, 8808c2ecf20Sopenharmony_ci tfm->base.crt_flags & 8818c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 8828c2ecf20Sopenharmony_ci ret = crypto_sync_skcipher_setkey(ctx->fallback.skcipher, key, keylen); 8838c2ecf20Sopenharmony_ci if (ret) 8848c2ecf20Sopenharmony_ci return ret; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci /* Setup Encryption Security Context & Command label template */ 8878c2ecf20Sopenharmony_ci if (sa_init_sc(&ctx->enc, key, keylen, NULL, 0, ad, 1, 8888c2ecf20Sopenharmony_ci &ctx->enc.epib[1])) 8898c2ecf20Sopenharmony_ci goto badkey; 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci cmdl_len = sa_format_cmdl_gen(&cfg, 8928c2ecf20Sopenharmony_ci (u8 *)ctx->enc.cmdl, 8938c2ecf20Sopenharmony_ci &ctx->enc.cmdl_upd_info); 8948c2ecf20Sopenharmony_ci if (cmdl_len <= 0 || (cmdl_len > SA_MAX_CMDL_WORDS * sizeof(u32))) 8958c2ecf20Sopenharmony_ci goto badkey; 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci ctx->enc.cmdl_size = cmdl_len; 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci /* Setup Decryption Security Context & Command label template */ 9008c2ecf20Sopenharmony_ci if (sa_init_sc(&ctx->dec, key, keylen, NULL, 0, ad, 0, 9018c2ecf20Sopenharmony_ci &ctx->dec.epib[1])) 9028c2ecf20Sopenharmony_ci goto badkey; 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci cfg.enc_eng_id = ad->enc_eng.eng_id; 9058c2ecf20Sopenharmony_ci cmdl_len = sa_format_cmdl_gen(&cfg, (u8 *)ctx->dec.cmdl, 9068c2ecf20Sopenharmony_ci &ctx->dec.cmdl_upd_info); 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci if (cmdl_len <= 0 || (cmdl_len > SA_MAX_CMDL_WORDS * sizeof(u32))) 9098c2ecf20Sopenharmony_ci goto badkey; 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci ctx->dec.cmdl_size = cmdl_len; 9128c2ecf20Sopenharmony_ci ctx->iv_idx = ad->iv_idx; 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci return 0; 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_cibadkey: 9178c2ecf20Sopenharmony_ci dev_err(sa_k3_dev, "%s: badkey\n", __func__); 9188c2ecf20Sopenharmony_ci return -EINVAL; 9198c2ecf20Sopenharmony_ci} 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_cistatic int sa_aes_cbc_setkey(struct crypto_skcipher *tfm, const u8 *key, 9228c2ecf20Sopenharmony_ci unsigned int keylen) 9238c2ecf20Sopenharmony_ci{ 9248c2ecf20Sopenharmony_ci struct algo_data ad = { 0 }; 9258c2ecf20Sopenharmony_ci /* Convert the key size (16/24/32) to the key size index (0/1/2) */ 9268c2ecf20Sopenharmony_ci int key_idx = (keylen >> 3) - 2; 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci if (key_idx >= 3) 9298c2ecf20Sopenharmony_ci return -EINVAL; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci ad.mci_enc = mci_cbc_enc_array[key_idx]; 9328c2ecf20Sopenharmony_ci ad.mci_dec = mci_cbc_dec_array[key_idx]; 9338c2ecf20Sopenharmony_ci ad.inv_key = true; 9348c2ecf20Sopenharmony_ci ad.ealg_id = SA_EALG_ID_AES_CBC; 9358c2ecf20Sopenharmony_ci ad.iv_idx = 4; 9368c2ecf20Sopenharmony_ci ad.iv_out_size = 16; 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci return sa_cipher_setkey(tfm, key, keylen, &ad); 9398c2ecf20Sopenharmony_ci} 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_cistatic int sa_aes_ecb_setkey(struct crypto_skcipher *tfm, const u8 *key, 9428c2ecf20Sopenharmony_ci unsigned int keylen) 9438c2ecf20Sopenharmony_ci{ 9448c2ecf20Sopenharmony_ci struct algo_data ad = { 0 }; 9458c2ecf20Sopenharmony_ci /* Convert the key size (16/24/32) to the key size index (0/1/2) */ 9468c2ecf20Sopenharmony_ci int key_idx = (keylen >> 3) - 2; 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci if (key_idx >= 3) 9498c2ecf20Sopenharmony_ci return -EINVAL; 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci ad.mci_enc = mci_ecb_enc_array[key_idx]; 9528c2ecf20Sopenharmony_ci ad.mci_dec = mci_ecb_dec_array[key_idx]; 9538c2ecf20Sopenharmony_ci ad.inv_key = true; 9548c2ecf20Sopenharmony_ci ad.ealg_id = SA_EALG_ID_AES_ECB; 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci return sa_cipher_setkey(tfm, key, keylen, &ad); 9578c2ecf20Sopenharmony_ci} 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_cistatic int sa_3des_cbc_setkey(struct crypto_skcipher *tfm, const u8 *key, 9608c2ecf20Sopenharmony_ci unsigned int keylen) 9618c2ecf20Sopenharmony_ci{ 9628c2ecf20Sopenharmony_ci struct algo_data ad = { 0 }; 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci ad.mci_enc = mci_cbc_3des_enc_array; 9658c2ecf20Sopenharmony_ci ad.mci_dec = mci_cbc_3des_dec_array; 9668c2ecf20Sopenharmony_ci ad.ealg_id = SA_EALG_ID_3DES_CBC; 9678c2ecf20Sopenharmony_ci ad.iv_idx = 6; 9688c2ecf20Sopenharmony_ci ad.iv_out_size = 8; 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci return sa_cipher_setkey(tfm, key, keylen, &ad); 9718c2ecf20Sopenharmony_ci} 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_cistatic int sa_3des_ecb_setkey(struct crypto_skcipher *tfm, const u8 *key, 9748c2ecf20Sopenharmony_ci unsigned int keylen) 9758c2ecf20Sopenharmony_ci{ 9768c2ecf20Sopenharmony_ci struct algo_data ad = { 0 }; 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci ad.mci_enc = mci_ecb_3des_enc_array; 9798c2ecf20Sopenharmony_ci ad.mci_dec = mci_ecb_3des_dec_array; 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci return sa_cipher_setkey(tfm, key, keylen, &ad); 9828c2ecf20Sopenharmony_ci} 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_cistatic void sa_sync_from_device(struct sa_rx_data *rxd) 9858c2ecf20Sopenharmony_ci{ 9868c2ecf20Sopenharmony_ci struct sg_table *sgt; 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci if (rxd->mapped_sg[0].dir == DMA_BIDIRECTIONAL) 9898c2ecf20Sopenharmony_ci sgt = &rxd->mapped_sg[0].sgt; 9908c2ecf20Sopenharmony_ci else 9918c2ecf20Sopenharmony_ci sgt = &rxd->mapped_sg[1].sgt; 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci dma_sync_sgtable_for_cpu(rxd->ddev, sgt, DMA_FROM_DEVICE); 9948c2ecf20Sopenharmony_ci} 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_cistatic void sa_free_sa_rx_data(struct sa_rx_data *rxd) 9978c2ecf20Sopenharmony_ci{ 9988c2ecf20Sopenharmony_ci int i; 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(rxd->mapped_sg); i++) { 10018c2ecf20Sopenharmony_ci struct sa_mapped_sg *mapped_sg = &rxd->mapped_sg[i]; 10028c2ecf20Sopenharmony_ci 10038c2ecf20Sopenharmony_ci if (mapped_sg->mapped) { 10048c2ecf20Sopenharmony_ci dma_unmap_sgtable(rxd->ddev, &mapped_sg->sgt, 10058c2ecf20Sopenharmony_ci mapped_sg->dir, 0); 10068c2ecf20Sopenharmony_ci kfree(mapped_sg->split_sg); 10078c2ecf20Sopenharmony_ci } 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci kfree(rxd); 10118c2ecf20Sopenharmony_ci} 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_cistatic void sa_aes_dma_in_callback(void *data) 10148c2ecf20Sopenharmony_ci{ 10158c2ecf20Sopenharmony_ci struct sa_rx_data *rxd = (struct sa_rx_data *)data; 10168c2ecf20Sopenharmony_ci struct skcipher_request *req; 10178c2ecf20Sopenharmony_ci u32 *result; 10188c2ecf20Sopenharmony_ci __be32 *mdptr; 10198c2ecf20Sopenharmony_ci size_t ml, pl; 10208c2ecf20Sopenharmony_ci int i; 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci sa_sync_from_device(rxd); 10238c2ecf20Sopenharmony_ci req = container_of(rxd->req, struct skcipher_request, base); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci if (req->iv) { 10268c2ecf20Sopenharmony_ci mdptr = (__be32 *)dmaengine_desc_get_metadata_ptr(rxd->tx_in, &pl, 10278c2ecf20Sopenharmony_ci &ml); 10288c2ecf20Sopenharmony_ci result = (u32 *)req->iv; 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci for (i = 0; i < (rxd->enc_iv_size / 4); i++) 10318c2ecf20Sopenharmony_ci result[i] = be32_to_cpu(mdptr[i + rxd->iv_idx]); 10328c2ecf20Sopenharmony_ci } 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_ci sa_free_sa_rx_data(rxd); 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci skcipher_request_complete(req, 0); 10378c2ecf20Sopenharmony_ci} 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_cistatic void 10408c2ecf20Sopenharmony_cisa_prepare_tx_desc(u32 *mdptr, u32 pslen, u32 *psdata, u32 epiblen, u32 *epib) 10418c2ecf20Sopenharmony_ci{ 10428c2ecf20Sopenharmony_ci u32 *out, *in; 10438c2ecf20Sopenharmony_ci int i; 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci for (out = mdptr, in = epib, i = 0; i < epiblen / sizeof(u32); i++) 10468c2ecf20Sopenharmony_ci *out++ = *in++; 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci mdptr[4] = (0xFFFF << 16); 10498c2ecf20Sopenharmony_ci for (out = &mdptr[5], in = psdata, i = 0; 10508c2ecf20Sopenharmony_ci i < pslen / sizeof(u32); i++) 10518c2ecf20Sopenharmony_ci *out++ = *in++; 10528c2ecf20Sopenharmony_ci} 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_cistatic int sa_run(struct sa_req *req) 10558c2ecf20Sopenharmony_ci{ 10568c2ecf20Sopenharmony_ci struct sa_rx_data *rxd; 10578c2ecf20Sopenharmony_ci gfp_t gfp_flags; 10588c2ecf20Sopenharmony_ci u32 cmdl[SA_MAX_CMDL_WORDS]; 10598c2ecf20Sopenharmony_ci struct sa_crypto_data *pdata = dev_get_drvdata(sa_k3_dev); 10608c2ecf20Sopenharmony_ci struct device *ddev; 10618c2ecf20Sopenharmony_ci struct dma_chan *dma_rx; 10628c2ecf20Sopenharmony_ci int sg_nents, src_nents, dst_nents; 10638c2ecf20Sopenharmony_ci struct scatterlist *src, *dst; 10648c2ecf20Sopenharmony_ci size_t pl, ml, split_size; 10658c2ecf20Sopenharmony_ci struct sa_ctx_info *sa_ctx = req->enc ? &req->ctx->enc : &req->ctx->dec; 10668c2ecf20Sopenharmony_ci int ret; 10678c2ecf20Sopenharmony_ci struct dma_async_tx_descriptor *tx_out; 10688c2ecf20Sopenharmony_ci u32 *mdptr; 10698c2ecf20Sopenharmony_ci bool diff_dst; 10708c2ecf20Sopenharmony_ci enum dma_data_direction dir_src; 10718c2ecf20Sopenharmony_ci struct sa_mapped_sg *mapped_sg; 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci gfp_flags = req->base->flags & CRYPTO_TFM_REQ_MAY_SLEEP ? 10748c2ecf20Sopenharmony_ci GFP_KERNEL : GFP_ATOMIC; 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci rxd = kzalloc(sizeof(*rxd), gfp_flags); 10778c2ecf20Sopenharmony_ci if (!rxd) 10788c2ecf20Sopenharmony_ci return -ENOMEM; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci if (req->src != req->dst) { 10818c2ecf20Sopenharmony_ci diff_dst = true; 10828c2ecf20Sopenharmony_ci dir_src = DMA_TO_DEVICE; 10838c2ecf20Sopenharmony_ci } else { 10848c2ecf20Sopenharmony_ci diff_dst = false; 10858c2ecf20Sopenharmony_ci dir_src = DMA_BIDIRECTIONAL; 10868c2ecf20Sopenharmony_ci } 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci /* 10898c2ecf20Sopenharmony_ci * SA2UL has an interesting feature where the receive DMA channel 10908c2ecf20Sopenharmony_ci * is selected based on the data passed to the engine. Within the 10918c2ecf20Sopenharmony_ci * transition range, there is also a space where it is impossible 10928c2ecf20Sopenharmony_ci * to determine where the data will end up, and this should be 10938c2ecf20Sopenharmony_ci * avoided. This will be handled by the SW fallback mechanism by 10948c2ecf20Sopenharmony_ci * the individual algorithm implementations. 10958c2ecf20Sopenharmony_ci */ 10968c2ecf20Sopenharmony_ci if (req->size >= 256) 10978c2ecf20Sopenharmony_ci dma_rx = pdata->dma_rx2; 10988c2ecf20Sopenharmony_ci else 10998c2ecf20Sopenharmony_ci dma_rx = pdata->dma_rx1; 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci ddev = dma_rx->device->dev; 11028c2ecf20Sopenharmony_ci rxd->ddev = ddev; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci memcpy(cmdl, sa_ctx->cmdl, sa_ctx->cmdl_size); 11058c2ecf20Sopenharmony_ci 11068c2ecf20Sopenharmony_ci sa_update_cmdl(req, cmdl, &sa_ctx->cmdl_upd_info); 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci if (req->type != CRYPTO_ALG_TYPE_AHASH) { 11098c2ecf20Sopenharmony_ci if (req->enc) 11108c2ecf20Sopenharmony_ci req->type |= 11118c2ecf20Sopenharmony_ci (SA_REQ_SUBTYPE_ENC << SA_REQ_SUBTYPE_SHIFT); 11128c2ecf20Sopenharmony_ci else 11138c2ecf20Sopenharmony_ci req->type |= 11148c2ecf20Sopenharmony_ci (SA_REQ_SUBTYPE_DEC << SA_REQ_SUBTYPE_SHIFT); 11158c2ecf20Sopenharmony_ci } 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci cmdl[sa_ctx->cmdl_size / sizeof(u32)] = req->type; 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_ci /* 11208c2ecf20Sopenharmony_ci * Map the packets, first we check if the data fits into a single 11218c2ecf20Sopenharmony_ci * sg entry and use that if possible. If it does not fit, we check 11228c2ecf20Sopenharmony_ci * if we need to do sg_split to align the scatterlist data on the 11238c2ecf20Sopenharmony_ci * actual data size being processed by the crypto engine. 11248c2ecf20Sopenharmony_ci */ 11258c2ecf20Sopenharmony_ci src = req->src; 11268c2ecf20Sopenharmony_ci sg_nents = sg_nents_for_len(src, req->size); 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci split_size = req->size; 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_ci mapped_sg = &rxd->mapped_sg[0]; 11318c2ecf20Sopenharmony_ci if (sg_nents == 1 && split_size <= req->src->length) { 11328c2ecf20Sopenharmony_ci src = &mapped_sg->static_sg; 11338c2ecf20Sopenharmony_ci src_nents = 1; 11348c2ecf20Sopenharmony_ci sg_init_table(src, 1); 11358c2ecf20Sopenharmony_ci sg_set_page(src, sg_page(req->src), split_size, 11368c2ecf20Sopenharmony_ci req->src->offset); 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci mapped_sg->sgt.sgl = src; 11398c2ecf20Sopenharmony_ci mapped_sg->sgt.orig_nents = src_nents; 11408c2ecf20Sopenharmony_ci ret = dma_map_sgtable(ddev, &mapped_sg->sgt, dir_src, 0); 11418c2ecf20Sopenharmony_ci if (ret) { 11428c2ecf20Sopenharmony_ci kfree(rxd); 11438c2ecf20Sopenharmony_ci return ret; 11448c2ecf20Sopenharmony_ci } 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_ci mapped_sg->dir = dir_src; 11478c2ecf20Sopenharmony_ci mapped_sg->mapped = true; 11488c2ecf20Sopenharmony_ci } else { 11498c2ecf20Sopenharmony_ci mapped_sg->sgt.sgl = req->src; 11508c2ecf20Sopenharmony_ci mapped_sg->sgt.orig_nents = sg_nents; 11518c2ecf20Sopenharmony_ci ret = dma_map_sgtable(ddev, &mapped_sg->sgt, dir_src, 0); 11528c2ecf20Sopenharmony_ci if (ret) { 11538c2ecf20Sopenharmony_ci kfree(rxd); 11548c2ecf20Sopenharmony_ci return ret; 11558c2ecf20Sopenharmony_ci } 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci mapped_sg->dir = dir_src; 11588c2ecf20Sopenharmony_ci mapped_sg->mapped = true; 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_ci ret = sg_split(mapped_sg->sgt.sgl, mapped_sg->sgt.nents, 0, 1, 11618c2ecf20Sopenharmony_ci &split_size, &src, &src_nents, gfp_flags); 11628c2ecf20Sopenharmony_ci if (ret) { 11638c2ecf20Sopenharmony_ci src_nents = mapped_sg->sgt.nents; 11648c2ecf20Sopenharmony_ci src = mapped_sg->sgt.sgl; 11658c2ecf20Sopenharmony_ci } else { 11668c2ecf20Sopenharmony_ci mapped_sg->split_sg = src; 11678c2ecf20Sopenharmony_ci } 11688c2ecf20Sopenharmony_ci } 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci dma_sync_sgtable_for_device(ddev, &mapped_sg->sgt, DMA_TO_DEVICE); 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci if (!diff_dst) { 11738c2ecf20Sopenharmony_ci dst_nents = src_nents; 11748c2ecf20Sopenharmony_ci dst = src; 11758c2ecf20Sopenharmony_ci } else { 11768c2ecf20Sopenharmony_ci dst_nents = sg_nents_for_len(req->dst, req->size); 11778c2ecf20Sopenharmony_ci mapped_sg = &rxd->mapped_sg[1]; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci if (dst_nents == 1 && split_size <= req->dst->length) { 11808c2ecf20Sopenharmony_ci dst = &mapped_sg->static_sg; 11818c2ecf20Sopenharmony_ci dst_nents = 1; 11828c2ecf20Sopenharmony_ci sg_init_table(dst, 1); 11838c2ecf20Sopenharmony_ci sg_set_page(dst, sg_page(req->dst), split_size, 11848c2ecf20Sopenharmony_ci req->dst->offset); 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci mapped_sg->sgt.sgl = dst; 11878c2ecf20Sopenharmony_ci mapped_sg->sgt.orig_nents = dst_nents; 11888c2ecf20Sopenharmony_ci ret = dma_map_sgtable(ddev, &mapped_sg->sgt, 11898c2ecf20Sopenharmony_ci DMA_FROM_DEVICE, 0); 11908c2ecf20Sopenharmony_ci if (ret) 11918c2ecf20Sopenharmony_ci goto err_cleanup; 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci mapped_sg->dir = DMA_FROM_DEVICE; 11948c2ecf20Sopenharmony_ci mapped_sg->mapped = true; 11958c2ecf20Sopenharmony_ci } else { 11968c2ecf20Sopenharmony_ci mapped_sg->sgt.sgl = req->dst; 11978c2ecf20Sopenharmony_ci mapped_sg->sgt.orig_nents = dst_nents; 11988c2ecf20Sopenharmony_ci ret = dma_map_sgtable(ddev, &mapped_sg->sgt, 11998c2ecf20Sopenharmony_ci DMA_FROM_DEVICE, 0); 12008c2ecf20Sopenharmony_ci if (ret) 12018c2ecf20Sopenharmony_ci goto err_cleanup; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci mapped_sg->dir = DMA_FROM_DEVICE; 12048c2ecf20Sopenharmony_ci mapped_sg->mapped = true; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci ret = sg_split(mapped_sg->sgt.sgl, mapped_sg->sgt.nents, 12078c2ecf20Sopenharmony_ci 0, 1, &split_size, &dst, &dst_nents, 12088c2ecf20Sopenharmony_ci gfp_flags); 12098c2ecf20Sopenharmony_ci if (ret) { 12108c2ecf20Sopenharmony_ci dst_nents = mapped_sg->sgt.nents; 12118c2ecf20Sopenharmony_ci dst = mapped_sg->sgt.sgl; 12128c2ecf20Sopenharmony_ci } else { 12138c2ecf20Sopenharmony_ci mapped_sg->split_sg = dst; 12148c2ecf20Sopenharmony_ci } 12158c2ecf20Sopenharmony_ci } 12168c2ecf20Sopenharmony_ci } 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci rxd->tx_in = dmaengine_prep_slave_sg(dma_rx, dst, dst_nents, 12198c2ecf20Sopenharmony_ci DMA_DEV_TO_MEM, 12208c2ecf20Sopenharmony_ci DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 12218c2ecf20Sopenharmony_ci if (!rxd->tx_in) { 12228c2ecf20Sopenharmony_ci dev_err(pdata->dev, "IN prep_slave_sg() failed\n"); 12238c2ecf20Sopenharmony_ci ret = -EINVAL; 12248c2ecf20Sopenharmony_ci goto err_cleanup; 12258c2ecf20Sopenharmony_ci } 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci rxd->req = (void *)req->base; 12288c2ecf20Sopenharmony_ci rxd->enc = req->enc; 12298c2ecf20Sopenharmony_ci rxd->iv_idx = req->ctx->iv_idx; 12308c2ecf20Sopenharmony_ci rxd->enc_iv_size = sa_ctx->cmdl_upd_info.enc_iv.size; 12318c2ecf20Sopenharmony_ci rxd->tx_in->callback = req->callback; 12328c2ecf20Sopenharmony_ci rxd->tx_in->callback_param = rxd; 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci tx_out = dmaengine_prep_slave_sg(pdata->dma_tx, src, 12358c2ecf20Sopenharmony_ci src_nents, DMA_MEM_TO_DEV, 12368c2ecf20Sopenharmony_ci DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci if (!tx_out) { 12398c2ecf20Sopenharmony_ci dev_err(pdata->dev, "OUT prep_slave_sg() failed\n"); 12408c2ecf20Sopenharmony_ci ret = -EINVAL; 12418c2ecf20Sopenharmony_ci goto err_cleanup; 12428c2ecf20Sopenharmony_ci } 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci /* 12458c2ecf20Sopenharmony_ci * Prepare metadata for DMA engine. This essentially describes the 12468c2ecf20Sopenharmony_ci * crypto algorithm to be used, data sizes, different keys etc. 12478c2ecf20Sopenharmony_ci */ 12488c2ecf20Sopenharmony_ci mdptr = (u32 *)dmaengine_desc_get_metadata_ptr(tx_out, &pl, &ml); 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci sa_prepare_tx_desc(mdptr, (sa_ctx->cmdl_size + (SA_PSDATA_CTX_WORDS * 12518c2ecf20Sopenharmony_ci sizeof(u32))), cmdl, sizeof(sa_ctx->epib), 12528c2ecf20Sopenharmony_ci sa_ctx->epib); 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ci ml = sa_ctx->cmdl_size + (SA_PSDATA_CTX_WORDS * sizeof(u32)); 12558c2ecf20Sopenharmony_ci dmaengine_desc_set_metadata_len(tx_out, req->mdata_size); 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci dmaengine_submit(tx_out); 12588c2ecf20Sopenharmony_ci dmaengine_submit(rxd->tx_in); 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_ci dma_async_issue_pending(dma_rx); 12618c2ecf20Sopenharmony_ci dma_async_issue_pending(pdata->dma_tx); 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci return -EINPROGRESS; 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_cierr_cleanup: 12668c2ecf20Sopenharmony_ci sa_free_sa_rx_data(rxd); 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci return ret; 12698c2ecf20Sopenharmony_ci} 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_cistatic int sa_cipher_run(struct skcipher_request *req, u8 *iv, int enc) 12728c2ecf20Sopenharmony_ci{ 12738c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = 12748c2ecf20Sopenharmony_ci crypto_skcipher_ctx(crypto_skcipher_reqtfm(req)); 12758c2ecf20Sopenharmony_ci struct crypto_alg *alg = req->base.tfm->__crt_alg; 12768c2ecf20Sopenharmony_ci struct sa_req sa_req = { 0 }; 12778c2ecf20Sopenharmony_ci int ret; 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci if (!req->cryptlen) 12808c2ecf20Sopenharmony_ci return 0; 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci if (req->cryptlen % alg->cra_blocksize) 12838c2ecf20Sopenharmony_ci return -EINVAL; 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci /* Use SW fallback if the data size is not supported */ 12868c2ecf20Sopenharmony_ci if (req->cryptlen > SA_MAX_DATA_SZ || 12878c2ecf20Sopenharmony_ci (req->cryptlen >= SA_UNSAFE_DATA_SZ_MIN && 12888c2ecf20Sopenharmony_ci req->cryptlen <= SA_UNSAFE_DATA_SZ_MAX)) { 12898c2ecf20Sopenharmony_ci SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback.skcipher); 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci skcipher_request_set_sync_tfm(subreq, ctx->fallback.skcipher); 12928c2ecf20Sopenharmony_ci skcipher_request_set_callback(subreq, req->base.flags, 12938c2ecf20Sopenharmony_ci NULL, NULL); 12948c2ecf20Sopenharmony_ci skcipher_request_set_crypt(subreq, req->src, req->dst, 12958c2ecf20Sopenharmony_ci req->cryptlen, req->iv); 12968c2ecf20Sopenharmony_ci if (enc) 12978c2ecf20Sopenharmony_ci ret = crypto_skcipher_encrypt(subreq); 12988c2ecf20Sopenharmony_ci else 12998c2ecf20Sopenharmony_ci ret = crypto_skcipher_decrypt(subreq); 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_ci skcipher_request_zero(subreq); 13028c2ecf20Sopenharmony_ci return ret; 13038c2ecf20Sopenharmony_ci } 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci sa_req.size = req->cryptlen; 13068c2ecf20Sopenharmony_ci sa_req.enc_size = req->cryptlen; 13078c2ecf20Sopenharmony_ci sa_req.src = req->src; 13088c2ecf20Sopenharmony_ci sa_req.dst = req->dst; 13098c2ecf20Sopenharmony_ci sa_req.enc_iv = iv; 13108c2ecf20Sopenharmony_ci sa_req.type = CRYPTO_ALG_TYPE_SKCIPHER; 13118c2ecf20Sopenharmony_ci sa_req.enc = enc; 13128c2ecf20Sopenharmony_ci sa_req.callback = sa_aes_dma_in_callback; 13138c2ecf20Sopenharmony_ci sa_req.mdata_size = 44; 13148c2ecf20Sopenharmony_ci sa_req.base = &req->base; 13158c2ecf20Sopenharmony_ci sa_req.ctx = ctx; 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci return sa_run(&sa_req); 13188c2ecf20Sopenharmony_ci} 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_cistatic int sa_encrypt(struct skcipher_request *req) 13218c2ecf20Sopenharmony_ci{ 13228c2ecf20Sopenharmony_ci return sa_cipher_run(req, req->iv, 1); 13238c2ecf20Sopenharmony_ci} 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_cistatic int sa_decrypt(struct skcipher_request *req) 13268c2ecf20Sopenharmony_ci{ 13278c2ecf20Sopenharmony_ci return sa_cipher_run(req, req->iv, 0); 13288c2ecf20Sopenharmony_ci} 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_cistatic void sa_sha_dma_in_callback(void *data) 13318c2ecf20Sopenharmony_ci{ 13328c2ecf20Sopenharmony_ci struct sa_rx_data *rxd = (struct sa_rx_data *)data; 13338c2ecf20Sopenharmony_ci struct ahash_request *req; 13348c2ecf20Sopenharmony_ci struct crypto_ahash *tfm; 13358c2ecf20Sopenharmony_ci unsigned int authsize; 13368c2ecf20Sopenharmony_ci int i; 13378c2ecf20Sopenharmony_ci size_t ml, pl; 13388c2ecf20Sopenharmony_ci u32 *result; 13398c2ecf20Sopenharmony_ci __be32 *mdptr; 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci sa_sync_from_device(rxd); 13428c2ecf20Sopenharmony_ci req = container_of(rxd->req, struct ahash_request, base); 13438c2ecf20Sopenharmony_ci tfm = crypto_ahash_reqtfm(req); 13448c2ecf20Sopenharmony_ci authsize = crypto_ahash_digestsize(tfm); 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_ci mdptr = (__be32 *)dmaengine_desc_get_metadata_ptr(rxd->tx_in, &pl, &ml); 13478c2ecf20Sopenharmony_ci result = (u32 *)req->result; 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_ci for (i = 0; i < (authsize / 4); i++) 13508c2ecf20Sopenharmony_ci result[i] = be32_to_cpu(mdptr[i + 4]); 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci sa_free_sa_rx_data(rxd); 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci ahash_request_complete(req, 0); 13558c2ecf20Sopenharmony_ci} 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_cistatic int zero_message_process(struct ahash_request *req) 13588c2ecf20Sopenharmony_ci{ 13598c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 13608c2ecf20Sopenharmony_ci int sa_digest_size = crypto_ahash_digestsize(tfm); 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci switch (sa_digest_size) { 13638c2ecf20Sopenharmony_ci case SHA1_DIGEST_SIZE: 13648c2ecf20Sopenharmony_ci memcpy(req->result, sha1_zero_message_hash, sa_digest_size); 13658c2ecf20Sopenharmony_ci break; 13668c2ecf20Sopenharmony_ci case SHA256_DIGEST_SIZE: 13678c2ecf20Sopenharmony_ci memcpy(req->result, sha256_zero_message_hash, sa_digest_size); 13688c2ecf20Sopenharmony_ci break; 13698c2ecf20Sopenharmony_ci case SHA512_DIGEST_SIZE: 13708c2ecf20Sopenharmony_ci memcpy(req->result, sha512_zero_message_hash, sa_digest_size); 13718c2ecf20Sopenharmony_ci break; 13728c2ecf20Sopenharmony_ci default: 13738c2ecf20Sopenharmony_ci return -EINVAL; 13748c2ecf20Sopenharmony_ci } 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci return 0; 13778c2ecf20Sopenharmony_ci} 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_cistatic int sa_sha_run(struct ahash_request *req) 13808c2ecf20Sopenharmony_ci{ 13818c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req)); 13828c2ecf20Sopenharmony_ci struct sa_sha_req_ctx *rctx = ahash_request_ctx(req); 13838c2ecf20Sopenharmony_ci struct sa_req sa_req = { 0 }; 13848c2ecf20Sopenharmony_ci size_t auth_len; 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci auth_len = req->nbytes; 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci if (!auth_len) 13898c2ecf20Sopenharmony_ci return zero_message_process(req); 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci if (auth_len > SA_MAX_DATA_SZ || 13928c2ecf20Sopenharmony_ci (auth_len >= SA_UNSAFE_DATA_SZ_MIN && 13938c2ecf20Sopenharmony_ci auth_len <= SA_UNSAFE_DATA_SZ_MAX)) { 13948c2ecf20Sopenharmony_ci struct ahash_request *subreq = &rctx->fallback_req; 13958c2ecf20Sopenharmony_ci int ret = 0; 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci ahash_request_set_tfm(subreq, ctx->fallback.ahash); 13988c2ecf20Sopenharmony_ci subreq->base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP; 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci crypto_ahash_init(subreq); 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci subreq->nbytes = auth_len; 14038c2ecf20Sopenharmony_ci subreq->src = req->src; 14048c2ecf20Sopenharmony_ci subreq->result = req->result; 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci ret |= crypto_ahash_update(subreq); 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_ci subreq->nbytes = 0; 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci ret |= crypto_ahash_final(subreq); 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci return ret; 14138c2ecf20Sopenharmony_ci } 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_ci sa_req.size = auth_len; 14168c2ecf20Sopenharmony_ci sa_req.auth_size = auth_len; 14178c2ecf20Sopenharmony_ci sa_req.src = req->src; 14188c2ecf20Sopenharmony_ci sa_req.dst = req->src; 14198c2ecf20Sopenharmony_ci sa_req.enc = true; 14208c2ecf20Sopenharmony_ci sa_req.type = CRYPTO_ALG_TYPE_AHASH; 14218c2ecf20Sopenharmony_ci sa_req.callback = sa_sha_dma_in_callback; 14228c2ecf20Sopenharmony_ci sa_req.mdata_size = 28; 14238c2ecf20Sopenharmony_ci sa_req.ctx = ctx; 14248c2ecf20Sopenharmony_ci sa_req.base = &req->base; 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci return sa_run(&sa_req); 14278c2ecf20Sopenharmony_ci} 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_cistatic int sa_sha_setup(struct sa_tfm_ctx *ctx, struct algo_data *ad) 14308c2ecf20Sopenharmony_ci{ 14318c2ecf20Sopenharmony_ci int bs = crypto_shash_blocksize(ctx->shash); 14328c2ecf20Sopenharmony_ci int cmdl_len; 14338c2ecf20Sopenharmony_ci struct sa_cmdl_cfg cfg; 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_ci ad->enc_eng.sc_size = SA_CTX_ENC_TYPE1_SZ; 14368c2ecf20Sopenharmony_ci ad->auth_eng.eng_id = SA_ENG_ID_AM1; 14378c2ecf20Sopenharmony_ci ad->auth_eng.sc_size = SA_CTX_AUTH_TYPE2_SZ; 14388c2ecf20Sopenharmony_ci 14398c2ecf20Sopenharmony_ci memset(ctx->authkey, 0, bs); 14408c2ecf20Sopenharmony_ci memset(&cfg, 0, sizeof(cfg)); 14418c2ecf20Sopenharmony_ci cfg.aalg = ad->aalg_id; 14428c2ecf20Sopenharmony_ci cfg.enc_eng_id = ad->enc_eng.eng_id; 14438c2ecf20Sopenharmony_ci cfg.auth_eng_id = ad->auth_eng.eng_id; 14448c2ecf20Sopenharmony_ci cfg.iv_size = 0; 14458c2ecf20Sopenharmony_ci cfg.akey = NULL; 14468c2ecf20Sopenharmony_ci cfg.akey_len = 0; 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci /* Setup Encryption Security Context & Command label template */ 14498c2ecf20Sopenharmony_ci if (sa_init_sc(&ctx->enc, NULL, 0, NULL, 0, ad, 0, 14508c2ecf20Sopenharmony_ci &ctx->enc.epib[1])) 14518c2ecf20Sopenharmony_ci goto badkey; 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_ci cmdl_len = sa_format_cmdl_gen(&cfg, 14548c2ecf20Sopenharmony_ci (u8 *)ctx->enc.cmdl, 14558c2ecf20Sopenharmony_ci &ctx->enc.cmdl_upd_info); 14568c2ecf20Sopenharmony_ci if (cmdl_len <= 0 || (cmdl_len > SA_MAX_CMDL_WORDS * sizeof(u32))) 14578c2ecf20Sopenharmony_ci goto badkey; 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci ctx->enc.cmdl_size = cmdl_len; 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_ci return 0; 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_cibadkey: 14648c2ecf20Sopenharmony_ci dev_err(sa_k3_dev, "%s: badkey\n", __func__); 14658c2ecf20Sopenharmony_ci return -EINVAL; 14668c2ecf20Sopenharmony_ci} 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_cistatic int sa_sha_cra_init_alg(struct crypto_tfm *tfm, const char *alg_base) 14698c2ecf20Sopenharmony_ci{ 14708c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_tfm_ctx(tfm); 14718c2ecf20Sopenharmony_ci struct sa_crypto_data *data = dev_get_drvdata(sa_k3_dev); 14728c2ecf20Sopenharmony_ci int ret; 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci memset(ctx, 0, sizeof(*ctx)); 14758c2ecf20Sopenharmony_ci ctx->dev_data = data; 14768c2ecf20Sopenharmony_ci ret = sa_init_ctx_info(&ctx->enc, data); 14778c2ecf20Sopenharmony_ci if (ret) 14788c2ecf20Sopenharmony_ci return ret; 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci if (alg_base) { 14818c2ecf20Sopenharmony_ci ctx->shash = crypto_alloc_shash(alg_base, 0, 14828c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 14838c2ecf20Sopenharmony_ci if (IS_ERR(ctx->shash)) { 14848c2ecf20Sopenharmony_ci dev_err(sa_k3_dev, "base driver %s couldn't be loaded\n", 14858c2ecf20Sopenharmony_ci alg_base); 14868c2ecf20Sopenharmony_ci return PTR_ERR(ctx->shash); 14878c2ecf20Sopenharmony_ci } 14888c2ecf20Sopenharmony_ci /* for fallback */ 14898c2ecf20Sopenharmony_ci ctx->fallback.ahash = 14908c2ecf20Sopenharmony_ci crypto_alloc_ahash(alg_base, 0, 14918c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 14928c2ecf20Sopenharmony_ci if (IS_ERR(ctx->fallback.ahash)) { 14938c2ecf20Sopenharmony_ci dev_err(ctx->dev_data->dev, 14948c2ecf20Sopenharmony_ci "Could not load fallback driver\n"); 14958c2ecf20Sopenharmony_ci return PTR_ERR(ctx->fallback.ahash); 14968c2ecf20Sopenharmony_ci } 14978c2ecf20Sopenharmony_ci } 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_ci dev_dbg(sa_k3_dev, "%s(0x%p) sc-ids(0x%x(0x%pad), 0x%x(0x%pad))\n", 15008c2ecf20Sopenharmony_ci __func__, tfm, ctx->enc.sc_id, &ctx->enc.sc_phys, 15018c2ecf20Sopenharmony_ci ctx->dec.sc_id, &ctx->dec.sc_phys); 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), 15048c2ecf20Sopenharmony_ci sizeof(struct sa_sha_req_ctx) + 15058c2ecf20Sopenharmony_ci crypto_ahash_reqsize(ctx->fallback.ahash)); 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci return 0; 15088c2ecf20Sopenharmony_ci} 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_cistatic int sa_sha_digest(struct ahash_request *req) 15118c2ecf20Sopenharmony_ci{ 15128c2ecf20Sopenharmony_ci return sa_sha_run(req); 15138c2ecf20Sopenharmony_ci} 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_cistatic int sa_sha_init(struct ahash_request *req) 15168c2ecf20Sopenharmony_ci{ 15178c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 15188c2ecf20Sopenharmony_ci struct sa_sha_req_ctx *rctx = ahash_request_ctx(req); 15198c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_ahash_ctx(tfm); 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ci dev_dbg(sa_k3_dev, "init: digest size: %u, rctx=%p\n", 15228c2ecf20Sopenharmony_ci crypto_ahash_digestsize(tfm), rctx); 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback.ahash); 15258c2ecf20Sopenharmony_ci rctx->fallback_req.base.flags = 15268c2ecf20Sopenharmony_ci req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP; 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci return crypto_ahash_init(&rctx->fallback_req); 15298c2ecf20Sopenharmony_ci} 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_cistatic int sa_sha_update(struct ahash_request *req) 15328c2ecf20Sopenharmony_ci{ 15338c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 15348c2ecf20Sopenharmony_ci struct sa_sha_req_ctx *rctx = ahash_request_ctx(req); 15358c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_ahash_ctx(tfm); 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_ci ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback.ahash); 15388c2ecf20Sopenharmony_ci rctx->fallback_req.base.flags = 15398c2ecf20Sopenharmony_ci req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP; 15408c2ecf20Sopenharmony_ci rctx->fallback_req.nbytes = req->nbytes; 15418c2ecf20Sopenharmony_ci rctx->fallback_req.src = req->src; 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci return crypto_ahash_update(&rctx->fallback_req); 15448c2ecf20Sopenharmony_ci} 15458c2ecf20Sopenharmony_ci 15468c2ecf20Sopenharmony_cistatic int sa_sha_final(struct ahash_request *req) 15478c2ecf20Sopenharmony_ci{ 15488c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 15498c2ecf20Sopenharmony_ci struct sa_sha_req_ctx *rctx = ahash_request_ctx(req); 15508c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_ahash_ctx(tfm); 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_ci ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback.ahash); 15538c2ecf20Sopenharmony_ci rctx->fallback_req.base.flags = 15548c2ecf20Sopenharmony_ci req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP; 15558c2ecf20Sopenharmony_ci rctx->fallback_req.result = req->result; 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci return crypto_ahash_final(&rctx->fallback_req); 15588c2ecf20Sopenharmony_ci} 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_cistatic int sa_sha_finup(struct ahash_request *req) 15618c2ecf20Sopenharmony_ci{ 15628c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 15638c2ecf20Sopenharmony_ci struct sa_sha_req_ctx *rctx = ahash_request_ctx(req); 15648c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_ahash_ctx(tfm); 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback.ahash); 15678c2ecf20Sopenharmony_ci rctx->fallback_req.base.flags = 15688c2ecf20Sopenharmony_ci req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP; 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci rctx->fallback_req.nbytes = req->nbytes; 15718c2ecf20Sopenharmony_ci rctx->fallback_req.src = req->src; 15728c2ecf20Sopenharmony_ci rctx->fallback_req.result = req->result; 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci return crypto_ahash_finup(&rctx->fallback_req); 15758c2ecf20Sopenharmony_ci} 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_cistatic int sa_sha_import(struct ahash_request *req, const void *in) 15788c2ecf20Sopenharmony_ci{ 15798c2ecf20Sopenharmony_ci struct sa_sha_req_ctx *rctx = ahash_request_ctx(req); 15808c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 15818c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_ahash_ctx(tfm); 15828c2ecf20Sopenharmony_ci 15838c2ecf20Sopenharmony_ci ahash_request_set_tfm(&rctx->fallback_req, ctx->fallback.ahash); 15848c2ecf20Sopenharmony_ci rctx->fallback_req.base.flags = req->base.flags & 15858c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MAY_SLEEP; 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci return crypto_ahash_import(&rctx->fallback_req, in); 15888c2ecf20Sopenharmony_ci} 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_cistatic int sa_sha_export(struct ahash_request *req, void *out) 15918c2ecf20Sopenharmony_ci{ 15928c2ecf20Sopenharmony_ci struct sa_sha_req_ctx *rctx = ahash_request_ctx(req); 15938c2ecf20Sopenharmony_ci struct crypto_ahash *tfm = crypto_ahash_reqtfm(req); 15948c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_ahash_ctx(tfm); 15958c2ecf20Sopenharmony_ci struct ahash_request *subreq = &rctx->fallback_req; 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_ci ahash_request_set_tfm(subreq, ctx->fallback.ahash); 15988c2ecf20Sopenharmony_ci subreq->base.flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP; 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci return crypto_ahash_export(subreq, out); 16018c2ecf20Sopenharmony_ci} 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_cistatic int sa_sha1_cra_init(struct crypto_tfm *tfm) 16048c2ecf20Sopenharmony_ci{ 16058c2ecf20Sopenharmony_ci struct algo_data ad = { 0 }; 16068c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_tfm_ctx(tfm); 16078c2ecf20Sopenharmony_ci 16088c2ecf20Sopenharmony_ci sa_sha_cra_init_alg(tfm, "sha1"); 16098c2ecf20Sopenharmony_ci 16108c2ecf20Sopenharmony_ci ad.aalg_id = SA_AALG_ID_SHA1; 16118c2ecf20Sopenharmony_ci ad.hash_size = SHA1_DIGEST_SIZE; 16128c2ecf20Sopenharmony_ci ad.auth_ctrl = SA_AUTH_SW_CTRL_SHA1; 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci sa_sha_setup(ctx, &ad); 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci return 0; 16178c2ecf20Sopenharmony_ci} 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_cistatic int sa_sha256_cra_init(struct crypto_tfm *tfm) 16208c2ecf20Sopenharmony_ci{ 16218c2ecf20Sopenharmony_ci struct algo_data ad = { 0 }; 16228c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_tfm_ctx(tfm); 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci sa_sha_cra_init_alg(tfm, "sha256"); 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci ad.aalg_id = SA_AALG_ID_SHA2_256; 16278c2ecf20Sopenharmony_ci ad.hash_size = SHA256_DIGEST_SIZE; 16288c2ecf20Sopenharmony_ci ad.auth_ctrl = SA_AUTH_SW_CTRL_SHA256; 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_ci sa_sha_setup(ctx, &ad); 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_ci return 0; 16338c2ecf20Sopenharmony_ci} 16348c2ecf20Sopenharmony_ci 16358c2ecf20Sopenharmony_cistatic int sa_sha512_cra_init(struct crypto_tfm *tfm) 16368c2ecf20Sopenharmony_ci{ 16378c2ecf20Sopenharmony_ci struct algo_data ad = { 0 }; 16388c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_tfm_ctx(tfm); 16398c2ecf20Sopenharmony_ci 16408c2ecf20Sopenharmony_ci sa_sha_cra_init_alg(tfm, "sha512"); 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci ad.aalg_id = SA_AALG_ID_SHA2_512; 16438c2ecf20Sopenharmony_ci ad.hash_size = SHA512_DIGEST_SIZE; 16448c2ecf20Sopenharmony_ci ad.auth_ctrl = SA_AUTH_SW_CTRL_SHA512; 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci sa_sha_setup(ctx, &ad); 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci return 0; 16498c2ecf20Sopenharmony_ci} 16508c2ecf20Sopenharmony_ci 16518c2ecf20Sopenharmony_cistatic void sa_sha_cra_exit(struct crypto_tfm *tfm) 16528c2ecf20Sopenharmony_ci{ 16538c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_tfm_ctx(tfm); 16548c2ecf20Sopenharmony_ci struct sa_crypto_data *data = dev_get_drvdata(sa_k3_dev); 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_ci dev_dbg(sa_k3_dev, "%s(0x%p) sc-ids(0x%x(0x%pad), 0x%x(0x%pad))\n", 16578c2ecf20Sopenharmony_ci __func__, tfm, ctx->enc.sc_id, &ctx->enc.sc_phys, 16588c2ecf20Sopenharmony_ci ctx->dec.sc_id, &ctx->dec.sc_phys); 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_ci if (crypto_tfm_alg_type(tfm) == CRYPTO_ALG_TYPE_AHASH) 16618c2ecf20Sopenharmony_ci sa_free_ctx_info(&ctx->enc, data); 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ci crypto_free_shash(ctx->shash); 16648c2ecf20Sopenharmony_ci crypto_free_ahash(ctx->fallback.ahash); 16658c2ecf20Sopenharmony_ci} 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_cistatic void sa_aead_dma_in_callback(void *data) 16688c2ecf20Sopenharmony_ci{ 16698c2ecf20Sopenharmony_ci struct sa_rx_data *rxd = (struct sa_rx_data *)data; 16708c2ecf20Sopenharmony_ci struct aead_request *req; 16718c2ecf20Sopenharmony_ci struct crypto_aead *tfm; 16728c2ecf20Sopenharmony_ci unsigned int start; 16738c2ecf20Sopenharmony_ci unsigned int authsize; 16748c2ecf20Sopenharmony_ci u8 auth_tag[SA_MAX_AUTH_TAG_SZ]; 16758c2ecf20Sopenharmony_ci size_t pl, ml; 16768c2ecf20Sopenharmony_ci int i; 16778c2ecf20Sopenharmony_ci int err = 0; 16788c2ecf20Sopenharmony_ci u16 auth_len; 16798c2ecf20Sopenharmony_ci u32 *mdptr; 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_ci sa_sync_from_device(rxd); 16828c2ecf20Sopenharmony_ci req = container_of(rxd->req, struct aead_request, base); 16838c2ecf20Sopenharmony_ci tfm = crypto_aead_reqtfm(req); 16848c2ecf20Sopenharmony_ci start = req->assoclen + req->cryptlen; 16858c2ecf20Sopenharmony_ci authsize = crypto_aead_authsize(tfm); 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci mdptr = (u32 *)dmaengine_desc_get_metadata_ptr(rxd->tx_in, &pl, &ml); 16888c2ecf20Sopenharmony_ci for (i = 0; i < (authsize / 4); i++) 16898c2ecf20Sopenharmony_ci mdptr[i + 4] = swab32(mdptr[i + 4]); 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_ci auth_len = req->assoclen + req->cryptlen; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci if (rxd->enc) { 16948c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(&mdptr[4], req->dst, start, authsize, 16958c2ecf20Sopenharmony_ci 1); 16968c2ecf20Sopenharmony_ci } else { 16978c2ecf20Sopenharmony_ci auth_len -= authsize; 16988c2ecf20Sopenharmony_ci start -= authsize; 16998c2ecf20Sopenharmony_ci scatterwalk_map_and_copy(auth_tag, req->src, start, authsize, 17008c2ecf20Sopenharmony_ci 0); 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci err = memcmp(&mdptr[4], auth_tag, authsize) ? -EBADMSG : 0; 17038c2ecf20Sopenharmony_ci } 17048c2ecf20Sopenharmony_ci 17058c2ecf20Sopenharmony_ci sa_free_sa_rx_data(rxd); 17068c2ecf20Sopenharmony_ci 17078c2ecf20Sopenharmony_ci aead_request_complete(req, err); 17088c2ecf20Sopenharmony_ci} 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_cistatic int sa_cra_init_aead(struct crypto_aead *tfm, const char *hash, 17118c2ecf20Sopenharmony_ci const char *fallback) 17128c2ecf20Sopenharmony_ci{ 17138c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_aead_ctx(tfm); 17148c2ecf20Sopenharmony_ci struct sa_crypto_data *data = dev_get_drvdata(sa_k3_dev); 17158c2ecf20Sopenharmony_ci int ret; 17168c2ecf20Sopenharmony_ci 17178c2ecf20Sopenharmony_ci memzero_explicit(ctx, sizeof(*ctx)); 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_ci ctx->shash = crypto_alloc_shash(hash, 0, CRYPTO_ALG_NEED_FALLBACK); 17208c2ecf20Sopenharmony_ci if (IS_ERR(ctx->shash)) { 17218c2ecf20Sopenharmony_ci dev_err(sa_k3_dev, "base driver %s couldn't be loaded\n", hash); 17228c2ecf20Sopenharmony_ci return PTR_ERR(ctx->shash); 17238c2ecf20Sopenharmony_ci } 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci ctx->fallback.aead = crypto_alloc_aead(fallback, 0, 17268c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK); 17278c2ecf20Sopenharmony_ci 17288c2ecf20Sopenharmony_ci if (IS_ERR(ctx->fallback.aead)) { 17298c2ecf20Sopenharmony_ci dev_err(sa_k3_dev, "fallback driver %s couldn't be loaded\n", 17308c2ecf20Sopenharmony_ci fallback); 17318c2ecf20Sopenharmony_ci return PTR_ERR(ctx->fallback.aead); 17328c2ecf20Sopenharmony_ci } 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ci crypto_aead_set_reqsize(tfm, sizeof(struct aead_request) + 17358c2ecf20Sopenharmony_ci crypto_aead_reqsize(ctx->fallback.aead)); 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_ci ret = sa_init_ctx_info(&ctx->enc, data); 17388c2ecf20Sopenharmony_ci if (ret) 17398c2ecf20Sopenharmony_ci return ret; 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci ret = sa_init_ctx_info(&ctx->dec, data); 17428c2ecf20Sopenharmony_ci if (ret) { 17438c2ecf20Sopenharmony_ci sa_free_ctx_info(&ctx->enc, data); 17448c2ecf20Sopenharmony_ci return ret; 17458c2ecf20Sopenharmony_ci } 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci dev_dbg(sa_k3_dev, "%s(0x%p) sc-ids(0x%x(0x%pad), 0x%x(0x%pad))\n", 17488c2ecf20Sopenharmony_ci __func__, tfm, ctx->enc.sc_id, &ctx->enc.sc_phys, 17498c2ecf20Sopenharmony_ci ctx->dec.sc_id, &ctx->dec.sc_phys); 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci return ret; 17528c2ecf20Sopenharmony_ci} 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_cistatic int sa_cra_init_aead_sha1(struct crypto_aead *tfm) 17558c2ecf20Sopenharmony_ci{ 17568c2ecf20Sopenharmony_ci return sa_cra_init_aead(tfm, "sha1", 17578c2ecf20Sopenharmony_ci "authenc(hmac(sha1-ce),cbc(aes-ce))"); 17588c2ecf20Sopenharmony_ci} 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_cistatic int sa_cra_init_aead_sha256(struct crypto_aead *tfm) 17618c2ecf20Sopenharmony_ci{ 17628c2ecf20Sopenharmony_ci return sa_cra_init_aead(tfm, "sha256", 17638c2ecf20Sopenharmony_ci "authenc(hmac(sha256-ce),cbc(aes-ce))"); 17648c2ecf20Sopenharmony_ci} 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_cistatic void sa_exit_tfm_aead(struct crypto_aead *tfm) 17678c2ecf20Sopenharmony_ci{ 17688c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_aead_ctx(tfm); 17698c2ecf20Sopenharmony_ci struct sa_crypto_data *data = dev_get_drvdata(sa_k3_dev); 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci crypto_free_shash(ctx->shash); 17728c2ecf20Sopenharmony_ci crypto_free_aead(ctx->fallback.aead); 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_ci sa_free_ctx_info(&ctx->enc, data); 17758c2ecf20Sopenharmony_ci sa_free_ctx_info(&ctx->dec, data); 17768c2ecf20Sopenharmony_ci} 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_ci/* AEAD algorithm configuration interface function */ 17798c2ecf20Sopenharmony_cistatic int sa_aead_setkey(struct crypto_aead *authenc, 17808c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen, 17818c2ecf20Sopenharmony_ci struct algo_data *ad) 17828c2ecf20Sopenharmony_ci{ 17838c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_aead_ctx(authenc); 17848c2ecf20Sopenharmony_ci struct crypto_authenc_keys keys; 17858c2ecf20Sopenharmony_ci int cmdl_len; 17868c2ecf20Sopenharmony_ci struct sa_cmdl_cfg cfg; 17878c2ecf20Sopenharmony_ci int key_idx; 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_ci if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) 17908c2ecf20Sopenharmony_ci return -EINVAL; 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci /* Convert the key size (16/24/32) to the key size index (0/1/2) */ 17938c2ecf20Sopenharmony_ci key_idx = (keys.enckeylen >> 3) - 2; 17948c2ecf20Sopenharmony_ci if (key_idx >= 3) 17958c2ecf20Sopenharmony_ci return -EINVAL; 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_ci ad->ctx = ctx; 17988c2ecf20Sopenharmony_ci ad->enc_eng.eng_id = SA_ENG_ID_EM1; 17998c2ecf20Sopenharmony_ci ad->enc_eng.sc_size = SA_CTX_ENC_TYPE1_SZ; 18008c2ecf20Sopenharmony_ci ad->auth_eng.eng_id = SA_ENG_ID_AM1; 18018c2ecf20Sopenharmony_ci ad->auth_eng.sc_size = SA_CTX_AUTH_TYPE2_SZ; 18028c2ecf20Sopenharmony_ci ad->mci_enc = mci_cbc_enc_no_iv_array[key_idx]; 18038c2ecf20Sopenharmony_ci ad->mci_dec = mci_cbc_dec_no_iv_array[key_idx]; 18048c2ecf20Sopenharmony_ci ad->inv_key = true; 18058c2ecf20Sopenharmony_ci ad->keyed_mac = true; 18068c2ecf20Sopenharmony_ci ad->ealg_id = SA_EALG_ID_AES_CBC; 18078c2ecf20Sopenharmony_ci ad->prep_iopad = sa_prepare_iopads; 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci memset(&cfg, 0, sizeof(cfg)); 18108c2ecf20Sopenharmony_ci cfg.enc = true; 18118c2ecf20Sopenharmony_ci cfg.aalg = ad->aalg_id; 18128c2ecf20Sopenharmony_ci cfg.enc_eng_id = ad->enc_eng.eng_id; 18138c2ecf20Sopenharmony_ci cfg.auth_eng_id = ad->auth_eng.eng_id; 18148c2ecf20Sopenharmony_ci cfg.iv_size = crypto_aead_ivsize(authenc); 18158c2ecf20Sopenharmony_ci cfg.akey = keys.authkey; 18168c2ecf20Sopenharmony_ci cfg.akey_len = keys.authkeylen; 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_ci /* Setup Encryption Security Context & Command label template */ 18198c2ecf20Sopenharmony_ci if (sa_init_sc(&ctx->enc, keys.enckey, keys.enckeylen, 18208c2ecf20Sopenharmony_ci keys.authkey, keys.authkeylen, 18218c2ecf20Sopenharmony_ci ad, 1, &ctx->enc.epib[1])) 18228c2ecf20Sopenharmony_ci return -EINVAL; 18238c2ecf20Sopenharmony_ci 18248c2ecf20Sopenharmony_ci cmdl_len = sa_format_cmdl_gen(&cfg, 18258c2ecf20Sopenharmony_ci (u8 *)ctx->enc.cmdl, 18268c2ecf20Sopenharmony_ci &ctx->enc.cmdl_upd_info); 18278c2ecf20Sopenharmony_ci if (cmdl_len <= 0 || (cmdl_len > SA_MAX_CMDL_WORDS * sizeof(u32))) 18288c2ecf20Sopenharmony_ci return -EINVAL; 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci ctx->enc.cmdl_size = cmdl_len; 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci /* Setup Decryption Security Context & Command label template */ 18338c2ecf20Sopenharmony_ci if (sa_init_sc(&ctx->dec, keys.enckey, keys.enckeylen, 18348c2ecf20Sopenharmony_ci keys.authkey, keys.authkeylen, 18358c2ecf20Sopenharmony_ci ad, 0, &ctx->dec.epib[1])) 18368c2ecf20Sopenharmony_ci return -EINVAL; 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_ci cfg.enc = false; 18398c2ecf20Sopenharmony_ci cmdl_len = sa_format_cmdl_gen(&cfg, (u8 *)ctx->dec.cmdl, 18408c2ecf20Sopenharmony_ci &ctx->dec.cmdl_upd_info); 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_ci if (cmdl_len <= 0 || (cmdl_len > SA_MAX_CMDL_WORDS * sizeof(u32))) 18438c2ecf20Sopenharmony_ci return -EINVAL; 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci ctx->dec.cmdl_size = cmdl_len; 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_ci crypto_aead_clear_flags(ctx->fallback.aead, CRYPTO_TFM_REQ_MASK); 18488c2ecf20Sopenharmony_ci crypto_aead_set_flags(ctx->fallback.aead, 18498c2ecf20Sopenharmony_ci crypto_aead_get_flags(authenc) & 18508c2ecf20Sopenharmony_ci CRYPTO_TFM_REQ_MASK); 18518c2ecf20Sopenharmony_ci 18528c2ecf20Sopenharmony_ci return crypto_aead_setkey(ctx->fallback.aead, key, keylen); 18538c2ecf20Sopenharmony_ci} 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_cistatic int sa_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize) 18568c2ecf20Sopenharmony_ci{ 18578c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_tfm_ctx(crypto_aead_tfm(tfm)); 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_ci return crypto_aead_setauthsize(ctx->fallback.aead, authsize); 18608c2ecf20Sopenharmony_ci} 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_cistatic int sa_aead_cbc_sha1_setkey(struct crypto_aead *authenc, 18638c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 18648c2ecf20Sopenharmony_ci{ 18658c2ecf20Sopenharmony_ci struct algo_data ad = { 0 }; 18668c2ecf20Sopenharmony_ci 18678c2ecf20Sopenharmony_ci ad.ealg_id = SA_EALG_ID_AES_CBC; 18688c2ecf20Sopenharmony_ci ad.aalg_id = SA_AALG_ID_HMAC_SHA1; 18698c2ecf20Sopenharmony_ci ad.hash_size = SHA1_DIGEST_SIZE; 18708c2ecf20Sopenharmony_ci ad.auth_ctrl = SA_AUTH_SW_CTRL_SHA1; 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_ci return sa_aead_setkey(authenc, key, keylen, &ad); 18738c2ecf20Sopenharmony_ci} 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_cistatic int sa_aead_cbc_sha256_setkey(struct crypto_aead *authenc, 18768c2ecf20Sopenharmony_ci const u8 *key, unsigned int keylen) 18778c2ecf20Sopenharmony_ci{ 18788c2ecf20Sopenharmony_ci struct algo_data ad = { 0 }; 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci ad.ealg_id = SA_EALG_ID_AES_CBC; 18818c2ecf20Sopenharmony_ci ad.aalg_id = SA_AALG_ID_HMAC_SHA2_256; 18828c2ecf20Sopenharmony_ci ad.hash_size = SHA256_DIGEST_SIZE; 18838c2ecf20Sopenharmony_ci ad.auth_ctrl = SA_AUTH_SW_CTRL_SHA256; 18848c2ecf20Sopenharmony_ci 18858c2ecf20Sopenharmony_ci return sa_aead_setkey(authenc, key, keylen, &ad); 18868c2ecf20Sopenharmony_ci} 18878c2ecf20Sopenharmony_ci 18888c2ecf20Sopenharmony_cistatic int sa_aead_run(struct aead_request *req, u8 *iv, int enc) 18898c2ecf20Sopenharmony_ci{ 18908c2ecf20Sopenharmony_ci struct crypto_aead *tfm = crypto_aead_reqtfm(req); 18918c2ecf20Sopenharmony_ci struct sa_tfm_ctx *ctx = crypto_aead_ctx(tfm); 18928c2ecf20Sopenharmony_ci struct sa_req sa_req = { 0 }; 18938c2ecf20Sopenharmony_ci size_t auth_size, enc_size; 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ci enc_size = req->cryptlen; 18968c2ecf20Sopenharmony_ci auth_size = req->assoclen + req->cryptlen; 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_ci if (!enc) { 18998c2ecf20Sopenharmony_ci enc_size -= crypto_aead_authsize(tfm); 19008c2ecf20Sopenharmony_ci auth_size -= crypto_aead_authsize(tfm); 19018c2ecf20Sopenharmony_ci } 19028c2ecf20Sopenharmony_ci 19038c2ecf20Sopenharmony_ci if (auth_size > SA_MAX_DATA_SZ || 19048c2ecf20Sopenharmony_ci (auth_size >= SA_UNSAFE_DATA_SZ_MIN && 19058c2ecf20Sopenharmony_ci auth_size <= SA_UNSAFE_DATA_SZ_MAX)) { 19068c2ecf20Sopenharmony_ci struct aead_request *subreq = aead_request_ctx(req); 19078c2ecf20Sopenharmony_ci int ret; 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci aead_request_set_tfm(subreq, ctx->fallback.aead); 19108c2ecf20Sopenharmony_ci aead_request_set_callback(subreq, req->base.flags, 19118c2ecf20Sopenharmony_ci req->base.complete, req->base.data); 19128c2ecf20Sopenharmony_ci aead_request_set_crypt(subreq, req->src, req->dst, 19138c2ecf20Sopenharmony_ci req->cryptlen, req->iv); 19148c2ecf20Sopenharmony_ci aead_request_set_ad(subreq, req->assoclen); 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci ret = enc ? crypto_aead_encrypt(subreq) : 19178c2ecf20Sopenharmony_ci crypto_aead_decrypt(subreq); 19188c2ecf20Sopenharmony_ci return ret; 19198c2ecf20Sopenharmony_ci } 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_ci sa_req.enc_offset = req->assoclen; 19228c2ecf20Sopenharmony_ci sa_req.enc_size = enc_size; 19238c2ecf20Sopenharmony_ci sa_req.auth_size = auth_size; 19248c2ecf20Sopenharmony_ci sa_req.size = auth_size; 19258c2ecf20Sopenharmony_ci sa_req.enc_iv = iv; 19268c2ecf20Sopenharmony_ci sa_req.type = CRYPTO_ALG_TYPE_AEAD; 19278c2ecf20Sopenharmony_ci sa_req.enc = enc; 19288c2ecf20Sopenharmony_ci sa_req.callback = sa_aead_dma_in_callback; 19298c2ecf20Sopenharmony_ci sa_req.mdata_size = 52; 19308c2ecf20Sopenharmony_ci sa_req.base = &req->base; 19318c2ecf20Sopenharmony_ci sa_req.ctx = ctx; 19328c2ecf20Sopenharmony_ci sa_req.src = req->src; 19338c2ecf20Sopenharmony_ci sa_req.dst = req->dst; 19348c2ecf20Sopenharmony_ci 19358c2ecf20Sopenharmony_ci return sa_run(&sa_req); 19368c2ecf20Sopenharmony_ci} 19378c2ecf20Sopenharmony_ci 19388c2ecf20Sopenharmony_ci/* AEAD algorithm encrypt interface function */ 19398c2ecf20Sopenharmony_cistatic int sa_aead_encrypt(struct aead_request *req) 19408c2ecf20Sopenharmony_ci{ 19418c2ecf20Sopenharmony_ci return sa_aead_run(req, req->iv, 1); 19428c2ecf20Sopenharmony_ci} 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci/* AEAD algorithm decrypt interface function */ 19458c2ecf20Sopenharmony_cistatic int sa_aead_decrypt(struct aead_request *req) 19468c2ecf20Sopenharmony_ci{ 19478c2ecf20Sopenharmony_ci return sa_aead_run(req, req->iv, 0); 19488c2ecf20Sopenharmony_ci} 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_cistatic struct sa_alg_tmpl sa_algs[] = { 19518c2ecf20Sopenharmony_ci { 19528c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 19538c2ecf20Sopenharmony_ci .alg.skcipher = { 19548c2ecf20Sopenharmony_ci .base.cra_name = "cbc(aes)", 19558c2ecf20Sopenharmony_ci .base.cra_driver_name = "cbc-aes-sa2ul", 19568c2ecf20Sopenharmony_ci .base.cra_priority = 30000, 19578c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | 19588c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 19598c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 19608c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 19618c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 19628c2ecf20Sopenharmony_ci .base.cra_ctxsize = sizeof(struct sa_tfm_ctx), 19638c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 19648c2ecf20Sopenharmony_ci .init = sa_cipher_cra_init, 19658c2ecf20Sopenharmony_ci .exit = sa_cipher_cra_exit, 19668c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 19678c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 19688c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 19698c2ecf20Sopenharmony_ci .setkey = sa_aes_cbc_setkey, 19708c2ecf20Sopenharmony_ci .encrypt = sa_encrypt, 19718c2ecf20Sopenharmony_ci .decrypt = sa_decrypt, 19728c2ecf20Sopenharmony_ci } 19738c2ecf20Sopenharmony_ci }, 19748c2ecf20Sopenharmony_ci { 19758c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 19768c2ecf20Sopenharmony_ci .alg.skcipher = { 19778c2ecf20Sopenharmony_ci .base.cra_name = "ecb(aes)", 19788c2ecf20Sopenharmony_ci .base.cra_driver_name = "ecb-aes-sa2ul", 19798c2ecf20Sopenharmony_ci .base.cra_priority = 30000, 19808c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | 19818c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 19828c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 19838c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 19848c2ecf20Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 19858c2ecf20Sopenharmony_ci .base.cra_ctxsize = sizeof(struct sa_tfm_ctx), 19868c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 19878c2ecf20Sopenharmony_ci .init = sa_cipher_cra_init, 19888c2ecf20Sopenharmony_ci .exit = sa_cipher_cra_exit, 19898c2ecf20Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 19908c2ecf20Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 19918c2ecf20Sopenharmony_ci .setkey = sa_aes_ecb_setkey, 19928c2ecf20Sopenharmony_ci .encrypt = sa_encrypt, 19938c2ecf20Sopenharmony_ci .decrypt = sa_decrypt, 19948c2ecf20Sopenharmony_ci } 19958c2ecf20Sopenharmony_ci }, 19968c2ecf20Sopenharmony_ci { 19978c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 19988c2ecf20Sopenharmony_ci .alg.skcipher = { 19998c2ecf20Sopenharmony_ci .base.cra_name = "cbc(des3_ede)", 20008c2ecf20Sopenharmony_ci .base.cra_driver_name = "cbc-des3-sa2ul", 20018c2ecf20Sopenharmony_ci .base.cra_priority = 30000, 20028c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | 20038c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 20048c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 20058c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 20068c2ecf20Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 20078c2ecf20Sopenharmony_ci .base.cra_ctxsize = sizeof(struct sa_tfm_ctx), 20088c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 20098c2ecf20Sopenharmony_ci .init = sa_cipher_cra_init, 20108c2ecf20Sopenharmony_ci .exit = sa_cipher_cra_exit, 20118c2ecf20Sopenharmony_ci .min_keysize = 3 * DES_KEY_SIZE, 20128c2ecf20Sopenharmony_ci .max_keysize = 3 * DES_KEY_SIZE, 20138c2ecf20Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 20148c2ecf20Sopenharmony_ci .setkey = sa_3des_cbc_setkey, 20158c2ecf20Sopenharmony_ci .encrypt = sa_encrypt, 20168c2ecf20Sopenharmony_ci .decrypt = sa_decrypt, 20178c2ecf20Sopenharmony_ci } 20188c2ecf20Sopenharmony_ci }, 20198c2ecf20Sopenharmony_ci { 20208c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_SKCIPHER, 20218c2ecf20Sopenharmony_ci .alg.skcipher = { 20228c2ecf20Sopenharmony_ci .base.cra_name = "ecb(des3_ede)", 20238c2ecf20Sopenharmony_ci .base.cra_driver_name = "ecb-des3-sa2ul", 20248c2ecf20Sopenharmony_ci .base.cra_priority = 30000, 20258c2ecf20Sopenharmony_ci .base.cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | 20268c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 20278c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 20288c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 20298c2ecf20Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 20308c2ecf20Sopenharmony_ci .base.cra_ctxsize = sizeof(struct sa_tfm_ctx), 20318c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 20328c2ecf20Sopenharmony_ci .init = sa_cipher_cra_init, 20338c2ecf20Sopenharmony_ci .exit = sa_cipher_cra_exit, 20348c2ecf20Sopenharmony_ci .min_keysize = 3 * DES_KEY_SIZE, 20358c2ecf20Sopenharmony_ci .max_keysize = 3 * DES_KEY_SIZE, 20368c2ecf20Sopenharmony_ci .setkey = sa_3des_ecb_setkey, 20378c2ecf20Sopenharmony_ci .encrypt = sa_encrypt, 20388c2ecf20Sopenharmony_ci .decrypt = sa_decrypt, 20398c2ecf20Sopenharmony_ci } 20408c2ecf20Sopenharmony_ci }, 20418c2ecf20Sopenharmony_ci { 20428c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 20438c2ecf20Sopenharmony_ci .alg.ahash = { 20448c2ecf20Sopenharmony_ci .halg.base = { 20458c2ecf20Sopenharmony_ci .cra_name = "sha1", 20468c2ecf20Sopenharmony_ci .cra_driver_name = "sha1-sa2ul", 20478c2ecf20Sopenharmony_ci .cra_priority = 400, 20488c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_AHASH | 20498c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 20508c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 20518c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 20528c2ecf20Sopenharmony_ci .cra_blocksize = SHA1_BLOCK_SIZE, 20538c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sa_tfm_ctx), 20548c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 20558c2ecf20Sopenharmony_ci .cra_init = sa_sha1_cra_init, 20568c2ecf20Sopenharmony_ci .cra_exit = sa_sha_cra_exit, 20578c2ecf20Sopenharmony_ci }, 20588c2ecf20Sopenharmony_ci .halg.digestsize = SHA1_DIGEST_SIZE, 20598c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct sa_sha_req_ctx) + 20608c2ecf20Sopenharmony_ci sizeof(struct sha1_state), 20618c2ecf20Sopenharmony_ci .init = sa_sha_init, 20628c2ecf20Sopenharmony_ci .update = sa_sha_update, 20638c2ecf20Sopenharmony_ci .final = sa_sha_final, 20648c2ecf20Sopenharmony_ci .finup = sa_sha_finup, 20658c2ecf20Sopenharmony_ci .digest = sa_sha_digest, 20668c2ecf20Sopenharmony_ci .export = sa_sha_export, 20678c2ecf20Sopenharmony_ci .import = sa_sha_import, 20688c2ecf20Sopenharmony_ci }, 20698c2ecf20Sopenharmony_ci }, 20708c2ecf20Sopenharmony_ci { 20718c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 20728c2ecf20Sopenharmony_ci .alg.ahash = { 20738c2ecf20Sopenharmony_ci .halg.base = { 20748c2ecf20Sopenharmony_ci .cra_name = "sha256", 20758c2ecf20Sopenharmony_ci .cra_driver_name = "sha256-sa2ul", 20768c2ecf20Sopenharmony_ci .cra_priority = 400, 20778c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_AHASH | 20788c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 20798c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 20808c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 20818c2ecf20Sopenharmony_ci .cra_blocksize = SHA256_BLOCK_SIZE, 20828c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sa_tfm_ctx), 20838c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 20848c2ecf20Sopenharmony_ci .cra_init = sa_sha256_cra_init, 20858c2ecf20Sopenharmony_ci .cra_exit = sa_sha_cra_exit, 20868c2ecf20Sopenharmony_ci }, 20878c2ecf20Sopenharmony_ci .halg.digestsize = SHA256_DIGEST_SIZE, 20888c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct sa_sha_req_ctx) + 20898c2ecf20Sopenharmony_ci sizeof(struct sha256_state), 20908c2ecf20Sopenharmony_ci .init = sa_sha_init, 20918c2ecf20Sopenharmony_ci .update = sa_sha_update, 20928c2ecf20Sopenharmony_ci .final = sa_sha_final, 20938c2ecf20Sopenharmony_ci .finup = sa_sha_finup, 20948c2ecf20Sopenharmony_ci .digest = sa_sha_digest, 20958c2ecf20Sopenharmony_ci .export = sa_sha_export, 20968c2ecf20Sopenharmony_ci .import = sa_sha_import, 20978c2ecf20Sopenharmony_ci }, 20988c2ecf20Sopenharmony_ci }, 20998c2ecf20Sopenharmony_ci { 21008c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AHASH, 21018c2ecf20Sopenharmony_ci .alg.ahash = { 21028c2ecf20Sopenharmony_ci .halg.base = { 21038c2ecf20Sopenharmony_ci .cra_name = "sha512", 21048c2ecf20Sopenharmony_ci .cra_driver_name = "sha512-sa2ul", 21058c2ecf20Sopenharmony_ci .cra_priority = 400, 21068c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_AHASH | 21078c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 21088c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 21098c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 21108c2ecf20Sopenharmony_ci .cra_blocksize = SHA512_BLOCK_SIZE, 21118c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sa_tfm_ctx), 21128c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 21138c2ecf20Sopenharmony_ci .cra_init = sa_sha512_cra_init, 21148c2ecf20Sopenharmony_ci .cra_exit = sa_sha_cra_exit, 21158c2ecf20Sopenharmony_ci }, 21168c2ecf20Sopenharmony_ci .halg.digestsize = SHA512_DIGEST_SIZE, 21178c2ecf20Sopenharmony_ci .halg.statesize = sizeof(struct sa_sha_req_ctx) + 21188c2ecf20Sopenharmony_ci sizeof(struct sha512_state), 21198c2ecf20Sopenharmony_ci .init = sa_sha_init, 21208c2ecf20Sopenharmony_ci .update = sa_sha_update, 21218c2ecf20Sopenharmony_ci .final = sa_sha_final, 21228c2ecf20Sopenharmony_ci .finup = sa_sha_finup, 21238c2ecf20Sopenharmony_ci .digest = sa_sha_digest, 21248c2ecf20Sopenharmony_ci .export = sa_sha_export, 21258c2ecf20Sopenharmony_ci .import = sa_sha_import, 21268c2ecf20Sopenharmony_ci }, 21278c2ecf20Sopenharmony_ci }, 21288c2ecf20Sopenharmony_ci { 21298c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 21308c2ecf20Sopenharmony_ci .alg.aead = { 21318c2ecf20Sopenharmony_ci .base = { 21328c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha1),cbc(aes))", 21338c2ecf20Sopenharmony_ci .cra_driver_name = 21348c2ecf20Sopenharmony_ci "authenc(hmac(sha1),cbc(aes))-sa2ul", 21358c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 21368c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_AEAD | 21378c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 21388c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 21398c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 21408c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sa_tfm_ctx), 21418c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 21428c2ecf20Sopenharmony_ci .cra_priority = 3000, 21438c2ecf20Sopenharmony_ci }, 21448c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 21458c2ecf20Sopenharmony_ci .maxauthsize = SHA1_DIGEST_SIZE, 21468c2ecf20Sopenharmony_ci 21478c2ecf20Sopenharmony_ci .init = sa_cra_init_aead_sha1, 21488c2ecf20Sopenharmony_ci .exit = sa_exit_tfm_aead, 21498c2ecf20Sopenharmony_ci .setkey = sa_aead_cbc_sha1_setkey, 21508c2ecf20Sopenharmony_ci .setauthsize = sa_aead_setauthsize, 21518c2ecf20Sopenharmony_ci .encrypt = sa_aead_encrypt, 21528c2ecf20Sopenharmony_ci .decrypt = sa_aead_decrypt, 21538c2ecf20Sopenharmony_ci }, 21548c2ecf20Sopenharmony_ci }, 21558c2ecf20Sopenharmony_ci { 21568c2ecf20Sopenharmony_ci .type = CRYPTO_ALG_TYPE_AEAD, 21578c2ecf20Sopenharmony_ci .alg.aead = { 21588c2ecf20Sopenharmony_ci .base = { 21598c2ecf20Sopenharmony_ci .cra_name = "authenc(hmac(sha256),cbc(aes))", 21608c2ecf20Sopenharmony_ci .cra_driver_name = 21618c2ecf20Sopenharmony_ci "authenc(hmac(sha256),cbc(aes))-sa2ul", 21628c2ecf20Sopenharmony_ci .cra_blocksize = AES_BLOCK_SIZE, 21638c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_AEAD | 21648c2ecf20Sopenharmony_ci CRYPTO_ALG_KERN_DRIVER_ONLY | 21658c2ecf20Sopenharmony_ci CRYPTO_ALG_ASYNC | 21668c2ecf20Sopenharmony_ci CRYPTO_ALG_NEED_FALLBACK, 21678c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct sa_tfm_ctx), 21688c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 21698c2ecf20Sopenharmony_ci .cra_alignmask = 0, 21708c2ecf20Sopenharmony_ci .cra_priority = 3000, 21718c2ecf20Sopenharmony_ci }, 21728c2ecf20Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 21738c2ecf20Sopenharmony_ci .maxauthsize = SHA256_DIGEST_SIZE, 21748c2ecf20Sopenharmony_ci 21758c2ecf20Sopenharmony_ci .init = sa_cra_init_aead_sha256, 21768c2ecf20Sopenharmony_ci .exit = sa_exit_tfm_aead, 21778c2ecf20Sopenharmony_ci .setkey = sa_aead_cbc_sha256_setkey, 21788c2ecf20Sopenharmony_ci .setauthsize = sa_aead_setauthsize, 21798c2ecf20Sopenharmony_ci .encrypt = sa_aead_encrypt, 21808c2ecf20Sopenharmony_ci .decrypt = sa_aead_decrypt, 21818c2ecf20Sopenharmony_ci }, 21828c2ecf20Sopenharmony_ci }, 21838c2ecf20Sopenharmony_ci}; 21848c2ecf20Sopenharmony_ci 21858c2ecf20Sopenharmony_ci/* Register the algorithms in crypto framework */ 21868c2ecf20Sopenharmony_cistatic void sa_register_algos(const struct device *dev) 21878c2ecf20Sopenharmony_ci{ 21888c2ecf20Sopenharmony_ci char *alg_name; 21898c2ecf20Sopenharmony_ci u32 type; 21908c2ecf20Sopenharmony_ci int i, err; 21918c2ecf20Sopenharmony_ci 21928c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(sa_algs); i++) { 21938c2ecf20Sopenharmony_ci type = sa_algs[i].type; 21948c2ecf20Sopenharmony_ci if (type == CRYPTO_ALG_TYPE_SKCIPHER) { 21958c2ecf20Sopenharmony_ci alg_name = sa_algs[i].alg.skcipher.base.cra_name; 21968c2ecf20Sopenharmony_ci err = crypto_register_skcipher(&sa_algs[i].alg.skcipher); 21978c2ecf20Sopenharmony_ci } else if (type == CRYPTO_ALG_TYPE_AHASH) { 21988c2ecf20Sopenharmony_ci alg_name = sa_algs[i].alg.ahash.halg.base.cra_name; 21998c2ecf20Sopenharmony_ci err = crypto_register_ahash(&sa_algs[i].alg.ahash); 22008c2ecf20Sopenharmony_ci } else if (type == CRYPTO_ALG_TYPE_AEAD) { 22018c2ecf20Sopenharmony_ci alg_name = sa_algs[i].alg.aead.base.cra_name; 22028c2ecf20Sopenharmony_ci err = crypto_register_aead(&sa_algs[i].alg.aead); 22038c2ecf20Sopenharmony_ci } else { 22048c2ecf20Sopenharmony_ci dev_err(dev, 22058c2ecf20Sopenharmony_ci "un-supported crypto algorithm (%d)", 22068c2ecf20Sopenharmony_ci sa_algs[i].type); 22078c2ecf20Sopenharmony_ci continue; 22088c2ecf20Sopenharmony_ci } 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci if (err) 22118c2ecf20Sopenharmony_ci dev_err(dev, "Failed to register '%s'\n", alg_name); 22128c2ecf20Sopenharmony_ci else 22138c2ecf20Sopenharmony_ci sa_algs[i].registered = true; 22148c2ecf20Sopenharmony_ci } 22158c2ecf20Sopenharmony_ci} 22168c2ecf20Sopenharmony_ci 22178c2ecf20Sopenharmony_ci/* Unregister the algorithms in crypto framework */ 22188c2ecf20Sopenharmony_cistatic void sa_unregister_algos(const struct device *dev) 22198c2ecf20Sopenharmony_ci{ 22208c2ecf20Sopenharmony_ci u32 type; 22218c2ecf20Sopenharmony_ci int i; 22228c2ecf20Sopenharmony_ci 22238c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(sa_algs); i++) { 22248c2ecf20Sopenharmony_ci type = sa_algs[i].type; 22258c2ecf20Sopenharmony_ci if (!sa_algs[i].registered) 22268c2ecf20Sopenharmony_ci continue; 22278c2ecf20Sopenharmony_ci if (type == CRYPTO_ALG_TYPE_SKCIPHER) 22288c2ecf20Sopenharmony_ci crypto_unregister_skcipher(&sa_algs[i].alg.skcipher); 22298c2ecf20Sopenharmony_ci else if (type == CRYPTO_ALG_TYPE_AHASH) 22308c2ecf20Sopenharmony_ci crypto_unregister_ahash(&sa_algs[i].alg.ahash); 22318c2ecf20Sopenharmony_ci else if (type == CRYPTO_ALG_TYPE_AEAD) 22328c2ecf20Sopenharmony_ci crypto_unregister_aead(&sa_algs[i].alg.aead); 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci sa_algs[i].registered = false; 22358c2ecf20Sopenharmony_ci } 22368c2ecf20Sopenharmony_ci} 22378c2ecf20Sopenharmony_ci 22388c2ecf20Sopenharmony_cistatic int sa_init_mem(struct sa_crypto_data *dev_data) 22398c2ecf20Sopenharmony_ci{ 22408c2ecf20Sopenharmony_ci struct device *dev = &dev_data->pdev->dev; 22418c2ecf20Sopenharmony_ci /* Setup dma pool for security context buffers */ 22428c2ecf20Sopenharmony_ci dev_data->sc_pool = dma_pool_create("keystone-sc", dev, 22438c2ecf20Sopenharmony_ci SA_CTX_MAX_SZ, 64, 0); 22448c2ecf20Sopenharmony_ci if (!dev_data->sc_pool) { 22458c2ecf20Sopenharmony_ci dev_err(dev, "Failed to create dma pool"); 22468c2ecf20Sopenharmony_ci return -ENOMEM; 22478c2ecf20Sopenharmony_ci } 22488c2ecf20Sopenharmony_ci 22498c2ecf20Sopenharmony_ci return 0; 22508c2ecf20Sopenharmony_ci} 22518c2ecf20Sopenharmony_ci 22528c2ecf20Sopenharmony_cistatic int sa_dma_init(struct sa_crypto_data *dd) 22538c2ecf20Sopenharmony_ci{ 22548c2ecf20Sopenharmony_ci int ret; 22558c2ecf20Sopenharmony_ci struct dma_slave_config cfg; 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci dd->dma_rx1 = NULL; 22588c2ecf20Sopenharmony_ci dd->dma_tx = NULL; 22598c2ecf20Sopenharmony_ci dd->dma_rx2 = NULL; 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_ci ret = dma_coerce_mask_and_coherent(dd->dev, DMA_BIT_MASK(48)); 22628c2ecf20Sopenharmony_ci if (ret) 22638c2ecf20Sopenharmony_ci return ret; 22648c2ecf20Sopenharmony_ci 22658c2ecf20Sopenharmony_ci dd->dma_rx1 = dma_request_chan(dd->dev, "rx1"); 22668c2ecf20Sopenharmony_ci if (IS_ERR(dd->dma_rx1)) 22678c2ecf20Sopenharmony_ci return dev_err_probe(dd->dev, PTR_ERR(dd->dma_rx1), 22688c2ecf20Sopenharmony_ci "Unable to request rx1 DMA channel\n"); 22698c2ecf20Sopenharmony_ci 22708c2ecf20Sopenharmony_ci dd->dma_rx2 = dma_request_chan(dd->dev, "rx2"); 22718c2ecf20Sopenharmony_ci if (IS_ERR(dd->dma_rx2)) { 22728c2ecf20Sopenharmony_ci ret = dev_err_probe(dd->dev, PTR_ERR(dd->dma_rx2), 22738c2ecf20Sopenharmony_ci "Unable to request rx2 DMA channel\n"); 22748c2ecf20Sopenharmony_ci goto err_dma_rx2; 22758c2ecf20Sopenharmony_ci } 22768c2ecf20Sopenharmony_ci 22778c2ecf20Sopenharmony_ci dd->dma_tx = dma_request_chan(dd->dev, "tx"); 22788c2ecf20Sopenharmony_ci if (IS_ERR(dd->dma_tx)) { 22798c2ecf20Sopenharmony_ci ret = dev_err_probe(dd->dev, PTR_ERR(dd->dma_tx), 22808c2ecf20Sopenharmony_ci "Unable to request tx DMA channel\n"); 22818c2ecf20Sopenharmony_ci goto err_dma_tx; 22828c2ecf20Sopenharmony_ci } 22838c2ecf20Sopenharmony_ci 22848c2ecf20Sopenharmony_ci memzero_explicit(&cfg, sizeof(cfg)); 22858c2ecf20Sopenharmony_ci 22868c2ecf20Sopenharmony_ci cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 22878c2ecf20Sopenharmony_ci cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 22888c2ecf20Sopenharmony_ci cfg.src_maxburst = 4; 22898c2ecf20Sopenharmony_ci cfg.dst_maxburst = 4; 22908c2ecf20Sopenharmony_ci 22918c2ecf20Sopenharmony_ci ret = dmaengine_slave_config(dd->dma_rx1, &cfg); 22928c2ecf20Sopenharmony_ci if (ret) { 22938c2ecf20Sopenharmony_ci dev_err(dd->dev, "can't configure IN dmaengine slave: %d\n", 22948c2ecf20Sopenharmony_ci ret); 22958c2ecf20Sopenharmony_ci goto err_dma_config; 22968c2ecf20Sopenharmony_ci } 22978c2ecf20Sopenharmony_ci 22988c2ecf20Sopenharmony_ci ret = dmaengine_slave_config(dd->dma_rx2, &cfg); 22998c2ecf20Sopenharmony_ci if (ret) { 23008c2ecf20Sopenharmony_ci dev_err(dd->dev, "can't configure IN dmaengine slave: %d\n", 23018c2ecf20Sopenharmony_ci ret); 23028c2ecf20Sopenharmony_ci goto err_dma_config; 23038c2ecf20Sopenharmony_ci } 23048c2ecf20Sopenharmony_ci 23058c2ecf20Sopenharmony_ci ret = dmaengine_slave_config(dd->dma_tx, &cfg); 23068c2ecf20Sopenharmony_ci if (ret) { 23078c2ecf20Sopenharmony_ci dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n", 23088c2ecf20Sopenharmony_ci ret); 23098c2ecf20Sopenharmony_ci goto err_dma_config; 23108c2ecf20Sopenharmony_ci } 23118c2ecf20Sopenharmony_ci 23128c2ecf20Sopenharmony_ci return 0; 23138c2ecf20Sopenharmony_ci 23148c2ecf20Sopenharmony_cierr_dma_config: 23158c2ecf20Sopenharmony_ci dma_release_channel(dd->dma_tx); 23168c2ecf20Sopenharmony_cierr_dma_tx: 23178c2ecf20Sopenharmony_ci dma_release_channel(dd->dma_rx2); 23188c2ecf20Sopenharmony_cierr_dma_rx2: 23198c2ecf20Sopenharmony_ci dma_release_channel(dd->dma_rx1); 23208c2ecf20Sopenharmony_ci 23218c2ecf20Sopenharmony_ci return ret; 23228c2ecf20Sopenharmony_ci} 23238c2ecf20Sopenharmony_ci 23248c2ecf20Sopenharmony_cistatic int sa_link_child(struct device *dev, void *data) 23258c2ecf20Sopenharmony_ci{ 23268c2ecf20Sopenharmony_ci struct device *parent = data; 23278c2ecf20Sopenharmony_ci 23288c2ecf20Sopenharmony_ci device_link_add(dev, parent, DL_FLAG_AUTOPROBE_CONSUMER); 23298c2ecf20Sopenharmony_ci 23308c2ecf20Sopenharmony_ci return 0; 23318c2ecf20Sopenharmony_ci} 23328c2ecf20Sopenharmony_ci 23338c2ecf20Sopenharmony_cistatic int sa_ul_probe(struct platform_device *pdev) 23348c2ecf20Sopenharmony_ci{ 23358c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 23368c2ecf20Sopenharmony_ci struct device_node *node = dev->of_node; 23378c2ecf20Sopenharmony_ci struct resource *res; 23388c2ecf20Sopenharmony_ci static void __iomem *saul_base; 23398c2ecf20Sopenharmony_ci struct sa_crypto_data *dev_data; 23408c2ecf20Sopenharmony_ci u32 val; 23418c2ecf20Sopenharmony_ci int ret; 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_ci dev_data = devm_kzalloc(dev, sizeof(*dev_data), GFP_KERNEL); 23448c2ecf20Sopenharmony_ci if (!dev_data) 23458c2ecf20Sopenharmony_ci return -ENOMEM; 23468c2ecf20Sopenharmony_ci 23478c2ecf20Sopenharmony_ci sa_k3_dev = dev; 23488c2ecf20Sopenharmony_ci dev_data->dev = dev; 23498c2ecf20Sopenharmony_ci dev_data->pdev = pdev; 23508c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, dev_data); 23518c2ecf20Sopenharmony_ci dev_set_drvdata(sa_k3_dev, dev_data); 23528c2ecf20Sopenharmony_ci 23538c2ecf20Sopenharmony_ci pm_runtime_enable(dev); 23548c2ecf20Sopenharmony_ci ret = pm_runtime_resume_and_get(dev); 23558c2ecf20Sopenharmony_ci if (ret < 0) { 23568c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "%s: failed to get sync: %d\n", __func__, 23578c2ecf20Sopenharmony_ci ret); 23588c2ecf20Sopenharmony_ci pm_runtime_disable(dev); 23598c2ecf20Sopenharmony_ci return ret; 23608c2ecf20Sopenharmony_ci } 23618c2ecf20Sopenharmony_ci 23628c2ecf20Sopenharmony_ci sa_init_mem(dev_data); 23638c2ecf20Sopenharmony_ci ret = sa_dma_init(dev_data); 23648c2ecf20Sopenharmony_ci if (ret) 23658c2ecf20Sopenharmony_ci goto destroy_dma_pool; 23668c2ecf20Sopenharmony_ci 23678c2ecf20Sopenharmony_ci spin_lock_init(&dev_data->scid_lock); 23688c2ecf20Sopenharmony_ci res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 23698c2ecf20Sopenharmony_ci saul_base = devm_ioremap_resource(dev, res); 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ci dev_data->base = saul_base; 23728c2ecf20Sopenharmony_ci val = SA_EEC_ENCSS_EN | SA_EEC_AUTHSS_EN | SA_EEC_CTXCACH_EN | 23738c2ecf20Sopenharmony_ci SA_EEC_CPPI_PORT_IN_EN | SA_EEC_CPPI_PORT_OUT_EN | 23748c2ecf20Sopenharmony_ci SA_EEC_TRNG_EN; 23758c2ecf20Sopenharmony_ci 23768c2ecf20Sopenharmony_ci writel_relaxed(val, saul_base + SA_ENGINE_ENABLE_CONTROL); 23778c2ecf20Sopenharmony_ci 23788c2ecf20Sopenharmony_ci sa_register_algos(dev); 23798c2ecf20Sopenharmony_ci 23808c2ecf20Sopenharmony_ci ret = of_platform_populate(node, NULL, NULL, &pdev->dev); 23818c2ecf20Sopenharmony_ci if (ret) 23828c2ecf20Sopenharmony_ci goto release_dma; 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_ci device_for_each_child(&pdev->dev, &pdev->dev, sa_link_child); 23858c2ecf20Sopenharmony_ci 23868c2ecf20Sopenharmony_ci return 0; 23878c2ecf20Sopenharmony_ci 23888c2ecf20Sopenharmony_cirelease_dma: 23898c2ecf20Sopenharmony_ci sa_unregister_algos(&pdev->dev); 23908c2ecf20Sopenharmony_ci 23918c2ecf20Sopenharmony_ci dma_release_channel(dev_data->dma_rx2); 23928c2ecf20Sopenharmony_ci dma_release_channel(dev_data->dma_rx1); 23938c2ecf20Sopenharmony_ci dma_release_channel(dev_data->dma_tx); 23948c2ecf20Sopenharmony_ci 23958c2ecf20Sopenharmony_cidestroy_dma_pool: 23968c2ecf20Sopenharmony_ci dma_pool_destroy(dev_data->sc_pool); 23978c2ecf20Sopenharmony_ci 23988c2ecf20Sopenharmony_ci pm_runtime_put_sync(&pdev->dev); 23998c2ecf20Sopenharmony_ci pm_runtime_disable(&pdev->dev); 24008c2ecf20Sopenharmony_ci 24018c2ecf20Sopenharmony_ci return ret; 24028c2ecf20Sopenharmony_ci} 24038c2ecf20Sopenharmony_ci 24048c2ecf20Sopenharmony_cistatic int sa_ul_remove(struct platform_device *pdev) 24058c2ecf20Sopenharmony_ci{ 24068c2ecf20Sopenharmony_ci struct sa_crypto_data *dev_data = platform_get_drvdata(pdev); 24078c2ecf20Sopenharmony_ci 24088c2ecf20Sopenharmony_ci sa_unregister_algos(&pdev->dev); 24098c2ecf20Sopenharmony_ci 24108c2ecf20Sopenharmony_ci dma_release_channel(dev_data->dma_rx2); 24118c2ecf20Sopenharmony_ci dma_release_channel(dev_data->dma_rx1); 24128c2ecf20Sopenharmony_ci dma_release_channel(dev_data->dma_tx); 24138c2ecf20Sopenharmony_ci 24148c2ecf20Sopenharmony_ci dma_pool_destroy(dev_data->sc_pool); 24158c2ecf20Sopenharmony_ci 24168c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, NULL); 24178c2ecf20Sopenharmony_ci 24188c2ecf20Sopenharmony_ci pm_runtime_put_sync(&pdev->dev); 24198c2ecf20Sopenharmony_ci pm_runtime_disable(&pdev->dev); 24208c2ecf20Sopenharmony_ci 24218c2ecf20Sopenharmony_ci return 0; 24228c2ecf20Sopenharmony_ci} 24238c2ecf20Sopenharmony_ci 24248c2ecf20Sopenharmony_cistatic const struct of_device_id of_match[] = { 24258c2ecf20Sopenharmony_ci {.compatible = "ti,j721e-sa2ul",}, 24268c2ecf20Sopenharmony_ci {.compatible = "ti,am654-sa2ul",}, 24278c2ecf20Sopenharmony_ci {}, 24288c2ecf20Sopenharmony_ci}; 24298c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, of_match); 24308c2ecf20Sopenharmony_ci 24318c2ecf20Sopenharmony_cistatic struct platform_driver sa_ul_driver = { 24328c2ecf20Sopenharmony_ci .probe = sa_ul_probe, 24338c2ecf20Sopenharmony_ci .remove = sa_ul_remove, 24348c2ecf20Sopenharmony_ci .driver = { 24358c2ecf20Sopenharmony_ci .name = "saul-crypto", 24368c2ecf20Sopenharmony_ci .of_match_table = of_match, 24378c2ecf20Sopenharmony_ci }, 24388c2ecf20Sopenharmony_ci}; 24398c2ecf20Sopenharmony_cimodule_platform_driver(sa_ul_driver); 24408c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 2441