MLK-9971 Add XCBC-AES support for CAAM in i.MX6 family
Add XCBC-AES support to the CAAM crypto accelerator core in the i.MX6 family of SoC devices. Note that CAAM also goes by sec-4.0 or sec-5.0 in other product families (such as QorIQ). Thus the property names are often tied to the sec-4.0+ nomenclature. Signed-off-by: Winston Hudson (b45308) <winston.h.hudson@freescale.com> Signed-off-by: Dan Douglass <dan.douglass@freescale.com>
This commit is contained in:
committed by
Jason Liu
parent
0238df32d3
commit
eeb599a4ed
@ -62,6 +62,7 @@
|
||||
#include "error.h"
|
||||
#include "sg_sw_sec4.h"
|
||||
#include "key_gen.h"
|
||||
#include <linux/string.h>
|
||||
|
||||
#define CAAM_CRA_PRIORITY 3000
|
||||
|
||||
@ -111,6 +112,7 @@ struct caam_hash_ctx {
|
||||
u8 key[CAAM_MAX_HASH_KEY_SIZE];
|
||||
int ctx_len;
|
||||
struct alginfo adata;
|
||||
unsigned int key_len;
|
||||
};
|
||||
|
||||
/* ahash state */
|
||||
@ -234,6 +236,68 @@ static inline int ctx_map_to_sec4_sg(u32 *desc, struct device *jrdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void append_key_axcbc(u32 *desc, struct caam_hash_ctx *ctx)
|
||||
{
|
||||
append_key_as_imm(desc, ctx->key, ctx->key_len,
|
||||
ctx->key_len, CLASS_1 |
|
||||
KEY_DEST_CLASS_REG);
|
||||
}
|
||||
|
||||
static inline void init_sh_desc_key_axcbc(u32 *desc, struct caam_hash_ctx *ctx)
|
||||
{
|
||||
u32 *key_jump_cmd;
|
||||
|
||||
init_sh_desc(desc, HDR_SHARE_SERIAL);
|
||||
|
||||
if (ctx->key_len) {
|
||||
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
||||
JUMP_COND_SHRD);
|
||||
|
||||
append_key_axcbc(desc, ctx);
|
||||
|
||||
set_jump_tgt_here(desc, key_jump_cmd);
|
||||
}
|
||||
|
||||
/* Propagate errors from shared to job descriptor */
|
||||
append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
|
||||
}
|
||||
|
||||
static inline void axcbc_append_load_str(u32 *desc, int digestsize)
|
||||
{
|
||||
/* Calculate remaining bytes to read */
|
||||
append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
|
||||
|
||||
/* Read remaining bytes */
|
||||
append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_LAST1 |
|
||||
FIFOLD_TYPE_MSG | KEY_VLF);
|
||||
|
||||
/* Store class1 context bytes */
|
||||
append_seq_store(desc, digestsize, LDST_CLASS_1_CCB |
|
||||
LDST_SRCDST_BYTE_CONTEXT);
|
||||
}
|
||||
|
||||
/*
|
||||
* For ahash update, final and finup, import context, read and write to seqout
|
||||
*/
|
||||
static inline void axcbc_ctx_data_to_out(u32 *desc, u32 op, u32 state,
|
||||
int digestsize,
|
||||
struct caam_hash_ctx *ctx)
|
||||
{
|
||||
init_sh_desc_key_axcbc(desc, ctx);
|
||||
|
||||
/* Import context from software */
|
||||
append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
|
||||
LDST_CLASS_1_CCB | ctx->ctx_len);
|
||||
|
||||
/* Class 1 operation */
|
||||
append_operation(desc, op | state | OP_ALG_ENCRYPT);
|
||||
|
||||
/*
|
||||
* Load from buf and/or src and write to req->result or state->context
|
||||
*/
|
||||
axcbc_append_load_str(desc, digestsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* For ahash update, final and finup (import_ctx = true)
|
||||
* import context, read and write to seqout
|
||||
@ -284,6 +348,21 @@ static inline void ahash_gen_sh_desc(u32 *desc, u32 state, int digestsize,
|
||||
LDST_SRCDST_BYTE_CONTEXT);
|
||||
}
|
||||
|
||||
/* For ahash firsts and digest, read and write to seqout */
|
||||
static inline void axcbc_data_to_out(u32 *desc, u32 op, u32 state,
|
||||
int digestsize, struct caam_hash_ctx *ctx)
|
||||
{
|
||||
init_sh_desc_key_axcbc(desc, ctx);
|
||||
|
||||
/* Class 1 operation */
|
||||
append_operation(desc, op | state | OP_ALG_ENCRYPT);
|
||||
|
||||
/*
|
||||
* Load from buf and/or src and write to req->result or state->context
|
||||
*/
|
||||
axcbc_append_load_str(desc, digestsize);
|
||||
}
|
||||
|
||||
static int ahash_set_sh_desc(struct crypto_ahash *ahash)
|
||||
{
|
||||
struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
|
||||
@ -339,6 +418,125 @@ static int ahash_set_sh_desc(struct crypto_ahash *ahash)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int axcbc_set_sh_desc(struct crypto_ahash *ahash)
|
||||
{
|
||||
struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
|
||||
int digestsize = crypto_ahash_digestsize(ahash);
|
||||
struct device *jrdev = ctx->jrdev;
|
||||
u32 have_key = 0;
|
||||
u32 *desc;
|
||||
|
||||
/* ahash_update shared descriptor */
|
||||
desc = ctx->sh_desc_update;
|
||||
|
||||
init_sh_desc(desc, HDR_SHARE_SERIAL);
|
||||
|
||||
/* Import context from software */
|
||||
append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
|
||||
LDST_CLASS_1_CCB | ctx->ctx_len);
|
||||
|
||||
/* Class 1 operation */
|
||||
append_operation(desc, ctx->adata.algtype | OP_ALG_AS_UPDATE |
|
||||
OP_ALG_ENCRYPT);
|
||||
|
||||
/* Load data and write to result or context */
|
||||
axcbc_append_load_str(desc, ctx->ctx_len);
|
||||
|
||||
ctx->sh_desc_update_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(jrdev, ctx->sh_desc_update_dma)) {
|
||||
dev_err(jrdev, "unable to map shared descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
print_hex_dump(KERN_ERR, "ahash update shdesc@"__stringify(__LINE__)": ",
|
||||
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
||||
#endif
|
||||
|
||||
/* ahash_update_first shared descriptor */
|
||||
desc = ctx->sh_desc_update_first;
|
||||
|
||||
axcbc_data_to_out(desc, have_key | ctx->adata.algtype, OP_ALG_AS_INIT,
|
||||
ctx->ctx_len, ctx);
|
||||
|
||||
ctx->sh_desc_update_first_dma = dma_map_single(jrdev, desc,
|
||||
desc_bytes(desc),
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(jrdev, ctx->sh_desc_update_first_dma)) {
|
||||
dev_err(jrdev, "unable to map shared descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
print_hex_dump(KERN_ERR, "ahash update first shdesc@"__stringify(__LINE__)": ",
|
||||
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
|
||||
#endif
|
||||
dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
|
||||
desc_bytes(desc), DMA_TO_DEVICE);
|
||||
|
||||
/* ahash_final shared descriptor */
|
||||
desc = ctx->sh_desc_fin;
|
||||
|
||||
axcbc_ctx_data_to_out(desc, have_key | ctx->adata.algtype,
|
||||
OP_ALG_AS_FINALIZE, digestsize, ctx);
|
||||
|
||||
ctx->sh_desc_fin_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(jrdev, ctx->sh_desc_fin_dma)) {
|
||||
dev_err(jrdev, "unable to map shared descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
print_hex_dump(KERN_ERR, "ahash final shdesc@"__stringify(__LINE__)": ",
|
||||
DUMP_PREFIX_ADDRESS, 16, 4, desc,
|
||||
desc_bytes(desc), 1);
|
||||
#endif
|
||||
dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
|
||||
desc_bytes(desc), DMA_TO_DEVICE);
|
||||
|
||||
/* ahash_finup shared descriptor */
|
||||
desc = ctx->sh_desc_fin;
|
||||
|
||||
axcbc_ctx_data_to_out(desc, have_key | ctx->adata.algtype,
|
||||
OP_ALG_AS_FINALIZE, digestsize, ctx);
|
||||
|
||||
ctx->sh_desc_fin_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(jrdev, ctx->sh_desc_fin_dma)) {
|
||||
dev_err(jrdev, "unable to map shared descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
print_hex_dump(KERN_ERR, "ahash finup shdesc@"__stringify(__LINE__)": ",
|
||||
DUMP_PREFIX_ADDRESS, 16, 4, desc,
|
||||
desc_bytes(desc), 1);
|
||||
#endif
|
||||
dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
|
||||
desc_bytes(desc), DMA_TO_DEVICE);
|
||||
|
||||
/* ahash_digest shared descriptor */
|
||||
desc = ctx->sh_desc_digest;
|
||||
|
||||
axcbc_data_to_out(desc, have_key | ctx->adata.algtype, OP_ALG_AS_INITFINAL,
|
||||
digestsize, ctx);
|
||||
|
||||
ctx->sh_desc_digest_dma = dma_map_single(jrdev, desc,
|
||||
desc_bytes(desc),
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(jrdev, ctx->sh_desc_digest_dma)) {
|
||||
dev_err(jrdev, "unable to map shared descriptor\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
print_hex_dump(KERN_ERR, "ahash digest shdesc@"__stringify(__LINE__)": ",
|
||||
DUMP_PREFIX_ADDRESS, 16, 4, desc,
|
||||
desc_bytes(desc), 1);
|
||||
#endif
|
||||
dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
|
||||
desc_bytes(desc), DMA_TO_DEVICE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Digest hash size if it is too large */
|
||||
static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
|
||||
u32 *keylen, u8 *key_out, u32 digestsize)
|
||||
@ -460,6 +658,25 @@ static int ahash_setkey(struct crypto_ahash *ahash,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int axcbc_setkey(struct crypto_ahash *ahash,
|
||||
const u8 *key, unsigned int keylen)
|
||||
{
|
||||
struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
|
||||
int ret = 0;
|
||||
|
||||
ctx->key_len = keylen;
|
||||
memcpy(ctx->key, key, keylen);
|
||||
|
||||
#ifdef DEBUG
|
||||
print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ",
|
||||
DUMP_PREFIX_ADDRESS, 16, 4, ctx->key,
|
||||
ctx->key_len, 1);
|
||||
#endif
|
||||
|
||||
ret = axcbc_set_sh_desc(ahash);
|
||||
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* ahash_edesc - s/w-extended ahash descriptor
|
||||
* @dst_dma: physical mapped address of req->result
|
||||
@ -1692,6 +1909,27 @@ static struct caam_hash_template driver_hash[] = {
|
||||
},
|
||||
.alg_type = OP_ALG_ALGSEL_MD5,
|
||||
},
|
||||
{
|
||||
.name = "xcbc(aes)",
|
||||
.driver_name = "xcbc-aes-caam",
|
||||
.hmac_name = "xcbc(aes)",
|
||||
.hmac_driver_name = "xcbc-aes-caam",
|
||||
.blocksize = XCBC_MAC_BLOCK_WORDS * 4,
|
||||
.template_ahash = {
|
||||
.init = ahash_init,
|
||||
.update = ahash_update,
|
||||
.final = ahash_final,
|
||||
.finup = ahash_finup,
|
||||
.digest = ahash_digest,
|
||||
.export = ahash_export,
|
||||
.import = ahash_import,
|
||||
.setkey = axcbc_setkey,
|
||||
.halg = {
|
||||
.digestsize = XCBC_MAC_DIGEST_SIZE,
|
||||
},
|
||||
},
|
||||
.alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_XCBC_MAC,
|
||||
},
|
||||
};
|
||||
|
||||
struct caam_hash_alg {
|
||||
@ -1761,6 +1999,40 @@ static int caam_hash_cra_init(struct crypto_tfm *tfm)
|
||||
return ahash_set_sh_desc(ahash);
|
||||
}
|
||||
|
||||
static int caam_axcbc_cra_init(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
|
||||
struct crypto_alg *base = tfm->__crt_alg;
|
||||
struct hash_alg_common *halg =
|
||||
container_of(base, struct hash_alg_common, base);
|
||||
struct ahash_alg *alg =
|
||||
container_of(halg, struct ahash_alg, halg);
|
||||
struct caam_hash_alg *caam_hash =
|
||||
container_of(alg, struct caam_hash_alg, ahash_alg);
|
||||
struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* Get a Job ring from Job Ring driver to ensure in-order
|
||||
* crypto request processing per tfm
|
||||
*/
|
||||
ctx->jrdev = caam_jr_alloc();
|
||||
if (IS_ERR(ctx->jrdev)) {
|
||||
pr_err("Job Ring Device allocation for transform failed\n");
|
||||
return PTR_ERR(ctx->jrdev);
|
||||
}
|
||||
|
||||
/* copy descriptor header template value */
|
||||
ctx->adata.algtype = OP_TYPE_CLASS1_ALG | caam_hash->alg_type;
|
||||
|
||||
crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
|
||||
sizeof(struct caam_hash_state));
|
||||
|
||||
ret = axcbc_set_sh_desc(ahash);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void caam_hash_cra_exit(struct crypto_tfm *tfm)
|
||||
{
|
||||
struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
@ -1817,7 +2089,11 @@ caam_hash_alloc(struct caam_hash_template *template,
|
||||
t_alg->ahash_alg.setkey = NULL;
|
||||
}
|
||||
alg->cra_module = THIS_MODULE;
|
||||
alg->cra_init = caam_hash_cra_init;
|
||||
|
||||
if (strstr(alg->cra_name, "xcbc") > 0)
|
||||
alg->cra_init = caam_axcbc_cra_init;
|
||||
else
|
||||
alg->cra_init = caam_hash_cra_init;
|
||||
alg->cra_exit = caam_hash_cra_exit;
|
||||
alg->cra_ctxsize = sizeof(struct caam_hash_ctx);
|
||||
alg->cra_priority = CAAM_CRA_PRIORITY;
|
||||
|
||||
@ -1649,4 +1649,8 @@
|
||||
#define ARC4_MAX_KEY_SIZE 256
|
||||
#define ARC4_MIN_KEY_SIZE 1
|
||||
|
||||
#define XCBC_MAC_DIGEST_SIZE 16
|
||||
#define XCBC_MAC_BLOCK_WORDS 16
|
||||
|
||||
|
||||
#endif /* DESC_H */
|
||||
|
||||
Reference in New Issue
Block a user