Skip to content

Commit d6bbd4e

Browse files
horiagherbertx
authored andcommitted
crypto: caam/jr - 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: Cristian Stoica <cristian.stoica@nxp.com> Signed-off-by: Horia Geantă <horia.geanta@nxp.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent 193188e commit d6bbd4e

File tree

6 files changed

+354
-5
lines changed

6 files changed

+354
-5
lines changed

drivers/crypto/caam/caamalg.c

Lines changed: 217 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@
7272
#define AUTHENC_DESC_JOB_IO_LEN (AEAD_DESC_JOB_IO_LEN + \
7373
CAAM_CMD_SZ * 5)
7474

75+
#define CHACHAPOLY_DESC_JOB_IO_LEN (AEAD_DESC_JOB_IO_LEN + CAAM_CMD_SZ * 6)
76+
7577
#define DESC_MAX_USED_BYTES (CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN)
7678
#define DESC_MAX_USED_LEN (DESC_MAX_USED_BYTES / CAAM_CMD_SZ)
7779

@@ -513,6 +515,61 @@ static int rfc4543_setauthsize(struct crypto_aead *authenc,
513515
return 0;
514516
}
515517

518+
static int chachapoly_set_sh_desc(struct crypto_aead *aead)
519+
{
520+
struct caam_ctx *ctx = crypto_aead_ctx(aead);
521+
struct device *jrdev = ctx->jrdev;
522+
unsigned int ivsize = crypto_aead_ivsize(aead);
523+
u32 *desc;
524+
525+
if (!ctx->cdata.keylen || !ctx->authsize)
526+
return 0;
527+
528+
desc = ctx->sh_desc_enc;
529+
cnstr_shdsc_chachapoly(desc, &ctx->cdata, &ctx->adata, ivsize,
530+
ctx->authsize, true);
531+
dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma,
532+
desc_bytes(desc), ctx->dir);
533+
534+
desc = ctx->sh_desc_dec;
535+
cnstr_shdsc_chachapoly(desc, &ctx->cdata, &ctx->adata, ivsize,
536+
ctx->authsize, false);
537+
dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma,
538+
desc_bytes(desc), ctx->dir);
539+
540+
return 0;
541+
}
542+
543+
static int chachapoly_setauthsize(struct crypto_aead *aead,
544+
unsigned int authsize)
545+
{
546+
struct caam_ctx *ctx = crypto_aead_ctx(aead);
547+
548+
if (authsize != POLY1305_DIGEST_SIZE)
549+
return -EINVAL;
550+
551+
ctx->authsize = authsize;
552+
return chachapoly_set_sh_desc(aead);
553+
}
554+
555+
static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key,
556+
unsigned int keylen)
557+
{
558+
struct caam_ctx *ctx = crypto_aead_ctx(aead);
559+
unsigned int ivsize = crypto_aead_ivsize(aead);
560+
unsigned int saltlen = CHACHAPOLY_IV_SIZE - ivsize;
561+
562+
if (keylen != CHACHA20_KEY_SIZE + saltlen) {
563+
crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN);
564+
return -EINVAL;
565+
}
566+
567+
ctx->cdata.key_virt = key;
568+
ctx->cdata.keylen = keylen - saltlen;
569+
570+
return chachapoly_set_sh_desc(aead);
571+
}
572+
516573
static int aead_setkey(struct crypto_aead *aead,
517574
const u8 *key, unsigned int keylen)
518575
{
@@ -1031,6 +1088,40 @@ static void init_gcm_job(struct aead_request *req,
10311088
/* End of blank commands */
10321089
}
10331090

1091+
static void init_chachapoly_job(struct aead_request *req,
1092+
struct aead_edesc *edesc, bool all_contig,
1093+
bool encrypt)
1094+
{
1095+
struct crypto_aead *aead = crypto_aead_reqtfm(req);
1096+
unsigned int ivsize = crypto_aead_ivsize(aead);
1097+
unsigned int assoclen = req->assoclen;
1098+
u32 *desc = edesc->hw_desc;
1099+
u32 ctx_iv_off = 4;
1100+
1101+
init_aead_job(req, edesc, all_contig, encrypt);
1102+
1103+
if (ivsize != CHACHAPOLY_IV_SIZE) {
1104+
/* IPsec specific: CONTEXT1[223:128] = {NONCE, IV} */
1105+
ctx_iv_off += 4;
1106+
1107+
/*
1108+
* The associated data comes already with the IV but we need
1109+
* to skip it when we authenticate or encrypt...
1110+
*/
1111+
assoclen -= ivsize;
1112+
}
1113+
1114+
append_math_add_imm_u32(desc, REG3, ZERO, IMM, assoclen);
1115+
1116+
/*
1117+
* For IPsec load the IV further in the same register.
1118+
* For RFC7539 simply load the 12 bytes nonce in a single operation
1119+
*/
1120+
append_load_as_imm(desc, req->iv, ivsize, LDST_CLASS_1_CCB |
1121+
LDST_SRCDST_BYTE_CONTEXT |
1122+
ctx_iv_off << LDST_OFFSET_SHIFT);
1123+
}
1124+
10341125
static void init_authenc_job(struct aead_request *req,
10351126
struct aead_edesc *edesc,
10361127
bool all_contig, bool encrypt)
@@ -1289,6 +1380,72 @@ static int gcm_encrypt(struct aead_request *req)
12891380
return ret;
12901381
}
12911382

1383+
static int chachapoly_encrypt(struct aead_request *req)
1384+
{
1385+
struct aead_edesc *edesc;
1386+
struct crypto_aead *aead = crypto_aead_reqtfm(req);
1387+
struct caam_ctx *ctx = crypto_aead_ctx(aead);
1388+
struct device *jrdev = ctx->jrdev;
1389+
bool all_contig;
1390+
u32 *desc;
1391+
int ret;
1392+
1393+
edesc = aead_edesc_alloc(req, CHACHAPOLY_DESC_JOB_IO_LEN, &all_contig,
1394+
true);
1395+
if (IS_ERR(edesc))
1396+
return PTR_ERR(edesc);
1397+
1398+
desc = edesc->hw_desc;
1399+
1400+
init_chachapoly_job(req, edesc, all_contig, true);
1401+
print_hex_dump_debug("chachapoly jobdesc@" __stringify(__LINE__)": ",
1402+
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
1403+
1);
1404+
1405+
ret = caam_jr_enqueue(jrdev, desc, aead_encrypt_done, req);
1406+
if (!ret) {
1407+
ret = -EINPROGRESS;
1408+
} else {
1409+
aead_unmap(jrdev, edesc, req);
1410+
kfree(edesc);
1411+
}
1412+
1413+
return ret;
1414+
}
1415+
1416+
static int chachapoly_decrypt(struct aead_request *req)
1417+
{
1418+
struct aead_edesc *edesc;
1419+
struct crypto_aead *aead = crypto_aead_reqtfm(req);
1420+
struct caam_ctx *ctx = crypto_aead_ctx(aead);
1421+
struct device *jrdev = ctx->jrdev;
1422+
bool all_contig;
1423+
u32 *desc;
1424+
int ret;
1425+
1426+
edesc = aead_edesc_alloc(req, CHACHAPOLY_DESC_JOB_IO_LEN, &all_contig,
1427+
false);
1428+
if (IS_ERR(edesc))
1429+
return PTR_ERR(edesc);
1430+
1431+
desc = edesc->hw_desc;
1432+
1433+
init_chachapoly_job(req, edesc, all_contig, false);
1434+
print_hex_dump_debug("chachapoly jobdesc@" __stringify(__LINE__)": ",
1435+
DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc),
1436+
1);
1437+
1438+
ret = caam_jr_enqueue(jrdev, desc, aead_decrypt_done, req);
1439+
if (!ret) {
1440+
ret = -EINPROGRESS;
1441+
} else {
1442+
aead_unmap(jrdev, edesc, req);
1443+
kfree(edesc);
1444+
}
1445+
1446+
return ret;
1447+
}
1448+
12921449
static int ipsec_gcm_encrypt(struct aead_request *req)
12931450
{
12941451
if (req->assoclen < 8)
@@ -3002,6 +3159,50 @@ static struct caam_aead_alg driver_aeads[] = {
30023159
.geniv = true,
30033160
},
30043161
},
3162+
{
3163+
.aead = {
3164+
.base = {
3165+
.cra_name = "rfc7539(chacha20,poly1305)",
3166+
.cra_driver_name = "rfc7539-chacha20-poly1305-"
3167+
"caam",
3168+
.cra_blocksize = 1,
3169+
},
3170+
.setkey = chachapoly_setkey,
3171+
.setauthsize = chachapoly_setauthsize,
3172+
.encrypt = chachapoly_encrypt,
3173+
.decrypt = chachapoly_decrypt,
3174+
.ivsize = CHACHAPOLY_IV_SIZE,
3175+
.maxauthsize = POLY1305_DIGEST_SIZE,
3176+
},
3177+
.caam = {
3178+
.class1_alg_type = OP_ALG_ALGSEL_CHACHA20 |
3179+
OP_ALG_AAI_AEAD,
3180+
.class2_alg_type = OP_ALG_ALGSEL_POLY1305 |
3181+
OP_ALG_AAI_AEAD,
3182+
},
3183+
},
3184+
{
3185+
.aead = {
3186+
.base = {
3187+
.cra_name = "rfc7539esp(chacha20,poly1305)",
3188+
.cra_driver_name = "rfc7539esp-chacha20-"
3189+
"poly1305-caam",
3190+
.cra_blocksize = 1,
3191+
},
3192+
.setkey = chachapoly_setkey,
3193+
.setauthsize = chachapoly_setauthsize,
3194+
.encrypt = chachapoly_encrypt,
3195+
.decrypt = chachapoly_decrypt,
3196+
.ivsize = 8,
3197+
.maxauthsize = POLY1305_DIGEST_SIZE,
3198+
},
3199+
.caam = {
3200+
.class1_alg_type = OP_ALG_ALGSEL_CHACHA20 |
3201+
OP_ALG_AAI_AEAD,
3202+
.class2_alg_type = OP_ALG_ALGSEL_POLY1305 |
3203+
OP_ALG_AAI_AEAD,
3204+
},
3205+
},
30053206
};
30063207

30073208
static int caam_init_common(struct caam_ctx *ctx, struct caam_alg_entry *caam,
@@ -3135,7 +3336,7 @@ static int __init caam_algapi_init(void)
31353336
struct device *ctrldev;
31363337
struct caam_drv_private *priv;
31373338
int i = 0, err = 0;
3138-
u32 aes_vid, aes_inst, des_inst, md_vid, md_inst;
3339+
u32 aes_vid, aes_inst, des_inst, md_vid, md_inst, ccha_inst, ptha_inst;
31393340
unsigned int md_limit = SHA512_DIGEST_SIZE;
31403341
bool registered = false;
31413342

@@ -3180,6 +3381,8 @@ static int __init caam_algapi_init(void)
31803381
CHA_ID_LS_DES_SHIFT;
31813382
aes_inst = cha_inst & CHA_ID_LS_AES_MASK;
31823383
md_inst = (cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT;
3384+
ccha_inst = 0;
3385+
ptha_inst = 0;
31833386
} else {
31843387
u32 aesa, mdha;
31853388

@@ -3192,6 +3395,8 @@ static int __init caam_algapi_init(void)
31923395
des_inst = rd_reg32(&priv->ctrl->vreg.desa) & CHA_VER_NUM_MASK;
31933396
aes_inst = aesa & CHA_VER_NUM_MASK;
31943397
md_inst = mdha & CHA_VER_NUM_MASK;
3398+
ccha_inst = rd_reg32(&priv->ctrl->vreg.ccha) & CHA_VER_NUM_MASK;
3399+
ptha_inst = rd_reg32(&priv->ctrl->vreg.ptha) & CHA_VER_NUM_MASK;
31953400
}
31963401

31973402
/* If MD is present, limit digest size based on LP256 */
@@ -3252,6 +3457,14 @@ static int __init caam_algapi_init(void)
32523457
if (!aes_inst && (c1_alg_sel == OP_ALG_ALGSEL_AES))
32533458
continue;
32543459

3460+
/* Skip CHACHA20 algorithms if not supported by device */
3461+
if (c1_alg_sel == OP_ALG_ALGSEL_CHACHA20 && !ccha_inst)
3462+
continue;
3463+
3464+
/* Skip POLY1305 algorithms if not supported by device */
3465+
if (c2_alg_sel == OP_ALG_ALGSEL_POLY1305 && !ptha_inst)
3466+
continue;
3467+
32553468
/*
32563469
* Check support for AES algorithms not available
32573470
* on LP devices.
@@ -3263,9 +3476,9 @@ static int __init caam_algapi_init(void)
32633476
* Skip algorithms requiring message digests
32643477
* if MD or MD size is not supported by device.
32653478
*/
3266-
if (c2_alg_sel &&
3267-
(!md_inst || (t_alg->aead.maxauthsize > md_limit)))
3268-
continue;
3479+
if ((c2_alg_sel & ~OP_ALG_ALGSEL_SUBMASK) == 0x40 &&
3480+
(!md_inst || t_alg->aead.maxauthsize > md_limit))
3481+
continue;
32693482

32703483
caam_aead_alg_init(t_alg);
32713484

0 commit comments

Comments
 (0)