Overhaul driver/subsystem api's:

o make all crypto drivers have a device_t; pseudo drivers like the s/w
  crypto driver synthesize one
o change the api between the crypto subsystem and drivers to use kobj;
  cryptodev_if.m defines this api
o use the fact that all crypto drivers now have a device_t to add support
  for specifying which of several potential devices to use when doing
  crypto operations
o add new ioctls that allow user apps to select a specific crypto device
  to use (previous ioctls maintained for compatibility)
o overhaul crypto subsystem code to eliminate lots of cruft and hide
  implementation details from drivers
o bring in numerous fixes from Michale Richardson/hifn; mostly for
  795x parts
o add an optional mechanism for mmap'ing the hifn 795x public key h/w
  to user space for use by openssl (not enabled by default)
o update crypto test tools to use new ioctl's and add cmd line options
  to specify a device to use for tests

These changes will also enable much future work on improving the core
crypto subsystem; including proper load balancing and interposing code
between the core and drivers to dispatch small operations to the s/w
driver as appropriate.

These changes were instigated by the work of Michael Richardson.

Reviewed by:	pjd
Approved by:	re
This commit is contained in:
sam 2007-03-21 03:42:51 +00:00
parent 3f9dd9edcb
commit f96ba7ffda
22 changed files with 1250 additions and 744 deletions

View File

@ -1919,6 +1919,7 @@ opencrypto/cast.c optional crypto | ipsec ipsec_esp
opencrypto/criov.c optional crypto
opencrypto/crypto.c optional crypto
opencrypto/cryptodev.c optional cryptodev
opencrypto/cryptodev_if.m optional crypto
opencrypto/cryptosoft.c optional crypto
opencrypto/deflate.c optional crypto
opencrypto/rmd160.c optional crypto | ipsec

View File

@ -332,7 +332,7 @@ MFILES?= dev/acpica/acpi_if.m dev/ata/ata_if.m dev/eisa/eisa_if.m \
dev/sound/midi/mpu_if.m dev/sound/midi/mpufoi_if.m \
dev/sound/midi/synth_if.m dev/usb/usb_if.m isa/isa_if.m \
kern/bus_if.m kern/cpufreq_if.m kern/device_if.m kern/serdev_if.m \
libkern/iconv_converter_if.m opencrypto/crypto_if.m \
libkern/iconv_converter_if.m opencrypto/cryptodev_if.m \
pc98/pc98/canbus_if.m pci/agp_if.m
.for _srcsrc in ${MFILES}

View File

@ -46,6 +46,10 @@ __FBSDID("$FreeBSD$");
#include <crypto/via/padlock.h>
#include <sys/kobj.h>
#include <sys/bus.h>
#include "cryptodev_if.h"
/*
* Technical documentation about the PadLock engine can be found here:
*
@ -59,26 +63,30 @@ struct padlock_softc {
struct mtx sc_sessions_mtx;
};
static struct padlock_softc *padlock_sc;
static int padlock_newsession(void *arg __unused, uint32_t *sidp,
struct cryptoini *cri);
static int padlock_freesession(void *arg __unused, uint64_t tid);
static int padlock_process(void *arg __unused, struct cryptop *crp,
int hint __unused);
static int padlock_newsession(device_t, uint32_t *sidp, struct cryptoini *cri);
static int padlock_freesession(device_t, uint64_t tid);
static int padlock_process(device_t, struct cryptop *crp, int hint __unused);
MALLOC_DEFINE(M_PADLOCK, "padlock_data", "PadLock Data");
static int
padlock_init(void)
static void
padlock_identify(device_t *dev, device_t parent)
{
/* NB: order 10 is so we get attached after h/w devices */
if (device_find_child(parent, "padlock", -1) == NULL &&
BUS_ADD_CHILD(parent, 10, "padlock", -1) == 0)
panic("padlock: could not attach");
}
static int
padlock_probe(device_t dev)
{
struct padlock_softc *sc;
char capp[256];
#if defined(__i386__) && !defined(PC98)
/* If there is no AES support, we has nothing to do here. */
if (!(via_feature_xcrypt & VIA_HAS_AES)) {
printf("PadLock: No ACE support.\n");
device_printf(dev, "No ACE support.\n");
return (EINVAL);
}
strlcpy(capp, "AES-CBC", sizeof(capp));
@ -97,63 +105,53 @@ padlock_init(void)
if (via_feature_xcrypt & VIA_HAS_MM)
strlcat(capp, ",RSA", sizeof(capp));
#endif
printf("PadLock: HW support loaded for %s.\n", capp);
device_set_desc_copy(dev, capp);
return (0);
#else
return (EINVAL);
#endif
}
static int
padlock_attach(device_t dev)
{
struct padlock_softc *sc = device_get_softc(dev);
padlock_sc = sc = malloc(sizeof(*padlock_sc), M_PADLOCK,
M_WAITOK | M_ZERO);
TAILQ_INIT(&sc->sc_sessions);
sc->sc_sid = 1;
sc->sc_cid = crypto_get_driverid(0);
sc->sc_cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE);
if (sc->sc_cid < 0) {
printf("PadLock: Could not get crypto driver id.\n");
free(padlock_sc, M_PADLOCK);
padlock_sc = NULL;
device_printf(dev, "Could not get crypto driver id.\n");
return (ENOMEM);
}
mtx_init(&sc->sc_sessions_mtx, "padlock_mtx", NULL, MTX_DEF);
crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0, padlock_newsession,
padlock_freesession, padlock_process, NULL);
crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0, padlock_newsession,
padlock_freesession, padlock_process, NULL);
crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0, padlock_newsession,
padlock_freesession, padlock_process, NULL);
crypto_register(sc->sc_cid, CRYPTO_RIPEMD160_HMAC, 0, 0,
padlock_newsession, padlock_freesession, padlock_process, NULL);
crypto_register(sc->sc_cid, CRYPTO_SHA2_256_HMAC, 0, 0,
padlock_newsession, padlock_freesession, padlock_process, NULL);
crypto_register(sc->sc_cid, CRYPTO_SHA2_384_HMAC, 0, 0,
padlock_newsession, padlock_freesession, padlock_process, NULL);
crypto_register(sc->sc_cid, CRYPTO_SHA2_512_HMAC, 0, 0,
padlock_newsession, padlock_freesession, padlock_process, NULL);
crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_RIPEMD160_HMAC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_SHA2_256_HMAC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_SHA2_384_HMAC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_SHA2_512_HMAC, 0, 0);
return (0);
}
static int
padlock_destroy(void)
padlock_detach(device_t dev)
{
struct padlock_softc *sc = padlock_sc;
struct padlock_softc *sc = device_get_softc(dev);
struct padlock_session *ses;
u_int active = 0;
if (sc == NULL)
return (0);
mtx_lock(&sc->sc_sessions_mtx);
TAILQ_FOREACH(ses, &sc->sc_sessions, ses_next) {
if (ses->ses_used)
active++;
if (ses->ses_used) {
mtx_unlock(&sc->sc_sessions_mtx);
device_printf(dev,
"Cannot detach, sessions still active.\n");
return (EBUSY);
}
}
if (active > 0) {
mtx_unlock(&sc->sc_sessions_mtx);
printf("PadLock: Cannot destroy, %u sessions active.\n",
active);
return (EBUSY);
}
padlock_sc = NULL;
for (ses = TAILQ_FIRST(&sc->sc_sessions); ses != NULL;
ses = TAILQ_FIRST(&sc->sc_sessions)) {
TAILQ_REMOVE(&sc->sc_sessions, ses, ses_next);
@ -161,19 +159,18 @@ padlock_destroy(void)
}
mtx_destroy(&sc->sc_sessions_mtx);
crypto_unregister_all(sc->sc_cid);
free(sc, M_PADLOCK);
return (0);
}
static int
padlock_newsession(void *arg __unused, uint32_t *sidp, struct cryptoini *cri)
padlock_newsession(device_t dev, uint32_t *sidp, struct cryptoini *cri)
{
struct padlock_softc *sc = padlock_sc;
struct padlock_softc *sc = device_get_softc(dev);
struct padlock_session *ses = NULL;
struct cryptoini *encini, *macini;
int error;
if (sc == NULL || sidp == NULL || cri == NULL)
if (sidp == NULL || cri == NULL)
return (EINVAL);
encini = macini = NULL;
@ -255,14 +252,12 @@ padlock_newsession(void *arg __unused, uint32_t *sidp, struct cryptoini *cri)
}
static int
padlock_freesession(void *arg __unused, uint64_t tid)
padlock_freesession(device_t dev, uint64_t tid)
{
struct padlock_softc *sc = padlock_sc;
struct padlock_softc *sc = device_get_softc(dev);
struct padlock_session *ses;
uint32_t sid = ((uint32_t)tid) & 0xffffffff;
if (sc == NULL)
return (EINVAL);
mtx_lock(&sc->sc_sessions_mtx);
TAILQ_FOREACH(ses, &sc->sc_sessions, ses_next) {
if (ses->ses_id == sid)
@ -282,9 +277,9 @@ padlock_freesession(void *arg __unused, uint64_t tid)
}
static int
padlock_process(void *arg __unused, struct cryptop *crp, int hint __unused)
padlock_process(device_t dev, struct cryptop *crp, int hint __unused)
{
struct padlock_softc *sc = padlock_sc;
struct padlock_softc *sc = device_get_softc(dev);
struct padlock_session *ses = NULL;
struct cryptodesc *crd, *enccrd, *maccrd;
int error = 0;
@ -373,28 +368,27 @@ padlock_process(void *arg __unused, struct cryptop *crp, int hint __unused)
return (error);
}
static int
padlock_modevent(module_t mod, int type, void *unused __unused)
{
int error;
static device_method_t padlock_methods[] = {
DEVMETHOD(device_identify, padlock_identify),
DEVMETHOD(device_probe, padlock_probe),
DEVMETHOD(device_attach, padlock_attach),
DEVMETHOD(device_detach, padlock_detach),
error = EOPNOTSUPP;
switch (type) {
case MOD_LOAD:
error = padlock_init();
break;
case MOD_UNLOAD:
error = padlock_destroy();
break;
}
return (error);
}
DEVMETHOD(cryptodev_newsession, padlock_newsession),
DEVMETHOD(cryptodev_freesession,padlock_freesession),
DEVMETHOD(cryptodev_process, padlock_process),
static moduledata_t padlock_mod = {
"padlock",
padlock_modevent,
0
{0, 0},
};
DECLARE_MODULE(padlock, padlock_mod, SI_SUB_DRIVERS, SI_ORDER_ANY);
static driver_t padlock_driver = {
"padlock",
padlock_methods,
sizeof(struct padlock_softc),
};
static devclass_t padlock_devclass;
/* XXX where to attach */
DRIVER_MODULE(padlock, nexus, padlock_driver, padlock_devclass, 0, 0);
MODULE_VERSION(padlock, 1);
MODULE_DEPEND(padlock, crypto, 1, 1, 1);

View File

@ -70,6 +70,9 @@ __FBSDID("$FreeBSD$");
#include <opencrypto/cryptodev.h>
#include <sys/random.h>
#include <sys/kobj.h>
#include "cryptodev_if.h"
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@ -80,6 +83,13 @@ __FBSDID("$FreeBSD$");
#include <dev/hifn/hifn7751reg.h>
#include <dev/hifn/hifn7751var.h>
#ifdef HIFN_VULCANDEV
#include <sys/conf.h>
#include <sys/uio.h>
static struct cdevsw vulcanpk_cdevsw; /* forward declaration */
#endif
/*
* Prototypes and count for the pci_device structure
*/
@ -90,6 +100,10 @@ static int hifn_suspend(device_t);
static int hifn_resume(device_t);
static void hifn_shutdown(device_t);
static int hifn_newsession(device_t, u_int32_t *, struct cryptoini *);
static int hifn_freesession(device_t, u_int64_t);
static int hifn_process(device_t, struct cryptop *, int);
static device_method_t hifn_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, hifn_probe),
@ -103,6 +117,11 @@ static device_method_t hifn_methods[] = {
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
/* crypto device methods */
DEVMETHOD(cryptodev_newsession, hifn_newsession),
DEVMETHOD(cryptodev_freesession,hifn_freesession),
DEVMETHOD(cryptodev_process, hifn_process),
{ 0, 0 }
};
static driver_t hifn_driver = {
@ -132,9 +151,6 @@ static void hifn_sessions(struct hifn_softc *);
static void hifn_intr(void *);
static u_int hifn_write_command(struct hifn_command *, u_int8_t *);
static u_int32_t hifn_next_signature(u_int32_t a, u_int cnt);
static int hifn_newsession(void *, u_int32_t *, struct cryptoini *);
static int hifn_freesession(void *, u_int64_t);
static int hifn_process(void *, struct cryptop *, int);
static void hifn_callback(struct hifn_softc *, struct hifn_command *, u_int8_t *);
static int hifn_crypto(struct hifn_softc *, struct hifn_command *, struct cryptop *, int);
static int hifn_readramaddr(struct hifn_softc *, int, u_int8_t *);
@ -279,6 +295,12 @@ checkmaxmin(device_t dev, const char *what, u_int v, u_int min, u_int max)
* always will allow the card to work. If a card is using the PCI
* bus clock and in a 33MHz slot then it will be operating at half
* speed until the correct information is provided.
*
* We use a default setting of "ext66" because according to Mike Ham
* of HiFn, almost every board in existence has an external crystal
* populated at 66Mhz. Using PCI can be a problem on modern motherboards,
* because PCI33 can have clocks from 0 to 33Mhz, and some have
* non-PCI-compliant spread-spectrum clocks, which can confuse the pll.
*/
static void
hifn_getpllconfig(device_t dev, u_int *pll)
@ -290,7 +312,7 @@ hifn_getpllconfig(device_t dev, u_int *pll)
if (resource_string_value("hifn", device_get_unit(dev),
"pllconfig", &pllspec))
pllspec = "pci66";
pllspec = "ext66";
fl = 33, fh = 66;
pllconfig = 0;
if (strncmp(pllspec, "ext", 3) == 0) {
@ -559,7 +581,7 @@ hifn_attach(device_t dev)
2 + 2*((sc->sc_pllconfig & HIFN_PLL_ND) >> 11));
printf("\n");
sc->sc_cid = crypto_get_driverid(0);
sc->sc_cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE);
if (sc->sc_cid < 0) {
device_printf(dev, "could not get crypto driver id\n");
goto fail_intr;
@ -571,26 +593,17 @@ hifn_attach(device_t dev)
switch (ena) {
case HIFN_PUSTAT_ENA_2:
crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0,
hifn_newsession, hifn_freesession, hifn_process, sc);
crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0,
hifn_newsession, hifn_freesession, hifn_process, sc);
crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0);
if (sc->sc_flags & HIFN_HAS_AES)
crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0,
hifn_newsession, hifn_freesession,
hifn_process, sc);
crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
/*FALLTHROUGH*/
case HIFN_PUSTAT_ENA_1:
crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0,
hifn_newsession, hifn_freesession, hifn_process, sc);
crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0,
hifn_newsession, hifn_freesession, hifn_process, sc);
crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0,
hifn_newsession, hifn_freesession, hifn_process, sc);
crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0,
hifn_newsession, hifn_freesession, hifn_process, sc);
crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0,
hifn_newsession, hifn_freesession, hifn_process, sc);
crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
break;
}
@ -790,6 +803,12 @@ hifn_init_pubrng(struct hifn_softc *sc)
WRITE_REG_1(sc, HIFN_1_PUB_IEN, HIFN_PUBIEN_DONE);
sc->sc_dmaier |= HIFN_DMAIER_PUBDONE;
WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
#ifdef HIFN_VULCANDEV
sc->sc_pkdev = make_dev(&vulcanpk_cdevsw, 0,
UID_ROOT, GID_WHEEL, 0666,
"vulcanpk");
sc->sc_pkdev->si_drv1 = sc;
#endif
}
return (0);
@ -804,6 +823,7 @@ hifn_rng(void *vsc)
int i;
if (sc->sc_flags & HIFN_IS_7811) {
/* ONLY VALID ON 7811!!!! */
for (i = 0; i < 5; i++) {
sts = READ_REG_1(sc, HIFN_1_7811_RNGSTS);
if (sts & HIFN_7811_RNGSTS_UFL) {
@ -846,10 +866,15 @@ static void
hifn_puc_wait(struct hifn_softc *sc)
{
int i;
int reg = HIFN_0_PUCTRL;
if (sc->sc_flags & HIFN_IS_7956) {
reg = HIFN_0_PUCTRL2;
}
for (i = 5000; i > 0; i--) {
DELAY(1);
if (!(READ_REG_0(sc, HIFN_0_PUCTRL) & HIFN_PUCTRL_RESET))
if (!(READ_REG_0(sc, reg) & HIFN_PUCTRL_RESET))
break;
}
if (!i)
@ -863,7 +888,13 @@ static void
hifn_reset_puc(struct hifn_softc *sc)
{
/* Reset processing unit */
WRITE_REG_0(sc, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
int reg = HIFN_0_PUCTRL;
if (sc->sc_flags & HIFN_IS_7956) {
reg = HIFN_0_PUCTRL2;
}
WRITE_REG_0(sc, reg, HIFN_PUCTRL_DMAENA);
hifn_puc_wait(sc);
}
@ -932,7 +963,16 @@ hifn_reset_board(struct hifn_softc *sc, int full)
}
if (reg == 1000)
printf(": cram init timeout\n");
} else {
/* set up DMA configuration register #2 */
/* turn off all PK and BAR0 swaps */
WRITE_REG_1(sc, HIFN_1_DMA_CNFG2,
(3 << HIFN_DMACNFG2_INIT_WRITE_BURST_SHIFT)|
(3 << HIFN_DMACNFG2_INIT_READ_BURST_SHIFT)|
(2 << HIFN_DMACNFG2_TGT_WRITE_BURST_SHIFT)|
(2 << HIFN_DMACNFG2_TGT_READ_BURST_SHIFT));
}
}
static u_int32_t
@ -1170,13 +1210,15 @@ hifn_init_pci_registers(struct hifn_softc *sc)
/* turn off the clocks and insure bypass is set */
pll = READ_REG_1(sc, HIFN_1_PLL);
pll = (pll &~ (HIFN_PLL_PK_CLK_SEL | HIFN_PLL_PE_CLK_SEL))
| HIFN_PLL_BP;
| HIFN_PLL_BP | HIFN_PLL_MBSET;
WRITE_REG_1(sc, HIFN_1_PLL, pll);
DELAY(10*1000); /* 10ms */
/* change configuration */
pll = (pll &~ HIFN_PLL_CONFIG) | sc->sc_pllconfig;
WRITE_REG_1(sc, HIFN_1_PLL, pll);
DELAY(10*1000); /* 10ms */
/* disable bypass */
pll &= ~HIFN_PLL_BP;
WRITE_REG_1(sc, HIFN_1_PLL, pll);
@ -1657,6 +1699,21 @@ hifn_dmamap_aligned(struct hifn_operand *op)
return (1);
}
static __inline int
hifn_dmamap_dstwrap(struct hifn_softc *sc, int idx)
{
struct hifn_dma *dma = sc->sc_dma;
if (++idx == HIFN_D_DST_RSIZE) {
dma->dstr[idx].l = htole32(HIFN_D_VALID | HIFN_D_JUMP |
HIFN_D_MASKDONEIRQ);
HIFN_DSTR_SYNC(sc, idx,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
idx = 0;
}
return (idx);
}
static int
hifn_dmamap_load_dst(struct hifn_softc *sc, struct hifn_command *cmd)
{
@ -1674,13 +1731,7 @@ hifn_dmamap_load_dst(struct hifn_softc *sc, struct hifn_command *cmd)
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
used++;
if (++idx == HIFN_D_DST_RSIZE) {
dma->dstr[idx].l = htole32(HIFN_D_VALID |
HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
HIFN_DSTR_SYNC(sc, idx,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
idx = 0;
}
idx = hifn_dmamap_dstwrap(sc, idx);
}
if (cmd->sloplen == 0) {
@ -1702,13 +1753,7 @@ hifn_dmamap_load_dst(struct hifn_softc *sc, struct hifn_command *cmd)
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
used++;
if (++idx == HIFN_D_DST_RSIZE) {
dma->dstr[idx].l = htole32(HIFN_D_VALID |
HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
HIFN_DSTR_SYNC(sc, idx,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
idx = 0;
}
idx = hifn_dmamap_dstwrap(sc, idx);
}
}
dma->dstr[idx].p = htole32(p);
@ -1716,19 +1761,28 @@ hifn_dmamap_load_dst(struct hifn_softc *sc, struct hifn_command *cmd)
HIFN_DSTR_SYNC(sc, idx, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
used++;
if (++idx == HIFN_D_DST_RSIZE) {
dma->dstr[idx].l = htole32(HIFN_D_VALID | HIFN_D_JUMP |
HIFN_D_MASKDONEIRQ);
HIFN_DSTR_SYNC(sc, idx,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
idx = 0;
}
idx = hifn_dmamap_dstwrap(sc, idx);
dma->dsti = idx;
dma->dstu += used;
return (idx);
}
static __inline int
hifn_dmamap_srcwrap(struct hifn_softc *sc, int idx)
{
struct hifn_dma *dma = sc->sc_dma;
if (++idx == HIFN_D_SRC_RSIZE) {
dma->srcr[idx].l = htole32(HIFN_D_VALID |
HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
idx = 0;
}
return (idx);
}
static int
hifn_dmamap_load_src(struct hifn_softc *sc, struct hifn_command *cmd)
{
@ -1748,13 +1802,7 @@ hifn_dmamap_load_src(struct hifn_softc *sc, struct hifn_command *cmd)
HIFN_SRCR_SYNC(sc, idx,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
if (++idx == HIFN_D_SRC_RSIZE) {
dma->srcr[idx].l = htole32(HIFN_D_VALID |
HIFN_D_JUMP | HIFN_D_MASKDONEIRQ);
HIFN_SRCR_SYNC(sc, HIFN_D_SRC_RSIZE,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
idx = 0;
}
idx = hifn_dmamap_srcwrap(sc, idx);
}
dma->srci = idx;
dma->srcu += src->nsegs;
@ -1782,7 +1830,7 @@ hifn_crypto(
int hint)
{
struct hifn_dma *dma = sc->sc_dma;
u_int32_t cmdlen;
u_int32_t cmdlen, csr;
int cmdi, resi, err = 0;
/*
@ -1995,10 +2043,6 @@ hifn_crypto(
HIFN_CMDR_SYNC(sc, cmdi,
BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
dma->cmdu++;
if (sc->sc_c_busy == 0) {
WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_C_CTRL_ENA);
sc->sc_c_busy = 1;
}
/*
* We don't worry about missing an interrupt (which a "command wait"
@ -2014,10 +2058,6 @@ hifn_crypto(
hifnstats.hst_ibytes += cmd->src_mapsize;
hifn_dmamap_load_src(sc, cmd);
if (sc->sc_s_busy == 0) {
WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_S_CTRL_ENA);
sc->sc_s_busy = 1;
}
/*
* Unlike other descriptors, we don't mask done interrupt from
@ -2054,20 +2094,31 @@ hifn_crypto(
HIFN_RESR_SYNC(sc, resi,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
dma->resu++;
if (sc->sc_r_busy == 0) {
WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_R_CTRL_ENA);
sc->sc_r_busy = 1;
}
if (cmd->sloplen)
cmd->slopidx = resi;
hifn_dmamap_load_dst(sc, cmd);
csr = 0;
if (sc->sc_c_busy == 0) {
csr |= HIFN_DMACSR_C_CTRL_ENA;
sc->sc_c_busy = 1;
}
if (sc->sc_s_busy == 0) {
csr |= HIFN_DMACSR_S_CTRL_ENA;
sc->sc_s_busy = 1;
}
if (sc->sc_r_busy == 0) {
csr |= HIFN_DMACSR_R_CTRL_ENA;
sc->sc_r_busy = 1;
}
if (sc->sc_d_busy == 0) {
WRITE_REG_1(sc, HIFN_1_DMA_CSR, HIFN_DMACSR_D_CTRL_ENA);
csr |= HIFN_DMACSR_D_CTRL_ENA;
sc->sc_d_busy = 1;
}
if (csr)
WRITE_REG_1(sc, HIFN_1_DMA_CSR, csr);
#ifdef HIFN_DEBUG
if (hifn_debug) {
@ -2292,10 +2343,10 @@ hifn_intr(void *arg)
* id on successful allocation.
*/
static int
hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
hifn_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
{
struct hifn_softc *sc = device_get_softc(dev);
struct cryptoini *c;
struct hifn_softc *sc = arg;
int mac = 0, cry = 0, sesn;
struct hifn_session *ses = NULL;
@ -2303,11 +2354,14 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
if (sidp == NULL || cri == NULL || sc == NULL)
return (EINVAL);
HIFN_LOCK(sc);
if (sc->sc_sessions == NULL) {
ses = sc->sc_sessions = (struct hifn_session *)malloc(
sizeof(*ses), M_DEVBUF, M_NOWAIT);
if (ses == NULL)
if (ses == NULL) {
HIFN_UNLOCK(sc);
return (ENOMEM);
}
sesn = 0;
sc->sc_nsessions = 1;
} else {
@ -2322,8 +2376,10 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
sesn = sc->sc_nsessions;
ses = (struct hifn_session *)malloc((sesn + 1) *
sizeof(*ses), M_DEVBUF, M_NOWAIT);
if (ses == NULL)
if (ses == NULL) {
HIFN_UNLOCK(sc);
return (ENOMEM);
}
bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
bzero(sc->sc_sessions, sesn * sizeof(*ses));
free(sc->sc_sessions, M_DEVBUF);
@ -2332,6 +2388,8 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
sc->sc_nsessions++;
}
}
HIFN_UNLOCK(sc);
bzero(ses, sizeof(*ses));
ses->hs_used = 1;
@ -2389,28 +2447,32 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
* XXX to blow away any keys already stored there.
*/
static int
hifn_freesession(void *arg, u_int64_t tid)
hifn_freesession(device_t dev, u_int64_t tid)
{
struct hifn_softc *sc = arg;
int session;
struct hifn_softc *sc = device_get_softc(dev);
int session, error;
u_int32_t sid = CRYPTO_SESID2LID(tid);
KASSERT(sc != NULL, ("hifn_freesession: null softc"));
if (sc == NULL)
return (EINVAL);
HIFN_LOCK(sc);
session = HIFN_SESSION(sid);
if (session >= sc->sc_nsessions)
return (EINVAL);
if (session < sc->sc_nsessions) {
bzero(&sc->sc_sessions[session], sizeof(struct hifn_session));
error = 0;
} else
error = EINVAL;
HIFN_UNLOCK(sc);
bzero(&sc->sc_sessions[session], sizeof(sc->sc_sessions[session]));
return (0);
return (error);
}
static int
hifn_process(void *arg, struct cryptop *crp, int hint)
hifn_process(device_t dev, struct cryptop *crp, int hint)
{
struct hifn_softc *sc = arg;
struct hifn_softc *sc = device_get_softc(dev);
struct hifn_command *cmd = NULL;
int session, err, ivlen;
struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
@ -2858,3 +2920,41 @@ hifn_write_reg_1(struct hifn_softc *sc, bus_size_t reg, u_int32_t val)
}
bus_space_write_4(sc->sc_st1, sc->sc_sh1, reg, val);
}
#ifdef HIFN_VULCANDEV
/*
* this code provides support for mapping the PK engine's register
* into a userspace program.
*
*/
static int
vulcanpk_mmap(struct cdev *dev, vm_offset_t offset,
vm_paddr_t *paddr, int nprot)
{
struct hifn_softc *sc;
vm_paddr_t pd;
void *b;
sc = dev->si_drv1;
pd = rman_get_start(sc->sc_bar1res);
b = rman_get_virtual(sc->sc_bar1res);
#if 0
printf("vpk mmap: %p(%08x) offset=%d\n", b, pd, offset);
hexdump(b, HIFN_1_PUB_MEMEND, "vpk", 0);
#endif
if (offset == 0) {
*paddr = pd;
return (0);
}
return (-1);
}
static struct cdevsw vulcanpk_cdevsw = {
.d_version = D_VERSION,
.d_mmap = vulcanpk_mmap,
.d_name = "vulcanpk",
};
#endif /* HIFN_VULCANDEV */

View File

@ -118,7 +118,10 @@ typedef struct hifn_desc {
#define HIFN_0_PUSTAT 0x14 /* Processing Unit Status/Chip ID */
#define HIFN_0_FIFOSTAT 0x18 /* FIFO Status */
#define HIFN_0_FIFOCNFG 0x1c /* FIFO Configuration */
#define HIFN_0_SPACESIZE 0x20 /* Register space size */
#define HIFN_0_PUCTRL2 0x28 /* Processing Unit Control (2nd map) */
#define HIFN_0_MUTE1 0x80
#define HIFN_0_MUTE2 0x90
#define HIFN_0_SPACESIZE 0x100 /* Register space size */
/* Processing Unit Control Register (HIFN_0_PUCTRL) */
#define HIFN_PUCTRL_CLRSRCFIFO 0x0010 /* clear source fifo */
@ -200,7 +203,7 @@ typedef struct hifn_desc {
#define HIFN_FIFOSTAT_DST 0x007f /* Destination FIFO available */
/* FIFO Configuration Register (HIFN_0_FIFOCNFG) */
#define HIFN_FIFOCNFG_THRESHOLD 0x0400 /* must be written as 1 */
#define HIFN_FIFOCNFG_THRESHOLD 0x0400 /* must be written as this value */
/*
* DMA Interface Registers (offset from BASEREG1)
@ -217,17 +220,21 @@ typedef struct hifn_desc {
#define HIFN_1_7811_RNGCFG 0x64 /* 7811: rng config */
#define HIFN_1_7811_RNGDAT 0x68 /* 7811: rng data */
#define HIFN_1_7811_RNGSTS 0x6c /* 7811: rng status */
#define HIFN_1_DMA_CNFG2 0x6c /* 7955/7956: dma config #2 */
#define HIFN_1_7811_MIPSRST 0x94 /* 7811: MIPS reset */
#define HIFN_1_REVID 0x98 /* Revision ID */
#define HIFN_1_PUB_RESET 0x204 /* Public/RNG Reset */
#define HIFN_1_PUB_BASE 0x300 /* Public Base Address */
#define HIFN_1_PUB_OPLEN 0x304 /* Public Operand Length */
#define HIFN_1_PUB_OP 0x308 /* Public Operand */
#define HIFN_1_PUB_STATUS 0x30c /* Public Status */
#define HIFN_1_PUB_IEN 0x310 /* Public Interrupt nable */
#define HIFN_1_PUB_OPLEN 0x304 /* 7951-compat Public Operand Length */
#define HIFN_1_PUB_OP 0x308 /* 7951-compat Public Operand */
#define HIFN_1_PUB_STATUS 0x30c /* 7951-compat Public Status */
#define HIFN_1_PUB_IEN 0x310 /* Public Interrupt enable */
#define HIFN_1_RNG_CONFIG 0x314 /* RNG config */
#define HIFN_1_RNG_DATA 0x318 /* RNG data */
#define HIFN_1_PUB_MODE 0x320 /* PK mode */
#define HIFN_1_PUB_FIFO_OPLEN 0x380 /* first element of oplen fifo */
#define HIFN_1_PUB_FIFO_OP 0x384 /* first element of op fifo */
#define HIFN_1_PUB_MEM 0x400 /* start of Public key memory */
#define HIFN_1_PUB_MEMEND 0xbff /* end of Public key memory */
@ -305,6 +312,16 @@ typedef struct hifn_desc {
#define HIFN_DMACNFG_DMARESET 0x00000002 /* DMA Reset # */
#define HIFN_DMACNFG_MSTRESET 0x00000001 /* Master Reset # */
/* DMA Configuration Register (HIFN_1_DMA_CNFG2) */
#define HIFN_DMACNFG2_PKSWAP32 (1 << 19) /* swap the OPLEN/OP reg */
#define HIFN_DMACNFG2_PKSWAP8 (1 << 18) /* swap the bits of OPLEN/OP */
#define HIFN_DMACNFG2_BAR0_SWAP32 (1<<17) /* swap the bytes of BAR0 */
#define HIFN_DMACNFG2_BAR1_SWAP8 (1<<16) /* swap the bits of BAR0 */
#define HIFN_DMACNFG2_INIT_WRITE_BURST_SHIFT 12
#define HIFN_DMACNFG2_INIT_READ_BURST_SHIFT 8
#define HIFN_DMACNFG2_TGT_WRITE_BURST_SHIFT 4
#define HIFN_DMACNFG2_TGT_READ_BURST_SHIFT 0
/* 7811 RNG Enable Register (HIFN_1_7811_RNGENA) */
#define HIFN_7811_RNGENA_ENA 0x00000001 /* enable RNG */
@ -358,6 +375,11 @@ typedef struct hifn_desc {
/* Public status register (HIFN_1_PUB_STATUS) */
#define HIFN_PUBSTS_DONE 0x00000001 /* operation done */
#define HIFN_PUBSTS_CARRY 0x00000002 /* carry */
#define HIFN_PUBSTS_FIFO_EMPTY 0x00000100 /* fifo empty */
#define HIFN_PUBSTS_FIFO_FULL 0x00000200 /* fifo full */
#define HIFN_PUBSTS_FIFO_OVFL 0x00000400 /* fifo overflow */
#define HIFN_PUBSTS_FIFO_WRITE 0x000f0000 /* fifo write */
#define HIFN_PUBSTS_FIFO_READ 0x0f000000 /* fifo read */
/* Public interrupt enable register (HIFN_1_PUB_IEN) */
#define HIFN_PUBIEN_DONE 0x00000001 /* operation done interrupt */
@ -407,6 +429,13 @@ typedef struct hifn_desc {
*/
#define HIFN_PLL_CONFIG (HIFN_PLL_IS|HIFN_PLL_ND|HIFN_PLL_REF_SEL)
/*
* Public Key Engine Mode Register
*/
#define HIFN_PKMODE_HOSTINVERT (1 << 0) /* HOST INVERT */
#define HIFN_PKMODE_ENHANCED (1 << 1) /* Enable enhanced mode */
/*********************************************************************
* Structs for board commands
*

View File

@ -183,6 +183,9 @@ struct hifn_softc {
int sc_needwakeup; /* ops q'd wating on resources */
int sc_curbatch; /* # ops submitted w/o int */
int sc_suspended;
#ifdef HIFN_VULCANDEV
struct cdev *sc_pkdev;
#endif
};
#define HIFN_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)

View File

@ -59,6 +59,9 @@ __FBSDID("$FreeBSD$");
#include <opencrypto/cryptosoft.h>
#include <sys/md5.h>
#include <sys/random.h>
#include <sys/kobj.h>
#include "cryptodev_if.h"
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@ -83,6 +86,10 @@ static int safe_suspend(device_t);
static int safe_resume(device_t);
static void safe_shutdown(device_t);
static int safe_newsession(device_t, u_int32_t *, struct cryptoini *);
static int safe_freesession(device_t, u_int64_t);
static int safe_process(device_t, struct cryptop *, int);
static device_method_t safe_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, safe_probe),
@ -96,6 +103,11 @@ static device_method_t safe_methods[] = {
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
/* crypto device methods */
DEVMETHOD(cryptodev_newsession, safe_newsession),
DEVMETHOD(cryptodev_freesession,safe_freesession),
DEVMETHOD(cryptodev_process, safe_process),
{ 0, 0 }
};
static driver_t safe_driver = {
@ -112,9 +124,6 @@ MODULE_DEPEND(safe, rndtest, 1, 1, 1);
#endif
static void safe_intr(void *);
static int safe_newsession(void *, u_int32_t *, struct cryptoini *);
static int safe_freesession(void *, u_int64_t);
static int safe_process(void *, struct cryptop *, int);
static void safe_callback(struct safe_softc *, struct safe_ringentry *);
static void safe_feed(struct safe_softc *, struct safe_ringentry *);
static void safe_mcopy(struct mbuf *, struct mbuf *, u_int);
@ -270,7 +279,7 @@ safe_attach(device_t dev)
goto bad2;
}
sc->sc_cid = crypto_get_driverid(0);
sc->sc_cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE);
if (sc->sc_cid < 0) {
device_printf(dev, "could not get crypto driver id\n");
goto bad3;
@ -388,39 +397,30 @@ safe_attach(device_t dev)
#if 0
printf(" key");
sc->sc_flags |= SAFE_FLAGS_KEY;
crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0,
safe_kprocess, sc);
crypto_kregister(sc->sc_cid, CRK_MOD_EXP_CRT, 0,
safe_kprocess, sc);
crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0);
crypto_kregister(sc->sc_cid, CRK_MOD_EXP_CRT, 0);
#endif
}
if (devinfo & SAFE_DEVINFO_DES) {
printf(" des/3des");
crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0,
safe_newsession, safe_freesession, safe_process, sc);
crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0,
safe_newsession, safe_freesession, safe_process, sc);
crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
}
if (devinfo & SAFE_DEVINFO_AES) {
printf(" aes");
crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0,
safe_newsession, safe_freesession, safe_process, sc);
crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0);
}
if (devinfo & SAFE_DEVINFO_MD5) {
printf(" md5");
crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0,
safe_newsession, safe_freesession, safe_process, sc);
crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
}
if (devinfo & SAFE_DEVINFO_SHA1) {
printf(" sha1");
crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0,
safe_newsession, safe_freesession, safe_process, sc);
crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
}
printf(" null");
crypto_register(sc->sc_cid, CRYPTO_NULL_CBC, 0, 0,
safe_newsession, safe_freesession, safe_process, sc);
crypto_register(sc->sc_cid, CRYPTO_NULL_HMAC, 0, 0,
safe_newsession, safe_freesession, safe_process, sc);
crypto_register(sc->sc_cid, CRYPTO_NULL_CBC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_NULL_HMAC, 0, 0);
/* XXX other supported algorithms */
printf("\n");
@ -710,10 +710,10 @@ safe_setup_mackey(struct safe_session *ses, int algo, caddr_t key, int klen)
* id on successful allocation.
*/
static int
safe_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
safe_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
{
struct safe_softc *sc = device_get_softc(dev);
struct cryptoini *c, *encini = NULL, *macini = NULL;
struct safe_softc *sc = arg;
struct safe_session *ses = NULL;
int sesn;
@ -826,9 +826,9 @@ safe_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
* Deallocate a session.
*/
static int
safe_freesession(void *arg, u_int64_t tid)
safe_freesession(device_t dev, u_int64_t tid)
{
struct safe_softc *sc = arg;
struct safe_softc *sc = device_get_softc(dev);
int session, ret;
u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
@ -859,10 +859,10 @@ safe_op_cb(void *arg, bus_dma_segment_t *seg, int nsegs, bus_size_t mapsize, int
}
static int
safe_process(void *arg, struct cryptop *crp, int hint)
safe_process(device_t dev, struct cryptop *crp, int hint)
{
struct safe_softc *sc = device_get_softc(dev);
int err = 0, i, nicealign, uniform;
struct safe_softc *sc = arg;
struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
int bypass, oplen, ivsize;
caddr_t iv;

View File

@ -73,6 +73,9 @@ __FBSDID("$FreeBSD$");
#include <opencrypto/cryptosoft.h>
#include <sys/md5.h>
#include <sys/random.h>
#include <sys/kobj.h>
#include "cryptodev_if.h"
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
@ -106,6 +109,11 @@ static int ubsec_suspend(device_t);
static int ubsec_resume(device_t);
static void ubsec_shutdown(device_t);
static int ubsec_newsession(device_t, u_int32_t *, struct cryptoini *);
static int ubsec_freesession(device_t, u_int64_t);
static int ubsec_process(device_t, struct cryptop *, int);
static int ubsec_kprocess(device_t, struct cryptkop *, int);
static device_method_t ubsec_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ubsec_probe),
@ -119,6 +127,12 @@ static device_method_t ubsec_methods[] = {
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
/* crypto device methods */
DEVMETHOD(cryptodev_newsession, ubsec_newsession),
DEVMETHOD(cryptodev_freesession,ubsec_freesession),
DEVMETHOD(cryptodev_process, ubsec_process),
DEVMETHOD(cryptodev_kprocess, ubsec_kprocess),
{ 0, 0 }
};
static driver_t ubsec_driver = {
@ -135,9 +149,6 @@ MODULE_DEPEND(ubsec, rndtest, 1, 1, 1);
#endif
static void ubsec_intr(void *);
static int ubsec_newsession(void *, u_int32_t *, struct cryptoini *);
static int ubsec_freesession(void *, u_int64_t);
static int ubsec_process(void *, struct cryptop *, int);
static void ubsec_callback(struct ubsec_softc *, struct ubsec_q *);
static void ubsec_feed(struct ubsec_softc *);
static void ubsec_mcopy(struct mbuf *, struct mbuf *, int, int);
@ -158,7 +169,6 @@ static void ubsec_totalreset(struct ubsec_softc *sc);
static int ubsec_free_q(struct ubsec_softc *sc, struct ubsec_q *q);
static int ubsec_kprocess(void*, struct cryptkop *, int);
static int ubsec_kprocess_modexp_hw(struct ubsec_softc *, struct cryptkop *, int);
static int ubsec_kprocess_modexp_sw(struct ubsec_softc *, struct cryptkop *, int);
static int ubsec_kprocess_rsapriv(struct ubsec_softc *, struct cryptkop *, int);
@ -350,7 +360,7 @@ ubsec_attach(device_t dev)
goto bad2;
}
sc->sc_cid = crypto_get_driverid(0);
sc->sc_cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE);
if (sc->sc_cid < 0) {
device_printf(dev, "could not get crypto driver id\n");
goto bad3;
@ -405,14 +415,10 @@ ubsec_attach(device_t dev)
device_printf(sc->sc_dev, "%s\n", ubsec_partname(sc));
crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0,
ubsec_newsession, ubsec_freesession, ubsec_process, sc);
crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0,
ubsec_newsession, ubsec_freesession, ubsec_process, sc);
crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0,
ubsec_newsession, ubsec_freesession, ubsec_process, sc);
crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0,
ubsec_newsession, ubsec_freesession, ubsec_process, sc);
crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0);
crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0);
/*
* Reset Broadcom chip
@ -475,11 +481,9 @@ ubsec_attach(device_t dev)
if (sc->sc_flags & UBS_FLAGS_KEY) {
sc->sc_statmask |= BS_STAT_MCR2_DONE;
crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0,
ubsec_kprocess, sc);
crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0);
#if 0
crypto_kregister(sc->sc_cid, CRK_MOD_EXP_CRT, 0,
ubsec_kprocess, sc);
crypto_kregister(sc->sc_cid, CRK_MOD_EXP_CRT, 0);
#endif
}
return (0);
@ -900,10 +904,10 @@ ubsec_setup_mackey(struct ubsec_session *ses, int algo, caddr_t key, int klen)
* id on successful allocation.
*/
static int
ubsec_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
ubsec_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
{
struct ubsec_softc *sc = device_get_softc(dev);
struct cryptoini *c, *encini = NULL, *macini = NULL;
struct ubsec_softc *sc = arg;
struct ubsec_session *ses = NULL;
int sesn;
@ -995,9 +999,9 @@ ubsec_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
* Deallocate a session.
*/
static int
ubsec_freesession(void *arg, u_int64_t tid)
ubsec_freesession(device_t dev, u_int64_t tid)
{
struct ubsec_softc *sc = arg;
struct ubsec_softc *sc = device_get_softc(dev);
int session, ret;
u_int32_t sid = CRYPTO_SESID2LID(tid);
@ -1035,11 +1039,11 @@ ubsec_op_cb(void *arg, bus_dma_segment_t *seg, int nsegs, bus_size_t mapsize, in
}
static int
ubsec_process(void *arg, struct cryptop *crp, int hint)
ubsec_process(device_t dev, struct cryptop *crp, int hint)
{
struct ubsec_softc *sc = device_get_softc(dev);
struct ubsec_q *q = NULL;
int err = 0, i, j, nicealign;
struct ubsec_softc *sc = arg;
struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
int encoffset = 0, macoffset = 0, cpskip, cpoffset;
int sskip, dskip, stheend, dtheend;
@ -2110,9 +2114,9 @@ ubsec_kfree(struct ubsec_softc *sc, struct ubsec_q2 *q)
}
static int
ubsec_kprocess(void *arg, struct cryptkop *krp, int hint)
ubsec_kprocess(device_t dev, struct cryptkop *krp, int hint)
{
struct ubsec_softc *sc = arg;
struct ubsec_softc *sc = device_get_softc(dev);
int r;
if (krp == NULL || krp->krp_callback == NULL)

View File

@ -662,12 +662,14 @@ g_eli_create(struct gctl_req *req, struct g_class *mp, struct g_provider *bpp,
* Use software cryptography, if we cannot get it.
*/
if (LIST_EMPTY(&sc->sc_workers)) {
error = crypto_newsession(&wr->w_sid, &crie, 1);
error = crypto_newsession(&wr->w_sid, &crie,
CRYPTOCAP_F_HARDWARE);
if (error == 0)
sc->sc_crypto = G_ELI_CRYPTO_HW;
}
if (sc->sc_crypto == G_ELI_CRYPTO_SW)
error = crypto_newsession(&wr->w_sid, &crie, 0);
error = crypto_newsession(&wr->w_sid, &crie,
CRYPTOCAP_F_SOFTWARE);
if (error != 0) {
free(wr, M_ELI);
if (req != NULL) {

View File

@ -73,7 +73,7 @@ g_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize,
cri.cri_alg = algo;
cri.cri_key = __DECONST(void *, key);
cri.cri_klen = keysize;
error = crypto_newsession(&sid, &cri, 0);
error = crypto_newsession(&sid, &cri, CRYPTOCAP_F_SOFTWARE);
if (error != 0)
return (error);
p = malloc(sizeof(*crp) + sizeof(*crd) + sizeof(*uio) + sizeof(*iov),

View File

@ -4,7 +4,7 @@
KMOD = hifn
SRCS = hifn7751.c opt_hifn.h
SRCS += device_if.h bus_if.h pci_if.h
SRCS += opt_bus.h crypto_if.h
SRCS += opt_bus.h cryptodev_if.h
.if !defined(KERNBUILDDIR)
opt_hifn.h:

View File

@ -30,7 +30,7 @@
KMOD = safe
SRCS = safe.c opt_safe.h
SRCS += device_if.h bus_if.h pci_if.h
SRCS += opt_bus.h crypto_if.h
SRCS += opt_bus.h cryptodev_if.h
.if !defined(KERNBUILDDIR)
opt_safe.h:

View File

@ -4,7 +4,7 @@
KMOD = ubsec
SRCS = ubsec.c opt_ubsec.h
SRCS += device_if.h bus_if.h pci_if.h
SRCS += opt_bus.h crypto_if.h
SRCS += opt_bus.h cryptodev_if.h
.if !defined(KERNBUILDDIR)
opt_ubsec.h:

View File

@ -117,7 +117,7 @@ int ip4_esp_randpad = -1;
* -1 require software support
* 0 take anything
*/
int crypto_support = 0;
int crypto_support = CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
SYSCTL_DECL(_net_inet_ipsec);

File diff suppressed because it is too large Load Diff

View File

@ -1,128 +0,0 @@
#-
# Copyright (c) 2002, Sam Leffler
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by Boris Popov.
# 4. Neither the name of the author nor the names of any co-contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# $FreeBSD$
#
#include <crypto/cryptodev.h>
INTERFACE crypto;
METHOD int32_t get_driverid {
u_int32_t flags;
};
# XXX define typedefs to work around inadequate parser
HEADER {
typedef int crypto_newsession_cb(void*, u_int32_t*, struct cryptoini*);
typedef int crypto_freesession_cb(void*, u_int64_t*);
typedef int crypto_process_cb(void*, struct cryptop*);
typedef int crypto_kprocess_cb(void*, struct cryptkop*);
};
METHOD int register {
u_int32_t driverid;
int alg;
u_int16_t maxoplen;
u_int32_t flags;
crypto_newsession_cb* newses;
crypto_freesession_cb* freeses;
crypto_process_cb* process;
void *arg;
};
METHOD int kregister {
u_int32_t driverid;
int kalg;
u_int32_t flags;
crypto_kprocess_cb* kprocess;
void *arg;
};
METHOD int unregister {
u_int32_t driverid;
int alg;
};
METHOD int unregister_all {
u_int32_t driverid;
};
METHOD int newsession {
u_int64_t *sid;
struct cryptoini *cri;
int hard;
};
METHOD int freesession {
u_int64_t sid;
};
METHOD int dispatch {
struct cryptop *crp;
};
METHOD int kdispatch {
struct cryptkop *krp;
};
METHOD int crypto_unblock {
u_int32_t driverid;
int what;
};
METHOD int invoke {
struct cryptop *crp;
};
METHOD int kinvoke {
struct cryptkop *krp;
};
METHOD struct cryptop * getreq {
int num;
};
METHOD void freereq {
struct cryptop *crp;
};
METHOD void done {
struct cryptop *crp;
};
METHOD void kdone {
struct cryptkop *krp;
};
METHOD int getfeat {
int *featp;
};

View File

@ -2,6 +2,7 @@
/*-
* Copyright (c) 2001 Theo de Raadt
* Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -50,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/fcntl.h>
#include <sys/bus.h>
#include <opencrypto/cryptodev.h>
#include <opencrypto/xform.h>
@ -113,6 +115,7 @@ static int csefree(struct csession *);
static int cryptodev_op(struct csession *, struct crypt_op *,
struct ucred *, struct thread *td);
static int cryptodev_key(struct crypt_kop *);
static int cryptodev_find(struct crypt_find_op *);
static int
cryptof_rw(
@ -126,6 +129,22 @@ cryptof_rw(
return (EIO);
}
/*
* Check a crypto identifier to see if it requested
* a software device/driver. This can be done either
* by device name/class or through search constraints.
*/
static int
checkforsoftware(int crid)
{
if (crid & CRYPTOCAP_F_SOFTWARE)
return EINVAL; /* XXX */
if ((crid & CRYPTOCAP_F_HARDWARE) == 0 &&
(crypto_getcaps(crid) & CRYPTOCAP_F_HARDWARE) == 0)
return EINVAL; /* XXX */
return 0;
}
/* ARGSUSED */
static int
cryptof_ioctl(
@ -135,6 +154,7 @@ cryptof_ioctl(
struct ucred *active_cred,
struct thread *td)
{
#define SES2(p) ((struct session2_op *)p)
struct cryptoini cria, crie;
struct fcrypt *fcr = fp->f_data;
struct csession *cse;
@ -142,16 +162,14 @@ cryptof_ioctl(
struct crypt_op *cop;
struct enc_xform *txform = NULL;
struct auth_hash *thash = NULL;
struct crypt_kop *kop;
u_int64_t sid;
u_int32_t ses;
int error = 0;
int error = 0, crid;
/*
* XXX: Not sure Giant is needed, but better safe than sorry
*/
mtx_lock(&Giant);
switch (cmd) {
case CIOCGSESSION:
case CIOCGSESSION2:
sop = (struct session_op *)data;
switch (sop->cipher) {
case 0:
@ -181,7 +199,6 @@ cryptof_ioctl(
txform = &enc_xform_arc4;
break;
default:
mtx_unlock(&Giant);
return (EINVAL);
}
@ -218,7 +235,6 @@ cryptof_ioctl(
thash = &auth_hash_null;
break;
default:
mtx_unlock(&Giant);
return (EINVAL);
}
@ -260,15 +276,17 @@ cryptof_ioctl(
}
}
error = crypto_newsession(&sid, (txform ? &crie : &cria), 1);
if (error) {
if (crypto_devallowsoft) {
error = crypto_newsession(&sid,
(txform ? &crie : &cria), 0);
}
/* NB: CIOGSESSION2 has the crid */
if (cmd == CIOCGSESSION2) {
crid = SES2(sop)->crid;
error = checkforsoftware(crid);
if (error)
goto bail;
}
} else
crid = CRYPTOCAP_F_HARDWARE;
error = crypto_newsession(&sid, (txform ? &crie : &cria), crid);
if (error)
goto bail;
cse = csecreate(fcr, sid, crie.cri_key, crie.cri_klen,
cria.cri_key, cria.cri_klen, sop->cipher, sop->mac, txform,
@ -280,7 +298,10 @@ cryptof_ioctl(
goto bail;
}
sop->ses = cse->ses;
if (cmd == CIOCGSESSION2) {
/* return hardware/driver id */
SES2(sop)->crid = CRYPTO_SESID2HID(cse->sid);
}
bail:
if (error) {
if (crie.cri_key)
@ -292,33 +313,53 @@ cryptof_ioctl(
case CIOCFSESSION:
ses = *(u_int32_t *)data;
cse = csefind(fcr, ses);
if (cse == NULL) {
mtx_unlock(&Giant);
if (cse == NULL)
return (EINVAL);
}
csedelete(fcr, cse);
error = csefree(cse);
break;
case CIOCCRYPT:
cop = (struct crypt_op *)data;
cse = csefind(fcr, cop->ses);
if (cse == NULL) {
mtx_unlock(&Giant);
if (cse == NULL)
return (EINVAL);
}
error = cryptodev_op(cse, cop, active_cred, td);
break;
case CIOCKEY:
error = cryptodev_key((struct crypt_kop *)data);
case CIOCKEY2:
if (!crypto_userasymcrypto)
return (EPERM); /* XXX compat? */
mtx_lock(&Giant);
kop = (struct crypt_kop *)data;
if (cmd == CIOCKEY) {
/* NB: crypto core enforces s/w driver use */
kop->crk_crid =
CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
}
error = cryptodev_key(kop);
mtx_unlock(&Giant);
break;
case CIOCASYMFEAT:
error = crypto_getfeat((int *)data);
if (!crypto_userasymcrypto) {
/*
* NB: if user asym crypto operations are
* not permitted return "no algorithms"
* so well-behaved applications will just
* fallback to doing them in software.
*/
*(int *)data = 0;
} else
error = crypto_getfeat((int *)data);
break;
case CIOCFINDDEV:
error = cryptodev_find((struct crypt_find_op *)data);
break;
default:
error = EINVAL;
break;
}
mtx_unlock(&Giant);
return (error);
#undef SES2
}
static int cryptodev_cb(void *);
@ -485,12 +526,16 @@ cryptodev_cb(void *op)
{
struct cryptop *crp = (struct cryptop *) op;
struct csession *cse = (struct csession *)crp->crp_opaque;
int error;
cse->error = crp->crp_etype;
if (crp->crp_etype == EAGAIN)
return crypto_dispatch(crp);
error = crp->crp_etype;
if (error == EAGAIN)
error = crypto_dispatch(crp);
mtx_lock(&cse->lock);
wakeup_one(crp);
if (error != 0 || (crp->crp_flags & CRYPTO_F_DONE)) {
cse->error = error;
wakeup_one(crp);
}
mtx_unlock(&cse->lock);
return (0);
}
@ -500,7 +545,7 @@ cryptodevkey_cb(void *op)
{
struct cryptkop *krp = (struct cryptkop *) op;
wakeup(krp);
wakeup_one(krp);
return (0);
}
@ -550,6 +595,7 @@ cryptodev_key(struct crypt_kop *kop)
krp->krp_status = kop->crk_status;
krp->krp_iparams = kop->crk_iparams;
krp->krp_oparams = kop->crk_oparams;
krp->krp_crid = kop->crk_crid;
krp->krp_status = 0;
krp->krp_callback = (int (*) (struct cryptkop *)) cryptodevkey_cb;
@ -576,6 +622,7 @@ cryptodev_key(struct crypt_kop *kop)
goto fail;
}
kop->crk_crid = krp->krp_crid; /* device that did the work */
if (krp->krp_status != 0) {
error = krp->krp_status;
goto fail;
@ -602,6 +649,25 @@ cryptodev_key(struct crypt_kop *kop)
return (error);
}
static int
cryptodev_find(struct crypt_find_op *find)
{
device_t dev;
if (find->crid != -1) {
dev = crypto_find_device_byhid(find->crid);
if (dev == NULL)
return (ENOENT);
strlcpy(find->name, device_get_nameunit(dev),
sizeof(find->name));
} else {
find->crid = crypto_find_driver(find->name);
if (find->crid == -1)
return (ENOENT);
}
return (0);
}
/* ARGSUSED */
static int
cryptof_poll(
@ -775,6 +841,12 @@ cryptoioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread
*(u_int32_t *)data = fd;
fdrop(f, td);
break;
case CRIOFINDDEV:
error = cryptodev_find((struct crypt_find_op *)data);
break;
case CRIOASYMFEAT:
error = crypto_getfeat((int *)data);
break;
default:
error = EINVAL;
break;

View File

@ -3,6 +3,7 @@
/*-
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
* Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
*
* This code was written by Angelos D. Keromytis in Athens, Greece, in
* February 2000. Network Security Technologies Inc. (NSTI) kindly
@ -127,6 +128,18 @@
#define CRYPTO_ALG_FLAG_RNG_ENABLE 0x02 /* Has HW RNG for DH/DSA */
#define CRYPTO_ALG_FLAG_DSA_SHA 0x04 /* Can do SHA on msg */
/*
* Crypto driver/device flags. They can set in the crid
* parameter when creating a session or submitting a key
* op to affect the device/driver assigned. If neither
* of these are specified then the crid is assumed to hold
* the driver id of an existing (and suitable) device that
* must be used to satisfy the request.
*/
#define CRYPTO_FLAG_HARDWARE 0x01000000 /* hardware accelerated */
#define CRYPTO_FLAG_SOFTWARE 0x02000000 /* software implementation */
/* NB: deprecated */
struct session_op {
u_int32_t cipher; /* ie. CRYPTO_DES_CBC */
u_int32_t mac; /* ie. CRYPTO_MD5_HMAC */
@ -139,6 +152,20 @@ struct session_op {
u_int32_t ses; /* returns: session # */
};
struct session2_op {
u_int32_t cipher; /* ie. CRYPTO_DES_CBC */
u_int32_t mac; /* ie. CRYPTO_MD5_HMAC */
u_int32_t keylen; /* cipher key */
caddr_t key;
int mackeylen; /* mac key */
caddr_t mackey;
u_int32_t ses; /* returns: session # */
int crid; /* driver id + flags (rw) */
int pad[4]; /* for future expansion */
};
struct crypt_op {
u_int32_t ses;
u_int16_t op; /* i.e. COP_ENCRYPT */
@ -152,6 +179,16 @@ struct crypt_op {
caddr_t iv;
};
/*
* Parameters for looking up a crypto driver/device by
* device name or by id. The latter are returned for
* created sessions (crid) and completed key operations.
*/
struct crypt_find_op {
int crid; /* driver id + flags */
char name[32]; /* device/driver name */
};
/* bignum parameter, in packed bytes, ... */
struct crparam {
caddr_t crp_p;
@ -165,7 +202,7 @@ 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_crid; /* NB: only used by CIOCKEY2 (rw) */
struct crparam crk_param[CRK_MAXPARAM];
};
#define CRK_ALGORITM_MIN 0
@ -187,14 +224,18 @@ struct crypt_kop {
* Please use F_SETFD against the cloned descriptor.
*/
#define CRIOGET _IOWR('c', 100, u_int32_t)
#define CRIOASYMFEAT CIOCASYMFEAT
#define CRIOFINDDEV CIOCFINDDEV
/* the following are done against the cloned descriptor */
#define CIOCGSESSION _IOWR('c', 101, struct session_op)
#define CIOCFSESSION _IOW('c', 102, u_int32_t)
#define CIOCCRYPT _IOWR('c', 103, struct crypt_op)
#define CIOCKEY _IOWR('c', 104, struct crypt_kop)
#define CIOCASYMFEAT _IOR('c', 105, u_int32_t)
#define CIOCGSESSION2 _IOWR('c', 106, struct session2_op)
#define CIOCKEY2 _IOWR('c', 107, struct crypt_kop)
#define CIOCFINDDEV _IOWR('c', 108, struct crypt_find_op)
struct cryptotstat {
struct timespec acc; /* total accumulated time */
@ -316,48 +357,12 @@ struct cryptkop {
u_int krp_status; /* return status */
u_short krp_iparams; /* # of input parameters */
u_short krp_oparams; /* # of output parameters */
u_int krp_crid; /* desired device, etc. */
u_int32_t krp_hid;
struct crparam krp_param[CRK_MAXPARAM]; /* kvm */
int (*krp_callback)(struct cryptkop *);
};
/*
* Crypto capabilities structure.
*
* Synchronization:
* (d) - protected by CRYPTO_DRIVER_LOCK()
* (q) - protected by CRYPTO_Q_LOCK()
* Not tagged fields are read-only.
*/
struct cryptocap {
u_int32_t cc_sessions; /* (d) number of sessions */
u_int32_t cc_koperations; /* (d) number os asym operations */
/*
* Largest possible operator length (in bits) for each type of
* encryption algorithm.
*/
u_int16_t cc_max_op_len[CRYPTO_ALGORITHM_MAX + 1];
u_int8_t cc_alg[CRYPTO_ALGORITHM_MAX + 1];
u_int8_t cc_kalg[CRK_ALGORITHM_MAX + 1];
u_int8_t cc_flags; /* (d) flags */
#define CRYPTOCAP_F_CLEANUP 0x01 /* needs resource cleanup */
#define CRYPTOCAP_F_SOFTWARE 0x02 /* software implementation */
#define CRYPTOCAP_F_SYNC 0x04 /* operates synchronously */
u_int8_t cc_qblocked; /* (q) symmetric q blocked */
u_int8_t cc_kqblocked; /* (q) asymmetric q blocked */
void *cc_arg; /* callback argument */
int (*cc_newsession)(void*, u_int32_t*, struct cryptoini*);
int (*cc_process)(void*, struct cryptop *, int);
int (*cc_freesession)(void*, u_int64_t);
void *cc_karg; /* callback argument */
int (*cc_kprocess) (void*, struct cryptkop *, int);
};
/*
* 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
@ -365,24 +370,24 @@ struct cryptocap {
* a copy of the driver's capabilities that can be used by client code to
* optimize operation.
*/
#define CRYPTO_SESID2HID(_sid) (((_sid) >> 32) & 0xffffff)
#define CRYPTO_SESID2CAPS(_sid) (((_sid) >> 56) & 0xff)
#define CRYPTO_SESID2HID(_sid) (((_sid) >> 32) & 0x00ffffff)
#define CRYPTO_SESID2CAPS(_sid) (((_sid) >> 32) & 0xff000000)
#define CRYPTO_SESID2LID(_sid) (((u_int32_t) (_sid)) & 0xffffffff)
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 int32_t crypto_get_driverid(u_int32_t flags);
#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 int crypto_find_driver(const char *);
extern device_t crypto_find_device_byhid(int hid);
extern int crypto_getcaps(int hid);
extern int crypto_register(u_int32_t driverid, int alg, u_int16_t maxoplen,
u_int32_t flags,
int (*newses)(void*, u_int32_t*, struct cryptoini*),
int (*freeses)(void*, u_int64_t),
int (*process)(void*, struct cryptop *, int),
void *arg);
extern int crypto_kregister(u_int32_t, int, u_int32_t,
int (*)(void*, struct cryptkop *, int),
void *arg);
u_int32_t flags);
extern int crypto_kregister(u_int32_t, int, u_int32_t);
extern int crypto_unregister(u_int32_t driverid, int alg);
extern int crypto_unregister_all(u_int32_t driverid);
extern int crypto_dispatch(struct cryptop *crp);

View File

@ -2,6 +2,7 @@
/*-
* The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
* Copyright (c) 2002-2006 Sam Leffler, Errno Consulting
*
* This code was written by Angelos D. Keromytis in Athens, Greece, in
* February 2000. Network Security Technologies Inc. (NSTI) kindly
@ -28,6 +29,7 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/sysctl.h>
#include <sys/errno.h>
#include <sys/random.h>
@ -45,19 +47,21 @@ __FBSDID("$FreeBSD$");
#include <opencrypto/cryptosoft.h>
#include <opencrypto/xform.h>
u_int8_t *hmac_ipad_buffer;
u_int8_t *hmac_opad_buffer;
#include <sys/kobj.h>
#include <sys/bus.h>
#include "cryptodev_if.h"
struct swcr_data **swcr_sessions = NULL;
u_int32_t swcr_sesnum = 0;
int32_t swcr_id = -1;
static int32_t swcr_id;
static struct swcr_data **swcr_sessions = NULL;
static u_int32_t swcr_sesnum;
u_int8_t hmac_ipad_buffer[HMAC_MAX_BLOCK_LEN];
u_int8_t hmac_opad_buffer[HMAC_MAX_BLOCK_LEN];
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_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
static int swcr_process(void *, struct cryptop *, int);
static int swcr_newsession(void *, u_int32_t *, struct cryptoini *);
static int swcr_freesession(void *, u_int64_t);
static int swcr_freesession(device_t dev, u_int64_t tid);
/*
* Apply a symmetric encryption/decryption algorithm.
@ -580,7 +584,7 @@ swcr_compdec(struct cryptodesc *crd, struct swcr_data *sw,
* Generate a new software session.
*/
static int
swcr_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
{
struct swcr_data **swd;
struct auth_hash *axf;
@ -618,7 +622,7 @@ swcr_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
}
/* Copy existing sessions */
if (swcr_sessions) {
if (swcr_sessions != NULL) {
bcopy(swcr_sessions, swd,
(swcr_sesnum / 2) * sizeof(struct swcr_data *));
free(swcr_sessions, M_CRYPTO_DATA);
@ -634,7 +638,7 @@ swcr_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
MALLOC(*swd, struct swcr_data *, sizeof(struct swcr_data),
M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
if (*swd == NULL) {
swcr_freesession(NULL, i);
swcr_freesession(dev, i);
return ENOBUFS;
}
@ -665,7 +669,7 @@ swcr_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
error = txf->setkey(&((*swd)->sw_kschedule),
cri->cri_key, cri->cri_klen / 8);
if (error) {
swcr_freesession(NULL, i);
swcr_freesession(dev, i);
return error;
}
}
@ -696,14 +700,14 @@ swcr_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
if ((*swd)->sw_ictx == NULL) {
swcr_freesession(NULL, i);
swcr_freesession(dev, i);
return ENOBUFS;
}
(*swd)->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
if ((*swd)->sw_octx == NULL) {
swcr_freesession(NULL, i);
swcr_freesession(dev, i);
return ENOBUFS;
}
@ -726,14 +730,14 @@ swcr_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
if ((*swd)->sw_ictx == NULL) {
swcr_freesession(NULL, i);
swcr_freesession(dev, i);
return ENOBUFS;
}
(*swd)->sw_octx = malloc(cri->cri_klen / 8,
M_CRYPTO_DATA, M_NOWAIT);
if ((*swd)->sw_octx == NULL) {
swcr_freesession(NULL, i);
swcr_freesession(dev, i);
return ENOBUFS;
}
@ -757,7 +761,7 @@ swcr_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
if ((*swd)->sw_ictx == NULL) {
swcr_freesession(NULL, i);
swcr_freesession(dev, i);
return ENOBUFS;
}
@ -771,7 +775,7 @@ swcr_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
(*swd)->sw_cxf = cxf;
break;
default:
swcr_freesession(NULL, i);
swcr_freesession(dev, i);
return EINVAL;
}
@ -786,7 +790,7 @@ swcr_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
* Free a session.
*/
static int
swcr_freesession(void *arg, u_int64_t tid)
swcr_freesession(device_t dev, u_int64_t tid)
{
struct swcr_data *swd;
struct enc_xform *txf;
@ -874,7 +878,7 @@ swcr_freesession(void *arg, u_int64_t tid)
* Process a software request.
*/
static int
swcr_process(void *arg, struct cryptop *crp, int hint)
swcr_process(device_t dev, struct cryptop *crp, int hint)
{
struct cryptodesc *crd;
struct swcr_data *sw;
@ -967,28 +971,37 @@ swcr_process(void *arg, struct cryptop *crp, int hint)
return 0;
}
/*
* Initialize the driver, called from the kernel main().
*/
static void
swcr_init(void)
swcr_identify(device_t *dev, device_t parent)
{
u_int i;
/* NB: order 10 is so we get attached after h/w devices */
if (device_find_child(parent, "cryptosoft", -1) == NULL &&
BUS_ADD_CHILD(parent, 10, "cryptosoft", -1) == 0)
panic("cryptosoft: could not attach");
}
hmac_ipad_buffer = malloc(HMAC_MAX_BLOCK_LEN, M_CRYPTO_DATA, M_WAITOK);
for (i = 0; i < HMAC_MAX_BLOCK_LEN; i++)
hmac_ipad_buffer[i] = HMAC_IPAD_VAL;
hmac_opad_buffer = malloc(HMAC_MAX_BLOCK_LEN, M_CRYPTO_DATA, M_WAITOK);
for (i = 0; i < HMAC_MAX_BLOCK_LEN; i++)
hmac_opad_buffer[i] = HMAC_OPAD_VAL;
static int
swcr_probe(device_t dev)
{
device_set_desc(dev, "software crypto");
return (0);
}
swcr_id = crypto_get_driverid(CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
if (swcr_id < 0)
panic("Software crypto device cannot initialize!");
crypto_register(swcr_id, CRYPTO_DES_CBC,
0, 0, swcr_newsession, swcr_freesession, swcr_process, NULL);
static int
swcr_attach(device_t dev)
{
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,
CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
if (swcr_id < 0) {
device_printf(dev, "cannot initialize!");
return ENOMEM;
}
#define REGISTER(alg) \
crypto_register(swcr_id, alg, 0,0,NULL,NULL,NULL,NULL)
crypto_register(swcr_id, alg, 0,0)
REGISTER(CRYPTO_DES_CBC);
REGISTER(CRYPTO_3DES_CBC);
REGISTER(CRYPTO_BLF_CBC);
REGISTER(CRYPTO_CAST_CBC);
@ -1008,16 +1021,47 @@ swcr_init(void)
REGISTER(CRYPTO_RIJNDAEL128_CBC);
REGISTER(CRYPTO_DEFLATE_COMP);
#undef REGISTER
return 0;
}
SYSINIT(cryptosoft_init, SI_SUB_PSEUDO, SI_ORDER_ANY, swcr_init, NULL)
static void
swcr_uninit(void)
swcr_detach(device_t dev)
{
crypto_unregister_all(swcr_id);
if (swcr_sessions != NULL)
FREE(swcr_sessions, M_CRYPTO_DATA);
free(hmac_ipad_buffer, M_CRYPTO_DATA);
free(hmac_opad_buffer, M_CRYPTO_DATA);
}
SYSUNINIT(cryptosoft_uninit, SI_SUB_PSEUDO, SI_ORDER_ANY, swcr_uninit, NULL);
static device_method_t swcr_methods[] = {
DEVMETHOD(device_identify, swcr_identify),
DEVMETHOD(device_probe, swcr_probe),
DEVMETHOD(device_attach, swcr_attach),
DEVMETHOD(device_detach, swcr_detach),
DEVMETHOD(cryptodev_newsession, swcr_newsession),
DEVMETHOD(cryptodev_freesession,swcr_freesession),
DEVMETHOD(cryptodev_process, swcr_process),
{0, 0},
};
static driver_t swcr_driver = {
"cryptosoft",
swcr_methods,
0, /* NB: no softc */
};
static devclass_t swcr_devclass;
/*
* NB: We explicitly reference the crypto module so we
* get the necessary ordering when built as a loadable
* module. This is required because we bundle the crypto
* module code together with the cryptosoft driver (otherwise
* normal module dependencies would handle things).
*/
extern int crypto_modevent(struct module *, int, void *);
/* XXX where to attach */
DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0);
MODULE_VERSION(cryptosoft, 1);
MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1);

View File

@ -60,8 +60,8 @@ struct swcr_data {
};
#ifdef _KERNEL
extern u_int8_t *hmac_ipad_buffer;
extern u_int8_t *hmac_opad_buffer;
extern u_int8_t hmac_ipad_buffer[];
extern u_int8_t hmac_opad_buffer[];
#endif /* _KERNEL */
#endif /* _CRYPTO_CRYPTO_H_ */

View File

@ -12,13 +12,55 @@
#include <sys/time.h>
#include <crypto/cryptodev.h>
#include <openssl/bn.h>
#include <paths.h>
#include <fcntl.h>
#include <err.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
static int crypto_fd = -1;
int crid = CRYPTO_FLAG_HARDWARE;
int verbose = 0;
static int
devcrypto(void)
{
static int fd = -1;
if (fd < 0) {
fd = open(_PATH_DEV "crypto", O_RDWR, 0);
if (fd < 0)
err(1, _PATH_DEV "crypto");
if (fcntl(fd, F_SETFD, 1) == -1)
err(1, "fcntl(F_SETFD) (devcrypto)");
}
return fd;
}
static int
crlookup(const char *devname)
{
struct crypt_find_op find;
find.crid = -1;
strlcpy(find.name, devname, sizeof(find.name));
if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1)
err(1, "ioctl(CIOCFINDDEV)");
return find.crid;
}
static const char *
crfind(int crid)
{
static struct crypt_find_op find;
bzero(&find, sizeof(find));
find.crid = crid;
if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1)
err(1, "ioctl(CIOCFINDDEV)");
return find.name;
}
/*
* Convert a little endian byte string in 'p' that
@ -85,17 +127,10 @@ UB_mod_exp(BIGNUM *res, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx)
{
struct crypt_kop kop;
u_int8_t *ale, *ble, *cle;
static int crypto_fd = -1;
if (crypto_fd == -1) {
int fd, fdc = open("/dev/crypto", O_RDONLY);
if (fdc == -1)
err(1, "/dev/crypto");
if (ioctl(fdc, CRIOGET, &fd) == -1)
err(1, "CRIOGET");
close(fdc);
crypto_fd = fd;
}
if (crypto_fd == -1 && ioctl(devcrypto(), CRIOGET, &crypto_fd) == -1)
err(1, "CRIOGET");
if ((ale = bignum_to_le(a, NULL)) == NULL)
err(1, "bignum_to_le, a");
@ -108,6 +143,7 @@ UB_mod_exp(BIGNUM *res, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx)
kop.crk_op = CRK_MOD_EXP;
kop.crk_iparams = 3;
kop.crk_oparams = 1;
kop.crk_crid = crid;
kop.crk_param[0].crp_p = ale;
kop.crk_param[0].crp_nbits = BN_num_bytes(a) * 8;
kop.crk_param[1].crp_p = ble;
@ -117,8 +153,10 @@ UB_mod_exp(BIGNUM *res, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx)
kop.crk_param[3].crp_p = cle;
kop.crk_param[3].crp_nbits = BN_num_bytes(c) * 8;
if (ioctl(crypto_fd, CIOCKEY, &kop) == -1)
err(1, "CIOCKEY");
if (ioctl(crypto_fd, CIOCKEY2, &kop) == -1)
err(1, "CIOCKEY2");
if (verbose)
printf("device = %s\n", crfind(kop.crk_crid));
bzero(ale, BN_num_bytes(a));
free(ale);
@ -211,10 +249,35 @@ testit(void)
BN_CTX_free(ctx);
}
int
main()
static void
usage(const char* cmd)
{
int i;
printf("usage: %s [-d dev] [-v] [count]\n", cmd);
printf("count is the number of bignum ops to do\n");
printf("\n");
printf("-d use specific device\n");
printf("-v be verbose\n");
exit(-1);
}
int
main(int argc, char *argv[])
{
int c, i;
while ((c = getopt(argc, argv, "d:v")) != -1) {
switch (c) {
case 'd':
crid = crlookup(optarg);
break;
case 'v':
verbose = 1;
break;
default:
usage(argv[0]);
}
}
argc -= optind, argv += optind;
for (i = 0; i < 1000; i++) {
fprintf(stderr, "test %d\n", i);

View File

@ -40,6 +40,7 @@
* Run count iterations of a crypt+decrypt or mac operation on a buffer of
* size bytes. A random key and iv are used. Options:
* -c check the results
* -d dev pin work on device dev
* -z run all available algorithms on a variety of buffer sizes
* -v be verbose
* -b mark operations for batching
@ -106,6 +107,7 @@ void hexdump(char *, int);
int verbose = 0;
int opflags = 0;
int verify = 0;
int crid = CRYPTO_FLAG_HARDWARE;
struct alg {
const char* name;
@ -139,7 +141,7 @@ struct alg {
static void
usage(const char* cmd)
{
printf("usage: %s [-c] [-z] [-s] [-b] [-v] [-a algorithm] [count] [size ...]\n",
printf("usage: %s [-czsbv] [-d dev] [-a algorithm] [count] [size ...]\n",
cmd);
printf("where algorithm is one of:\n");
printf(" des 3des (default) blowfish cast skipjack\n");
@ -148,6 +150,7 @@ usage(const char* cmd)
printf("size is the number of bytes of text to encrypt+decrypt\n");
printf("\n");
printf("-c check the results (slows timing)\n");
printf("-d use specific device\n");
printf("-z run all available algorithms on a variety of sizes\n");
printf("-v be verbose\n");
printf("-b mark operations for batching\n");
@ -192,6 +195,30 @@ devcrypto(void)
return fd;
}
static int
crlookup(const char *devname)
{
struct crypt_find_op find;
find.crid = -1;
strlcpy(find.name, devname, sizeof(find.name));
if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1)
err(1, "ioctl(CIOCFINDDEV)");
return find.crid;
}
static const char *
crfind(int crid)
{
static struct crypt_find_op find;
bzero(&find, sizeof(find));
find.crid = crid;
if (ioctl(devcrypto(), CRIOFINDDEV, &find) == -1)
err(1, "ioctl(CIOCFINDDEV): crid %d", crid);
return find.name;
}
static int
crget(void)
{
@ -220,7 +247,7 @@ runtest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv)
int i, fd = crget();
struct timeval start, stop, dt;
char *cleartext, *ciphertext, *originaltext;
struct session_op sop;
struct session2_op sop;
struct crypt_op cop;
char iv[8];
@ -242,8 +269,9 @@ runtest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv)
sop.mackey[i] = rdigit();
sop.mac = alg->code;
}
sop.crid = crid;
if (ioctl(fd, cmd, &sop) < 0) {
if (cmd == CIOCGSESSION) {
if (cmd == CIOCGSESSION || cmd == CIOCGSESSION2) {
close(fd);
if (verbose) {
printf("cipher %s", alg->name);
@ -274,6 +302,7 @@ runtest(struct alg *alg, int count, int size, u_long cmd, struct timeval *tv)
if (verbose) {
printf("session = 0x%x\n", sop.ses);
printf("device = %s\n", crfind(sop.crid));
printf("count = %d, size = %d\n", count, size);
if (!alg->ishash) {
printf("iv:");
@ -448,10 +477,17 @@ runtests(struct alg *alg, int count, int size, u_long cmd, int threads, int prof
if (t) {
int nops = alg->ishash ? count : 2*count;
#if 0
t /= threads;
printf("%6.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n",
t, nops, alg->name, size, (double)nops*size / t,
(double)nops*size / t * 8 / 1024 / 1024);
#else
nops *= threads;
printf("%8.3lf sec, %7d %6s crypts, %7d bytes, %8.0lf byte/sec, %7.1lf Mb/sec\n",
t, nops, alg->name, size, (double)nops*size / t,
(double)nops*size / t * 8 / 1024 / 1024);
#endif
}
#ifdef __FreeBSD__
if (profile) {
@ -480,13 +516,13 @@ main(int argc, char **argv)
struct alg *alg = NULL;
int count = 1;
int sizes[128], nsizes = 0;
u_long cmd = CIOCGSESSION;
u_long cmd = CIOCGSESSION2;
int testall = 0;
int maxthreads = 1;
int profile = 0;
int i, ch;
while ((ch = getopt(argc, argv, "cpzsva:bt:")) != -1) {
while ((ch = getopt(argc, argv, "cpzsva:bd:t:")) != -1) {
switch (ch) {
#ifdef CIOCGSSESSION
case 's':
@ -505,6 +541,9 @@ main(int argc, char **argv)
usage(argv[0]);
}
break;
case 'd':
crid = crlookup(optarg);
break;
case 't':
maxthreads = atoi(optarg);
break;