![Mark A. Allyn](/assets/img/avatar_default.png)
This gets the SEP crypto layer up and running with things like dmcrypt. It's a fairly big set of changes because it has to rework the whole context handling system. [This is picked out of the differences between the upstream driver and the staging driver. I'm resolving the differences as a series of updates -AC] Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
360 lines
9.5 KiB
C
360 lines
9.5 KiB
C
/*
|
|
*
|
|
* 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);
|