crypto: caam/qi2 - add support for Chacha20 + Poly1305
Add support for Chacha20 + Poly1305 combined AEAD: -generic (rfc7539) -IPsec (rfc7634 - known as rfc7539esp in the kernel) Signed-off-by: Horia Geantă <horia.geanta@nxp.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
d6bbd4eea2
commit
c10a533679
|
@ -527,13 +527,13 @@ static int chachapoly_set_sh_desc(struct crypto_aead *aead)
|
||||||
|
|
||||||
desc = ctx->sh_desc_enc;
|
desc = ctx->sh_desc_enc;
|
||||||
cnstr_shdsc_chachapoly(desc, &ctx->cdata, &ctx->adata, ivsize,
|
cnstr_shdsc_chachapoly(desc, &ctx->cdata, &ctx->adata, ivsize,
|
||||||
ctx->authsize, true);
|
ctx->authsize, true, false);
|
||||||
dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma,
|
dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma,
|
||||||
desc_bytes(desc), ctx->dir);
|
desc_bytes(desc), ctx->dir);
|
||||||
|
|
||||||
desc = ctx->sh_desc_dec;
|
desc = ctx->sh_desc_dec;
|
||||||
cnstr_shdsc_chachapoly(desc, &ctx->cdata, &ctx->adata, ivsize,
|
cnstr_shdsc_chachapoly(desc, &ctx->cdata, &ctx->adata, ivsize,
|
||||||
ctx->authsize, false);
|
ctx->authsize, false, false);
|
||||||
dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma,
|
dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma,
|
||||||
desc_bytes(desc), ctx->dir);
|
desc_bytes(desc), ctx->dir);
|
||||||
|
|
||||||
|
|
|
@ -1227,10 +1227,12 @@ EXPORT_SYMBOL(cnstr_shdsc_rfc4543_decap);
|
||||||
* @ivsize: initialization vector size
|
* @ivsize: initialization vector size
|
||||||
* @icvsize: integrity check value (ICV) size (truncated or full)
|
* @icvsize: integrity check value (ICV) size (truncated or full)
|
||||||
* @encap: true if encapsulation, false if decapsulation
|
* @encap: true if encapsulation, false if decapsulation
|
||||||
|
* @is_qi: true when called from caam/qi
|
||||||
*/
|
*/
|
||||||
void cnstr_shdsc_chachapoly(u32 * const desc, struct alginfo *cdata,
|
void cnstr_shdsc_chachapoly(u32 * const desc, struct alginfo *cdata,
|
||||||
struct alginfo *adata, unsigned int ivsize,
|
struct alginfo *adata, unsigned int ivsize,
|
||||||
unsigned int icvsize, const bool encap)
|
unsigned int icvsize, const bool encap,
|
||||||
|
const bool is_qi)
|
||||||
{
|
{
|
||||||
u32 *key_jump_cmd, *wait_cmd;
|
u32 *key_jump_cmd, *wait_cmd;
|
||||||
u32 nfifo;
|
u32 nfifo;
|
||||||
|
@ -1267,6 +1269,26 @@ void cnstr_shdsc_chachapoly(u32 * const desc, struct alginfo *cdata,
|
||||||
OP_ALG_DECRYPT);
|
OP_ALG_DECRYPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_qi) {
|
||||||
|
u32 *wait_load_cmd;
|
||||||
|
u32 ctx1_iv_off = is_ipsec ? 8 : 4;
|
||||||
|
|
||||||
|
/* REG3 = assoclen */
|
||||||
|
append_seq_load(desc, 4, LDST_CLASS_DECO |
|
||||||
|
LDST_SRCDST_WORD_DECO_MATH3 |
|
||||||
|
4 << LDST_OFFSET_SHIFT);
|
||||||
|
|
||||||
|
wait_load_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
|
||||||
|
JUMP_COND_CALM | JUMP_COND_NCP |
|
||||||
|
JUMP_COND_NOP | JUMP_COND_NIP |
|
||||||
|
JUMP_COND_NIFP);
|
||||||
|
set_jump_tgt_here(desc, wait_load_cmd);
|
||||||
|
|
||||||
|
append_seq_load(desc, ivsize, LDST_CLASS_1_CCB |
|
||||||
|
LDST_SRCDST_BYTE_CONTEXT |
|
||||||
|
ctx1_iv_off << LDST_OFFSET_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MAGIC with NFIFO
|
* MAGIC with NFIFO
|
||||||
* Read associated data from the input and send them to class1 and
|
* Read associated data from the input and send them to class1 and
|
||||||
|
|
|
@ -98,7 +98,8 @@ void cnstr_shdsc_rfc4543_decap(u32 * const desc, struct alginfo *cdata,
|
||||||
|
|
||||||
void cnstr_shdsc_chachapoly(u32 * const desc, struct alginfo *cdata,
|
void cnstr_shdsc_chachapoly(u32 * const desc, struct alginfo *cdata,
|
||||||
struct alginfo *adata, unsigned int ivsize,
|
struct alginfo *adata, unsigned int ivsize,
|
||||||
unsigned int icvsize, const bool encap);
|
unsigned int icvsize, const bool encap,
|
||||||
|
const bool is_qi);
|
||||||
|
|
||||||
void cnstr_shdsc_skcipher_encap(u32 * const desc, struct alginfo *cdata,
|
void cnstr_shdsc_skcipher_encap(u32 * const desc, struct alginfo *cdata,
|
||||||
unsigned int ivsize, const bool is_rfc3686,
|
unsigned int ivsize, const bool is_rfc3686,
|
||||||
|
|
|
@ -462,7 +462,15 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
|
||||||
edesc->dst_nents = dst_nents;
|
edesc->dst_nents = dst_nents;
|
||||||
edesc->iv_dma = iv_dma;
|
edesc->iv_dma = iv_dma;
|
||||||
|
|
||||||
edesc->assoclen = cpu_to_caam32(req->assoclen);
|
if ((alg->caam.class1_alg_type & OP_ALG_ALGSEL_MASK) ==
|
||||||
|
OP_ALG_ALGSEL_CHACHA20 && ivsize != CHACHAPOLY_IV_SIZE)
|
||||||
|
/*
|
||||||
|
* The associated data comes already with the IV but we need
|
||||||
|
* to skip it when we authenticate or encrypt...
|
||||||
|
*/
|
||||||
|
edesc->assoclen = cpu_to_caam32(req->assoclen - ivsize);
|
||||||
|
else
|
||||||
|
edesc->assoclen = cpu_to_caam32(req->assoclen);
|
||||||
edesc->assoclen_dma = dma_map_single(dev, &edesc->assoclen, 4,
|
edesc->assoclen_dma = dma_map_single(dev, &edesc->assoclen, 4,
|
||||||
DMA_TO_DEVICE);
|
DMA_TO_DEVICE);
|
||||||
if (dma_mapping_error(dev, edesc->assoclen_dma)) {
|
if (dma_mapping_error(dev, edesc->assoclen_dma)) {
|
||||||
|
@ -532,6 +540,68 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
|
||||||
return edesc;
|
return edesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int chachapoly_set_sh_desc(struct crypto_aead *aead)
|
||||||
|
{
|
||||||
|
struct caam_ctx *ctx = crypto_aead_ctx(aead);
|
||||||
|
unsigned int ivsize = crypto_aead_ivsize(aead);
|
||||||
|
struct device *dev = ctx->dev;
|
||||||
|
struct caam_flc *flc;
|
||||||
|
u32 *desc;
|
||||||
|
|
||||||
|
if (!ctx->cdata.keylen || !ctx->authsize)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
flc = &ctx->flc[ENCRYPT];
|
||||||
|
desc = flc->sh_desc;
|
||||||
|
cnstr_shdsc_chachapoly(desc, &ctx->cdata, &ctx->adata, ivsize,
|
||||||
|
ctx->authsize, true, true);
|
||||||
|
flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */
|
||||||
|
dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT],
|
||||||
|
sizeof(flc->flc) + desc_bytes(desc),
|
||||||
|
ctx->dir);
|
||||||
|
|
||||||
|
flc = &ctx->flc[DECRYPT];
|
||||||
|
desc = flc->sh_desc;
|
||||||
|
cnstr_shdsc_chachapoly(desc, &ctx->cdata, &ctx->adata, ivsize,
|
||||||
|
ctx->authsize, false, true);
|
||||||
|
flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */
|
||||||
|
dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT],
|
||||||
|
sizeof(flc->flc) + desc_bytes(desc),
|
||||||
|
ctx->dir);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int chachapoly_setauthsize(struct crypto_aead *aead,
|
||||||
|
unsigned int authsize)
|
||||||
|
{
|
||||||
|
struct caam_ctx *ctx = crypto_aead_ctx(aead);
|
||||||
|
|
||||||
|
if (authsize != POLY1305_DIGEST_SIZE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ctx->authsize = authsize;
|
||||||
|
return chachapoly_set_sh_desc(aead);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key,
|
||||||
|
unsigned int keylen)
|
||||||
|
{
|
||||||
|
struct caam_ctx *ctx = crypto_aead_ctx(aead);
|
||||||
|
unsigned int ivsize = crypto_aead_ivsize(aead);
|
||||||
|
unsigned int saltlen = CHACHAPOLY_IV_SIZE - ivsize;
|
||||||
|
|
||||||
|
if (keylen != CHACHA20_KEY_SIZE + saltlen) {
|
||||||
|
crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->cdata.key_virt = key;
|
||||||
|
ctx->cdata.keylen = keylen - saltlen;
|
||||||
|
|
||||||
|
return chachapoly_set_sh_desc(aead);
|
||||||
|
}
|
||||||
|
|
||||||
static int gcm_set_sh_desc(struct crypto_aead *aead)
|
static int gcm_set_sh_desc(struct crypto_aead *aead)
|
||||||
{
|
{
|
||||||
struct caam_ctx *ctx = crypto_aead_ctx(aead);
|
struct caam_ctx *ctx = crypto_aead_ctx(aead);
|
||||||
|
@ -2626,6 +2696,50 @@ static struct caam_aead_alg driver_aeads[] = {
|
||||||
.geniv = true,
|
.geniv = true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.aead = {
|
||||||
|
.base = {
|
||||||
|
.cra_name = "rfc7539(chacha20,poly1305)",
|
||||||
|
.cra_driver_name = "rfc7539-chacha20-poly1305-"
|
||||||
|
"caam-qi2",
|
||||||
|
.cra_blocksize = 1,
|
||||||
|
},
|
||||||
|
.setkey = chachapoly_setkey,
|
||||||
|
.setauthsize = chachapoly_setauthsize,
|
||||||
|
.encrypt = aead_encrypt,
|
||||||
|
.decrypt = aead_decrypt,
|
||||||
|
.ivsize = CHACHAPOLY_IV_SIZE,
|
||||||
|
.maxauthsize = POLY1305_DIGEST_SIZE,
|
||||||
|
},
|
||||||
|
.caam = {
|
||||||
|
.class1_alg_type = OP_ALG_ALGSEL_CHACHA20 |
|
||||||
|
OP_ALG_AAI_AEAD,
|
||||||
|
.class2_alg_type = OP_ALG_ALGSEL_POLY1305 |
|
||||||
|
OP_ALG_AAI_AEAD,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.aead = {
|
||||||
|
.base = {
|
||||||
|
.cra_name = "rfc7539esp(chacha20,poly1305)",
|
||||||
|
.cra_driver_name = "rfc7539esp-chacha20-"
|
||||||
|
"poly1305-caam-qi2",
|
||||||
|
.cra_blocksize = 1,
|
||||||
|
},
|
||||||
|
.setkey = chachapoly_setkey,
|
||||||
|
.setauthsize = chachapoly_setauthsize,
|
||||||
|
.encrypt = aead_encrypt,
|
||||||
|
.decrypt = aead_decrypt,
|
||||||
|
.ivsize = 8,
|
||||||
|
.maxauthsize = POLY1305_DIGEST_SIZE,
|
||||||
|
},
|
||||||
|
.caam = {
|
||||||
|
.class1_alg_type = OP_ALG_ALGSEL_CHACHA20 |
|
||||||
|
OP_ALG_AAI_AEAD,
|
||||||
|
.class2_alg_type = OP_ALG_ALGSEL_POLY1305 |
|
||||||
|
OP_ALG_AAI_AEAD,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.aead = {
|
.aead = {
|
||||||
.base = {
|
.base = {
|
||||||
|
@ -4963,11 +5077,22 @@ static int dpaa2_caam_probe(struct fsl_mc_device *dpseci_dev)
|
||||||
c1_alg_sel == OP_ALG_ALGSEL_AES)
|
c1_alg_sel == OP_ALG_ALGSEL_AES)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Skip CHACHA20 algorithms if not supported by device */
|
||||||
|
if (c1_alg_sel == OP_ALG_ALGSEL_CHACHA20 &&
|
||||||
|
!priv->sec_attr.ccha_acc_num)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Skip POLY1305 algorithms if not supported by device */
|
||||||
|
if (c2_alg_sel == OP_ALG_ALGSEL_POLY1305 &&
|
||||||
|
!priv->sec_attr.ptha_acc_num)
|
||||||
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip algorithms requiring message digests
|
* Skip algorithms requiring message digests
|
||||||
* if MD not supported by device.
|
* if MD not supported by device.
|
||||||
*/
|
*/
|
||||||
if (!priv->sec_attr.md_acc_num && c2_alg_sel)
|
if ((c2_alg_sel & ~OP_ALG_ALGSEL_SUBMASK) == 0x40 &&
|
||||||
|
!priv->sec_attr.md_acc_num)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
t_alg->caam.dev = dev;
|
t_alg->caam.dev = dev;
|
||||||
|
|
Loading…
Reference in New Issue