diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-08-22 14:59:50 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-09-21 10:29:41 +0200 |
commit | 3489e3b6396ee9944a6a2e19e675ca54c36993b4 (patch) | |
tree | cd55cfac1c96ff4b888a9606fd6a0d8eb65bb446 /freebsd/sys/opencrypto | |
parent | ck: Define CK_MD_PPC32_LWSYNC if available (diff) | |
download | rtems-libbsd-3489e3b6396ee9944a6a2e19e675ca54c36993b4.tar.bz2 |
Update to FreeBSD head 2018-09-17
Git mirror commit 6c2192b1ef8c50788c751f878552526800b1e319.
Update #3472.
Diffstat (limited to 'freebsd/sys/opencrypto')
-rw-r--r-- | freebsd/sys/opencrypto/_cryptodev.h | 8 | ||||
-rw-r--r-- | freebsd/sys/opencrypto/crypto.c | 174 | ||||
-rw-r--r-- | freebsd/sys/opencrypto/cryptodev.c | 55 | ||||
-rw-r--r-- | freebsd/sys/opencrypto/cryptodev.h | 64 | ||||
-rw-r--r-- | freebsd/sys/opencrypto/cryptosoft.c | 335 | ||||
-rw-r--r-- | freebsd/sys/opencrypto/cryptosoft.h | 5 | ||||
-rw-r--r-- | freebsd/sys/opencrypto/xform_auth.h | 7 | ||||
-rw-r--r-- | freebsd/sys/opencrypto/xform_md5.c | 4 | ||||
-rw-r--r-- | freebsd/sys/opencrypto/xform_poly1305.c | 93 | ||||
-rw-r--r-- | freebsd/sys/opencrypto/xform_poly1305.h | 16 | ||||
-rw-r--r-- | freebsd/sys/opencrypto/xform_rmd160.c | 4 | ||||
-rw-r--r-- | freebsd/sys/opencrypto/xform_sha1.c | 16 | ||||
-rw-r--r-- | freebsd/sys/opencrypto/xform_sha2.c | 81 |
13 files changed, 574 insertions, 288 deletions
diff --git a/freebsd/sys/opencrypto/_cryptodev.h b/freebsd/sys/opencrypto/_cryptodev.h new file mode 100644 index 00000000..d13b41da --- /dev/null +++ b/freebsd/sys/opencrypto/_cryptodev.h @@ -0,0 +1,8 @@ +/* + * This trivial work is released to the public domain, or licensed under the + * terms of the CC0, at your option. + * $FreeBSD$ + */ +#pragma once + +typedef struct crypto_session *crypto_session_t; diff --git a/freebsd/sys/opencrypto/crypto.c b/freebsd/sys/opencrypto/crypto.c index 5db2e872..d66fe5d5 100644 --- a/freebsd/sys/opencrypto/crypto.c +++ b/freebsd/sys/opencrypto/crypto.c @@ -91,6 +91,13 @@ __FBSDID("$FreeBSD$"); #include <machine/pcb.h> #endif +struct crypto_session { + device_t parent; + void *softc; + uint32_t hid; + uint32_t capabilities; +}; + SDT_PROVIDER_DEFINE(opencrypto); /* @@ -127,6 +134,7 @@ struct cryptocap { #define CRYPTOCAP_F_CLEANUP 0x80000000 /* needs resource cleanup */ int cc_qblocked; /* (q) symmetric q blocked */ int cc_kqblocked; /* (q) asymmetric q blocked */ + size_t cc_session_size; }; static struct cryptocap *crypto_drivers = NULL; static int crypto_drivers_num = 0; @@ -187,6 +195,7 @@ SYSCTL_INT(_kern, OID_AUTO, crypto_workers_num, CTLFLAG_RDTUN, static uma_zone_t cryptop_zone; static uma_zone_t cryptodesc_zone; +static uma_zone_t cryptoses_zone; int crypto_userasymcrypto = 1; /* userland may do asym crypto reqs */ SYSCTL_INT(_kern, OID_AUTO, userasymcrypto, CTLFLAG_RW, @@ -205,6 +214,7 @@ static void crypto_ret_proc(struct crypto_ret_worker *ret_worker); static void crypto_destroy(void); static int crypto_invoke(struct cryptocap *cap, struct cryptop *crp, int hint); static int crypto_kinvoke(struct cryptkop *krp, int flags); +static void crypto_remove(struct cryptocap *cap); static void crypto_task_invoke(void *ctx, int pending); static void crypto_batch_enqueue(struct cryptop *crp); @@ -268,7 +278,12 @@ crypto_init(void) cryptodesc_zone = uma_zcreate("cryptodesc", sizeof (struct cryptodesc), 0, 0, 0, 0, UMA_ALIGN_PTR, UMA_ZONE_ZINIT); - if (cryptodesc_zone == NULL || cryptop_zone == NULL) { + cryptoses_zone = uma_zcreate("crypto_session", + sizeof(struct crypto_session), NULL, NULL, NULL, NULL, + UMA_ALIGN_PTR, UMA_ZONE_ZINIT); + + if (cryptodesc_zone == NULL || cryptop_zone == NULL || + cryptoses_zone == NULL) { printf("crypto_init: cannot setup crypto zones\n"); error = ENOMEM; goto bad; @@ -395,6 +410,8 @@ crypto_destroy(void) if (crypto_drivers != NULL) free(crypto_drivers, M_CRYPTO_DATA); + if (cryptoses_zone != NULL) + uma_zdestroy(cryptoses_zone); if (cryptodesc_zone != NULL) uma_zdestroy(cryptodesc_zone); if (cryptop_zone != NULL) @@ -408,6 +425,24 @@ crypto_destroy(void) mtx_destroy(&crypto_drivers_mtx); } +uint32_t +crypto_ses2hid(crypto_session_t crypto_session) +{ + return (crypto_session->hid); +} + +uint32_t +crypto_ses2caps(crypto_session_t crypto_session) +{ + return (crypto_session->capabilities); +} + +void * +crypto_get_driver_session(crypto_session_t crypto_session) +{ + return (crypto_session->softc); +} + static struct cryptocap * crypto_checkdriver(u_int32_t hid) { @@ -495,12 +530,19 @@ again: * must be capable of the requested crypto algorithms. */ int -crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int crid) +crypto_newsession(crypto_session_t *cses, struct cryptoini *cri, int crid) { + crypto_session_t res; + void *softc_mem; struct cryptocap *cap; - u_int32_t hid, lid; + u_int32_t hid; + size_t softc_size; int err; +restart: + res = NULL; + softc_mem = NULL; + CRYPTO_DRIVER_LOCK(); if ((crid & (CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE)) == 0) { /* @@ -520,24 +562,53 @@ crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int crid) * XXX layer right about here. */ } - if (cap != NULL) { - /* Call the driver initialization routine. */ - hid = cap - crypto_drivers; - lid = hid; /* Pass the driver ID. */ - err = CRYPTODEV_NEWSESSION(cap->cc_dev, &lid, cri); - if (err == 0) { - (*sid) = (cap->cc_flags & 0xff000000) - | (hid & 0x00ffffff); - (*sid) <<= 32; - (*sid) |= (lid & 0xffffffff); - cap->cc_sessions++; - } else - CRYPTDEB("dev newsession failed: %d", err); - } else { + if (cap == NULL) { CRYPTDEB("no driver"); err = EOPNOTSUPP; + goto out; + } + cap->cc_sessions++; + softc_size = cap->cc_session_size; + hid = cap - crypto_drivers; + cap = NULL; + CRYPTO_DRIVER_UNLOCK(); + + softc_mem = malloc(softc_size, M_CRYPTO_DATA, M_WAITOK | M_ZERO); + res = uma_zalloc(cryptoses_zone, M_WAITOK | M_ZERO); + res->softc = softc_mem; + + CRYPTO_DRIVER_LOCK(); + cap = crypto_checkdriver(hid); + if (cap != NULL && (cap->cc_flags & CRYPTOCAP_F_CLEANUP) != 0) { + cap->cc_sessions--; + crypto_remove(cap); + cap = NULL; + } + if (cap == NULL) { + free(softc_mem, M_CRYPTO_DATA); + uma_zfree(cryptoses_zone, res); + CRYPTO_DRIVER_UNLOCK(); + goto restart; + } + + /* Call the driver initialization routine. */ + err = CRYPTODEV_NEWSESSION(cap->cc_dev, res, cri); + if (err != 0) { + CRYPTDEB("dev newsession failed: %d", err); + goto out; } + + res->capabilities = cap->cc_flags & 0xff000000; + res->hid = hid; + *cses = res; + +out: CRYPTO_DRIVER_UNLOCK(); + if (err != 0) { + free(softc_mem, M_CRYPTO_DATA); + if (res != NULL) + uma_zfree(cryptoses_zone, res); + } return err; } @@ -554,41 +625,41 @@ crypto_remove(struct cryptocap *cap) * Delete an existing session (or a reserved session on an unregistered * driver). */ -int -crypto_freesession(u_int64_t sid) +void +crypto_freesession(crypto_session_t cses) { struct cryptocap *cap; + void *ses; + size_t ses_size; u_int32_t hid; - int err; - CRYPTO_DRIVER_LOCK(); - - if (crypto_drivers == NULL) { - err = EINVAL; - goto done; - } + if (cses == NULL) + return; - /* Determine two IDs. */ - hid = CRYPTO_SESID2HID(sid); + CRYPTO_DRIVER_LOCK(); - if (hid >= crypto_drivers_num) { - err = ENOENT; - goto done; - } + hid = crypto_ses2hid(cses); + KASSERT(hid < crypto_drivers_num, + ("bogus crypto_session %p hid %u", cses, hid)); cap = &crypto_drivers[hid]; + ses = cses->softc; + ses_size = cap->cc_session_size; + if (cap->cc_sessions) cap->cc_sessions--; /* Call the driver cleanup routine, if available. */ - err = CRYPTODEV_FREESESSION(cap->cc_dev, sid); + CRYPTODEV_FREESESSION(cap->cc_dev, cses); + + explicit_bzero(ses, ses_size); + free(ses, M_CRYPTO_DATA); + uma_zfree(cryptoses_zone, cses); if (cap->cc_flags & CRYPTOCAP_F_CLEANUP) crypto_remove(cap); -done: CRYPTO_DRIVER_UNLOCK(); - return err; } /* @@ -596,7 +667,7 @@ done: * support for the algorithms they handle. */ int32_t -crypto_get_driverid(device_t dev, int flags) +crypto_get_driverid(device_t dev, size_t sessionsize, int flags) { struct cryptocap *newdrv; int i; @@ -646,6 +717,7 @@ crypto_get_driverid(device_t dev, int flags) crypto_drivers[i].cc_sessions = 1; /* Mark */ crypto_drivers[i].cc_dev = dev; crypto_drivers[i].cc_flags = flags; + crypto_drivers[i].cc_session_size = sessionsize; if (bootverbose) printf("crypto: assign %s driver id %u, flags 0x%x\n", device_get_nameunit(dev), i, flags); @@ -903,7 +975,7 @@ crypto_dispatch(struct cryptop *crp) binuptime(&crp->crp_tstamp); #endif - crp->crp_retw_id = crp->crp_sid % crypto_workers_num; + crp->crp_retw_id = ((uintptr_t)crp->crp_session) % crypto_workers_num; if (CRYPTOP_ASYNC(crp)) { if (crp->crp_flags & CRYPTO_F_ASYNC_KEEPORDER) { @@ -922,7 +994,7 @@ crypto_dispatch(struct cryptop *crp) } if ((crp->crp_flags & CRYPTO_F_BATCH) == 0) { - hid = CRYPTO_SESID2HID(crp->crp_sid); + hid = crypto_ses2hid(crp->crp_session); /* * Caller marked the request to be processed @@ -1143,7 +1215,7 @@ crypto_task_invoke(void *ctx, int pending) crp = (struct cryptop *)ctx; - hid = CRYPTO_SESID2HID(crp->crp_sid); + hid = crypto_ses2hid(crp->crp_session); cap = crypto_checkdriver(hid); result = crypto_invoke(cap, crp, 0); @@ -1169,7 +1241,7 @@ crypto_invoke(struct cryptocap *cap, struct cryptop *crp, int hint) #endif if (cap->cc_flags & CRYPTOCAP_F_CLEANUP) { struct cryptodesc *crd; - u_int64_t nid; + crypto_session_t nses; /* * Driver has unregistered; migrate the session and return @@ -1178,15 +1250,15 @@ crypto_invoke(struct cryptocap *cap, struct cryptop *crp, int hint) * XXX: What if there are more already queued requests for this * session? */ - crypto_freesession(crp->crp_sid); + crypto_freesession(crp->crp_session); for (crd = crp->crp_desc; crd->crd_next; crd = crd->crd_next) crd->CRD_INI.cri_next = &(crd->crd_next->CRD_INI); /* XXX propagate flags from initial session? */ - if (crypto_newsession(&nid, &(crp->crp_desc->CRD_INI), + if (crypto_newsession(&nses, &(crp->crp_desc->CRD_INI), CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE) == 0) - crp->crp_sid = nid; + crp->crp_session = nses; crp->crp_etype = EAGAIN; crypto_done(crp); @@ -1292,7 +1364,7 @@ crypto_done(struct cryptop *crp) if (!CRYPTOP_ASYNC_KEEPORDER(crp) && ((crp->crp_flags & CRYPTO_F_CBIMM) || ((crp->crp_flags & CRYPTO_F_CBIFSYNC) && - (CRYPTO_SESID2CAPS(crp->crp_sid) & CRYPTOCAP_F_SYNC)))) { + (crypto_ses2caps(crp->crp_session) & CRYPTOCAP_F_SYNC)))) { /* * Do the callback directly. This is ok when the * callback routine does very little (e.g. the @@ -1454,7 +1526,7 @@ crypto_proc(void) submit = NULL; hint = 0; TAILQ_FOREACH(crp, &crp_q, crp_next) { - hid = CRYPTO_SESID2HID(crp->crp_sid); + hid = crypto_ses2hid(crp->crp_session); cap = crypto_checkdriver(hid); /* * Driver cannot disappeared when there is an active @@ -1478,7 +1550,7 @@ crypto_proc(void) * better to just use a per-driver * queue instead. */ - if (CRYPTO_SESID2HID(submit->crp_sid) == hid) + if (crypto_ses2hid(submit->crp_session) == hid) hint = CRYPTO_HINT_MORE; break; } else { @@ -1491,7 +1563,7 @@ crypto_proc(void) } if (submit != NULL) { TAILQ_REMOVE(&crp_q, submit, crp_next); - hid = CRYPTO_SESID2HID(submit->crp_sid); + hid = crypto_ses2hid(submit->crp_session); cap = crypto_checkdriver(hid); KASSERT(cap != NULL, ("%s:%u Driver disappeared.", __func__, __LINE__)); @@ -1507,7 +1579,7 @@ crypto_proc(void) * it at the end does not work. */ /* XXX validate sid again? */ - crypto_drivers[CRYPTO_SESID2HID(submit->crp_sid)].cc_qblocked = 1; + crypto_drivers[crypto_ses2hid(submit->crp_session)].cc_qblocked = 1; TAILQ_INSERT_HEAD(&crp_q, submit, crp_next); cryptostats.cs_blocks++; } @@ -1696,8 +1768,8 @@ DB_SHOW_COMMAND(crypto, db_show_crypto) "Desc", "Callback"); TAILQ_FOREACH(crp, &crp_q, crp_next) { db_printf("%4u %08x %4u %4u %4u %04x %8p %8p\n" - , (int) CRYPTO_SESID2HID(crp->crp_sid) - , (int) CRYPTO_SESID2CAPS(crp->crp_sid) + , (int) crypto_ses2hid(crp->crp_session) + , (int) crypto_ses2caps(crp->crp_session) , crp->crp_ilen, crp->crp_olen , crp->crp_etype , crp->crp_flags @@ -1712,7 +1784,7 @@ DB_SHOW_COMMAND(crypto, db_show_crypto) TAILQ_FOREACH(crp, &ret_worker->crp_ret_q, crp_next) { db_printf("%8td %4u %4u %04x %8p\n" , CRYPTO_RETW_ID(ret_worker) - , (int) CRYPTO_SESID2HID(crp->crp_sid) + , (int) crypto_ses2hid(crp->crp_session) , crp->crp_etype , crp->crp_flags , crp->crp_callback diff --git a/freebsd/sys/opencrypto/cryptodev.c b/freebsd/sys/opencrypto/cryptodev.c index 162a247c..b569cbf7 100644 --- a/freebsd/sys/opencrypto/cryptodev.c +++ b/freebsd/sys/opencrypto/cryptodev.c @@ -267,7 +267,7 @@ crypt_kop_to_32(const struct crypt_kop *from, struct crypt_kop32 *to) struct csession { TAILQ_ENTRY(csession) next; - u_int64_t sid; + crypto_session_t cses; u_int32_t ses; struct mtx lock; /* for op submission */ @@ -326,10 +326,10 @@ static const rtems_filesystem_file_handlers_r cryptofops; static struct csession *csefind(struct fcrypt *, u_int); static int csedelete(struct fcrypt *, struct csession *); static struct csession *cseadd(struct fcrypt *, struct csession *); -static struct csession *csecreate(struct fcrypt *, u_int64_t, caddr_t, +static struct csession *csecreate(struct fcrypt *, crypto_session_t, caddr_t, u_int64_t, caddr_t, u_int64_t, u_int32_t, u_int32_t, struct enc_xform *, struct auth_hash *); -static int csefree(struct csession *); +static void csefree(struct csession *); static int cryptodev_op(struct csession *, struct crypt_op *, struct ucred *, struct thread *td); @@ -384,7 +384,7 @@ cryptof_ioctl( struct enc_xform *txform = NULL; struct auth_hash *thash = NULL; struct crypt_kop *kop; - u_int64_t sid; + crypto_session_t cses; u_int32_t ses; int error = 0, crid; #ifdef COMPAT_FREEBSD32 @@ -463,9 +463,15 @@ cryptof_ioctl( case CRYPTO_MD5_HMAC: thash = &auth_hash_hmac_md5; break; + case CRYPTO_POLY1305: + thash = &auth_hash_poly1305; + break; case CRYPTO_SHA1_HMAC: thash = &auth_hash_hmac_sha1; break; + case CRYPTO_SHA2_224_HMAC: + thash = &auth_hash_hmac_sha2_224; + break; case CRYPTO_SHA2_256_HMAC: thash = &auth_hash_hmac_sha2_256; break; @@ -492,10 +498,23 @@ cryptof_ioctl( case CRYPTO_MD5: thash = &auth_hash_md5; break; +#endif case CRYPTO_SHA1: thash = &auth_hash_sha1; break; -#endif + case CRYPTO_SHA2_224: + thash = &auth_hash_sha2_224; + break; + case CRYPTO_SHA2_256: + thash = &auth_hash_sha2_256; + break; + case CRYPTO_SHA2_384: + thash = &auth_hash_sha2_384; + break; + case CRYPTO_SHA2_512: + thash = &auth_hash_sha2_512; + break; + case CRYPTO_NULL_HMAC: thash = &auth_hash_null; break; @@ -582,19 +601,19 @@ cryptof_ioctl( } } else crid = CRYPTOCAP_F_HARDWARE; - error = crypto_newsession(&sid, (txform ? &crie : &cria), crid); + error = crypto_newsession(&cses, (txform ? &crie : &cria), crid); if (error) { CRYPTDEB("crypto_newsession"); SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); goto bail; } - cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen, + cse = csecreate(fcr, cses, crie.cri_key, crie.cri_klen, cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, txform, thash); if (cse == NULL) { - crypto_freesession(sid); + crypto_freesession(cses); error = EINVAL; SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__); CRYPTDEB("csecreate"); @@ -607,7 +626,7 @@ cryptof_ioctl( #endif ) { /* return hardware/driver id */ - SES2(sop)->crid = CRYPTO_SESID2HID(cse->sid); + SES2(sop)->crid = crypto_ses2hid(cse->cses); } bail: if (error) { @@ -634,7 +653,7 @@ bail: return (EINVAL); } csedelete(fcr, cse); - error = csefree(cse); + csefree(cse); break; case CIOCCRYPT: #ifdef COMPAT_FREEBSD32 @@ -867,7 +886,7 @@ cryptodev_op( | (cop->flags & COP_F_BATCH); crp->crp_uio = &cod->uio; crp->crp_callback = cryptodev_cb; - crp->crp_sid = cse->sid; + crp->crp_session = cse->cses; crp->crp_opaque = cod; if (cop->iv) { @@ -1043,7 +1062,7 @@ cryptodev_aead( | (caead->flags & COP_F_BATCH); crp->crp_uio = &cod->uio; crp->crp_callback = cryptodev_cb; - crp->crp_sid = cse->sid; + crp->crp_session = cse->cses; crp->crp_opaque = cod; if (caead->iv) { @@ -1318,7 +1337,7 @@ cryptof_close(struct file *fp, struct thread *td) while ((cse = TAILQ_FIRST(&fcr->csessions))) { TAILQ_REMOVE(&fcr->csessions, cse, next); - (void)csefree(cse); + csefree(cse); } free(fcr, M_XDATA); fp->f_data = NULL; @@ -1389,7 +1408,7 @@ cseadd(struct fcrypt *fcr, struct csession *cse) } struct csession * -csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen, +csecreate(struct fcrypt *fcr, crypto_session_t cses, caddr_t key, u_int64_t keylen, caddr_t mackey, u_int64_t mackeylen, u_int32_t cipher, u_int32_t mac, struct enc_xform *txform, struct auth_hash *thash) { @@ -1403,7 +1422,7 @@ csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen, cse->keylen = keylen/8; cse->mackey = mackey; cse->mackeylen = mackeylen/8; - cse->sid = sid; + cse->cses = cses; cse->cipher = cipher; cse->mac = mac; cse->txform = txform; @@ -1412,19 +1431,17 @@ csecreate(struct fcrypt *fcr, u_int64_t sid, caddr_t key, u_int64_t keylen, return (cse); } -static int +static void csefree(struct csession *cse) { - int error; - error = crypto_freesession(cse->sid); + crypto_freesession(cse->cses); mtx_destroy(&cse->lock); if (cse->key) free(cse->key, M_XDATA); if (cse->mackey) free(cse->mackey, M_XDATA); free(cse, M_XDATA); - return (error); } static int diff --git a/freebsd/sys/opencrypto/cryptodev.h b/freebsd/sys/opencrypto/cryptodev.h index 65422541..b3f81563 100644 --- a/freebsd/sys/opencrypto/cryptodev.h +++ b/freebsd/sys/opencrypto/cryptodev.h @@ -65,6 +65,10 @@ #include <sys/ioccom.h> #include <sys/_task.h> +#ifdef _KERNEL +#include <opencrypto/_cryptodev.h> +#endif + /* Some initial values */ #define CRYPTO_DRIVERS_INITIAL 4 #define CRYPTO_SW_SESSIONS 32 @@ -74,25 +78,29 @@ #define MD5_HASH_LEN 16 #define SHA1_HASH_LEN 20 #define RIPEMD160_HASH_LEN 20 +#define SHA2_224_HASH_LEN 28 #define SHA2_256_HASH_LEN 32 #define SHA2_384_HASH_LEN 48 #define SHA2_512_HASH_LEN 64 #define MD5_KPDK_HASH_LEN 16 #define SHA1_KPDK_HASH_LEN 20 #define AES_GMAC_HASH_LEN 16 +#define POLY1305_HASH_LEN 16 /* Maximum hash algorithm result length */ #define HASH_MAX_LEN SHA2_512_HASH_LEN /* Keep this updated */ +#define MD5_BLOCK_LEN 64 +#define SHA1_BLOCK_LEN 64 +#define RIPEMD160_BLOCK_LEN 64 +#define SHA2_224_BLOCK_LEN 64 +#define SHA2_256_BLOCK_LEN 64 +#define SHA2_384_BLOCK_LEN 128 +#define SHA2_512_BLOCK_LEN 128 + /* HMAC values */ #define NULL_HMAC_BLOCK_LEN 64 -#define MD5_HMAC_BLOCK_LEN 64 -#define SHA1_HMAC_BLOCK_LEN 64 -#define RIPEMD160_HMAC_BLOCK_LEN 64 -#define SHA2_256_HMAC_BLOCK_LEN 64 -#define SHA2_384_HMAC_BLOCK_LEN 128 -#define SHA2_512_HMAC_BLOCK_LEN 128 /* Maximum HMAC block length */ -#define HMAC_MAX_BLOCK_LEN SHA2_512_HMAC_BLOCK_LEN /* Keep this updated */ +#define HMAC_MAX_BLOCK_LEN SHA2_512_BLOCK_LEN /* Keep this updated */ #define HMAC_IPAD_VAL 0x36 #define HMAC_OPAD_VAL 0x5C /* HMAC Key Length */ @@ -100,6 +108,8 @@ #define AES_192_GMAC_KEY_LEN 24 #define AES_256_GMAC_KEY_LEN 32 +#define POLY1305_KEY_LEN 32 + /* Encryption algorithm block sizes */ #define NULL_BLOCK_LEN 4 /* IPsec to maintain alignment */ #define DES_BLOCK_LEN 8 @@ -182,7 +192,14 @@ #define CRYPTO_BLAKE2B 29 /* Blake2b hash */ #define CRYPTO_BLAKE2S 30 /* Blake2s hash */ #define CRYPTO_CHACHA20 31 /* Chacha20 stream cipher */ -#define CRYPTO_ALGORITHM_MAX 31 /* Keep updated - see below */ +#define CRYPTO_SHA2_224_HMAC 32 +#define CRYPTO_RIPEMD160 33 +#define CRYPTO_SHA2_224 34 +#define CRYPTO_SHA2_256 35 +#define CRYPTO_SHA2_384 36 +#define CRYPTO_SHA2_512 37 +#define CRYPTO_POLY1305 38 +#define CRYPTO_ALGORITHM_MAX 38 /* Keep updated - see below */ #define CRYPTO_ALGO_VALID(x) ((x) >= CRYPTO_ALGORITHM_MIN && \ (x) <= CRYPTO_ALGORITHM_MAX) @@ -216,6 +233,11 @@ struct session_op { u_int32_t ses; /* returns: session # */ }; +/* + * session and crypt _op structs are used by userspace programs to interact + * with /dev/crypto. Confusingly, the internal kernel interface is named + * "cryptop" (no underscore). + */ struct session2_op { u_int32_t cipher; /* ie. CRYPTO_DES_CBC */ u_int32_t mac; /* ie. CRYPTO_MD5_HMAC */ @@ -399,7 +421,7 @@ struct cryptop { struct task crp_task; - u_int64_t crp_sid; /* Session ID */ + crypto_session_t crp_session; /* Session */ int crp_ilen; /* Input data total length */ int crp_olen; /* Result total length */ @@ -408,7 +430,7 @@ struct cryptop { * All error codes except EAGAIN * indicate possible data corruption (as in, * the data have been touched). On all - * errors, the crp_sid may have changed + * errors, the crp_session may have changed * (reset to a new one), so the caller * should always check and use the new * value on future requests. @@ -450,7 +472,7 @@ struct cryptop { #define CRYPTOP_ASYNC(crp) \ (((crp)->crp_flags & CRYPTO_F_ASYNC) && \ - CRYPTO_SESID2CAPS((crp)->crp_sid) & CRYPTOCAP_F_SYNC) + crypto_ses2caps((crp)->crp_session) & CRYPTOCAP_F_SYNC) #define CRYPTOP_ASYNC_KEEPORDER(crp) \ (CRYPTOP_ASYNC(crp) && \ (crp)->crp_flags & CRYPTO_F_ASYNC_KEEPORDER) @@ -480,25 +502,19 @@ struct cryptkop { int (*krp_callback)(struct cryptkop *); }; -/* - * Session ids are 64 bits. The lower 32 bits contain a "local id" which - * is a driver-private session identifier. The upper 32 bits contain a - * "hardware id" used by the core crypto code to identify the driver and - * a copy of the driver's capabilities that can be used by client code to - * optimize operation. - */ -#define CRYPTO_SESID2HID(_sid) (((_sid) >> 32) & 0x00ffffff) -#define CRYPTO_SESID2CAPS(_sid) (((_sid) >> 32) & 0xff000000) -#define CRYPTO_SESID2LID(_sid) (((u_int32_t) (_sid)) & 0xffffffff) +uint32_t crypto_ses2hid(crypto_session_t crypto_session); +uint32_t crypto_ses2caps(crypto_session_t crypto_session); +void *crypto_get_driver_session(crypto_session_t crypto_session); MALLOC_DECLARE(M_CRYPTO_DATA); -extern int crypto_newsession(u_int64_t *sid, struct cryptoini *cri, int hard); -extern int crypto_freesession(u_int64_t sid); +extern int crypto_newsession(crypto_session_t *cses, struct cryptoini *cri, int hard); +extern void crypto_freesession(crypto_session_t cses); #define CRYPTOCAP_F_HARDWARE CRYPTO_FLAG_HARDWARE #define CRYPTOCAP_F_SOFTWARE CRYPTO_FLAG_SOFTWARE #define CRYPTOCAP_F_SYNC 0x04000000 /* operates synchronously */ -extern int32_t crypto_get_driverid(device_t dev, int flags); +extern int32_t crypto_get_driverid(device_t dev, size_t session_size, + int flags); extern int crypto_find_driver(const char *); extern device_t crypto_find_device_byhid(int hid); extern int crypto_getcaps(int hid); diff --git a/freebsd/sys/opencrypto/cryptosoft.c b/freebsd/sys/opencrypto/cryptosoft.c index 69993ae0..8dff61c1 100644 --- a/freebsd/sys/opencrypto/cryptosoft.c +++ b/freebsd/sys/opencrypto/cryptosoft.c @@ -64,10 +64,6 @@ __FBSDID("$FreeBSD$"); #include <rtems/bsd/local/cryptodev_if.h> static int32_t swcr_id; -static struct swcr_data **swcr_sessions = NULL; -static u_int32_t swcr_sesnum; -/* Protects swcr_sessions pointer, not data. */ -static struct rwlock swcr_sessions_lock; u_int8_t hmac_ipad_buffer[HMAC_MAX_BLOCK_LEN]; u_int8_t hmac_opad_buffer[HMAC_MAX_BLOCK_LEN]; @@ -76,8 +72,7 @@ static int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); static int swcr_authcompute(struct cryptodesc *, struct swcr_data *, caddr_t, int); static int swcr_authenc(struct cryptop *crp); static int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); -static int swcr_freesession(device_t dev, u_int64_t tid); -static int swcr_freesession_locked(device_t dev, u_int64_t tid); +static void swcr_freesession(device_t dev, crypto_session_t cses); /* * Apply a symmetric encryption/decryption algorithm. @@ -328,7 +323,7 @@ out: return (error); } -static void +static int __result_use_check swcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key, int klen) { @@ -339,6 +334,7 @@ swcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key, switch (axf->type) { case CRYPTO_MD5_HMAC: case CRYPTO_SHA1_HMAC: + case CRYPTO_SHA2_224_HMAC: case CRYPTO_SHA2_256_HMAC: case CRYPTO_SHA2_384_HMAC: case CRYPTO_SHA2_512_HMAC: @@ -383,6 +379,12 @@ swcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key, axf->Final(buf, sw->sw_ictx); break; } + case CRYPTO_POLY1305: + if (klen != POLY1305_KEY_LEN) { + CRYPTDEB("bad poly1305 key size %d", klen); + return EINVAL; + } + /* FALLTHROUGH */ case CRYPTO_BLAKE2B: case CRYPTO_BLAKE2S: axf->Setkey(sw->sw_ictx, key, klen); @@ -391,7 +393,9 @@ swcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key, default: printf("%s: CRD_F_KEY_EXPLICIT flag given, but algorithm %d " "doesn't use keys.\n", __func__, axf->type); + return EINVAL; } + return 0; } /* @@ -411,8 +415,11 @@ swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, axf = sw->sw_axf; - if (crd->crd_flags & CRD_F_KEY_EXPLICIT) - swcr_authprepare(axf, sw, crd->crd_key, crd->crd_klen); + if (crd->crd_flags & CRD_F_KEY_EXPLICIT) { + err = swcr_authprepare(axf, sw, crd->crd_key, crd->crd_klen); + if (err != 0) + return err; + } bcopy(sw->sw_ictx, &ctx, axf->ctxsize); @@ -422,8 +429,17 @@ swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, return err; switch (sw->sw_alg) { + case CRYPTO_SHA1: + case CRYPTO_SHA2_224: + case CRYPTO_SHA2_256: + case CRYPTO_SHA2_384: + case CRYPTO_SHA2_512: + axf->Final(aalg, &ctx); + break; + case CRYPTO_MD5_HMAC: case CRYPTO_SHA1_HMAC: + case CRYPTO_SHA2_224_HMAC: case CRYPTO_SHA2_256_HMAC: case CRYPTO_SHA2_384_HMAC: case CRYPTO_SHA2_512_HMAC: @@ -457,6 +473,7 @@ swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, case CRYPTO_BLAKE2B: case CRYPTO_BLAKE2S: case CRYPTO_NULL_HMAC: + case CRYPTO_POLY1305: axf->Final(aalg, &ctx); break; } @@ -482,6 +499,7 @@ swcr_authenc(struct cryptop *crp) u_char uaalg[AALG_MAX_RESULT_LEN]; u_char iv[EALG_MAX_BLOCK_LEN]; union authctx ctx; + struct swcr_session *ses; struct cryptodesc *crd, *crda = NULL, *crde = NULL; struct swcr_data *sw, *swa, *swe = NULL; struct auth_hash *axf = NULL; @@ -492,14 +510,16 @@ swcr_authenc(struct cryptop *crp) ivlen = blksz = iskip = oskip = 0; + ses = crypto_get_driver_session(crp->crp_session); + for (crd = crp->crp_desc; crd; crd = crd->crd_next) { - for (sw = swcr_sessions[crp->crp_sid & 0xffffffff]; - sw && sw->sw_alg != crd->crd_alg; - sw = sw->sw_next) + for (i = 0; i < nitems(ses->swcr_algorithms) && + ses->swcr_algorithms[i].sw_alg != crd->crd_alg; i++) ; - if (sw == NULL) + if (i == nitems(ses->swcr_algorithms)) return (EINVAL); + sw = &ses->swcr_algorithms[i]; switch (sw->sw_alg) { case CRYPTO_AES_NIST_GCM_16: case CRYPTO_AES_NIST_GMAC: @@ -732,68 +752,24 @@ swcr_compdec(struct cryptodesc *crd, struct swcr_data *sw, * Generate a new software session. */ static int -swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri) +swcr_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) { - struct swcr_data **swd; + struct swcr_session *ses; + struct swcr_data *swd; struct auth_hash *axf; struct enc_xform *txf; struct comp_algo *cxf; - u_int32_t i; + size_t i; int len; int error; - if (sid == NULL || cri == NULL) + if (cses == NULL || cri == NULL) return EINVAL; - rw_wlock(&swcr_sessions_lock); - if (swcr_sessions) { - for (i = 1; i < swcr_sesnum; i++) - if (swcr_sessions[i] == NULL) - break; - } else - i = 1; /* NB: to silence compiler warning */ - - if (swcr_sessions == NULL || i == swcr_sesnum) { - if (swcr_sessions == NULL) { - i = 1; /* We leave swcr_sessions[0] empty */ - swcr_sesnum = CRYPTO_SW_SESSIONS; - } else - swcr_sesnum *= 2; - - swd = malloc(swcr_sesnum * sizeof(struct swcr_data *), - M_CRYPTO_DATA, M_NOWAIT|M_ZERO); - if (swd == NULL) { - /* Reset session number */ - if (swcr_sesnum == CRYPTO_SW_SESSIONS) - swcr_sesnum = 0; - else - swcr_sesnum /= 2; - rw_wunlock(&swcr_sessions_lock); - return ENOBUFS; - } - - /* Copy existing sessions */ - if (swcr_sessions != NULL) { - bcopy(swcr_sessions, swd, - (swcr_sesnum / 2) * sizeof(struct swcr_data *)); - free(swcr_sessions, M_CRYPTO_DATA); - } - - swcr_sessions = swd; - } + ses = crypto_get_driver_session(cses); - rw_downgrade(&swcr_sessions_lock); - swd = &swcr_sessions[i]; - *sid = i; - - while (cri) { - *swd = malloc(sizeof(struct swcr_data), - M_CRYPTO_DATA, M_NOWAIT|M_ZERO); - if (*swd == NULL) { - swcr_freesession_locked(dev, i); - rw_runlock(&swcr_sessions_lock); - return ENOBUFS; - } + for (i = 0; cri != NULL && i < nitems(ses->swcr_algorithms); i++) { + swd = &ses->swcr_algorithms[i]; switch (cri->cri_alg) { case CRYPTO_DES_CBC: @@ -825,7 +801,7 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri) goto enccommon; case CRYPTO_AES_NIST_GMAC: txf = &enc_xform_aes_nist_gmac; - (*swd)->sw_exf = txf; + swd->sw_exf = txf; break; case CRYPTO_CAMELLIA_CBC: txf = &enc_xform_camellia; @@ -838,15 +814,14 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri) goto enccommon; enccommon: if (cri->cri_key != NULL) { - error = txf->setkey(&((*swd)->sw_kschedule), + error = txf->setkey(&swd->sw_kschedule, cri->cri_key, cri->cri_klen / 8); if (error) { - swcr_freesession_locked(dev, i); - rw_runlock(&swcr_sessions_lock); + swcr_freesession(dev, cses); return error; } } - (*swd)->sw_exf = txf; + swd->sw_exf = txf; break; case CRYPTO_MD5_HMAC: @@ -855,6 +830,9 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri) case CRYPTO_SHA1_HMAC: axf = &auth_hash_hmac_sha1; goto authcommon; + case CRYPTO_SHA2_224_HMAC: + axf = &auth_hash_hmac_sha2_224; + goto authcommon; case CRYPTO_SHA2_256_HMAC: axf = &auth_hash_hmac_sha2_256; goto authcommon; @@ -870,29 +848,31 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri) case CRYPTO_RIPEMD160_HMAC: axf = &auth_hash_hmac_ripemd_160; authcommon: - (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, + swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); - if ((*swd)->sw_ictx == NULL) { - swcr_freesession_locked(dev, i); - rw_runlock(&swcr_sessions_lock); + if (swd->sw_ictx == NULL) { + swcr_freesession(dev, cses); return ENOBUFS; } - (*swd)->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA, + swd->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); - if ((*swd)->sw_octx == NULL) { - swcr_freesession_locked(dev, i); - rw_runlock(&swcr_sessions_lock); + if (swd->sw_octx == NULL) { + swcr_freesession(dev, cses); return ENOBUFS; } if (cri->cri_key != NULL) { - swcr_authprepare(axf, *swd, cri->cri_key, - cri->cri_klen); + error = swcr_authprepare(axf, swd, + cri->cri_key, cri->cri_klen); + if (error != 0) { + swcr_freesession(dev, cses); + return error; + } } - (*swd)->sw_mlen = cri->cri_mlen; - (*swd)->sw_axf = axf; + swd->sw_mlen = cri->cri_mlen; + swd->sw_axf = axf; break; case CRYPTO_MD5_KPDK: @@ -902,52 +882,66 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri) case CRYPTO_SHA1_KPDK: axf = &auth_hash_key_sha1; auth2common: - (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, + swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); - if ((*swd)->sw_ictx == NULL) { - swcr_freesession_locked(dev, i); - rw_runlock(&swcr_sessions_lock); + if (swd->sw_ictx == NULL) { + swcr_freesession(dev, cses); return ENOBUFS; } - (*swd)->sw_octx = malloc(cri->cri_klen / 8, + swd->sw_octx = malloc(cri->cri_klen / 8, M_CRYPTO_DATA, M_NOWAIT); - if ((*swd)->sw_octx == NULL) { - swcr_freesession_locked(dev, i); - rw_runlock(&swcr_sessions_lock); + if (swd->sw_octx == NULL) { + swcr_freesession(dev, cses); return ENOBUFS; } /* Store the key so we can "append" it to the payload */ if (cri->cri_key != NULL) { - swcr_authprepare(axf, *swd, cri->cri_key, - cri->cri_klen); + error = swcr_authprepare(axf, swd, + cri->cri_key, cri->cri_klen); + if (error != 0) { + swcr_freesession(dev, cses); + return error; + } } - (*swd)->sw_mlen = cri->cri_mlen; - (*swd)->sw_axf = axf; + swd->sw_mlen = cri->cri_mlen; + swd->sw_axf = axf; break; #ifdef notdef case CRYPTO_MD5: axf = &auth_hash_md5; goto auth3common; +#endif case CRYPTO_SHA1: axf = &auth_hash_sha1; + goto auth3common; + case CRYPTO_SHA2_224: + axf = &auth_hash_sha2_224; + goto auth3common; + case CRYPTO_SHA2_256: + axf = &auth_hash_sha2_256; + goto auth3common; + case CRYPTO_SHA2_384: + axf = &auth_hash_sha2_384; + goto auth3common; + case CRYPTO_SHA2_512: + axf = &auth_hash_sha2_512; + auth3common: - (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, + swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); - if ((*swd)->sw_ictx == NULL) { - swcr_freesession_locked(dev, i); - rw_runlock(&swcr_sessions_lock); + if (swd->sw_ictx == NULL) { + swcr_freesession(dev, cses); return ENOBUFS; } - axf->Init((*swd)->sw_ictx); - (*swd)->sw_mlen = cri->cri_mlen; - (*swd)->sw_axf = axf; + axf->Init(swd->sw_ictx); + swd->sw_mlen = cri->cri_mlen; + swd->sw_axf = axf; break; -#endif case CRYPTO_AES_128_NIST_GMAC: axf = &auth_hash_nist_gmac_aes_128; @@ -962,21 +956,19 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri) auth4common: len = cri->cri_klen / 8; if (len != 16 && len != 24 && len != 32) { - swcr_freesession_locked(dev, i); - rw_runlock(&swcr_sessions_lock); + swcr_freesession(dev, cses); return EINVAL; } - (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, + swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); - if ((*swd)->sw_ictx == NULL) { - swcr_freesession_locked(dev, i); - rw_runlock(&swcr_sessions_lock); + if (swd->sw_ictx == NULL) { + swcr_freesession(dev, cses); return ENOBUFS; } - axf->Init((*swd)->sw_ictx); - axf->Setkey((*swd)->sw_ictx, cri->cri_key, len); - (*swd)->sw_axf = axf; + axf->Init(swd->sw_ictx); + axf->Setkey(swd->sw_ictx, cri->cri_key, len); + swd->sw_axf = axf; break; case CRYPTO_BLAKE2B: @@ -984,70 +976,56 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri) goto auth5common; case CRYPTO_BLAKE2S: axf = &auth_hash_blake2s; + goto auth5common; + case CRYPTO_POLY1305: + axf = &auth_hash_poly1305; auth5common: - (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, + swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, M_NOWAIT); - if ((*swd)->sw_ictx == NULL) { - swcr_freesession_locked(dev, i); - rw_runlock(&swcr_sessions_lock); + if (swd->sw_ictx == NULL) { + swcr_freesession(dev, cses); return ENOBUFS; } - axf->Setkey((*swd)->sw_ictx, cri->cri_key, + axf->Setkey(swd->sw_ictx, cri->cri_key, cri->cri_klen / 8); - axf->Init((*swd)->sw_ictx); - (*swd)->sw_axf = axf; + axf->Init(swd->sw_ictx); + swd->sw_axf = axf; break; case CRYPTO_DEFLATE_COMP: cxf = &comp_algo_deflate; - (*swd)->sw_cxf = cxf; + swd->sw_cxf = cxf; break; default: - swcr_freesession_locked(dev, i); - rw_runlock(&swcr_sessions_lock); + swcr_freesession(dev, cses); return EINVAL; } - (*swd)->sw_alg = cri->cri_alg; + swd->sw_alg = cri->cri_alg; cri = cri->cri_next; - swd = &((*swd)->sw_next); + ses->swcr_nalgs++; } - rw_runlock(&swcr_sessions_lock); - return 0; -} -static int -swcr_freesession(device_t dev, u_int64_t tid) -{ - int error; - - rw_rlock(&swcr_sessions_lock); - error = swcr_freesession_locked(dev, tid); - rw_runlock(&swcr_sessions_lock); - return error; + if (cri != NULL) { + CRYPTDEB("Bogus session request for three or more algorithms"); + return EINVAL; + } + return 0; } -/* - * Free a session. - */ -static int -swcr_freesession_locked(device_t dev, u_int64_t tid) +static void +swcr_freesession(device_t dev, crypto_session_t cses) { + struct swcr_session *ses; struct swcr_data *swd; struct enc_xform *txf; struct auth_hash *axf; - u_int32_t sid = CRYPTO_SESID2LID(tid); - - if (sid > swcr_sesnum || swcr_sessions == NULL || - swcr_sessions[sid] == NULL) - return EINVAL; + size_t i; - /* Silently accept and return */ - if (sid == 0) - return 0; + ses = crypto_get_driver_session(cses); - while ((swd = swcr_sessions[sid]) != NULL) { - swcr_sessions[sid] = swd->sw_next; + for (i = 0; i < nitems(ses->swcr_algorithms); i++) { + swd = &ses->swcr_algorithms[i]; switch (swd->sw_alg) { case CRYPTO_DES_CBC: @@ -1071,6 +1049,7 @@ swcr_freesession_locked(device_t dev, u_int64_t tid) case CRYPTO_MD5_HMAC: case CRYPTO_SHA1_HMAC: + case CRYPTO_SHA2_224_HMAC: case CRYPTO_SHA2_256_HMAC: case CRYPTO_SHA2_384_HMAC: case CRYPTO_SHA2_512_HMAC: @@ -1105,7 +1084,12 @@ swcr_freesession_locked(device_t dev, u_int64_t tid) case CRYPTO_BLAKE2B: case CRYPTO_BLAKE2S: case CRYPTO_MD5: + case CRYPTO_POLY1305: case CRYPTO_SHA1: + case CRYPTO_SHA2_224: + case CRYPTO_SHA2_256: + case CRYPTO_SHA2_384: + case CRYPTO_SHA2_512: axf = swd->sw_axf; if (swd->sw_ictx) { @@ -1118,10 +1102,7 @@ swcr_freesession_locked(device_t dev, u_int64_t tid) /* Nothing to do */ break; } - - free(swd, M_CRYPTO_DATA); } - return 0; } /* @@ -1130,9 +1111,10 @@ swcr_freesession_locked(device_t dev, u_int64_t tid) static int swcr_process(device_t dev, struct cryptop *crp, int hint) { + struct swcr_session *ses; struct cryptodesc *crd; struct swcr_data *sw; - u_int32_t lid; + size_t i; /* Sanity check */ if (crp == NULL) @@ -1143,15 +1125,7 @@ swcr_process(device_t dev, struct cryptop *crp, int hint) goto done; } - lid = CRYPTO_SESID2LID(crp->crp_sid); - rw_rlock(&swcr_sessions_lock); - if (swcr_sessions == NULL || lid >= swcr_sesnum || lid == 0 || - swcr_sessions[lid] == NULL) { - rw_runlock(&swcr_sessions_lock); - crp->crp_etype = ENOENT; - goto done; - } - rw_runlock(&swcr_sessions_lock); + ses = crypto_get_driver_session(crp->crp_session); /* Go through crypto descriptors, processing as we go */ for (crd = crp->crp_desc; crd; crd = crd->crd_next) { @@ -1165,23 +1139,16 @@ swcr_process(device_t dev, struct cryptop *crp, int hint) * XXX between the various instances of an algorithm (so we can * XXX locate the correct crypto context). */ - rw_rlock(&swcr_sessions_lock); - if (swcr_sessions == NULL) { - rw_runlock(&swcr_sessions_lock); - crp->crp_etype = ENOENT; - goto done; - } - for (sw = swcr_sessions[lid]; - sw && sw->sw_alg != crd->crd_alg; - sw = sw->sw_next) + for (i = 0; i < nitems(ses->swcr_algorithms) && + ses->swcr_algorithms[i].sw_alg != crd->crd_alg; i++) ; - rw_runlock(&swcr_sessions_lock); /* No such context ? */ - if (sw == NULL) { + if (i == nitems(ses->swcr_algorithms)) { crp->crp_etype = EINVAL; goto done; } + sw = &ses->swcr_algorithms[i]; switch (sw->sw_alg) { case CRYPTO_DES_CBC: case CRYPTO_3DES_CBC: @@ -1202,6 +1169,7 @@ swcr_process(device_t dev, struct cryptop *crp, int hint) break; case CRYPTO_MD5_HMAC: case CRYPTO_SHA1_HMAC: + case CRYPTO_SHA2_224_HMAC: case CRYPTO_SHA2_256_HMAC: case CRYPTO_SHA2_384_HMAC: case CRYPTO_SHA2_512_HMAC: @@ -1211,8 +1179,13 @@ swcr_process(device_t dev, struct cryptop *crp, int hint) case CRYPTO_SHA1_KPDK: case CRYPTO_MD5: case CRYPTO_SHA1: + case CRYPTO_SHA2_224: + case CRYPTO_SHA2_256: + case CRYPTO_SHA2_384: + case CRYPTO_SHA2_512: case CRYPTO_BLAKE2B: case CRYPTO_BLAKE2S: + case CRYPTO_POLY1305: if ((crp->crp_etype = swcr_authcompute(crd, sw, crp->crp_buf, crp->crp_flags)) != 0) goto done; @@ -1265,11 +1238,10 @@ swcr_probe(device_t dev) static int swcr_attach(device_t dev) { - rw_init(&swcr_sessions_lock, "swcr_sessions_lock"); memset(hmac_ipad_buffer, HMAC_IPAD_VAL, HMAC_MAX_BLOCK_LEN); memset(hmac_opad_buffer, HMAC_OPAD_VAL, HMAC_MAX_BLOCK_LEN); - swcr_id = crypto_get_driverid(dev, + swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session), CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC); if (swcr_id < 0) { device_printf(dev, "cannot initialize!"); @@ -1285,6 +1257,7 @@ swcr_attach(device_t dev) REGISTER(CRYPTO_NULL_CBC); REGISTER(CRYPTO_MD5_HMAC); REGISTER(CRYPTO_SHA1_HMAC); + REGISTER(CRYPTO_SHA2_224_HMAC); REGISTER(CRYPTO_SHA2_256_HMAC); REGISTER(CRYPTO_SHA2_384_HMAC); REGISTER(CRYPTO_SHA2_512_HMAC); @@ -1294,6 +1267,10 @@ swcr_attach(device_t dev) REGISTER(CRYPTO_SHA1_KPDK); REGISTER(CRYPTO_MD5); REGISTER(CRYPTO_SHA1); + REGISTER(CRYPTO_SHA2_224); + REGISTER(CRYPTO_SHA2_256); + REGISTER(CRYPTO_SHA2_384); + REGISTER(CRYPTO_SHA2_512); REGISTER(CRYPTO_RIJNDAEL128_CBC); REGISTER(CRYPTO_AES_XTS); REGISTER(CRYPTO_AES_ICM); @@ -1307,6 +1284,7 @@ swcr_attach(device_t dev) REGISTER(CRYPTO_BLAKE2B); REGISTER(CRYPTO_BLAKE2S); REGISTER(CRYPTO_CHACHA20); + REGISTER(CRYPTO_POLY1305); #undef REGISTER return 0; @@ -1316,11 +1294,6 @@ static int swcr_detach(device_t dev) { crypto_unregister_all(swcr_id); - rw_wlock(&swcr_sessions_lock); - free(swcr_sessions, M_CRYPTO_DATA); - swcr_sessions = NULL; - rw_wunlock(&swcr_sessions_lock); - rw_destroy(&swcr_sessions_lock); return 0; } diff --git a/freebsd/sys/opencrypto/cryptosoft.h b/freebsd/sys/opencrypto/cryptosoft.h index af78dc18..d88b09d4 100644 --- a/freebsd/sys/opencrypto/cryptosoft.h +++ b/freebsd/sys/opencrypto/cryptosoft.h @@ -55,8 +55,11 @@ struct swcr_data { #define sw_exf SWCR_UN.SWCR_ENC.SW_exf #define sw_size SWCR_UN.SWCR_COMP.SW_size #define sw_cxf SWCR_UN.SWCR_COMP.SW_cxf +}; - struct swcr_data *sw_next; +struct swcr_session { + struct swcr_data swcr_algorithms[2]; + unsigned swcr_nalgs; }; #ifdef _KERNEL diff --git a/freebsd/sys/opencrypto/xform_auth.h b/freebsd/sys/opencrypto/xform_auth.h index 74c6d063..06183868 100644 --- a/freebsd/sys/opencrypto/xform_auth.h +++ b/freebsd/sys/opencrypto/xform_auth.h @@ -69,14 +69,21 @@ extern struct auth_hash auth_hash_key_sha1; extern struct auth_hash auth_hash_hmac_md5; extern struct auth_hash auth_hash_hmac_sha1; extern struct auth_hash auth_hash_hmac_ripemd_160; +extern struct auth_hash auth_hash_hmac_sha2_224; extern struct auth_hash auth_hash_hmac_sha2_256; extern struct auth_hash auth_hash_hmac_sha2_384; extern struct auth_hash auth_hash_hmac_sha2_512; +extern struct auth_hash auth_hash_sha1; +extern struct auth_hash auth_hash_sha2_224; +extern struct auth_hash auth_hash_sha2_256; +extern struct auth_hash auth_hash_sha2_384; +extern struct auth_hash auth_hash_sha2_512; extern struct auth_hash auth_hash_nist_gmac_aes_128; extern struct auth_hash auth_hash_nist_gmac_aes_192; extern struct auth_hash auth_hash_nist_gmac_aes_256; extern struct auth_hash auth_hash_blake2b; extern struct auth_hash auth_hash_blake2s; +extern struct auth_hash auth_hash_poly1305; union authctx { MD5_CTX md5ctx; diff --git a/freebsd/sys/opencrypto/xform_md5.c b/freebsd/sys/opencrypto/xform_md5.c index 47dfc75c..5611ee39 100644 --- a/freebsd/sys/opencrypto/xform_md5.c +++ b/freebsd/sys/opencrypto/xform_md5.c @@ -59,10 +59,10 @@ static int MD5Update_int(void *, const u_int8_t *, u_int16_t); struct auth_hash auth_hash_hmac_md5 = { .type = CRYPTO_MD5_HMAC, .name = "HMAC-MD5", - .keysize = MD5_HMAC_BLOCK_LEN, + .keysize = MD5_BLOCK_LEN, .hashsize = MD5_HASH_LEN, .ctxsize = sizeof(MD5_CTX), - .blocksize = MD5_HMAC_BLOCK_LEN, + .blocksize = MD5_BLOCK_LEN, .Init = (void (*) (void *)) MD5Init, .Update = MD5Update_int, .Final = (void (*) (u_int8_t *, void *)) MD5Final, diff --git a/freebsd/sys/opencrypto/xform_poly1305.c b/freebsd/sys/opencrypto/xform_poly1305.c new file mode 100644 index 00000000..a138a3f5 --- /dev/null +++ b/freebsd/sys/opencrypto/xform_poly1305.c @@ -0,0 +1,93 @@ +#include <machine/rtems-bsd-kernel-space.h> + +/* This file is in the public domain. */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <opencrypto/xform_auth.h> +#include <opencrypto/xform_poly1305.h> + +#include <sodium/crypto_onetimeauth_poly1305.h> + +struct poly1305_xform_ctx { + struct crypto_onetimeauth_poly1305_state state; +}; +CTASSERT(sizeof(union authctx) >= sizeof(struct poly1305_xform_ctx)); + +CTASSERT(POLY1305_KEY_LEN == crypto_onetimeauth_poly1305_KEYBYTES); +CTASSERT(POLY1305_HASH_LEN == crypto_onetimeauth_poly1305_BYTES); + +void +Poly1305_Init(struct poly1305_xform_ctx *polyctx) +{ + /* Nop */ +} + +void +Poly1305_Setkey(struct poly1305_xform_ctx *polyctx, + const uint8_t key[__min_size(POLY1305_KEY_LEN)], size_t klen) +{ + int rc; + + if (klen != POLY1305_KEY_LEN) + panic("%s: Bogus keylen: %u bytes", __func__, (unsigned)klen); + + rc = crypto_onetimeauth_poly1305_init(&polyctx->state, key); + if (rc != 0) + panic("%s: Invariant violated: %d", __func__, rc); +} + +static void +xform_Poly1305_Setkey(void *ctx, const uint8_t *key, uint16_t klen) +{ + Poly1305_Setkey(ctx, key, klen); +} + +int +Poly1305_Update(struct poly1305_xform_ctx *polyctx, const void *data, + size_t len) +{ + int rc; + + rc = crypto_onetimeauth_poly1305_update(&polyctx->state, data, len); + if (rc != 0) + panic("%s: Invariant violated: %d", __func__, rc); + return (0); +} + +static int +xform_Poly1305_Update(void *ctx, const uint8_t *data, uint16_t len) +{ + return (Poly1305_Update(ctx, data, len)); +} + +void +Poly1305_Final(uint8_t digest[__min_size(POLY1305_HASH_LEN)], + struct poly1305_xform_ctx *polyctx) +{ + int rc; + + rc = crypto_onetimeauth_poly1305_final(&polyctx->state, digest); + if (rc != 0) + panic("%s: Invariant violated: %d", __func__, rc); +} + +static void +xform_Poly1305_Final(uint8_t *digest, void *ctx) +{ + Poly1305_Final(digest, ctx); +} + +struct auth_hash auth_hash_poly1305 = { + .type = CRYPTO_POLY1305, + .name = "Poly-1305", + .keysize = POLY1305_KEY_LEN, + .hashsize = POLY1305_HASH_LEN, + .ctxsize = sizeof(struct poly1305_xform_ctx), + .blocksize = crypto_onetimeauth_poly1305_BYTES, + .Init = (void *)Poly1305_Init, + .Setkey = xform_Poly1305_Setkey, + .Update = xform_Poly1305_Update, + .Final = xform_Poly1305_Final, +}; diff --git a/freebsd/sys/opencrypto/xform_poly1305.h b/freebsd/sys/opencrypto/xform_poly1305.h new file mode 100644 index 00000000..7364ecde --- /dev/null +++ b/freebsd/sys/opencrypto/xform_poly1305.h @@ -0,0 +1,16 @@ +/* This file is in the public domain. */ +/* $FreeBSD$ */ +#pragma once + +#include <sys/types.h> + +struct poly1305_xform_ctx; + +void Poly1305_Init(struct poly1305_xform_ctx *); + +void Poly1305_Setkey(struct poly1305_xform_ctx *, + const uint8_t [__min_size(32)], size_t); + +int Poly1305_Update(struct poly1305_xform_ctx *, const void *, size_t); + +void Poly1305_Final(uint8_t [__min_size(16)], struct poly1305_xform_ctx *); diff --git a/freebsd/sys/opencrypto/xform_rmd160.c b/freebsd/sys/opencrypto/xform_rmd160.c index ee344e80..98297308 100644 --- a/freebsd/sys/opencrypto/xform_rmd160.c +++ b/freebsd/sys/opencrypto/xform_rmd160.c @@ -59,10 +59,10 @@ static int RMD160Update_int(void *, const u_int8_t *, u_int16_t); struct auth_hash auth_hash_hmac_ripemd_160 = { .type = CRYPTO_RIPEMD160_HMAC, .name = "HMAC-RIPEMD-160", - .keysize = RIPEMD160_HMAC_BLOCK_LEN, + .keysize = RIPEMD160_BLOCK_LEN, .hashsize = RIPEMD160_HASH_LEN, .ctxsize = sizeof(RMD160_CTX), - .blocksize = RIPEMD160_HMAC_BLOCK_LEN, + .blocksize = RIPEMD160_BLOCK_LEN, .Init = (void (*)(void *)) RMD160Init, .Update = RMD160Update_int, .Final = (void (*)(u_int8_t *, void *)) RMD160Final, diff --git a/freebsd/sys/opencrypto/xform_sha1.c b/freebsd/sys/opencrypto/xform_sha1.c index 974dfb8a..44ac8c0e 100644 --- a/freebsd/sys/opencrypto/xform_sha1.c +++ b/freebsd/sys/opencrypto/xform_sha1.c @@ -57,14 +57,26 @@ static void SHA1Init_int(void *); static int SHA1Update_int(void *, const u_int8_t *, u_int16_t); static void SHA1Final_int(u_int8_t *, void *); +/* Plain hash */ +struct auth_hash auth_hash_sha1 = { + .type = CRYPTO_SHA1, + .name = "SHA1", + .hashsize = SHA1_HASH_LEN, + .ctxsize = sizeof(SHA1_CTX), + .blocksize = SHA1_BLOCK_LEN, + .Init = SHA1Init_int, + .Update = SHA1Update_int, + .Final = SHA1Final_int, +}; + /* Authentication instances */ struct auth_hash auth_hash_hmac_sha1 = { .type = CRYPTO_SHA1_HMAC, .name = "HMAC-SHA1", - .keysize = SHA1_HMAC_BLOCK_LEN, + .keysize = SHA1_BLOCK_LEN, .hashsize = SHA1_HASH_LEN, .ctxsize = sizeof(SHA1_CTX), - .blocksize = SHA1_HMAC_BLOCK_LEN, + .blocksize = SHA1_BLOCK_LEN, .Init = SHA1Init_int, .Update = SHA1Update_int, .Final = SHA1Final_int, diff --git a/freebsd/sys/opencrypto/xform_sha2.c b/freebsd/sys/opencrypto/xform_sha2.c index 7844b8ff..0775247a 100644 --- a/freebsd/sys/opencrypto/xform_sha2.c +++ b/freebsd/sys/opencrypto/xform_sha2.c @@ -50,23 +50,85 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <crypto/sha2/sha224.h> #include <crypto/sha2/sha256.h> #include <crypto/sha2/sha384.h> #include <crypto/sha2/sha512.h> #include <opencrypto/xform_auth.h> +static int SHA224Update_int(void *, const u_int8_t *, u_int16_t); static int SHA256Update_int(void *, const u_int8_t *, u_int16_t); static int SHA384Update_int(void *, const u_int8_t *, u_int16_t); static int SHA512Update_int(void *, const u_int8_t *, u_int16_t); +/* Plain hashes */ +struct auth_hash auth_hash_sha2_224 = { + .type = CRYPTO_SHA2_224, + .name = "SHA2-224", + .hashsize = SHA2_224_HASH_LEN, + .ctxsize = sizeof(SHA224_CTX), + .blocksize = SHA2_224_BLOCK_LEN, + .Init = (void (*)(void *)) SHA224_Init, + .Update = SHA224Update_int, + .Final = (void (*)(u_int8_t *, void *)) SHA224_Final, +}; + +struct auth_hash auth_hash_sha2_256 = { + .type = CRYPTO_SHA2_256, + .name = "SHA2-256", + .keysize = SHA2_256_BLOCK_LEN, + .hashsize = SHA2_256_HASH_LEN, + .ctxsize = sizeof(SHA256_CTX), + .blocksize = SHA2_256_BLOCK_LEN, + .Init = (void (*)(void *)) SHA256_Init, + .Update = SHA256Update_int, + .Final = (void (*)(u_int8_t *, void *)) SHA256_Final, +}; + +struct auth_hash auth_hash_sha2_384 = { + .type = CRYPTO_SHA2_384, + .name = "SHA2-384", + .keysize = SHA2_384_BLOCK_LEN, + .hashsize = SHA2_384_HASH_LEN, + .ctxsize = sizeof(SHA384_CTX), + .blocksize = SHA2_384_BLOCK_LEN, + .Init = (void (*)(void *)) SHA384_Init, + .Update = SHA384Update_int, + .Final = (void (*)(u_int8_t *, void *)) SHA384_Final, +}; + +struct auth_hash auth_hash_sha2_512 = { + .type = CRYPTO_SHA2_512, + .name = "SHA2-512", + .keysize = SHA2_512_BLOCK_LEN, + .hashsize = SHA2_512_HASH_LEN, + .ctxsize = sizeof(SHA512_CTX), + .blocksize = SHA2_512_BLOCK_LEN, + .Init = (void (*)(void *)) SHA512_Init, + .Update = SHA512Update_int, + .Final = (void (*)(u_int8_t *, void *)) SHA512_Final, +}; + /* Authentication instances */ +struct auth_hash auth_hash_hmac_sha2_224 = { + .type = CRYPTO_SHA2_224_HMAC, + .name = "HMAC-SHA2-224", + .keysize = SHA2_224_BLOCK_LEN, + .hashsize = SHA2_224_HASH_LEN, + .ctxsize = sizeof(SHA224_CTX), + .blocksize = SHA2_224_BLOCK_LEN, + .Init = (void (*)(void *)) SHA224_Init, + .Update = SHA224Update_int, + .Final = (void (*)(u_int8_t *, void *)) SHA224_Final, +}; + struct auth_hash auth_hash_hmac_sha2_256 = { .type = CRYPTO_SHA2_256_HMAC, .name = "HMAC-SHA2-256", - .keysize = SHA2_256_HMAC_BLOCK_LEN, + .keysize = SHA2_256_BLOCK_LEN, .hashsize = SHA2_256_HASH_LEN, .ctxsize = sizeof(SHA256_CTX), - .blocksize = SHA2_256_HMAC_BLOCK_LEN, + .blocksize = SHA2_256_BLOCK_LEN, .Init = (void (*)(void *)) SHA256_Init, .Update = SHA256Update_int, .Final = (void (*)(u_int8_t *, void *)) SHA256_Final, @@ -75,10 +137,10 @@ struct auth_hash auth_hash_hmac_sha2_256 = { struct auth_hash auth_hash_hmac_sha2_384 = { .type = CRYPTO_SHA2_384_HMAC, .name = "HMAC-SHA2-384", - .keysize = SHA2_384_HMAC_BLOCK_LEN, + .keysize = SHA2_384_BLOCK_LEN, .hashsize = SHA2_384_HASH_LEN, .ctxsize = sizeof(SHA384_CTX), - .blocksize = SHA2_384_HMAC_BLOCK_LEN, + .blocksize = SHA2_384_BLOCK_LEN, .Init = (void (*)(void *)) SHA384_Init, .Update = SHA384Update_int, .Final = (void (*)(u_int8_t *, void *)) SHA384_Final, @@ -87,10 +149,10 @@ struct auth_hash auth_hash_hmac_sha2_384 = { struct auth_hash auth_hash_hmac_sha2_512 = { .type = CRYPTO_SHA2_512_HMAC, .name = "HMAC-SHA2-512", - .keysize = SHA2_512_HMAC_BLOCK_LEN, + .keysize = SHA2_512_BLOCK_LEN, .hashsize = SHA2_512_HASH_LEN, .ctxsize = sizeof(SHA512_CTX), - .blocksize = SHA2_512_HMAC_BLOCK_LEN, + .blocksize = SHA2_512_BLOCK_LEN, .Init = (void (*)(void *)) SHA512_Init, .Update = SHA512Update_int, .Final = (void (*)(u_int8_t *, void *)) SHA512_Final, @@ -100,6 +162,13 @@ struct auth_hash auth_hash_hmac_sha2_512 = { * And now for auth. */ static int +SHA224Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) +{ + SHA224_Update(ctx, buf, len); + return 0; +} + +static int SHA256Update_int(void *ctx, const u_int8_t *buf, u_int16_t len) { SHA256_Update(ctx, buf, len); |