From 2febfb8fba8728d31e5a1b6728e95da773395e16 Mon Sep 17 00:00:00 2001 From: makejian Date: Mon, 19 Aug 2024 15:20:10 +0800 Subject: [PATCH] nuttx/crypto: export asynchronous calling process Signed-off-by: makejian --- crypto/cryptodev.c | 198 ++++++++++++++++++++++++++++++------- include/crypto/cryptodev.h | 14 ++- 2 files changed, 173 insertions(+), 39 deletions(-) diff --git a/crypto/cryptodev.c b/crypto/cryptodev.c index 2e6adcf09e71b..310aae8be87cb 100644 --- a/crypto/cryptodev.c +++ b/crypto/cryptodev.c @@ -36,7 +36,6 @@ #include #include -#include #include #include #include @@ -94,7 +93,9 @@ struct csession struct fcrypt { TAILQ_HEAD(csessionlist, csession) csessions; + TAILQ_HEAD(cryptkoplist, cryptkop) crpk_ret; int sesn; + FAR struct pollfd *fds; }; /**************************************************************************** @@ -122,6 +123,23 @@ static ssize_t cryptowrite(FAR struct file *filep, static int cryptoclose(FAR struct file *filep); static int cryptoioctl(FAR struct file *filep, int cmd, unsigned long arg); +static FAR struct csession *csefind(FAR struct fcrypt *, u_int); +static int csedelete(FAR struct fcrypt *, FAR struct csession *); +static FAR struct csession *cseadd(FAR struct fcrypt *, + FAR struct csession *); +static FAR struct csession *csecreate(FAR struct fcrypt *, uint64_t, + caddr_t, uint64_t, + caddr_t, uint64_t, uint32_t, + uint32_t, bool, bool); +static int csefree(FAR struct csession *); + +static int cryptodev_op(FAR struct csession *, + FAR struct crypt_op *); +static int cryptodev_key(FAR struct fcrypt *, FAR struct crypt_kop *); +static int cryptodevkey_cb(FAR struct cryptkop *); +static int cryptodev_getkeystatus(FAR struct fcrypt *, + FAR struct crypt_kop *); + /**************************************************************************** * Private Data ****************************************************************************/ @@ -154,6 +172,7 @@ static const struct file_operations g_cryptoops = static struct inode g_cryptoinode = { + .i_flags = FSNODEFLAG_TYPE_DRIVER, .i_crefs = 1, .u.i_ops = &g_cryptofops }; @@ -162,23 +181,6 @@ static struct inode g_cryptoinode = * Private Functions ****************************************************************************/ -FAR struct csession *csefind(FAR struct fcrypt *, u_int); -int csedelete(FAR struct fcrypt *, FAR struct csession *); -FAR struct csession *cseadd(FAR struct fcrypt *, FAR struct csession *); -FAR struct csession *csecreate(FAR struct fcrypt *, uint64_t, - caddr_t, uint64_t, - caddr_t, uint64_t, uint32_t, - uint32_t, bool, bool); -int csefree(FAR struct csession *); - -int cryptodev_op(FAR struct csession *, - FAR struct crypt_op *); -int cryptodev_key(FAR struct crypt_kop *); -int cryptodev_dokey(FAR struct crypt_kop *kop, FAR struct crparam *kvp); - -int cryptodev_cb(FAR struct cryptop *); -int cryptodevkey_cb(FAR struct cryptkop *); - /* ARGSUSED */ static ssize_t cryptof_read(FAR struct file *filep, @@ -365,7 +367,10 @@ static int cryptof_ioctl(FAR struct file *filep, error = cryptodev_op(cse, cop); break; case CIOCKEY: - error = cryptodev_key((FAR struct crypt_kop *)arg); + error = cryptodev_key(fcr, (FAR struct crypt_kop *)arg); + break; + case CIOCKEYRET: + error = cryptodev_getkeystatus(fcr, (FAR struct crypt_kop *)arg); break; case CIOCASYMFEAT: error = crypto_getfeat((FAR int *)arg); @@ -377,8 +382,8 @@ static int cryptof_ioctl(FAR struct file *filep, return error; } -int cryptodev_op(FAR struct csession *cse, - FAR struct crypt_op *cop) +static int cryptodev_op(FAR struct csession *cse, + FAR struct crypt_op *cop) { FAR struct cryptop *crp = NULL; FAR struct cryptodesc *crde = NULL; @@ -549,7 +554,7 @@ int cryptodev_op(FAR struct csession *cse, return error; } -int cryptodev_key(FAR struct crypt_kop *kop) +static int cryptodev_key(FAR struct fcrypt *fcr, FAR struct crypt_kop *kop) { FAR struct cryptkop *krp = NULL; int error = -EINVAL; @@ -642,11 +647,19 @@ int cryptodev_key(FAR struct crypt_kop *kop) } krp = kmm_zalloc(sizeof *krp); + if (krp == NULL) + { + return -ENOMEM; + } + krp->krp_op = kop->crk_op; - krp->krp_status = kop->crk_status; krp->krp_iparams = kop->crk_iparams; krp->krp_oparams = kop->crk_oparams; krp->krp_status = 0; + krp->krp_flags = kop->crk_flags; + krp->krp_reqid = kop->crk_reqid; + krp->krp_fcr = fcr; + krp->krp_callback = cryptodevkey_cb; for (i = 0; i < CRK_MAXPARAM; i++) { @@ -720,12 +733,100 @@ int cryptodev_key(FAR struct crypt_kop *kop) return error; } +static int cryptodevkey_cb(FAR struct cryptkop *krp) +{ + TAILQ_INSERT_TAIL(&krp->krp_fcr->crpk_ret, krp, krp_next); + if (krp->krp_fcr->fds != NULL) + { + poll_notify(&krp->krp_fcr->fds, 1, POLLIN); + } + + return OK; +} + +static int cryptodev_getkeystatus(struct fcrypt *fcr, struct crypt_kop *ret) +{ + FAR struct cryptkop *krp = NULL; + int i; + int size; + + if (TAILQ_EMPTY(&fcr->crpk_ret)) + { + return -EAGAIN; + } + + /* return the result in task list to the upper layer */ + + krp = TAILQ_FIRST(&fcr->crpk_ret); + TAILQ_REMOVE(&fcr->crpk_ret, krp, krp_next); + + ret->crk_op = krp->krp_op; + ret->crk_status = krp->krp_status; + ret->crk_iparams = krp->krp_iparams; + ret->crk_oparams = krp->krp_oparams; + for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) + { + size = (krp->krp_param[i].crp_nbits + 7) / 8; + + /* copy result into oparams */ + + if (i < ret->crk_iparams || size == 0) + { + continue; + } + + memcpy(ret->crk_param[i].crp_p, krp->krp_param[i].crp_p, size); + } + + /* free asynchronous result */ + + for (i = 0; i < CRK_MAXPARAM; i++) + { + if (krp->krp_param[i].crp_p) + { + explicit_bzero(krp->krp_param[i].crp_p, + (krp->krp_param[i].crp_nbits + 7) / 8); + kmm_free(krp->krp_param[i].crp_p); + } + } + + kmm_free(krp); + return OK; +} + /* ARGSUSED */ static int cryptof_poll(FAR struct file *filep, FAR struct pollfd *fds, bool setup) { - return 0; + FAR struct fcrypt *fcr = filep->f_priv; + + if (fcr == NULL || fds == NULL) + { + return -EINVAL; + } + + if (setup) + { + if (!TAILQ_EMPTY(&fcr->crpk_ret)) + { + poll_notify(&fds, 1, POLLIN); + return OK; + } + + if (fcr->fds) + { + return -EBUSY; + } + + fcr->fds = fds; + } + else + { + fcr->fds = NULL; + } + + return OK; } /* ARGSUSED */ @@ -734,6 +835,8 @@ static int cryptof_close(FAR struct file *filep) { FAR struct fcrypt *fcr = filep->f_priv; FAR struct csession *cse; + FAR struct cryptkop *krp; + int i; while ((cse = TAILQ_FIRST(&fcr->csessions))) { @@ -741,9 +844,24 @@ static int cryptof_close(FAR struct file *filep) (void)csefree(cse); } - kmm_free(fcr); - filep->f_priv = NULL; + while ((krp = TAILQ_FIRST(&fcr->crpk_ret))) + { + TAILQ_REMOVE(&fcr->crpk_ret, krp, krp_next); + for (i = 0; i < CRK_MAXPARAM; i++) + { + if (krp->krp_param[i].crp_p) + { + explicit_bzero(krp->krp_param[i].crp_p, + (krp->krp_param[i].crp_nbits + 7) / 8); + kmm_free(krp->krp_param[i].crp_p); + } + } + + kmm_free(krp); + } + kmm_free(fcr); + filep->f_priv = NULL; return 0; } @@ -899,8 +1017,14 @@ static int cryptoioctl(FAR struct file *filep, int cmd, unsigned long arg) switch (cmd) { case CRIOGET: - fcr = kmm_malloc(sizeof(struct fcrypt)); + fcr = kmm_zalloc(sizeof(struct fcrypt)); + if (fcr == NULL) + { + return -ENOMEM; + } + TAILQ_INIT(&fcr->csessions); + TAILQ_INIT(&fcr->crpk_ret); fd = file_allocate(&g_cryptoinode, 0, 0, fcr, 0, true); @@ -921,7 +1045,7 @@ static int cryptoioctl(FAR struct file *filep, int cmd, unsigned long arg) return error; } -FAR struct csession *csefind(FAR struct fcrypt *fcr, u_int ses) +static FAR struct csession *csefind(FAR struct fcrypt *fcr, u_int ses) { FAR struct csession *cse; @@ -934,7 +1058,7 @@ FAR struct csession *csefind(FAR struct fcrypt *fcr, u_int ses) return NULL; } -int csedelete(FAR struct fcrypt *fcr, FAR struct csession *cse_del) +static int csedelete(FAR struct fcrypt *fcr, FAR struct csession *cse_del) { FAR struct csession *cse; @@ -950,19 +1074,19 @@ int csedelete(FAR struct fcrypt *fcr, FAR struct csession *cse_del) return 0; } -FAR struct csession *cseadd(FAR struct fcrypt *fcr, - FAR struct csession *cse) +static FAR struct csession *cseadd(FAR struct fcrypt *fcr, + FAR struct csession *cse) { TAILQ_INSERT_TAIL(&fcr->csessions, cse, next); cse->ses = fcr->sesn++; return cse; } -FAR struct csession *csecreate(FAR struct fcrypt *fcr, uint64_t sid, - caddr_t key, uint64_t keylen, - caddr_t mackey, uint64_t mackeylen, - uint32_t cipher, uint32_t mac, - bool txform, bool thash) +static FAR struct csession *csecreate(FAR struct fcrypt *fcr, uint64_t sid, + caddr_t key, uint64_t keylen, + caddr_t mackey, uint64_t mackeylen, + uint32_t cipher, uint32_t mac, + bool txform, bool thash) { FAR struct csession *cse; @@ -985,7 +1109,7 @@ FAR struct csession *csecreate(FAR struct fcrypt *fcr, uint64_t sid, return cse; } -int csefree(FAR struct csession *cse) +static int csefree(FAR struct csession *cse) { int error; diff --git a/include/crypto/cryptodev.h b/include/crypto/cryptodev.h index a499ba113d6a7..6ea4f0ba5ad10 100644 --- a/include/crypto/cryptodev.h +++ b/include/crypto/cryptodev.h @@ -56,6 +56,7 @@ ****************************************************************************/ #include +#include /* Some initial values */ @@ -210,6 +211,8 @@ struct cryptop #define CRYPTO_F_REL 0x0004 /* Must return data in same place */ #define CRYPTO_F_NOQUEUE 0x0008 /* Don't use crypto queue/thread */ #define CRYPTO_F_DONE 0x0010 /* request completed */ +#define CRYPTO_F_CBIMM 0x0020 /* Do callback immediately */ +#define CRYPTO_F_CANCEL 0x0040 /* Cancel the current crypto operation */ FAR void *crp_buf; /* Data to be processed */ FAR void *crp_opaque; /* Opaque pointer, passed along */ @@ -245,8 +248,9 @@ struct crypt_kop u_int crk_status; /* return status */ u_short crk_iparams; /* # of input parameters */ u_short crk_oparams; /* # of output parameters */ - u_int crk_pad1; + u_int crk_flags; struct crparam crk_param[CRK_MAXPARAM]; + uint32_t crk_reqid; }; #define CRK_MOD_EXP 0 @@ -273,6 +277,7 @@ struct crypt_kop struct cryptkop { + TAILQ_ENTRY(cryptkop) krp_next; u_int krp_op; /* ie. CRK_MOD_EXP or other */ u_int krp_status; /* return status */ u_short krp_iparams; /* # of input parameters */ @@ -280,6 +285,10 @@ struct cryptkop uint32_t krp_hid; struct crparam krp_param[CRK_MAXPARAM]; /* kvm */ CODE int (*krp_callback)(FAR struct cryptkop *); + + FAR struct fcrypt *krp_fcr; + u_int krp_flags; /* same as cryptop */ + uint32_t krp_reqid; /* distinguish tasks in asynchronous calling */ }; /* Crypto capabilities structure */ @@ -376,7 +385,8 @@ extern const uint8_t hmac_opad_buffer[HMAC_MAX_BLOCK_LEN]; #define CIOCFSESSION 102 #define CIOCCRYPT 103 #define CIOCKEY 104 -#define CIOCASYMFEAT 105 +#define CIOCKEYRET 105 +#define CIOCASYMFEAT 106 int crypto_newsession(FAR uint64_t *, FAR struct cryptoini *, int); int crypto_freesession(uint64_t);