staging: ccree: add skcipher support

Add CryptoCell skcipher support

Signed-off-by: Gilad Ben-Yossef <gilad@benyossef.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Gilad Ben-Yossef 2017-04-23 12:26:11 +03:00 committed by Greg Kroah-Hartman
parent 50cfbbb7e6
commit 302ef8ebb4
9 changed files with 1765 additions and 1 deletions

View File

@ -3,11 +3,19 @@ config CRYPTO_DEV_CCREE
depends on CRYPTO_HW && OF && HAS_DMA
default n
select CRYPTO_HASH
select CRYPTO_BLKCIPHER
select CRYPTO_DES
select CRYPTO_AUTHENC
select CRYPTO_SHA1
select CRYPTO_MD5
select CRYPTO_SHA256
select CRYPTO_SHA512
select CRYPTO_HMAC
select CRYPTO_AES
select CRYPTO_CBC
select CRYPTO_ECB
select CRYPTO_CTR
select CRYPTO_XTS
help
Say 'Y' to enable a driver for the Arm TrustZone CryptoCell
C7xx. Currently only the CryptoCell 712 REE is supported.

View File

@ -1,2 +1,2 @@
obj-$(CONFIG_CRYPTO_DEV_CCREE) := ccree.o
ccree-y := ssi_driver.o ssi_sysfs.o ssi_buffer_mgr.o ssi_request_mgr.o ssi_hash.o ssi_sram_mgr.o ssi_pm.o ssi_pm_ext.o
ccree-y := ssi_driver.o ssi_sysfs.o ssi_buffer_mgr.o ssi_request_mgr.o ssi_cipher.o ssi_hash.o ssi_sram_mgr.o ssi_pm.o ssi_pm_ext.o

View File

@ -242,6 +242,27 @@ struct drv_ctx_hmac {
CC_DIGEST_SIZE_MAX - CC_HMAC_BLOCK_SIZE_MAX];
};
struct drv_ctx_cipher {
enum drv_crypto_alg alg; /* DRV_CRYPTO_ALG_AES */
enum drv_cipher_mode mode;
enum drv_crypto_direction direction;
enum drv_crypto_key_type crypto_key_type;
enum drv_crypto_padding_type padding_type;
uint32_t key_size; /* numeric value in bytes */
uint32_t data_unit_size; /* required for XTS */
/* block_state is the AES engine block state.
* It is used by the host to pass IV or counter at initialization.
* It is used by SeP for intermediate block chaining state and for
* returning MAC algorithms results. */
uint8_t block_state[CC_AES_BLOCK_SIZE];
uint8_t key[CC_AES_KEY_SIZE_MAX];
uint8_t xex_key[CC_AES_KEY_SIZE_MAX];
/* reserve to end of allocated context size */
uint32_t reserved[CC_DRV_CTX_SIZE_WORDS - 7 -
CC_AES_BLOCK_SIZE/sizeof(uint32_t) - 2 *
(CC_AES_KEY_SIZE_MAX/sizeof(uint32_t))];
};
/*******************************************************************/
/***************** MESSAGE BASED CONTEXTS **************************/
/*******************************************************************/

View File

@ -28,6 +28,7 @@
#include "ssi_buffer_mgr.h"
#include "cc_lli_defs.h"
#include "ssi_cipher.h"
#include "ssi_hash.h"
#define LLI_MAX_NUM_OF_DATA_ENTRIES 128
@ -517,6 +518,152 @@ static inline int ssi_ahash_handle_curr_buf(struct device *dev,
return 0;
}
void ssi_buffer_mgr_unmap_blkcipher_request(
struct device *dev,
void *ctx,
unsigned int ivsize,
struct scatterlist *src,
struct scatterlist *dst)
{
struct blkcipher_req_ctx *req_ctx = (struct blkcipher_req_ctx *)ctx;
if (likely(req_ctx->gen_ctx.iv_dma_addr != 0)) {
SSI_LOG_DEBUG("Unmapped iv: iv_dma_addr=0x%llX iv_size=%u\n",
(unsigned long long)req_ctx->gen_ctx.iv_dma_addr,
ivsize);
SSI_RESTORE_DMA_ADDR_TO_48BIT(req_ctx->gen_ctx.iv_dma_addr);
dma_unmap_single(dev, req_ctx->gen_ctx.iv_dma_addr,
ivsize,
DMA_TO_DEVICE);
}
/* Release pool */
if (req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI) {
SSI_RESTORE_DMA_ADDR_TO_48BIT(req_ctx->mlli_params.mlli_dma_addr);
dma_pool_free(req_ctx->mlli_params.curr_pool,
req_ctx->mlli_params.mlli_virt_addr,
req_ctx->mlli_params.mlli_dma_addr);
}
SSI_RESTORE_DMA_ADDR_TO_48BIT(sg_dma_address(src));
dma_unmap_sg(dev, src, req_ctx->in_nents,
DMA_BIDIRECTIONAL);
SSI_LOG_DEBUG("Unmapped req->src=%pK\n",
sg_virt(src));
if (src != dst) {
SSI_RESTORE_DMA_ADDR_TO_48BIT(sg_dma_address(dst));
dma_unmap_sg(dev, dst, req_ctx->out_nents,
DMA_BIDIRECTIONAL);
SSI_LOG_DEBUG("Unmapped req->dst=%pK\n",
sg_virt(dst));
}
}
int ssi_buffer_mgr_map_blkcipher_request(
struct ssi_drvdata *drvdata,
void *ctx,
unsigned int ivsize,
unsigned int nbytes,
void *info,
struct scatterlist *src,
struct scatterlist *dst)
{
struct blkcipher_req_ctx *req_ctx = (struct blkcipher_req_ctx *)ctx;
struct mlli_params *mlli_params = &req_ctx->mlli_params;
struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle;
struct device *dev = &drvdata->plat_dev->dev;
struct buffer_array sg_data;
uint32_t dummy = 0;
int rc = 0;
uint32_t mapped_nents = 0;
req_ctx->dma_buf_type = SSI_DMA_BUF_DLLI;
mlli_params->curr_pool = NULL;
sg_data.num_of_buffers = 0;
/* Map IV buffer */
if (likely(ivsize != 0) ) {
dump_byte_array("iv", (uint8_t *)info, ivsize);
req_ctx->gen_ctx.iv_dma_addr =
dma_map_single(dev, (void *)info,
ivsize,
DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(dev,
req_ctx->gen_ctx.iv_dma_addr))) {
SSI_LOG_ERR("Mapping iv %u B at va=%pK "
"for DMA failed\n", ivsize, info);
return -ENOMEM;
}
SSI_UPDATE_DMA_ADDR_TO_48BIT(req_ctx->gen_ctx.iv_dma_addr,
ivsize);
SSI_LOG_DEBUG("Mapped iv %u B at va=%pK to dma=0x%llX\n",
ivsize, info,
(unsigned long long)req_ctx->gen_ctx.iv_dma_addr);
} else
req_ctx->gen_ctx.iv_dma_addr = 0;
/* Map the src SGL */
rc = ssi_buffer_mgr_map_scatterlist(dev, src,
nbytes, DMA_BIDIRECTIONAL, &req_ctx->in_nents,
LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy, &mapped_nents);
if (unlikely(rc != 0)) {
rc = -ENOMEM;
goto ablkcipher_exit;
}
if (mapped_nents > 1)
req_ctx->dma_buf_type = SSI_DMA_BUF_MLLI;
if (unlikely(src == dst)) {
/* Handle inplace operation */
if (unlikely(req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI)) {
req_ctx->out_nents = 0;
ssi_buffer_mgr_add_scatterlist_entry(&sg_data,
req_ctx->in_nents, src,
nbytes, 0, true, &req_ctx->in_mlli_nents);
}
} else {
/* Map the dst sg */
if (unlikely(ssi_buffer_mgr_map_scatterlist(
dev,dst, nbytes,
DMA_BIDIRECTIONAL, &req_ctx->out_nents,
LLI_MAX_NUM_OF_DATA_ENTRIES, &dummy,
&mapped_nents))){
rc = -ENOMEM;
goto ablkcipher_exit;
}
if (mapped_nents > 1)
req_ctx->dma_buf_type = SSI_DMA_BUF_MLLI;
if (unlikely((req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI))) {
ssi_buffer_mgr_add_scatterlist_entry(&sg_data,
req_ctx->in_nents, src,
nbytes, 0, true,
&req_ctx->in_mlli_nents);
ssi_buffer_mgr_add_scatterlist_entry(&sg_data,
req_ctx->out_nents, dst,
nbytes, 0, true,
&req_ctx->out_mlli_nents);
}
}
if (unlikely(req_ctx->dma_buf_type == SSI_DMA_BUF_MLLI)) {
mlli_params->curr_pool = buff_mgr->mlli_buffs_pool;
rc = ssi_buffer_mgr_generate_mlli(dev, &sg_data, mlli_params);
if (unlikely(rc!= 0))
goto ablkcipher_exit;
}
SSI_LOG_DEBUG("areq_ctx->dma_buf_type = %s\n",
GET_DMA_BUFFER_TYPE(req_ctx->dma_buf_type));
return 0;
ablkcipher_exit:
ssi_buffer_mgr_unmap_blkcipher_request(dev, req_ctx, ivsize, src, dst);
return rc;
}
int ssi_buffer_mgr_map_hash_request_final(
struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, bool do_update)
{

View File

@ -55,6 +55,22 @@ int ssi_buffer_mgr_init(struct ssi_drvdata *drvdata);
int ssi_buffer_mgr_fini(struct ssi_drvdata *drvdata);
int ssi_buffer_mgr_map_blkcipher_request(
struct ssi_drvdata *drvdata,
void *ctx,
unsigned int ivsize,
unsigned int nbytes,
void *info,
struct scatterlist *src,
struct scatterlist *dst);
void ssi_buffer_mgr_unmap_blkcipher_request(
struct device *dev,
void *ctx,
unsigned int ivsize,
struct scatterlist *src,
struct scatterlist *dst);
int ssi_buffer_mgr_map_hash_request_final(struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, bool do_update);
int ssi_buffer_mgr_map_hash_request_update(struct ssi_drvdata *drvdata, void *ctx, struct scatterlist *src, unsigned int nbytes, unsigned int block_size);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2012-2017 ARM Limited or its affiliates.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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, see <http://www.gnu.org/licenses/>.
*/
/* \file ssi_cipher.h
ARM CryptoCell Cipher Crypto API
*/
#ifndef __SSI_CIPHER_H__
#define __SSI_CIPHER_H__
#include <linux/kernel.h>
#include <crypto/algapi.h>
#include "ssi_driver.h"
#include "ssi_buffer_mgr.h"
/* Crypto cipher flags */
#define CC_CRYPTO_CIPHER_KEY_KFDE0 (1 << 0)
#define CC_CRYPTO_CIPHER_KEY_KFDE1 (1 << 1)
#define CC_CRYPTO_CIPHER_KEY_KFDE2 (1 << 2)
#define CC_CRYPTO_CIPHER_KEY_KFDE3 (1 << 3)
#define CC_CRYPTO_CIPHER_DU_SIZE_512B (1 << 4)
#define CC_CRYPTO_CIPHER_KEY_KFDE_MASK (CC_CRYPTO_CIPHER_KEY_KFDE0 | CC_CRYPTO_CIPHER_KEY_KFDE1 | CC_CRYPTO_CIPHER_KEY_KFDE2 | CC_CRYPTO_CIPHER_KEY_KFDE3)
struct blkcipher_req_ctx {
struct async_gen_req_ctx gen_ctx;
enum ssi_req_dma_buf_type dma_buf_type;
uint32_t in_nents;
uint32_t in_mlli_nents;
uint32_t out_nents;
uint32_t out_mlli_nents;
uint8_t *backup_info; /*store iv for generated IV flow*/
struct mlli_params mlli_params;
};
int ssi_ablkcipher_alloc(struct ssi_drvdata *drvdata);
int ssi_ablkcipher_free(struct ssi_drvdata *drvdata);
#ifndef CRYPTO_ALG_BULK_MASK
#define CRYPTO_ALG_BULK_DU_512 0x00002000
#define CRYPTO_ALG_BULK_DU_4096 0x00004000
#define CRYPTO_ALG_BULK_MASK (CRYPTO_ALG_BULK_DU_512 |\
CRYPTO_ALG_BULK_DU_4096)
#endif /* CRYPTO_ALG_BULK_MASK */
#ifdef CRYPTO_TFM_REQ_HW_KEY
static inline bool ssi_is_hw_key(struct crypto_tfm *tfm)
{
return (crypto_tfm_get_flags(tfm) & CRYPTO_TFM_REQ_HW_KEY);
}
#else
struct arm_hw_key_info {
int hw_key1;
int hw_key2;
};
static inline bool ssi_is_hw_key(struct crypto_tfm *tfm)
{
return 0;
}
#endif /* CRYPTO_TFM_REQ_HW_KEY */
#endif /*__SSI_CIPHER_H__*/

View File

@ -23,6 +23,7 @@
#include <crypto/sha.h>
#include <crypto/authenc.h>
#include <crypto/scatterwalk.h>
#include <crypto/internal/skcipher.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
@ -61,6 +62,7 @@
#include "ssi_request_mgr.h"
#include "ssi_buffer_mgr.h"
#include "ssi_sysfs.h"
#include "ssi_cipher.h"
#include "ssi_hash.h"
#include "ssi_sram_mgr.h"
#include "ssi_pm.h"
@ -219,6 +221,9 @@ static int init_cc_resources(struct platform_device *plat_dev)
goto init_cc_res_err;
}
/*Initialize inflight counter used in dx_ablkcipher_secure_complete used for count of BYSPASS blocks operations*/
new_drvdata->inflight_counter = 0;
dev_set_drvdata(&plat_dev->dev, new_drvdata);
/* Get device resources */
/* First CC registers space */
@ -343,6 +348,13 @@ static int init_cc_resources(struct platform_device *plat_dev)
goto init_cc_res_err;
}
/* Allocate crypto algs */
rc = ssi_ablkcipher_alloc(new_drvdata);
if (unlikely(rc != 0)) {
SSI_LOG_ERR("ssi_ablkcipher_alloc failed\n");
goto init_cc_res_err;
}
rc = ssi_hash_alloc(new_drvdata);
if (unlikely(rc != 0)) {
SSI_LOG_ERR("ssi_hash_alloc failed\n");
@ -356,6 +368,7 @@ init_cc_res_err:
if (new_drvdata != NULL) {
ssi_hash_free(new_drvdata);
ssi_ablkcipher_free(new_drvdata);
ssi_power_mgr_fini(new_drvdata);
ssi_buffer_mgr_fini(new_drvdata);
request_mgr_fini(new_drvdata);
@ -396,6 +409,7 @@ static void cleanup_cc_resources(struct platform_device *plat_dev)
(struct ssi_drvdata *)dev_get_drvdata(&plat_dev->dev);
ssi_hash_free(drvdata);
ssi_ablkcipher_free(drvdata);
ssi_power_mgr_fini(drvdata);
ssi_buffer_mgr_fini(drvdata);
request_mgr_fini(drvdata);

View File

@ -29,6 +29,7 @@
#endif
#include <linux/dma-mapping.h>
#include <crypto/algapi.h>
#include <crypto/internal/skcipher.h>
#include <crypto/aes.h>
#include <crypto/sha.h>
#include <crypto/authenc.h>
@ -141,15 +142,44 @@ struct ssi_drvdata {
struct completion icache_setup_completion;
void *buff_mgr_handle;
void *hash_handle;
void *blkcipher_handle;
void *request_mgr_handle;
void *sram_mgr_handle;
#ifdef ENABLE_CYCLE_COUNT
cycles_t isr_exit_cycles; /* Save for isr-to-tasklet latency */
#endif
uint32_t inflight_counter;
};
struct ssi_crypto_alg {
struct list_head entry;
int cipher_mode;
int flow_mode; /* Note: currently, refers to the cipher mode only. */
int auth_mode;
struct ssi_drvdata *drvdata;
struct crypto_alg crypto_alg;
};
struct ssi_alg_template {
char name[CRYPTO_MAX_ALG_NAME];
char driver_name[CRYPTO_MAX_ALG_NAME];
unsigned int blocksize;
u32 type;
union {
struct ablkcipher_alg ablkcipher;
struct blkcipher_alg blkcipher;
struct cipher_alg cipher;
struct compress_alg compress;
} template_u;
int cipher_mode;
int flow_mode; /* Note: currently, refers to the cipher mode only. */
int auth_mode;
bool synchronous;
struct ssi_drvdata *drvdata;
};
struct async_gen_req_ctx {
dma_addr_t iv_dma_addr;
enum drv_crypto_direction op_type;