// SPDX-License-Identifier: GPL-2.0/* * K3 SA2UL crypto accelerator driver * * Copyright (C) 2018-2020 Texas Instruments Incorporated - http://www.ti.com * * Authors: Keerthy * Vitaly Andrianov * Tero Kristo */#include <linux/bitfield.h>#include <linux/clk.h>#include <linux/dma-mapping.h>#include <linux/dmaengine.h>#include <linux/dmapool.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/of.h>#include <linux/of_platform.h>#include <linux/platform_device.h>#include <linux/pm_runtime.h> #include <crypto/aes.h>#include <crypto/authenc.h>#include <crypto/utils.h>#include <crypto/des.h>#include <crypto/internal/aead.h>#include <crypto/internal/hash.h>#include <crypto/internal/skcipher.h>#include <crypto/scatterwalk.h>#include <crypto/sha1.h>#include <crypto/sha2.h> #include "sa2ul.h" /* Byte offset for key in encryption security context */#define SC_ENC_KEY_OFFSET (1 + 27 + 4)/* Byte offset for Aux-1 in encryption security context */#define SC_ENC_AUX1_OFFSET (1 + 27 + 4 + 32) #define SA_CMDL_UPD_ENC 0x0001#define SA_CMDL_UPD_AUTH 0x0002#define SA_CMDL_UPD_ENC_IV 0x0004#define SA_CMDL_UPD_AUTH_IV 0x0008#define SA_CMDL_UPD_AUX_KEY 0x0010 #define SA_AUTH_SUBKEY_LEN 16#define SA_CMDL_PAYLOAD_LENGTH_MASK 0xFFFF#define SA_CMDL_SOP_BYPASS_LEN_MASK 0xFF000000 #define MODE_CONTROL_BYTES 27#define SA_HASH_PROCESSING 0#define SA_CRYPTO_PROCESSING 0#define SA_UPLOAD_HASH_TO_TLR BIT(6) #define SA_SW0_FLAGS_MASK 0xF0000#define SA_SW0_CMDL_INFO_MASK 0x1F00000#define SA_SW0_CMDL_PRESENT BIT(4)#define SA_SW0_ENG_ID_MASK 0x3E000000#define SA_SW0_DEST_INFO_PRESENT BIT(30)#define SA_SW2_EGRESS_LENGTH 0xFF000000#define SA_BASIC_HASH 0x10 #define SHA256_DIGEST_WORDS 8/* Make 32-bit word from 4 bytes */#define SA_MK_U32(b0, b1, b2, b3) (((b0) << 24) | ((b1) << 16) | \ ((b2) << 8) | (b3)) /* size of SCCTL structure in bytes */#define SA_SCCTL_SZ 16 /* Max Authentication tag size */#define SA_MAX_AUTH_TAG_SZ 64 enum sa_algo_id { SA_ALG_CBC_AES = 0, SA_ALG_EBC_AES, SA_ALG_CBC_DES3, SA_ALG_ECB_DES3, SA_ALG_SHA1, SA_ALG_SHA256, SA_ALG_SHA512, SA_ALG_AUTHENC_SHA1_AES, SA_ALG_AUTHENC_SHA256_AES,}; struct sa_match_data { u8 priv; u8 priv_id; u32 supported_algos;}; static struct device *sa_k3_dev; /** * struct sa_cmdl_cfg - Command label configuration descriptor * @aalg: authentication algorithm ID * @enc_eng_id: Encryption Engine ID supported by the SA hardware * @auth_eng_id: Authentication Engine ID * @iv_size: Initialization Vector size * @akey: Authentication key * @akey_len: Authentication key length * @enc: True, if this is an encode request */struct sa_cmdl_cfg { int aalg; u8 enc_eng_id; u8 auth_eng_id; u8 iv_size; const u8 *akey; u16 akey_len; bool enc;}; /** * struct algo_data - Crypto algorithm specific data * @enc_eng: Encryption engine info structure * @auth_eng: Authentication engine info structure * @auth_ctrl: Authentication control word * @hash_size: Size of digest * @iv_idx: iv index in psdata * @iv_out_size: iv out size * @ealg_id: Encryption Algorithm ID * @aalg_id: Authentication algorithm ID * @mci_enc: Mode Control Instruction for Encryption algorithm * @mci_dec: Mode Control Instruction for Decryption * @inv_key: Whether the encryption algorithm demands key inversion * @ctx: Pointer to the algorithm context * @keyed_mac: Whether the authentication algorithm has key * @prep_iopad: Function pointer to generate intermediate ipad/opad */struct algo_data { struct sa_eng_info enc_eng; struct sa_eng_info auth_eng; u8 auth_ctrl; u8 hash_size; u8 iv_idx; u8 iv_out_size; u8 ealg_id; u8 aalg_id; u8 *mci_enc; u8 *mci_dec; bool inv_key; struct sa_tfm_ctx *ctx; bool keyed_mac; void (*prep_iopad)(struct algo_data *algo, const u8 *key, u16 key_sz, __be32 *ipad, __be32 *opad);}; /** * struct sa_alg_tmpl: A generic template encompassing crypto/aead algorithms * @type: Type of the crypto algorithm. * @alg: Union of crypto algorithm definitions. * @registered: Flag indicating if the crypto algorithm is already registered */struct sa_alg_tmpl { u32 type; /* CRYPTO_ALG_TYPE from <linux/crypto.h> */ union { struct skcipher_alg skcipher; struct ahash_alg ahash; struct aead_alg aead; } alg; bool registered;}; /** * struct sa_mapped_sg: scatterlist information for tx and rx * @mapped: Set to true if the @sgt is mapped * @dir: mapping direction used for @sgt * @split_sg: Set if the sg is split and needs to be freed up * @static_sg: Static scatterlist entry for overriding data * @sgt: scatterlist table for DMA API use */struct sa_mapped_sg { bool mapped; enum dma_data_direction dir; struct scatterlist static_sg; struct scatterlist *split_sg; struct sg_table sgt;};/** * struct sa_rx_data: RX Packet miscellaneous data place holder * @req: crypto request data pointer * @ddev: pointer to the DMA device * @tx_in: dma_async_tx_descriptor pointer for rx channel * @mapped_sg: Information on tx (0) and rx (1) scatterlist DMA mapping * @enc: Flag indicating either encryption or decryption * @enc_iv_size: Initialisation vector size * @iv_idx: Initialisation vector index */struct sa_rx_data { void *req; struct device *ddev; struct dma_async_tx_descriptor *tx_in; struct sa_mapped_sg mapped_sg[2]; u8 enc; u8 enc_iv_size; u8 iv_idx;}; /** * struct sa_req: SA request definition * @dev: device for the request * @size: total data to the xmitted via DMA * @enc_offset: offset of cipher data * @enc_size: data to be passed to cipher engine * @enc_iv: cipher IV * @auth_offset: offset of the authentication data * @auth_size: size of the authentication data * @auth_iv: authentication IV * @type: algorithm type for the request * @cmdl: command label pointer * @base: pointer to the base request * @ctx: pointer to the algorithm context data * @enc: true if this is an encode request * @src: source data * @dst: destination data * @callback: DMA callback for the request * @mdata_size: metadata size passed to DMA */struct sa_req { struct device *dev; u16 size; u8 enc_offset; u16 enc_size; u8 *enc_iv; u8 auth_offset; u16 auth_size; u8 *auth_iv; u32 type; u32 *cmdl; struct crypto_async_request *base; struct sa_tfm_ctx *ctx; bool enc; struct scatterlist *src; struct scatterlist *dst; dma_async_tx_callback callback; u16 mdata_size;}; /* * Mode Control Instructions for various Key lengths 128, 192, 256 * For CBC (Cipher Block Chaining) mode for encryption */static u8 mci_cbc_enc_array[3][MODE_CONTROL_BYTES] = { { 0x61, 0x00, 0x00, 0x18, 0x88, 0x0a, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x61, 0x00, 0x00, 0x18, 0x88, 0x4a, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x61, 0x00, 0x00, 0x18, 0x88, 0x8a, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },}; /* * Mode Control Instructions for various Key lengths 128, 192, 256 * For CBC (Cipher Block Chaining) mode for decryption */static u8 mci_cbc_dec_array[3][MODE_CONTROL_BYTES] = { { 0x71, 0x00, 0x00, 0x80, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x71, 0x00, 0x00, 0x84, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x71, 0x00, 0x00, 0x88, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },}; /* * Mode Control Instructions for various Key lengths 128, 192, 256 * For CBC (Cipher Block Chaining) mode for encryption */static u8 mci_cbc_enc_no_iv_array[3][MODE_CONTROL_BYTES] = { { 0x21, 0x00, 0x00, 0x18, 0x88, 0x0a, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x21, 0x00, 0x00, 0x18, 0x88, 0x4a, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x21, 0x00, 0x00, 0x18, 0x88, 0x8a, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },}; /* * Mode Control Instructions for various Key lengths 128, 192, 256 * For CBC (Cipher Block Chaining) mode for decryption */static u8 mci_cbc_dec_no_iv_array[3][MODE_CONTROL_BYTES] = { { 0x31, 0x00, 0x00, 0x80, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x31, 0x00, 0x00, 0x84, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x31, 0x00, 0x00, 0x88, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },}; /* * Mode Control Instructions for various Key lengths 128, 192, 256 * For ECB (Electronic Code Book) mode for encryption */static u8 mci_ecb_enc_array[3][27] = { { 0x21, 0x00, 0x00, 0x80, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x21, 0x00, 0x00, 0x84, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x21, 0x00, 0x00, 0x88, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },}; /* * Mode Control Instructions for various Key lengths 128, 192, 256 * For ECB (Electronic Code Book) mode for decryption */static u8 mci_ecb_dec_array[3][27] = { { 0x31, 0x00, 0x00, 0x80, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x31, 0x00, 0x00, 0x84, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x31, 0x00, 0x00, 0x88, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },}; /* * Mode Control Instructions for DES algorithm * For CBC (Cipher Block Chaining) mode and ECB mode * encryption and for decryption respectively */static u8 mci_cbc_3des_enc_array[MODE_CONTROL_BYTES] = { 0x60, 0x00, 0x00, 0x18, 0x88, 0x52, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}; static u8 mci_cbc_3des_dec_array[MODE_CONTROL_BYTES] = { 0x70, 0x00, 0x00, 0x85, 0x0a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}; static u8 mci_ecb_3des_enc_array[MODE_CONTROL_BYTES] = { 0x20, 0x00, 0x00, 0x85, 0x0a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}; static u8 mci_ecb_3des_dec_array[MODE_CONTROL_BYTES] = { 0x30, 0x00, 0x00, 0x85, 0x0a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,}; /* * Perform 16 byte or 128 bit swizzling * The SA2UL Expects the security context to * be in little Endian and the bus width is 128 bits or 16 bytes * Hence swap 16 bytes at a time from higher to lower address */static void sa_swiz_128(u8 *in, u16 len){ u8 data[16]; int i, j; for (i = 0; i < len; i += 16) { memcpy(data, &in[i], 16); for (j = 0; j < 16; j++) in[i + j] = data[15 - j]; }} /* Prepare the ipad and opad from key as per SHA algorithm step 1*/static void prepare_kipad(u8 *k_ipad, const u8 *key, u16 key_sz){ int i; for (i = 0; i < key_sz; i++) k_ipad[i] = key[i] ^ 0x36; /* Instead of XOR with 0 */ for (; i < SHA1_BLOCK_SIZE; i++) k_ipad[i] = 0x36;} static void prepare_kopad(u8 *k_opad, const u8 *key, u16 key_sz){ int i; for (i = 0; i < key_sz; i++) k_opad[i] = key[i] ^ 0x5c; /* Instead of XOR with 0 */ for (; i < SHA1_BLOCK_SIZE; i++) k_opad[i] = 0x5c;} static void sa_export_shash(void *state, struct shash_desc *hash, int digest_size, __be32 *out){ struct sha1_state *sha1; struct sha256_state *sha256; u32 *result; switch (digest_size) { case SHA1_DIGEST_SIZE: sha1 = state; result = sha1->state; break; case SHA256_DIGEST_SIZE: sha256 = state; result = sha256->state; break; default: dev_err(sa_k3_dev, "%s: bad digest_size=%d\n", __func__, digest_size); return; } crypto_shash_export(hash, state); cpu_to_be32_array(out, result, digest_size / 4);} static void sa_prepare_iopads(struct algo_data *data, const u8 *key, u16 key_sz, __be32 *ipad, __be32 *opad){ SHASH_DESC_ON_STACK(shash, data->ctx->shash); int block_size = crypto_shash_blocksize(data->ctx->shash); int digest_size = crypto_shash_digestsize(data->ctx->shash); union { struct sha1_state sha1; struct sha256_state sha256; u8 k_pad[SHA1_BLOCK_SIZE]; } sha; shash->tfm = data->ctx->shash; prepare_kipad(sha.k_pad, key, key_sz); crypto_shash_init(shash); crypto_shash_update(shash, sha.k_pad, block_size); sa_export_shash(&sha, shash, digest_size, ipad); prepare_kopad(sha.k_pad, key, key_sz); crypto_shash_init(shash); crypto_shash_update(shash, sha.k_pad, block_size); sa_export_shash(&sha, shash, digest_size, opad); memzero_explicit(&sha, sizeof(sha));} /* Derive the inverse key used in AES-CBC decryption operation */static inline int sa_aes_inv_key(u8 *inv_key, const u8 *key, u16 key_sz){ struct crypto_aes_ctx ctx; int key_pos; if (aes_expandkey(&ctx, key, key_sz)) { dev_err(sa_k3_dev, "%s: bad key len(%d)\n", __func__, key_sz); return -EINVAL; } /* work around to get the right inverse for AES_KEYSIZE_192 size keys */ if (key_sz == AES_KEYSIZE_192) { ctx.key_enc[52] = ctx.key_enc[51] ^ ctx.key_enc[46]; ctx.key_enc[53] = ctx.key_enc[52] ^ ctx.key_enc[47]; } /* Based crypto_aes_expand_key logic */ switch (key_sz) { case AES_KEYSIZE_128: case AES_KEYSIZE_192: key_pos = key_sz + 24; break; case AES_KEYSIZE_256: key_pos = key_sz + 24 - 4; break; default: dev_err(sa_k3_dev, "%s: bad key len(%d)\n", __func__, key_sz); return -EINVAL; } memcpy(inv_key, &ctx.key_enc[key_pos], key_sz); return 0;Lines 1–500 of 2474. Load more
// SPDX-License-Identifier: GPL-2.0 /* * K3 SA2UL crypto accelerator driver * * Copyright (C) 2018-2020 Texas Instruments Incorporated - http://www.ti.com * * Authors: Keerthy * Vitaly Andrianov * Tero Kristo */ #include <linux/bitfield.h> #include <linux/clk.h> #include <linux/dma-mapping.h> #include <linux/dmaengine.h> #include <linux/dmapool.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <crypto/aes.h> #include <crypto/authenc.h> #include <crypto/utils.h> #include <crypto/des.h> #include <crypto/internal/aead.h> #include <crypto/internal/hash.h> #include <crypto/internal/skcipher.h> #include <crypto/scatterwalk.h> #include <crypto/sha1.h> #include <crypto/sha2.h> #include "sa2ul.h" /* Byte offset for key in encryption security context */ #define SC_ENC_KEY_OFFSET (1 + 27 + 4) /* Byte offset for Aux-1 in encryption security context */ #define SC_ENC_AUX1_OFFSET (1 + 27 + 4 + 32) #define SA_CMDL_UPD_ENC 0x0001 #define SA_CMDL_UPD_AUTH 0x0002 #define SA_CMDL_UPD_ENC_IV 0x0004 #define SA_CMDL_UPD_AUTH_IV 0x0008 #define SA_CMDL_UPD_AUX_KEY 0x0010 #define SA_AUTH_SUBKEY_LEN 16 #define SA_CMDL_PAYLOAD_LENGTH_MASK 0xFFFF #define SA_CMDL_SOP_BYPASS_LEN_MASK 0xFF000000 #define MODE_CONTROL_BYTES 27 #define SA_HASH_PROCESSING 0 #define SA_CRYPTO_PROCESSING 0 #define SA_UPLOAD_HASH_TO_TLR BIT(6) #define SA_SW0_FLAGS_MASK 0xF0000 #define SA_SW0_CMDL_INFO_MASK 0x1F00000 #define SA_SW0_CMDL_PRESENT BIT(4) #define SA_SW0_ENG_ID_MASK 0x3E000000 #define SA_SW0_DEST_INFO_PRESENT BIT(30) #define SA_SW2_EGRESS_LENGTH 0xFF000000 #define SA_BASIC_HASH 0x10 #define SHA256_DIGEST_WORDS 8 /* Make 32-bit word from 4 bytes */ #define SA_MK_U32(b0, b1, b2, b3) (((b0) << 24) | ((b1) << 16) | \ ((b2) << 8) | (b3)) /* size of SCCTL structure in bytes */ #define SA_SCCTL_SZ 16 /* Max Authentication tag size */ #define SA_MAX_AUTH_TAG_SZ 64 enum sa_algo_id { SA_ALG_CBC_AES = 0, SA_ALG_EBC_AES, SA_ALG_CBC_DES3, SA_ALG_ECB_DES3, SA_ALG_SHA1, SA_ALG_SHA256, SA_ALG_SHA512, SA_ALG_AUTHENC_SHA1_AES, SA_ALG_AUTHENC_SHA256_AES, }; struct sa_match_data { u8 priv; u8 priv_id; u32 supported_algos; }; static struct device *sa_k3_dev; /** * struct sa_cmdl_cfg - Command label configuration descriptor * @aalg: authentication algorithm ID * @enc_eng_id: Encryption Engine ID supported by the SA hardware * @auth_eng_id: Authentication Engine ID * @iv_size: Initialization Vector size * @akey: Authentication key * @akey_len: Authentication key length * @enc: True, if this is an encode request */ struct sa_cmdl_cfg { int aalg; u8 enc_eng_id; u8 auth_eng_id; u8 iv_size; const u8 *akey; u16 akey_len; bool enc; }; /** * struct algo_data - Crypto algorithm specific data * @enc_eng: Encryption engine info structure * @auth_eng: Authentication engine info structure * @auth_ctrl: Authentication control word * @hash_size: Size of digest * @iv_idx: iv index in psdata * @iv_out_size: iv out size * @ealg_id: Encryption Algorithm ID * @aalg_id: Authentication algorithm ID * @mci_enc: Mode Control Instruction for Encryption algorithm * @mci_dec: Mode Control Instruction for Decryption * @inv_key: Whether the encryption algorithm demands key inversion * @ctx: Pointer to the algorithm context * @keyed_mac: Whether the authentication algorithm has key * @prep_iopad: Function pointer to generate intermediate ipad/opad */ struct algo_data { struct sa_eng_info enc_eng; struct sa_eng_info auth_eng; u8 auth_ctrl; u8 hash_size; u8 iv_idx; u8 iv_out_size; u8 ealg_id; u8 aalg_id; u8 *mci_enc; u8 *mci_dec; bool inv_key; struct sa_tfm_ctx *ctx; bool keyed_mac; void (*prep_iopad)(struct algo_data *algo, const u8 *key, u16 key_sz, __be32 *ipad, __be32 *opad); }; /** * struct sa_alg_tmpl: A generic template encompassing crypto/aead algorithms * @type: Type of the crypto algorithm. * @alg: Union of crypto algorithm definitions. * @registered: Flag indicating if the crypto algorithm is already registered */ struct sa_alg_tmpl { u32 type; /* CRYPTO_ALG_TYPE from <linux/crypto.h> */ union { struct skcipher_alg skcipher; struct ahash_alg ahash; struct aead_alg aead; } alg; bool registered; }; /** * struct sa_mapped_sg: scatterlist information for tx and rx * @mapped: Set to true if the @sgt is mapped * @dir: mapping direction used for @sgt * @split_sg: Set if the sg is split and needs to be freed up * @static_sg: Static scatterlist entry for overriding data * @sgt: scatterlist table for DMA API use */ struct sa_mapped_sg { bool mapped; enum dma_data_direction dir; struct scatterlist static_sg; struct scatterlist *split_sg; struct sg_table sgt; }; /** * struct sa_rx_data: RX Packet miscellaneous data place holder * @req: crypto request data pointer * @ddev: pointer to the DMA device * @tx_in: dma_async_tx_descriptor pointer for rx channel * @mapped_sg: Information on tx (0) and rx (1) scatterlist DMA mapping * @enc: Flag indicating either encryption or decryption * @enc_iv_size: Initialisation vector size * @iv_idx: Initialisation vector index */ struct sa_rx_data { void *req; struct device *ddev; struct dma_async_tx_descriptor *tx_in; struct sa_mapped_sg mapped_sg[2]; u8 enc; u8 enc_iv_size; u8 iv_idx; }; /** * struct sa_req: SA request definition * @dev: device for the request * @size: total data to the xmitted via DMA * @enc_offset: offset of cipher data * @enc_size: data to be passed to cipher engine * @enc_iv: cipher IV * @auth_offset: offset of the authentication data * @auth_size: size of the authentication data * @auth_iv: authentication IV * @type: algorithm type for the request * @cmdl: command label pointer * @base: pointer to the base request * @ctx: pointer to the algorithm context data * @enc: true if this is an encode request * @src: source data * @dst: destination data * @callback: DMA callback for the request * @mdata_size: metadata size passed to DMA */ struct sa_req { struct device *dev; u16 size; u8 enc_offset; u16 enc_size; u8 *enc_iv; u8 auth_offset; u16 auth_size; u8 *auth_iv; u32 type; u32 *cmdl; struct crypto_async_request *base; struct sa_tfm_ctx *ctx; bool enc; struct scatterlist *src; struct scatterlist *dst; dma_async_tx_callback callback; u16 mdata_size; }; /* * Mode Control Instructions for various Key lengths 128, 192, 256 * For CBC (Cipher Block Chaining) mode for encryption */ static u8 mci_cbc_enc_array[3][MODE_CONTROL_BYTES] = { { 0x61, 0x00, 0x00, 0x18, 0x88, 0x0a, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x61, 0x00, 0x00, 0x18, 0x88, 0x4a, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x61, 0x00, 0x00, 0x18, 0x88, 0x8a, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, }; /* * Mode Control Instructions for various Key lengths 128, 192, 256 * For CBC (Cipher Block Chaining) mode for decryption */ static u8 mci_cbc_dec_array[3][MODE_CONTROL_BYTES] = { { 0x71, 0x00, 0x00, 0x80, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x71, 0x00, 0x00, 0x84, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x71, 0x00, 0x00, 0x88, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, }; /* * Mode Control Instructions for various Key lengths 128, 192, 256 * For CBC (Cipher Block Chaining) mode for encryption */ static u8 mci_cbc_enc_no_iv_array[3][MODE_CONTROL_BYTES] = { { 0x21, 0x00, 0x00, 0x18, 0x88, 0x0a, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x21, 0x00, 0x00, 0x18, 0x88, 0x4a, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x21, 0x00, 0x00, 0x18, 0x88, 0x8a, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, }; /* * Mode Control Instructions for various Key lengths 128, 192, 256 * For CBC (Cipher Block Chaining) mode for decryption */ static u8 mci_cbc_dec_no_iv_array[3][MODE_CONTROL_BYTES] = { { 0x31, 0x00, 0x00, 0x80, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x31, 0x00, 0x00, 0x84, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x31, 0x00, 0x00, 0x88, 0x8a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, }; /* * Mode Control Instructions for various Key lengths 128, 192, 256 * For ECB (Electronic Code Book) mode for encryption */ static u8 mci_ecb_enc_array[3][27] = { { 0x21, 0x00, 0x00, 0x80, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x21, 0x00, 0x00, 0x84, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x21, 0x00, 0x00, 0x88, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, }; /* * Mode Control Instructions for various Key lengths 128, 192, 256 * For ECB (Electronic Code Book) mode for decryption */ static u8 mci_ecb_dec_array[3][27] = { { 0x31, 0x00, 0x00, 0x80, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x31, 0x00, 0x00, 0x84, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x31, 0x00, 0x00, 0x88, 0x8a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, }; /* * Mode Control Instructions for DES algorithm * For CBC (Cipher Block Chaining) mode and ECB mode * encryption and for decryption respectively */ static u8 mci_cbc_3des_enc_array[MODE_CONTROL_BYTES] = { 0x60, 0x00, 0x00, 0x18, 0x88, 0x52, 0xaa, 0x4b, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static u8 mci_cbc_3des_dec_array[MODE_CONTROL_BYTES] = { 0x70, 0x00, 0x00, 0x85, 0x0a, 0xca, 0x98, 0xf4, 0x40, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static u8 mci_ecb_3des_enc_array[MODE_CONTROL_BYTES] = { 0x20, 0x00, 0x00, 0x85, 0x0a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; static u8 mci_ecb_3des_dec_array[MODE_CONTROL_BYTES] = { 0x30, 0x00, 0x00, 0x85, 0x0a, 0x04, 0xb7, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; /* * Perform 16 byte or 128 bit swizzling * The SA2UL Expects the security context to * be in little Endian and the bus width is 128 bits or 16 bytes * Hence swap 16 bytes at a time from higher to lower address */ static void sa_swiz_128(u8 *in, u16 len) { u8 data[16]; int i, j; for (i = 0; i < len; i += 16) { memcpy(data, &in[i], 16); for (j = 0; j < 16; j++) in[i + j] = data[15 - j]; } } /* Prepare the ipad and opad from key as per SHA algorithm step 1*/ static void prepare_kipad(u8 *k_ipad, const u8 *key, u16 key_sz) { int i; for (i = 0; i < key_sz; i++) k_ipad[i] = key[i] ^ 0x36; /* Instead of XOR with 0 */ for (; i < SHA1_BLOCK_SIZE; i++) k_ipad[i] = 0x36; } static void prepare_kopad(u8 *k_opad, const u8 *key, u16 key_sz) { int i; for (i = 0; i < key_sz; i++) k_opad[i] = key[i] ^ 0x5c; /* Instead of XOR with 0 */ for (; i < SHA1_BLOCK_SIZE; i++) k_opad[i] = 0x5c; } static void sa_export_shash(void *state, struct shash_desc *hash, int digest_size, __be32 *out) { struct sha1_state *sha1; struct sha256_state *sha256; u32 *result; switch (digest_size) { case SHA1_DIGEST_SIZE: sha1 = state; result = sha1->state; break; case SHA256_DIGEST_SIZE: sha256 = state; result = sha256->state; break; default: dev_err(sa_k3_dev, "%s: bad digest_size=%d\n", __func__, digest_size); return; } crypto_shash_export(hash, state); cpu_to_be32_array(out, result, digest_size / 4); } static void sa_prepare_iopads(struct algo_data *data, const u8 *key, u16 key_sz, __be32 *ipad, __be32 *opad) { SHASH_DESC_ON_STACK(shash, data->ctx->shash); int block_size = crypto_shash_blocksize(data->ctx->shash); int digest_size = crypto_shash_digestsize(data->ctx->shash); union { struct sha1_state sha1; struct sha256_state sha256; u8 k_pad[SHA1_BLOCK_SIZE]; } sha; shash->tfm = data->ctx->shash; prepare_kipad(sha.k_pad, key, key_sz); crypto_shash_init(shash); crypto_shash_update(shash, sha.k_pad, block_size); sa_export_shash(&sha, shash, digest_size, ipad); prepare_kopad(sha.k_pad, key, key_sz); crypto_shash_init(shash); crypto_shash_update(shash, sha.k_pad, block_size); sa_export_shash(&sha, shash, digest_size, opad); memzero_explicit(&sha, sizeof(sha)); } /* Derive the inverse key used in AES-CBC decryption operation */ static inline int sa_aes_inv_key(u8 *inv_key, const u8 *key, u16 key_sz) { struct crypto_aes_ctx ctx; int key_pos; if (aes_expandkey(&ctx, key, key_sz)) { dev_err(sa_k3_dev, "%s: bad key len(%d)\n", __func__, key_sz); return -EINVAL; } /* work around to get the right inverse for AES_KEYSIZE_192 size keys */ if (key_sz == AES_KEYSIZE_192) { ctx.key_enc[52] = ctx.key_enc[51] ^ ctx.key_enc[46]; ctx.key_enc[53] = ctx.key_enc[52] ^ ctx.key_enc[47]; } /* Based crypto_aes_expand_key logic */ switch (key_sz) { case AES_KEYSIZE_128: case AES_KEYSIZE_192: key_pos = key_sz + 24; break; case AES_KEYSIZE_256: key_pos = key_sz + 24 - 4; break; default: dev_err(sa_k3_dev, "%s: bad key len(%d)\n", __func__, key_sz); return -EINVAL; } memcpy(inv_key, &ctx.key_enc[key_pos], key_sz); return 0;