From 43d2c595b18cd98cfd3c59a57e6709ac9c5492f1 Mon Sep 17 00:00:00 2001 From: anjiahao Date: Fri, 11 Nov 2022 16:00:25 +0800 Subject: [PATCH] crypto:support crypto can handle streaming data in user space Use the flag (COP_FLAG_UPDATE)structure member to mark whether it is just input data. like this: can do manys times,just input data .... cryp.ses = session.ses; cryp.op = COP_ENCRYPT; cryp.src = (caddr_t) s; cryp.len = len; cryp.flags = COP_FLAG_UPDATE; cryp.dst = 0; cryp.mac = (caddr_t) out; cryp.iv = 0; if (ioctl(cryptodev_fd, CIOCCRYPT, &cryp) == -1) { warn("CIOCCRYPT"); goto err; } can do manys times like frist... then,the last time Don't use any flay structure member to mark this is last time,need get final result .... cryp.ses = session.ses; cryp.op = COP_ENCRYPT; cryp.src = (caddr_t) s; cryp.len = len; cryp.flags = 0; cryp.dst = 0; cryp.mac = (caddr_t) out; cryp.iv = 0; if (ioctl(cryptodev_fd, CIOCCRYPT, &cryp) == -1) { warn("CIOCCRYPT"); goto err; } .... that will get last result. Signed-off-by: anjiahao --- crypto/cryptodev.c | 24 +++++++++++++--- crypto/cryptosoft.c | 56 +++++++++++++++---------------------- include/crypto/cryptodev.h | 9 ++++++ include/crypto/cryptosoft.h | 3 ++ 4 files changed, 54 insertions(+), 38 deletions(-) diff --git a/crypto/cryptodev.c b/crypto/cryptodev.c index 778ec2aa2d..f5f0d783f3 100644 --- a/crypto/cryptodev.c +++ b/crypto/cryptodev.c @@ -452,6 +452,14 @@ int cryptodev_op(FAR struct csession *cse, crda->crd_alg = cse->mac; crda->crd_key = cse->mackey; crda->crd_klen = cse->mackeylen * 8; + if (cop->flags & COP_FLAG_UPDATE) + { + crda->crd_flags |= CRD_F_UPDATE; + } + else + { + crda->crd_flags &= ~CRD_F_UPDATE; + } } if (crde) @@ -485,10 +493,13 @@ int cryptodev_op(FAR struct csession *cse, goto bail; } - memcpy(cse->tmp_iv, cop->iv, cse->txform->blocksize); - bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize); - crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; - crde->crd_skip = 0; + if (!(crde->crd_flags & CRD_F_IV_EXPLICIT)) + { + memcpy(cse->tmp_iv, cop->iv, cse->txform->blocksize); + bcopy(cse->tmp_iv, crde->crd_iv, cse->txform->blocksize); + crde->crd_flags |= CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT; + crde->crd_skip = 0; + } } else if (crde) { @@ -553,6 +564,11 @@ dispatch: crypto_invoke(crp); processed: + if ((cop->flags & COP_FLAG_UPDATE) == 0) + { + crde->crd_flags &= ~CRD_F_IV_EXPLICIT; + } + if (cse->error) { error = cse->error; diff --git a/crypto/cryptosoft.c b/crypto/cryptosoft.c index 1d1817e4a9..2ad6671bf5 100644 --- a/crypto/cryptosoft.c +++ b/crypto/cryptosoft.c @@ -60,8 +60,8 @@ int swcr_id = -1; int swcr_encdec(FAR struct cryptop *crp, FAR struct cryptodesc *crd, FAR struct swcr_data *sw, caddr_t buf) { - unsigned char iv[EALG_MAX_BLOCK_LEN]; unsigned char blk[EALG_MAX_BLOCK_LEN]; + FAR unsigned char *iv; FAR unsigned char *ivp; FAR unsigned char *nivp; unsigned char iv2[EALG_MAX_BLOCK_LEN]; @@ -86,22 +86,12 @@ int swcr_encdec(FAR struct cryptop *crp, FAR struct cryptodesc *crd, if (crd->crd_flags & CRD_F_ENCRYPT) { - /* IV explicitly provided ? */ - - if (crd->crd_flags & CRD_F_IV_EXPLICIT) - { - bcopy(crd->crd_iv, iv, ivlen); - } - else - { - arc4random_buf(iv, ivlen); - } - /* Do we need to write the IV */ if (!(crd->crd_flags & CRD_F_IV_PRESENT)) { - bcopy(iv, buf + crd->crd_inject, ivlen); + arc4random_buf(crd->crd_iv, ivlen); + bcopy(crd->crd_iv, buf + crd->crd_inject, ivlen); } } else @@ -110,18 +100,15 @@ int swcr_encdec(FAR struct cryptop *crp, FAR struct cryptodesc *crd, /* IV explicitly provided ? */ - if (crd->crd_flags & CRD_F_IV_EXPLICIT) - { - bcopy(crd->crd_iv, iv, ivlen); - } - else + if (!(crd->crd_flags & CRD_F_IV_EXPLICIT)) { /* Get IV off buf */ - bcopy(iv, buf + crd->crd_inject, ivlen); + bcopy(crd->crd_iv, buf + crd->crd_inject, ivlen); } } + iv = crd->crd_iv; ivp = iv; /* xforms that provide a reinit method perform all IV @@ -135,6 +122,7 @@ int swcr_encdec(FAR struct cryptop *crp, FAR struct cryptodesc *crd, i = crd->crd_len; + buf = buf + crd->crd_skip; while (i > 0) { bcopy(buf, blk, exf->blocksize); @@ -215,8 +203,7 @@ int swcr_authcompute(FAR struct cryptop *crp, caddr_t buf) { unsigned char aalg[AALG_MAX_RESULT_LEN]; - FAR const struct auth_hash *axf; - union authctx ctx; + FAR const struct auth_hash *axf = sw->sw_axf; int err; if (sw->sw_ictx == 0) @@ -224,10 +211,9 @@ int swcr_authcompute(FAR struct cryptop *crp, return -EINVAL; } - axf = sw->sw_axf; + err = axf->update(&sw->sw_ctx, (FAR uint8_t *)buf + crd->crd_skip, + crd->crd_len); - bcopy(sw->sw_ictx, &ctx, axf->ctxsize); - err = axf->update(&ctx, (FAR uint8_t *)buf, crd->crd_len); if (err) { return err; @@ -235,7 +221,7 @@ int swcr_authcompute(FAR struct cryptop *crp, if (crd->crd_flags & CRD_F_ESN) { - axf->update(&ctx, crd->crd_esn, 4); + axf->update(&sw->sw_ctx, crd->crd_esn, 4); } switch (sw->sw_alg) @@ -251,18 +237,19 @@ int swcr_authcompute(FAR struct cryptop *crp, return -EINVAL; } - axf->final(aalg, &ctx); - bcopy(sw->sw_octx, &ctx, axf->ctxsize); - axf->update(&ctx, aalg, axf->hashsize); - axf->final(aalg, &ctx); + if (crd->crd_flags & CRD_F_UPDATE) + { + break; + } + + axf->final(aalg, &sw->sw_ctx); + bcopy(sw->sw_octx, &sw->sw_ctx, axf->ctxsize); + axf->update(&sw->sw_ctx, aalg, axf->hashsize); + axf->final((FAR uint8_t *)crp->crp_mac, &sw->sw_ctx); + bcopy(sw->sw_ictx, &sw->sw_ctx, axf->ctxsize); break; - default: - return -EINVAL; } - /* Inject the authentication data */ - - bcopy(aalg, crp->crp_mac, axf->hashsize); return 0; } @@ -746,6 +733,7 @@ int swcr_newsession(FAR uint32_t *sid, FAR struct cryptoini *cri) } (*swd)->sw_axf = axf; + bcopy((*swd)->sw_ictx, &(*swd)->sw_ctx, axf->ctxsize); break; case CRYPTO_AES_128_GMAC: diff --git a/include/crypto/cryptodev.h b/include/crypto/cryptodev.h index b61ecba96a..fe6ca1a3da 100644 --- a/include/crypto/cryptodev.h +++ b/include/crypto/cryptodev.h @@ -156,6 +156,7 @@ struct cryptodesc #define CRD_F_IV_EXPLICIT 0x04 /* IV explicitly provided */ #define CRD_F_COMP 0x10 /* Set when doing compression */ #define CRD_F_ESN 0x20 /* Set when ESN field is provided */ + #define CRD_F_UPDATE 0x40 /* Set just update source */ struct cryptoini CRD_INI; /* Initialization/context data */ #define crd_esn CRD_INI.cri_esn @@ -306,6 +307,14 @@ struct crypt_op uint16_t op; /* i.e. COP_ENCRYPT */ +#define COP_FLAG_UPDATE (1 << 0) /* Indicates that this operation is a + * stream operation. This operation will not get + * the final result of hash. If the iv is not equal, + * only the iv initialized for the first time will + * be used, and the subsequent iv will be saved + * in the driver. + */ + uint16_t flags; unsigned len; caddr_t src, dst; /* become iov[] inside kernel */ diff --git a/include/crypto/cryptosoft.h b/include/crypto/cryptosoft.h index ff7fa64f51..36aca9a838 100644 --- a/include/crypto/cryptosoft.h +++ b/include/crypto/cryptosoft.h @@ -32,6 +32,7 @@ #include #include +#include /* Software session entry */ @@ -46,6 +47,7 @@ struct swcr_data FAR uint8_t *octx; uint32_t klen; FAR const struct auth_hash *axf; + union authctx ctx; } SWCR_AUTH; struct @@ -65,6 +67,7 @@ struct swcr_data #define sw_octx SWCR_UN.SWCR_AUTH.octx #define sw_klen SWCR_UN.SWCR_AUTH.klen #define sw_axf SWCR_UN.SWCR_AUTH.axf +#define sw_ctx SWCR_UN.SWCR_AUTH.ctx #define sw_kschedule SWCR_UN.SWCR_ENC.kschedule #define sw_exf SWCR_UN.SWCR_ENC.exf #define sw_size SWCR_UN.SWCR_COMP.size