| /* |
| * |
| * 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); |