summaryrefslogtreecommitdiffstats
path: root/sys/dev/hifn/hifn7751.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2003-10-08 20:25:47 +0000
committersam <sam@FreeBSD.org>2003-10-08 20:25:47 +0000
commit5c5eacb0283c559e222baa813182f692abbf08a2 (patch)
tree389e53e6bdf62a8671139c6fdcd0a0a2e17dcefb /sys/dev/hifn/hifn7751.c
parente54e3cef6f62d2a087d82969c54e450b632b7197 (diff)
downloadFreeBSD-src-5c5eacb0283c559e222baa813182f692abbf08a2.zip
FreeBSD-src-5c5eacb0283c559e222baa813182f692abbf08a2.tar.gz
Add symmetric crypto support for the 7955 and 7956.
Note performance is currently suboptimal. Submitted by: Rajesh Vaidyanath <RVaidyanath@hifn.com>
Diffstat (limited to 'sys/dev/hifn/hifn7751.c')
-rw-r--r--sys/dev/hifn/hifn7751.c174
1 files changed, 137 insertions, 37 deletions
diff --git a/sys/dev/hifn/hifn7751.c b/sys/dev/hifn/hifn7751.c
index 3c06bbf..9519cd2 100644
--- a/sys/dev/hifn/hifn7751.c
+++ b/sys/dev/hifn/hifn7751.c
@@ -6,6 +6,7 @@
* Copyright (c) 1999 Theo de Raadt
* Copyright (c) 2000-2001 Network Security Technologies, Inc.
* http://www.netsec.net
+ * Copyright (c) 2003 Hifn Inc.
*
* This driver is based on a previous driver by Invertex, for which they
* requested: Please send any comments, feedback, bug-fixes, or feature
@@ -43,7 +44,7 @@
__FBSDID("$FreeBSD$");
/*
- * Driver for the Hifn 7751 encryption processor.
+ * Driver for various Hifn encryption processors.
*/
#include "opt_hifn.h"
@@ -195,6 +196,8 @@ hifn_probe(device_t dev)
if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
(pci_get_device(dev) == PCI_PRODUCT_HIFN_7751 ||
pci_get_device(dev) == PCI_PRODUCT_HIFN_7951 ||
+ pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
+ pci_get_device(dev) == PCI_PRODUCT_HIFN_7956 ||
pci_get_device(dev) == PCI_PRODUCT_HIFN_7811))
return (0);
if (pci_get_vendor(dev) == PCI_VENDOR_NETSEC &&
@@ -221,6 +224,8 @@ hifn_partname(struct hifn_softc *sc)
case PCI_PRODUCT_HIFN_7751: return "Hifn 7751";
case PCI_PRODUCT_HIFN_7811: return "Hifn 7811";
case PCI_PRODUCT_HIFN_7951: return "Hifn 7951";
+ case PCI_PRODUCT_HIFN_7955: return "Hifn 7955";
+ case PCI_PRODUCT_HIFN_7956: return "Hifn 7956";
}
return "Hifn unknown-part";
case PCI_VENDOR_INVERTEX:
@@ -265,11 +270,13 @@ hifn_attach(device_t dev)
/* XXX handle power management */
/*
- * The 7951 has a random number generator and
+ * The 7951 and 795x have a random number generator and
* public key support; note this.
*/
if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
- pci_get_device(dev) == PCI_PRODUCT_HIFN_7951)
+ (pci_get_device(dev) == PCI_PRODUCT_HIFN_7951 ||
+ pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
+ pci_get_device(dev) == PCI_PRODUCT_HIFN_7956))
sc->sc_flags = HIFN_HAS_RNG | HIFN_HAS_PUBLIC;
/*
* The 7811 has a random number generator and
@@ -280,6 +287,14 @@ hifn_attach(device_t dev)
sc->sc_flags |= HIFN_IS_7811 | HIFN_HAS_RNG;
/*
+ * The 795x parts support AES.
+ */
+ if (pci_get_vendor(dev) == PCI_VENDOR_HIFN &&
+ (pci_get_device(dev) == PCI_PRODUCT_HIFN_7955 ||
+ pci_get_device(dev) == PCI_PRODUCT_HIFN_7956))
+ sc->sc_flags |= HIFN_IS_7956 | HIFN_HAS_AES;
+
+ /*
* Configure support for memory-mapped access to
* registers and for DMA operations.
*/
@@ -395,7 +410,10 @@ hifn_attach(device_t dev)
hifn_init_dma(sc);
hifn_init_pci_registers(sc);
- if (hifn_ramtype(sc))
+ /* XXX can't dynamically determine ram type for 795x; force dram */
+ if (sc->sc_flags & HIFN_IS_7956)
+ sc->sc_drammodel = 1;
+ else if (hifn_ramtype(sc))
goto fail_mem;
if (sc->sc_drammodel == 0)
@@ -467,6 +485,10 @@ hifn_attach(device_t dev)
hifn_newsession, hifn_freesession, hifn_process, sc);
crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0,
hifn_newsession, hifn_freesession, hifn_process, sc);
+ if (sc->sc_flags & HIFN_HAS_AES)
+ crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0,
+ hifn_newsession, hifn_freesession,
+ hifn_process, sc);
/*FALLTHROUGH*/
case HIFN_PUSTAT_ENA_1:
crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0,
@@ -875,6 +897,16 @@ static struct pci2id pci2id[] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00 }
}, {
+ PCI_VENDOR_HIFN,
+ PCI_PRODUCT_HIFN_7955,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00 }
+ }, {
+ PCI_VENDOR_HIFN,
+ PCI_PRODUCT_HIFN_7956,
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00 }
+ }, {
PCI_VENDOR_NETSEC,
PCI_PRODUCT_NETSEC_7751,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1055,10 +1087,18 @@ hifn_init_pci_registers(struct hifn_softc *sc)
sc->sc_dmaier &= ~HIFN_DMAIER_C_WAIT;
WRITE_REG_1(sc, HIFN_1_DMA_IER, sc->sc_dmaier);
- WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
- HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES |
- HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32 |
- (sc->sc_drammodel ? HIFN_PUCNFG_DRAM : HIFN_PUCNFG_SRAM));
+
+ if (sc->sc_flags & HIFN_IS_7956) {
+ WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
+ HIFN_PUCNFG_TCALLPHASES |
+ HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32);
+ WRITE_REG_1(sc, HIFN_1_PLL, HIFN_PLL_7956);
+ } else {
+ WRITE_REG_0(sc, HIFN_0_PUCNFG, HIFN_PUCNFG_COMPSING |
+ HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES |
+ HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32 |
+ (sc->sc_drammodel ? HIFN_PUCNFG_DRAM : HIFN_PUCNFG_SRAM));
+ }
WRITE_REG_0(sc, HIFN_0_PUISR, HIFN_PUISR_DSTOVER);
WRITE_REG_1(sc, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
@@ -1087,8 +1127,14 @@ hifn_sessions(struct hifn_softc *sc)
ctxsize = 128;
else
ctxsize = 512;
- sc->sc_maxses = 1 +
- ((sc->sc_ramsize - 32768) / ctxsize);
+ /*
+ * 7955/7956 has internal context memory of 32K
+ */
+ if (sc->sc_flags & HIFN_IS_7956)
+ sc->sc_maxses = 32768 / ctxsize;
+ else
+ sc->sc_maxses = 1 +
+ ((sc->sc_ramsize - 32768) / ctxsize);
} else
sc->sc_maxses = sc->sc_ramsize / 16384;
@@ -1175,9 +1221,16 @@ hifn_dramsize(struct hifn_softc *sc)
{
u_int32_t cnfg;
- cnfg = READ_REG_0(sc, HIFN_0_PUCNFG) &
- HIFN_PUCNFG_DRAMMASK;
- sc->sc_ramsize = 1 << ((cnfg >> 13) + 18);
+ if (sc->sc_flags & HIFN_IS_7956) {
+ /*
+ * 7955/7956 have a fixed internal ram of only 32K.
+ */
+ sc->sc_ramsize = 32768;
+ } else {
+ cnfg = READ_REG_0(sc, HIFN_0_PUCNFG) &
+ HIFN_PUCNFG_DRAMMASK;
+ sc->sc_ramsize = 1 << ((cnfg >> 13) + 18);
+ }
return (0);
}
@@ -1393,7 +1446,7 @@ hifn_write_command(struct hifn_command *cmd, u_int8_t *buf)
hifn_base_command_t *base_cmd;
hifn_mac_command_t *mac_cmd;
hifn_crypt_command_t *cry_cmd;
- int using_mac, using_crypt, len;
+ int using_mac, using_crypt, len, ivlen;
u_int32_t dlen, slen;
buf_pos = buf;
@@ -1453,7 +1506,7 @@ hifn_write_command(struct hifn_command *cmd, u_int8_t *buf)
break;
case HIFN_CRYPT_CMD_ALG_DES:
bcopy(cmd->ck, buf_pos, HIFN_DES_KEY_LENGTH);
- buf_pos += cmd->cklen;
+ buf_pos += HIFN_DES_KEY_LENGTH;
break;
case HIFN_CRYPT_CMD_ALG_RC4:
len = 256;
@@ -1468,12 +1521,28 @@ hifn_write_command(struct hifn_command *cmd, u_int8_t *buf)
bzero(buf_pos, 4);
buf_pos += 4;
break;
+ case HIFN_CRYPT_CMD_ALG_AES:
+ /*
+ * AES keys are variable 128, 192 and
+ * 256 bits (16, 24 and 32 bytes).
+ */
+ bcopy(cmd->ck, buf_pos, cmd->cklen);
+ buf_pos += cmd->cklen;
+ break;
}
}
if (using_crypt && cmd->cry_masks & HIFN_CRYPT_CMD_NEW_IV) {
- bcopy(cmd->iv, buf_pos, HIFN_IV_LENGTH);
- buf_pos += HIFN_IV_LENGTH;
+ switch (cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) {
+ case HIFN_CRYPT_CMD_ALG_AES:
+ ivlen = HIFN_AES_IV_LENGTH;
+ break;
+ default:
+ ivlen = HIFN_IV_LENGTH;
+ break;
+ }
+ bcopy(cmd->iv, buf_pos, ivlen);
+ buf_pos += ivlen;
}
if ((cmd->base_masks & (HIFN_BASE_CMD_MAC|HIFN_BASE_CMD_CRYPT)) == 0) {
@@ -2161,8 +2230,11 @@ hifn_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
break;
case CRYPTO_DES_CBC:
case CRYPTO_3DES_CBC:
+ case CRYPTO_AES_CBC:
/* XXX this may read fewer, does it matter? */
- read_random(sc->sc_sessions[i].hs_iv, HIFN_IV_LENGTH);
+ read_random(sc->sc_sessions[i].hs_iv,
+ c->cri_alg == CRYPTO_AES_CBC ?
+ HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
/*FALLTHROUGH*/
case CRYPTO_ARC4:
if (cry)
@@ -2211,7 +2283,7 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
{
struct hifn_softc *sc = arg;
struct hifn_command *cmd = NULL;
- int session, err;
+ int session, err, ivlen;
struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
if (crp == NULL || crp->crp_callback == NULL) {
@@ -2259,6 +2331,7 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
enccrd = NULL;
} else if (crd1->crd_alg == CRYPTO_DES_CBC ||
crd1->crd_alg == CRYPTO_3DES_CBC ||
+ crd1->crd_alg == CRYPTO_AES_CBC ||
crd1->crd_alg == CRYPTO_ARC4) {
if ((crd1->crd_flags & CRD_F_ENCRYPT) == 0)
cmd->base_masks |= HIFN_BASE_CMD_DECODE;
@@ -2275,6 +2348,7 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
crd1->crd_alg == CRYPTO_SHA1) &&
(crd2->crd_alg == CRYPTO_DES_CBC ||
crd2->crd_alg == CRYPTO_3DES_CBC ||
+ crd2->crd_alg == CRYPTO_AES_CBC ||
crd2->crd_alg == CRYPTO_ARC4) &&
((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
cmd->base_masks = HIFN_BASE_CMD_DECODE;
@@ -2282,7 +2356,8 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
enccrd = crd2;
} else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
crd1->crd_alg == CRYPTO_ARC4 ||
- crd1->crd_alg == CRYPTO_3DES_CBC) &&
+ crd1->crd_alg == CRYPTO_3DES_CBC ||
+ crd1->crd_alg == CRYPTO_AES_CBC) &&
(crd2->crd_alg == CRYPTO_MD5_HMAC ||
crd2->crd_alg == CRYPTO_SHA1_HMAC ||
crd2->crd_alg == CRYPTO_MD5 ||
@@ -2320,48 +2395,72 @@ hifn_process(void *arg, struct cryptop *crp, int hint)
HIFN_CRYPT_CMD_MODE_CBC |
HIFN_CRYPT_CMD_NEW_IV;
break;
+ case CRYPTO_AES_CBC:
+ cmd->cry_masks |= HIFN_CRYPT_CMD_ALG_AES |
+ HIFN_CRYPT_CMD_MODE_CBC |
+ HIFN_CRYPT_CMD_NEW_IV;
+ break;
default:
err = EINVAL;
goto errout;
}
if (enccrd->crd_alg != CRYPTO_ARC4) {
+ ivlen = ((enccrd->crd_alg == CRYPTO_AES_CBC) ?
+ HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
if (enccrd->crd_flags & CRD_F_ENCRYPT) {
if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
- bcopy(enccrd->crd_iv, cmd->iv,
- HIFN_IV_LENGTH);
+ bcopy(enccrd->crd_iv, cmd->iv, ivlen);
else
bcopy(sc->sc_sessions[session].hs_iv,
- cmd->iv, HIFN_IV_LENGTH);
+ cmd->iv, ivlen);
if ((enccrd->crd_flags & CRD_F_IV_PRESENT)
== 0) {
if (crp->crp_flags & CRYPTO_F_IMBUF)
m_copyback(cmd->src_m,
enccrd->crd_inject,
- HIFN_IV_LENGTH, cmd->iv);
+ ivlen, cmd->iv);
else if (crp->crp_flags & CRYPTO_F_IOV)
cuio_copyback(cmd->src_io,
enccrd->crd_inject,
- HIFN_IV_LENGTH, cmd->iv);
+ ivlen, cmd->iv);
}
} else {
if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
- bcopy(enccrd->crd_iv, cmd->iv,
- HIFN_IV_LENGTH);
+ bcopy(enccrd->crd_iv, cmd->iv, ivlen);
else if (crp->crp_flags & CRYPTO_F_IMBUF)
m_copydata(cmd->src_m,
- enccrd->crd_inject,
- HIFN_IV_LENGTH, cmd->iv);
+ enccrd->crd_inject, ivlen, cmd->iv);
else if (crp->crp_flags & CRYPTO_F_IOV)
cuio_copydata(cmd->src_io,
- enccrd->crd_inject,
- HIFN_IV_LENGTH, cmd->iv);
+ enccrd->crd_inject, ivlen, cmd->iv);
}
}
cmd->ck = enccrd->crd_key;
cmd->cklen = enccrd->crd_klen >> 3;
+ /*
+ * Need to specify the size for the AES key in the masks.
+ */
+ if ((cmd->cry_masks & HIFN_CRYPT_CMD_ALG_MASK) ==
+ HIFN_CRYPT_CMD_ALG_AES) {
+ switch (cmd->cklen) {
+ case 16:
+ cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_128;
+ break;
+ case 24:
+ cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_192;
+ break;
+ case 32:
+ cmd->cry_masks |= HIFN_CRYPT_CMD_KSZ_256;
+ break;
+ default:
+ err = EINVAL;
+ goto errout;
+ }
+ }
+
if (sc->sc_sessions[session].hs_state == HS_STATE_USED)
cmd->cry_masks |= HIFN_CRYPT_CMD_NEW_KEY;
}
@@ -2527,7 +2626,7 @@ hifn_callback(struct hifn_softc *sc, struct hifn_command *cmd, u_int8_t *macbuf)
struct cryptop *crp = cmd->crp;
struct cryptodesc *crd;
struct mbuf *m;
- int totlen, i, u;
+ int totlen, i, u, ivlen;
if (cmd->src_map == cmd->dst_map) {
bus_dmamap_sync(sc->sc_dmat, cmd->src_map,
@@ -2587,17 +2686,18 @@ hifn_callback(struct hifn_softc *sc, struct hifn_command *cmd, u_int8_t *macbuf)
HIFN_BASE_CMD_CRYPT) {
for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
if (crd->crd_alg != CRYPTO_DES_CBC &&
- crd->crd_alg != CRYPTO_3DES_CBC)
+ crd->crd_alg != CRYPTO_3DES_CBC &&
+ crd->crd_alg != CRYPTO_AES_CBC)
continue;
+ ivlen = ((crd->crd_alg == CRYPTO_AES_CBC) ?
+ HIFN_AES_IV_LENGTH : HIFN_IV_LENGTH);
if (crp->crp_flags & CRYPTO_F_IMBUF)
m_copydata((struct mbuf *)crp->crp_buf,
- crd->crd_skip + crd->crd_len - HIFN_IV_LENGTH,
- HIFN_IV_LENGTH,
+ crd->crd_skip + crd->crd_len - ivlen, ivlen,
cmd->softc->sc_sessions[cmd->session_num].hs_iv);
else if (crp->crp_flags & CRYPTO_F_IOV) {
cuio_copydata((struct uio *)crp->crp_buf,
- crd->crd_skip + crd->crd_len - HIFN_IV_LENGTH,
- HIFN_IV_LENGTH,
+ crd->crd_skip + crd->crd_len - ivlen, ivlen,
cmd->softc->sc_sessions[cmd->session_num].hs_iv);
}
break;
OpenPOWER on IntegriCloud