Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
/*
 *
 *  sep_crypto.h - Crypto interface structures
 *
 *  Copyright(c) 2009-2011 Intel Corporation. All rights reserved.
 *  Contributions(c) 2009-2010 Discretix. All rights reserved.
 *
 *  This program is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU General Public License as published by the Free
 *  Software Foundation; version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful, but WITHOUT
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 *  more details.
 *
 *  You should have received a copy of the GNU General Public License along with
 *  this program; if not, write to the Free Software Foundation, Inc., 59
 *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 *  CONTACTS:
 *
 *  Mark Allyn		mark.a.allyn@intel.com
 *  Jayant Mangalampalli jayant.mangalampalli@intel.com
 *
 *  CHANGES:
 *
 *  2009.06.26	Initial publish
 *  2011.02.22  Enable Kernel Crypto
 *
 */

/* Constants for SEP (from vendor) */
#define SEP_START_MSG_TOKEN	0x02558808

#define SEP_DES_IV_SIZE_WORDS	2
#define SEP_DES_IV_SIZE_BYTES	(SEP_DES_IV_SIZE_WORDS * \
	sizeof(u32))
#define SEP_DES_KEY_SIZE_WORDS	2
#define SEP_DES_KEY_SIZE_BYTES	(SEP_DES_KEY_SIZE_WORDS * \
	sizeof(u32))
#define SEP_DES_BLOCK_SIZE	8
#define SEP_DES_DUMMY_SIZE	16

#define SEP_DES_INIT_OPCODE	0x10
#define SEP_DES_BLOCK_OPCODE	0x11

#define SEP_AES_BLOCK_SIZE_WORDS 4
#define SEP_AES_BLOCK_SIZE_BYTES \
	(SEP_AES_BLOCK_SIZE_WORDS * sizeof(u32))

#define SEP_AES_DUMMY_BLOCK_SIZE 16
#define SEP_AES_IV_SIZE_WORDS	SEP_AES_BLOCK_SIZE_WORDS
#define SEP_AES_IV_SIZE_BYTES \
	(SEP_AES_IV_SIZE_WORDS * sizeof(u32))

#define SEP_AES_KEY_128_SIZE	16
#define SEP_AES_KEY_192_SIZE	24
#define SEP_AES_KEY_256_SIZE	32
#define SEP_AES_KEY_512_SIZE	64
#define SEP_AES_MAX_KEY_SIZE_WORDS	16
#define SEP_AES_MAX_KEY_SIZE_BYTES \
	(SEP_AES_MAX_KEY_SIZE_WORDS * sizeof(u32))

#define SEP_AES_WRAP_MIN_SIZE	8
#define SEP_AES_WRAP_MAX_SIZE	0x10000000

#define SEP_AES_WRAP_BLOCK_SIZE_WORDS	2
#define SEP_AES_WRAP_BLOCK_SIZE_BYTES \
	(SEP_AES_WRAP_BLOCK_SIZE_WORDS * sizeof(u32))

#define SEP_AES_SECRET_RKEK1		0x1
#define SEP_AES_SECRET_RKEK2		0x2

#define SEP_AES_INIT_OPCODE		0x2
#define SEP_AES_BLOCK_OPCODE		0x3
#define SEP_AES_FINISH_OPCODE		0x4
#define SEP_AES_WRAP_OPCODE		0x6
#define SEP_AES_UNWRAP_OPCODE		0x7
#define SEP_AES_XTS_FINISH_OPCODE	0x8

#define SEP_HASH_RESULT_SIZE_WORDS	16
#define SEP_MD5_DIGEST_SIZE_WORDS	4
#define SEP_MD5_DIGEST_SIZE_BYTES \
	(SEP_MD5_DIGEST_SIZE_WORDS * sizeof(u32))
#define SEP_SHA1_DIGEST_SIZE_WORDS	5
#define SEP_SHA1_DIGEST_SIZE_BYTES \
	(SEP_SHA1_DIGEST_SIZE_WORDS * sizeof(u32))
#define SEP_SHA224_DIGEST_SIZE_WORDS	7
#define SEP_SHA224_DIGEST_SIZE_BYTES \
	(SEP_SHA224_DIGEST_SIZE_WORDS * sizeof(u32))
#define SEP_SHA256_DIGEST_SIZE_WORDS	8
#define SEP_SHA256_DIGEST_SIZE_BYTES \
	(SEP_SHA256_DIGEST_SIZE_WORDS * sizeof(u32))
#define SEP_SHA384_DIGEST_SIZE_WORDS	12
#define SEP_SHA384_DIGEST_SIZE_BYTES \
	(SEP_SHA384_DIGEST_SIZE_WORDS * sizeof(u32))
#define SEP_SHA512_DIGEST_SIZE_WORDS	16
#define SEP_SHA512_DIGEST_SIZE_BYTES \
	(SEP_SHA512_DIGEST_SIZE_WORDS * sizeof(u32))
#define SEP_HASH_BLOCK_SIZE_WORDS	16
#define SEP_HASH_BLOCK_SIZE_BYTES \
	(SEP_HASH_BLOCK_SIZE_WORDS * sizeof(u32))
#define SEP_SHA2_BLOCK_SIZE_WORDS	32
#define SEP_SHA2_BLOCK_SIZE_BYTES \
	(SEP_SHA2_BLOCK_SIZE_WORDS * sizeof(u32))

#define SEP_HASH_INIT_OPCODE		0x20
#define SEP_HASH_UPDATE_OPCODE		0x21
#define SEP_HASH_FINISH_OPCODE		0x22
#define SEP_HASH_SINGLE_OPCODE		0x23

#define SEP_HOST_ERROR		0x0b000000
#define SEP_OK			0x0
#define SEP_INVALID_START	(SEP_HOST_ERROR + 0x3)
#define SEP_WRONG_OPCODE	(SEP_HOST_ERROR + 0x1)

#define SEP_TRANSACTION_WAIT_TIME 5

#define SEP_QUEUE_LENGTH	2
/* Macros */
#ifndef __LITTLE_ENDIAN
#define CHG_ENDIAN(val) \
	(((val) >> 24) | \
	(((val) & 0x00FF0000) >> 8) | \
	(((val) & 0x0000FF00) << 8) | \
	(((val) & 0x000000FF) << 24))
#else
#define CHG_ENDIAN(val) val
#endif
/* Enums for SEP (from vendor) */
enum des_numkey {
	DES_KEY_1 = 1,
	DES_KEY_2 = 2,
	DES_KEY_3 = 3,
	SEP_NUMKEY_OPTIONS,
	SEP_NUMKEY_LAST = 0x7fffffff,
};

enum des_enc_mode {
	SEP_DES_ENCRYPT = 0,
	SEP_DES_DECRYPT = 1,
	SEP_DES_ENC_OPTIONS,
	SEP_DES_ENC_LAST = 0x7fffffff,
};

enum des_op_mode {
	SEP_DES_ECB = 0,
	SEP_DES_CBC = 1,
	SEP_OP_OPTIONS,
	SEP_OP_LAST = 0x7fffffff,
};

enum aes_keysize {
	AES_128 = 0,
	AES_192 = 1,
	AES_256 = 2,
	AES_512 = 3,
	AES_SIZE_OPTIONS,
	AEA_SIZE_LAST = 0x7FFFFFFF,
};

enum aes_enc_mode {
	SEP_AES_ENCRYPT = 0,
	SEP_AES_DECRYPT = 1,
	SEP_AES_ENC_OPTIONS,
	SEP_AES_ENC_LAST = 0x7FFFFFFF,
};

enum aes_op_mode {
	SEP_AES_ECB = 0,
	SEP_AES_CBC = 1,
	SEP_AES_MAC = 2,
	SEP_AES_CTR = 3,
	SEP_AES_XCBC = 4,
	SEP_AES_CMAC = 5,
	SEP_AES_XTS = 6,
	SEP_AES_OP_OPTIONS,
	SEP_AES_OP_LAST = 0x7FFFFFFF,
};

enum hash_op_mode {
	SEP_HASH_SHA1 = 0,
	SEP_HASH_SHA224 = 1,
	SEP_HASH_SHA256 = 2,
	SEP_HASH_SHA384 = 3,
	SEP_HASH_SHA512 = 4,
	SEP_HASH_MD5 = 5,
	SEP_HASH_OPTIONS,
	SEP_HASH_LAST_MODE = 0x7FFFFFFF,
};

/* Structures for SEP (from vendor) */
struct sep_des_internal_key {
	u32 key1[SEP_DES_KEY_SIZE_WORDS];
	u32 key2[SEP_DES_KEY_SIZE_WORDS];
	u32 key3[SEP_DES_KEY_SIZE_WORDS];
};

struct sep_des_internal_context {
	u32 iv_context[SEP_DES_IV_SIZE_WORDS];
	struct sep_des_internal_key context_key;
	enum des_numkey nbr_keys;
	enum des_enc_mode encryption;
	enum des_op_mode operation;
	u8 dummy_block[SEP_DES_DUMMY_SIZE];
};

struct sep_des_private_context {
	u32 valid_tag;
	u32 iv;
	u8 ctx_buf[sizeof(struct sep_des_internal_context)];
};

/* This is the structure passed to SEP via msg area */
struct sep_des_key {
	u32 key1[SEP_DES_KEY_SIZE_WORDS];
	u32 key2[SEP_DES_KEY_SIZE_WORDS];
	u32 key3[SEP_DES_KEY_SIZE_WORDS];
	u32 pad[SEP_DES_KEY_SIZE_WORDS];
};

struct sep_aes_internal_context {
	u32 aes_ctx_iv[SEP_AES_IV_SIZE_WORDS];
	u32 aes_ctx_key[SEP_AES_MAX_KEY_SIZE_WORDS / 2];
	enum aes_keysize keysize;
	enum aes_enc_mode encmode;
	enum aes_op_mode opmode;
	u8 secret_key;
	u32 no_add_blocks;
	u32 last_block_size;
	u32 last_block[SEP_AES_BLOCK_SIZE_WORDS];
	u32 prev_iv[SEP_AES_BLOCK_SIZE_WORDS];
	u32 remaining_size;
	union {
		struct {
			u32 dkey1[SEP_AES_BLOCK_SIZE_WORDS];
			u32 dkey2[SEP_AES_BLOCK_SIZE_WORDS];
			u32 dkey3[SEP_AES_BLOCK_SIZE_WORDS];
		} cmac_data;
		struct {
			u32 xts_key[SEP_AES_MAX_KEY_SIZE_WORDS / 2];
			u32 temp1[SEP_AES_BLOCK_SIZE_WORDS];
			u32 temp2[SEP_AES_BLOCK_SIZE_WORDS];
		} xtx_data;
	} s_data;
	u8 dummy_block[SEP_AES_DUMMY_BLOCK_SIZE];
};

struct sep_aes_private_context {
	u32 valid_tag;
	u32 aes_iv;
	u32 op_mode;
	u8 cbuff[sizeof(struct sep_aes_internal_context)];
};

struct sep_hash_internal_context {
	u32 hash_result[SEP_HASH_RESULT_SIZE_WORDS];
	enum hash_op_mode hash_opmode;
	u32 previous_data[SEP_SHA2_BLOCK_SIZE_WORDS];
	u16 prev_update_bytes;
	u32 total_proc_128bit[4];
	u16 op_mode_block_size;
	u8 dummy_aes_block[SEP_AES_DUMMY_BLOCK_SIZE];
};

struct sep_hash_private_context {
	u32 valid_tag;
	u32 iv;
	u8 internal_context[sizeof(struct sep_hash_internal_context)];
};

union key_t {
	struct sep_des_key des;
	u32 aes[SEP_AES_MAX_KEY_SIZE_WORDS];
};

/* Context structures for crypto API */
/**
 * Structure for this current task context
 * This same structure is used for both hash
 * and crypt in order to reduce duplicate code
 * for stuff that is done for both hash operations
 * and crypto operations. We cannot trust that the
 * system context is not pulled out from under
 * us during operation to operation, so all
 * critical stuff such as data pointers must
 * be in in a context that is exclusive for this
 * particular task at hand.
 */
struct this_task_ctx {
	struct sep_device *sep_used;
	u32 done;
	unsigned char iv[100];
	enum des_enc_mode des_encmode;
	enum des_op_mode des_opmode;
	enum aes_enc_mode aes_encmode;
	enum aes_op_mode aes_opmode;
	u32 init_opcode;
	u32 block_opcode;
	size_t data_length;
	size_t ivlen;
	struct ablkcipher_walk walk;
	int i_own_sep; /* Do I have custody of the sep? */
	struct sep_call_status call_status;
	struct build_dcb_struct_kernel dcb_input_data;
	struct sep_dma_context *dma_ctx;
	void *dmatables_region;
	size_t nbytes;
	struct sep_dcblock *dcb_region;
	struct sep_queue_info *queue_elem;
	int msg_len_words;
	unsigned char msg[SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES];
	void *msgptr;
	struct scatterlist *src_sg;
	struct scatterlist *dst_sg;
	struct scatterlist *src_sg_hold;
	struct scatterlist *dst_sg_hold;
	struct ahash_request *current_hash_req;
	struct ablkcipher_request *current_cypher_req;
	enum type_of_request current_request;
	int digest_size_words;
	int digest_size_bytes;
	int block_size_words;
	int block_size_bytes;
	enum hash_op_mode hash_opmode;
	enum hash_stage current_hash_stage;
	/**
	 * Not that this is a pointer. The are_we_done_yet variable is
	 * allocated by the task function. This way, even if the kernel
	 * crypto infrastructure has grabbed the task structure out from
	 * under us, the task function can still see this variable.
	 */
	int *are_we_done_yet;
	unsigned long end_time;
	};

struct sep_system_ctx {
	union key_t key;
	size_t keylen;
	int key_sent;
	enum des_numkey des_nbr_keys;
	enum aes_keysize aes_key_size;
	unsigned long end_time;
	struct sep_des_private_context des_private_ctx;
	struct sep_aes_private_context aes_private_ctx;
	struct sep_hash_private_context hash_private_ctx;
	};

/* work queue structures */
struct sep_work_struct {
	struct work_struct work;
	void (*callback)(void *);
	void *data;
	};

/* Functions */
int sep_crypto_setup(void);
void sep_crypto_takedown(void);