diff options
author | Jason Wright <jason@cvs.openbsd.org> | 2002-05-15 21:33:23 +0000 |
---|---|---|
committer | Jason Wright <jason@cvs.openbsd.org> | 2002-05-15 21:33:23 +0000 |
commit | 491e5c6b0c116bbda1fd014744e96d71caf73738 (patch) | |
tree | 0528b6be1a530fca8f2305bbcace72d6921af57e /sys/dev/pci | |
parent | 8452c3d8fbf96be6c1011daa6f636c4b56c03ebd (diff) |
Driver for the Hifn 7814/7851/7854 HIPP1 processors; currently only supports
the public key engine (very much like the 6500, surprise) and the rng.
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/files.pci | 7 | ||||
-rw-r--r-- | sys/dev/pci/nofn.c | 708 | ||||
-rw-r--r-- | sys/dev/pci/nofnreg.h | 183 | ||||
-rw-r--r-- | sys/dev/pci/nofnvar.h | 80 |
4 files changed, 977 insertions, 1 deletions
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index c91efd1e8dd..9b0478f93d0 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $OpenBSD: files.pci,v 1.133 2002/05/06 16:37:43 mickey Exp $ +# $OpenBSD: files.pci,v 1.134 2002/05/15 21:33:22 jason Exp $ # $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $ # # Config file and device description for machine-independent PCI code. @@ -306,6 +306,11 @@ device hifn: crypto attach hifn at pci file dev/pci/hifn7751.c hifn +# Hi/fn 7814/7851/7854 +device nofn: crypto +attach nofn at pci +file dev/pci/nofn.c nofn + # Bluesteelnet (Broadcom) 5501/5601 device ubsec: crypto attach ubsec at pci diff --git a/sys/dev/pci/nofn.c b/sys/dev/pci/nofn.c new file mode 100644 index 00000000000..6ccab9c549e --- /dev/null +++ b/sys/dev/pci/nofn.c @@ -0,0 +1,708 @@ +/* $OpenBSD: nofn.c,v 1.3 2002/05/15 21:33:22 jason Exp $ */ + +/* + * Copyright (c) 2002 Jason L. Wright (jason@thought.net) + * 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 Jason L. Wright + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. + */ + +/* + * Driver for the Hifn 7814/7851/7854 HIPP1 processor. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/errno.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/mbuf.h> +#include <sys/device.h> +#include <sys/queue.h> + +#include <uvm/uvm_extern.h> + +#include <crypto/cryptodev.h> +#include <crypto/cryptosoft.h> +#include <dev/rndvar.h> +#include <sys/md5k.h> +#include <crypto/sha1.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#include <dev/pci/nofnreg.h> +#include <dev/pci/nofnvar.h> + +int nofn_match(struct device *, void *, void *); +void nofn_attach(struct device *, struct device *, void *); +int nofn_intr(void *); + +void nofn_rng_enable(struct nofn_softc *); +void nofn_rng_disable(struct nofn_softc *); +void nofn_rng_tick(void *); +int nofn_rng_intr(struct nofn_softc *); +int nofn_rng_read(struct nofn_softc *); + +int nofn_pk_process(struct cryptkop *); +void nofn_pk_enable(struct nofn_softc *); +void nofn_pk_feed(struct nofn_softc *); +struct nofn_softc *nofn_pk_find(struct cryptkop *); +void nofn_pk_write_reg(struct nofn_softc *, int, union nofn_pk_reg *); +void nofn_pk_read_reg(struct nofn_softc *, int, union nofn_pk_reg *); +void nofn_pk_zero_reg(struct nofn_softc *, int); +int nofn_modexp_start(struct nofn_softc *, struct nofn_pk_q *); +void nofn_modexp_finish(struct nofn_softc *, struct nofn_pk_q *); +int nofn_pk_sigbits(const u_int8_t *, u_int); + +struct cfattach nofn_ca = { + sizeof(struct nofn_softc), nofn_match, nofn_attach +}; + +struct cfdriver nofn_cd = { + 0, "nofn", DV_DULL +}; + +int +nofn_match(parent, match, aux) + struct device *parent; + void *match, *aux; +{ + struct pci_attach_args *pa = (struct pci_attach_args *)aux; + + if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_HIFN && + PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_HIFN_78XX) + return (1); + return (0); +} + +void +nofn_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct nofn_softc *sc = (struct nofn_softc *)self; + struct pci_attach_args *pa = aux; + pci_chipset_tag_t pc = pa->pa_pc; + pci_intr_handle_t ih; + const char *intrstr = NULL; + bus_size_t bar0size = 0, bar3size = 0; + u_int32_t cmd; + + sc->sc_dmat = pa->pa_dmat; + + cmd = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); + cmd |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE; + pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, cmd); + cmd = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); + + if (!(cmd & PCI_COMMAND_MEM_ENABLE)) { + printf(": failed to enable memory mapping\n"); + goto fail; + } + + if (!(cmd & PCI_COMMAND_MASTER_ENABLE)) { + printf(": failed to enable bus mastering\n"); + goto fail; + } + + if (pci_mapreg_map(pa, NOFN_BAR0_REGS, PCI_MAPREG_TYPE_MEM, 0, + &sc->sc_st, &sc->sc_sh, NULL, &bar0size, 0)) { + printf(": can't map bar0 regs\n"); + goto fail; + } + + if (pci_intr_map(pa, &ih)) { + printf(": couldn't map interrupt\n"); + bus_space_unmap(sc->sc_st, sc->sc_sh, bar0size); + goto fail; + } + + intrstr = pci_intr_string(pc, ih); + sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, nofn_intr, sc, + self->dv_xname); + if (sc->sc_ih == NULL) { + printf(": couldn't establish interrupt"); + if (intrstr != NULL) + printf(" at %s", intrstr); + printf("\n"); + goto fail; + } + + sc->sc_revid = REG_READ_4(sc, NOFN_REVID); + + switch (sc->sc_revid) { + case REVID_7814_7854_1: + case REVID_8154_1:/* XXX ? */ + case REVID_8065_1:/* XXX ? */ + case REVID_8165_1:/* XXX ? */ + if (pci_mapreg_map(pa, NOFN_BAR3_PK, PCI_MAPREG_TYPE_MEM, 0, + &sc->sc_pk_t, &sc->sc_pk_h, NULL, &bar3size, 0)) { + printf(": can't map bar3 regs\n"); + goto fail; + } + nofn_rng_enable(sc); + nofn_pk_enable(sc); + break; + case REVID_7851_1: + case REVID_7851_2: + break; + default: + printf(": unknown revid %x\n", sc->sc_revid); + break; + } + + printf(": %s", intrstr); + if (sc->sc_flags & NOFN_FLAGS_PK) + printf(", pk"); + if (sc->sc_flags & NOFN_FLAGS_RNG) + printf(", rng"); + printf("\n"); + + REG_WRITE_4(sc, NOFN_PCI_INT_MASK, sc->sc_intrmask); + + return; + +fail: + if (bar3size != 0) + bus_space_unmap(sc->sc_pk_t, sc->sc_pk_h, bar3size); + if (bar0size != 0) + bus_space_unmap(sc->sc_st, sc->sc_sh, bar0size); +} + +int +nofn_intr(vsc) + void *vsc; +{ + struct nofn_softc *sc = vsc; + u_int32_t stat; + int r = 0; + + stat = REG_READ_4(sc, NOFN_PCI_INT_STAT) & sc->sc_intrmask; + + if (stat & PCIINTSTAT_RNGRDY) + r |= nofn_rng_intr(sc); + + if (stat & PCIINTSTAT_PK) { + struct nofn_pk_q *q; + u_int32_t sr; + + r = 1; + sr = PK_READ_4(sc, NOFN_PK_SR); + if (sr & PK_SR_DONE && sc->sc_pk_current != NULL) { + q = sc->sc_pk_current; + sc->sc_pk_current = NULL; + q->q_finish(sc, q); + free(q, M_DEVBUF); + nofn_pk_feed(sc); + } + } + + return (r); +} + +int +nofn_rng_read(sc) + struct nofn_softc *sc; +{ + u_int32_t buf[8], reg; + int ret = 0, i; + + for (;;) { + reg = PK_READ_4(sc, NOFN_PK_SR); + if (reg & PK_SR_UFLOW) { + ret = -1; + printf("%s: rng underflow, disabling.\n"); + nofn_rng_disable(sc); + break; + } + + if ((reg & PK_SR_RRDY) == 0) + break; + + ret = 1; + bus_space_read_region_4(sc->sc_pk_t, sc->sc_pk_h, + NOFN_PK_RNGFIFO_BEGIN, buf, 8); + if (sc->sc_rngskip > 0) + sc->sc_rngskip -= 8; + else + for (i = 0; i < 8; i++) + add_true_randomness(buf[i]); + } + + return (ret); +} + +int +nofn_rng_intr(sc) + struct nofn_softc *sc; +{ + int r; + + r = nofn_rng_read(sc); + if (r == 0) + return (0); + return (1); +} + +void +nofn_rng_tick(vsc) + void *vsc; +{ + struct nofn_softc *sc = vsc; + int s, r; + + s = splnet(); + r = nofn_rng_read(sc); + if (r != -1) + timeout_add(&sc->sc_rngto, sc->sc_rngtick); + splx(s); +} + +void +nofn_rng_disable(sc) + struct nofn_softc *sc; +{ + u_int32_t r; + + /* disable rng unit */ + r = PK_READ_4(sc, NOFN_PK_CFG2); + r &= PK_CFG2_ALU_ENA; /* preserve */ + PK_WRITE_4(sc, NOFN_PK_CFG2, r); + + switch (sc->sc_revid) { + case REVID_7814_7854_1: + if (timeout_pending(&sc->sc_rngto)) + timeout_del(&sc->sc_rngto); + break; + case REVID_8154_1: + case REVID_8065_1: + case REVID_8165_1: + /* disable rng interrupts */ + r = PK_READ_4(sc, NOFN_PK_IER); + r &= PK_IER_DONE; /* preserve */ + PK_WRITE_4(sc, NOFN_PK_IER, r); + + sc->sc_intrmask &= ~PCIINTMASK_RNGRDY; + REG_WRITE_4(sc, NOFN_PCI_INT_MASK, sc->sc_intrmask); + break; + default: + printf("%s: nofn_rng_disable: unknown rev %x\n", sc->sc_revid); + break; + } + + sc->sc_flags &= ~NOFN_FLAGS_RNG; +} + +void +nofn_rng_enable(sc) + struct nofn_softc *sc; +{ + u_int32_t r; + + /* setup scalar */ + PK_WRITE_4(sc, NOFN_PK_RNC, PK_RNC_SCALER); + + /* enable rng unit */ + r = PK_READ_4(sc, NOFN_PK_CFG2); + r &= PK_CFG2_ALU_ENA; /* preserve */ + r |= PK_CFG2_RNG_ENA; + PK_WRITE_4(sc, NOFN_PK_CFG2, r); + + /* 78xx chips cannot use interrupts to gather rng's */ + switch (sc->sc_revid) { + case REVID_7814_7854_1: + timeout_set(&sc->sc_rngto, nofn_rng_tick, sc); + if (hz < 100) + sc->sc_rngtick = 1; + else + sc->sc_rngtick = hz / 100; + timeout_add(&sc->sc_rngto, sc->sc_rngtick); + break; + case REVID_8154_1: + case REVID_8065_1: + case REVID_8165_1: + /* enable rng interrupts */ + r = PK_READ_4(sc, NOFN_PK_IER); + r &= PK_IER_DONE; /* preserve */ + r |= PK_IER_RRDY; + PK_WRITE_4(sc, NOFN_PK_IER, r); + sc->sc_intrmask |= PCIINTMASK_RNGRDY; + break; + default: + printf("%s: nofn_rng_enable: unknown rev %x\n", sc->sc_revid); + break; + } + + sc->sc_flags |= NOFN_FLAGS_RNG; +} + +void +nofn_pk_enable(sc) + struct nofn_softc *sc; +{ + u_int32_t r; + + if ((sc->sc_cid = crypto_get_driverid(0)) < 0) { + printf(": failed to register cid\n"); + return; + } + + SIMPLEQ_INIT(&sc->sc_pk_queue); + sc->sc_pk_current = NULL; + + crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0, nofn_pk_process); + + /* enable ALU */ + r = PK_READ_4(sc, NOFN_PK_CFG2); + r &= PK_CFG2_RNG_ENA; /* preserve */ + r |= PK_CFG2_ALU_ENA; + PK_WRITE_4(sc, NOFN_PK_CFG2, r); + + sc->sc_intrmask |= PCIINTMASK_PK; + sc->sc_flags |= NOFN_FLAGS_PK; +} + +void +nofn_pk_feed(sc) + struct nofn_softc *sc; +{ + struct nofn_pk_q *q; + u_int32_t r; + + /* Queue is empty and nothing being processed, turn off interrupt */ + if (SIMPLEQ_EMPTY(&sc->sc_pk_queue) && + sc->sc_pk_current == NULL) { + r = PK_READ_4(sc, NOFN_PK_IER); + r &= PK_IER_RRDY; /* preserve */ + PK_WRITE_4(sc, NOFN_PK_IER, r); + return; + } + + /* Operation already pending, wait. */ + if (sc->sc_pk_current != NULL) + return; + + while (!SIMPLEQ_EMPTY(&sc->sc_pk_queue)) { + q = SIMPLEQ_FIRST(&sc->sc_pk_queue); + if (q->q_start(sc, q) == 0) { + sc->sc_pk_current = q; + SIMPLEQ_REMOVE_HEAD(&sc->sc_pk_queue, q, q_next); + + r = PK_READ_4(sc, NOFN_PK_IER); + r &= PK_IER_RRDY; /* preserve */ + r |= PK_IER_DONE; + PK_WRITE_4(sc, NOFN_PK_IER, r); + break; + } else { + SIMPLEQ_REMOVE_HEAD(&sc->sc_pk_queue, q, q_next); + free(q, M_DEVBUF); + } + } +} + +int +nofn_pk_process(krp) + struct cryptkop *krp; +{ + struct nofn_softc *sc; + struct nofn_pk_q *q; + int s; + + if (krp == NULL || krp->krp_callback == NULL) + return (EINVAL); + if ((sc = nofn_pk_find(krp)) == NULL) { + krp->krp_status = EINVAL; + crypto_kdone(krp); + return (0); + } + + q = (struct nofn_pk_q *)malloc(sizeof(*q), M_DEVBUF, M_NOWAIT); + if (q == NULL) { + krp->krp_status = ENOMEM; + crypto_kdone(krp); + return (0); + } + + switch (krp->krp_op) { + case CRK_MOD_EXP: + q->q_start = nofn_modexp_start; + q->q_finish = nofn_modexp_finish; + q->q_krp = krp; + s = splnet(); + SIMPLEQ_INSERT_TAIL(&sc->sc_pk_queue, q, q_next); + nofn_pk_feed(sc); + splx(s); + return (0); + default: + printf("%s: kprocess: invalid op 0x%x\n", + sc->sc_dev.dv_xname, krp->krp_op); + krp->krp_status = EOPNOTSUPP; + crypto_kdone(krp); + free(q, M_DEVBUF); + return (0); + } +} + +struct nofn_softc * +nofn_pk_find(krp) + struct cryptkop *krp; +{ + struct nofn_softc *sc; + int i; + + for (i = 0; i < nofn_cd.cd_ndevs; i++) { + sc = nofn_cd.cd_devs[i]; + if (sc == NULL) + continue; + if (sc->sc_cid == krp->krp_hid) + return (sc); + } + return (NULL); +} + +void +nofn_pk_read_reg(sc, ridx, rp) + struct nofn_softc *sc; + int ridx; + union nofn_pk_reg *rp; +{ + bus_space_read_region_4(sc->sc_pk_t, sc->sc_pk_h, + NOFN_PK_REGADDR(NOFN_PK_WIN_2, ridx, 0), rp->w, 1024/32); +} + +void +nofn_pk_write_reg(sc, ridx, rp) + struct nofn_softc *sc; + int ridx; + union nofn_pk_reg *rp; +{ + bus_space_write_region_4(sc->sc_pk_t, sc->sc_pk_h, + NOFN_PK_REGADDR(NOFN_PK_WIN_2, ridx, 0), rp->w, 1024/32); +} + +void +nofn_pk_zero_reg(sc, ridx) + struct nofn_softc *sc; + int ridx; +{ + nofn_pk_write_reg(sc, ridx, &sc->sc_pk_zero); +} + +int +nofn_modexp_start(sc, q) + struct nofn_softc *sc; + struct nofn_pk_q *q; +{ + struct cryptkop *krp = q->q_krp; + int ip = 0, err = 0; + int mshift, eshift, nshift; + int mbits, ebits, nbits; + + if (krp->krp_param[NOFN_MODEXP_PAR_M].crp_nbits > 1024) { + err = ERANGE; + goto errout; + } + + /* Zero out registers. */ + nofn_pk_zero_reg(sc, 0); + nofn_pk_zero_reg(sc, 1); + nofn_pk_zero_reg(sc, 2); + nofn_pk_zero_reg(sc, 3); + + /* Write out N... */ + nbits = nofn_pk_sigbits(krp->krp_param[NOFN_MODEXP_PAR_N].crp_p, + krp->krp_param[NOFN_MODEXP_PAR_N].crp_nbits); + if (nbits > 1024) { + err = E2BIG; + goto errout; + } + if (nbits < 5) { + err = ERANGE; + goto errout; + } + bzero(&sc->sc_pk_tmp, sizeof(sc->sc_pk_tmp)); + bcopy(krp->krp_param[NOFN_MODEXP_PAR_N].crp_p, &sc->sc_pk_tmp, + (nbits + 7) / 8); + nofn_pk_write_reg(sc, 2, &sc->sc_pk_tmp); + + nshift = 1024 - nbits; + PK_WRITE_4(sc, NOFN_PK_LENADDR(2), 1024); + if (nshift != 0) { + PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip, + NOFN_PK_INSTR2(0, PK_OPCODE_SL, 2, 2, nshift)); + ip += 4; + + PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip, + NOFN_PK_INSTR2(0, PK_OPCODE_TAG, 2, 2, nbits)); + ip += 4; + } + + /* Write out M... */ + mbits = nofn_pk_sigbits(krp->krp_param[NOFN_MODEXP_PAR_M].crp_p, + krp->krp_param[NOFN_MODEXP_PAR_M].crp_nbits); + if (mbits > 1024 || mbits > nbits) { + err = E2BIG; + goto errout; + } + bzero(&sc->sc_pk_tmp, sizeof(sc->sc_pk_tmp)); + bcopy(krp->krp_param[NOFN_MODEXP_PAR_M].crp_p, &sc->sc_pk_tmp, + (mbits + 7) / 8); + nofn_pk_write_reg(sc, 0, &sc->sc_pk_tmp); + + mshift = 1024 - nbits; + PK_WRITE_4(sc, NOFN_PK_LENADDR(0), 1024); + if (mshift != 0) { + PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip, + NOFN_PK_INSTR2(0, PK_OPCODE_SL, 0, 0, mshift)); + ip += 4; + + PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip, + NOFN_PK_INSTR2(0, PK_OPCODE_TAG, 0, 0, nbits)); + ip += 4; + } + + /* Write out E... */ + ebits = nofn_pk_sigbits(krp->krp_param[NOFN_MODEXP_PAR_E].crp_p, + krp->krp_param[NOFN_MODEXP_PAR_E].crp_nbits); + if (ebits > 1024 || ebits > nbits) { + err = E2BIG; + goto errout; + } + if (ebits < 1) { + err = ERANGE; + goto errout; + } + bzero(&sc->sc_pk_tmp, sizeof(sc->sc_pk_tmp)); + bcopy(krp->krp_param[NOFN_MODEXP_PAR_E].crp_p, &sc->sc_pk_tmp, + (ebits + 7) / 8); + nofn_pk_write_reg(sc, 1, &sc->sc_pk_tmp); + + eshift = 1024 - nbits; + PK_WRITE_4(sc, NOFN_PK_LENADDR(1), 1024); + if (eshift != 0) { + PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip, + NOFN_PK_INSTR2(0, PK_OPCODE_SL, 1, 1, eshift)); + ip += 4; + + PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip, + NOFN_PK_INSTR2(0, PK_OPCODE_TAG, 1, 1, nbits)); + ip += 4; + } + + if (nshift == 0) { + PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip, + NOFN_PK_INSTR(PK_OP_DONE, PK_OPCODE_MODEXP, 3, 0, 1, 2)); + ip += 4; + } else { + PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip, + NOFN_PK_INSTR(0, PK_OPCODE_MODEXP, 3, 0, 1, 2)); + ip += 4; + + PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip, + NOFN_PK_INSTR2(0, PK_OPCODE_SR, 3, 3, nshift)); + ip += 4; + + PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip, + NOFN_PK_INSTR2(PK_OP_DONE, PK_OPCODE_TAG, 3, 3, nbits)); + ip += 4; + } + + /* Start microprogram */ + PK_WRITE_4(sc, NOFN_PK_CR, 0 << PK_CR_OFFSET_S); + + return (0); + +errout: + bzero(&sc->sc_pk_tmp, sizeof(sc->sc_pk_tmp)); + nofn_pk_zero_reg(sc, 0); + nofn_pk_zero_reg(sc, 1); + nofn_pk_zero_reg(sc, 2); + nofn_pk_zero_reg(sc, 3); + krp->krp_status = err; + crypto_kdone(krp); + return (1); +} + +void +nofn_modexp_finish(sc, q) + struct nofn_softc *sc; + struct nofn_pk_q *q; +{ + struct cryptkop *krp = q->q_krp; + int reglen, crplen; + + nofn_pk_read_reg(sc, 3, &sc->sc_pk_tmp); + + reglen = ((PK_READ_4(sc, NOFN_PK_LENADDR(3)) & NOFN_PK_LENMASK) + 7) + / 8; + crplen = (krp->krp_param[NOFN_MODEXP_PAR_C].crp_nbits + 7) / 8; + + if (crplen <= reglen) + bcopy(sc->sc_pk_tmp.b, krp->krp_param[NOFN_MODEXP_PAR_C].crp_p, + reglen); + else { + bcopy(sc->sc_pk_tmp.b, krp->krp_param[NOFN_MODEXP_PAR_C].crp_p, + reglen); + bzero(krp->krp_param[NOFN_MODEXP_PAR_C].crp_p + reglen, + crplen - reglen); + } + bzero(&sc->sc_pk_tmp, sizeof(sc->sc_pk_tmp)); + nofn_pk_zero_reg(sc, 0); + nofn_pk_zero_reg(sc, 1); + nofn_pk_zero_reg(sc, 2); + nofn_pk_zero_reg(sc, 3); + crypto_kdone(krp); +} + +/* + * Return the number of significant bits of a little endian big number. + */ +int +nofn_pk_sigbits(p, pbits) + const u_int8_t *p; + u_int pbits; +{ + u_int plen = (pbits + 7) / 8; + int i, sig = plen * 8; + u_int8_t c; + + for (i = plen - 1; i >= 0; i--) { + c = p[i]; + if (c != 0) { + while ((c & 0x80) == 0) { + sig--; + c <<= 1; + } + break; + } + sig -= 8; + } + return (sig); +} diff --git a/sys/dev/pci/nofnreg.h b/sys/dev/pci/nofnreg.h new file mode 100644 index 00000000000..339136d87f2 --- /dev/null +++ b/sys/dev/pci/nofnreg.h @@ -0,0 +1,183 @@ +/* $OpenBSD: nofnreg.h,v 1.3 2002/05/15 21:33:22 jason Exp $ */ + +/* + * Copyright (c) 2002 Jason L. Wright (jason@thought.net) + * 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 Jason L. Wright + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. + */ + +#define NOFN_BAR0_REGS 0x10 /* main register set */ +#define NOFN_BAR1 0x14 /* memory space 1 */ +#define NOFN_BAR2 0x18 /* memory space 2 */ +#define NOFN_BAR3_PK 0x1c /* public key unit */ + +#define NOFN_REVID 0x0098 /* revision id */ +#define NOFN_SPINLOCK_0 0x0118 /* spinlock 0 */ +#define NOFN_SPINLOCK_1 0x0120 /* spinlock 1 */ +#define NOFN_PCI_INT 0x0130 /* generate a pci intr */ +#define NOFN_PCI_INT_STAT 0x0138 /* pci interrupt status */ +#define NOFN_PCI_INT_MASK 0x0140 /* pci interrupt mask */ + +#define REVID_7851_1 0x00140000 /* 7851, first silicon */ +#define REVID_7851_2 0x00140001 /* 7851, second silicon */ +#define REVID_7814_7854_1 0x00140002 /* 7814/7854, first silicon */ +#define REVID_8154_1 0x00180000 /* 8154, first silicon */ +#define REVID_8065_1 0x00160000 /* 8065, first silicon */ +#define REVID_8165_1 0x00170000 /* 8165, first silicon */ + +#define PCIINTMASK_PK 0x80000000 /* pk processor idle */ +#define PCIINTMASK_RNGRDY 0x40000000 /* pk rng has 8 32bit words */ +#define PCIINTMASK_MIPSINT 0x00080000 /* mips interrupt */ +#define PCIINTMASK_ERR_OUT 0x00010000 /* err: outbound dma */ +#define PCIINTMASK_ERR_FREE 0x00008000 /* err: free descriptor */ +#define PCIINTMASK_ERR_DEST 0x00004000 /* err: dest descriptor */ +#define PCIINTMASK_ERR_RES 0x00002000 /* err: result cycle */ +#define PCIINTMASK_ERR_RESP 0x00001000 /* err: post address cycle */ +#define PCIINTMASK_DESCOVF 0x00000800 /* descriptor overflow */ +#define PCIINTMASK_RESDONE 0x00000400 /* result done */ +#define PCIINTMASK_DESTINV 0x00000200 /* destination invalidated */ +#define PCIINTMASK_POOLINV 0x00000100 /* free desc invalidated */ +#define PCIINTMASK_ERR_CMD 0x00000080 /* pci error fetching cmd */ +#define PCIINTMASK_ERR_SRC 0x00000040 /* pci error fetching src */ +#define PCIINTMASK_ERR_IN 0x00000020 /* pci error during input */ +#define PCIINTMASK_ERR_MULTI 0x00000010 /* multibit ecc error */ +#define PCIINTMASK_MIPSPAR 0x00000004 /* mips parity error */ +#define PCIINTMASK_MIPSPCI 0x00000002 /* write to pciint register */ +#define PCIINTMASK_FREE_E 0x00000001 /* free-pool empty */ + +#define PCIINTSTAT_PK 0x80000000 /* pk processor idle */ +#define PCIINTSTAT_RNGRDY 0x40000000 /* pk rng has 8 32bit words */ +#define PCIINTSTAT_MIPSINT 0x00080000 /* mips interrupt */ +#define PCIINTSTAT_ERR_OUT 0x00010000 /* err: outbound dma */ +#define PCIINTSTAT_ERR_FREE 0x00008000 /* err: free descriptor */ +#define PCIINTSTAT_ERR_DEST 0x00004000 /* err: dest descriptor */ +#define PCIINTSTAT_ERR_RES 0x00002000 /* err: result cycle */ +#define PCIINTSTAT_ERR_RESP 0x00001000 /* err: post address cycle */ +#define PCIINTSTAT_DESCOVF 0x00000800 /* descriptor overflow */ +#define PCIINTSTAT_RESDONE 0x00000400 /* result done */ +#define PCIINTSTAT_DESTINV 0x00000200 /* destination invalidated */ +#define PCIINTSTAT_POOLINV 0x00000100 /* free desc invalidated */ +#define PCIINTSTAT_ERR_CMD 0x00000080 /* pci error fetching cmd */ +#define PCIINTSTAT_ERR_SRC 0x00000040 /* pci error fetching src */ +#define PCIINTSTAT_ERR_IN 0x00000020 /* pci error during input */ +#define PCIINTSTAT_ERR_MULTI 0x00000010 /* multibit ecc error */ +#define PCIINTSTAT_MIPSPAR 0x00000004 /* mips parity error */ +#define PCIINTSTAT_MIPSPCI 0x00000002 /* write to pciint register */ +#define PCIINTSTAT_FREE_E 0x00000001 /* free-pool empty */ + +#define NOFN_PK_WIN_0 0x0000 /* big endian byte and words */ +#define NOFN_PK_WIN_1 0x2000 /* big endian byte, little endian words */ +#define NOFN_PK_WIN_2 0x4000 /* little endian byte and words */ +#define NOFN_PK_WIN_3 0x6000 /* little endian byte, big endian words */ + +#define NOFN_PK_REGADDR(win,r,i) \ + ((win) | (((r) & 0xf) << 7) | (((i) & 0x1f) << 2)) + +#define NOFN_PK_LENADDR(r) (0x1000 + ((r) << 2)) +#define NOFN_PK_LENMASK 0x000007ff /* mask of length bits */ + +#define NOFN_PK_RNGFIFO_BEGIN 0x1080 +#define NOFN_PK_RNGFIFO_END 0x10bc +#define NOFN_PK_INSTR_BEGIN 0x1100 +#define NOFN_PK_INSTR_END 0x12fc + +#define NOFN_PK_CR 0x1fd4 /* command */ +#define NOFN_PK_SR 0x1fd8 /* status */ +#define NOFN_PK_IER 0x1fdc /* interrupt enable */ +#define NOFN_PK_RNC 0x1fe0 /* random number config */ +#define NOFN_PK_CFG1 0x1fe4 /* config1 */ +#define NOFN_PK_CFG2 0x1fe8 /* config2 */ +#define NOFN_PK_CHIPID 0x1fec /* chipid */ +#define NOFN_PK_SCR 0x1ff0 /* stack content */ + +#define PK_CR_OFFSET_M 0x000001fc /* instruction offset mask */ +#define PK_CR_OFFSET_S 2 /* instruction offset shift */ + +#define PK_SR_DONE 0x00008000 /* proc is idle */ +#define PK_SR_RRDY 0x00004000 /* random number ready */ +#define PK_SR_UFLOW 0x00001000 /* random number underflow */ +#define PK_SR_CARRY 0x00000008 /* alu carry bit */ + +#define PK_IER_DONE 0x00008000 /* intr when alu is idle */ +#define PK_IER_RRDY 0x00004000 /* intr when rng ready */ + +#define PK_RNC_FST_SCALER 0x00000f00 /* first prescaler */ +#define PK_RNC_OUT_SCALER 0x00000080 /* output prescaler */ + +#define PK_CFG1_RESET 0x00000001 /* reset pk unit */ + +#define PK_CFG2_ALU_ENA 0x00000002 /* enable alu */ +#define PK_CFG2_RNG_ENA 0x00000001 /* enable rng */ + +/* alu registers are 1024 bits wide, but must be addressed by word. */ +union nofn_pk_reg { + u_int8_t b[128]; + u_int32_t w[32]; +}; + +#define PK_OP_DONE 0x80000000 /* end of program */ +#define PK_OPCODE_MASK 0x7c000000 /* opcode mask */ +#define PK_OPCODE_MODEXP 0x00000000 /* modular exponentiation */ +#define PK_OPCODE_MODMUL 0x04000000 /* modular multiplication */ +#define PK_OPCODE_MODRED 0x08000000 /* modular reduction */ +#define PK_OPCODE_MODADD 0x0c000000 /* modular addition */ +#define PK_OPCODE_MODSUB 0x10000000 /* modular subtraction */ +#define PK_OPCODE_ADD 0x14000000 /* addition */ +#define PK_OPCODE_SUB 0x18000000 /* subtraction */ +#define PK_OPCODE_ADDC 0x1c000000 /* addition with carry */ +#define PK_OPCODE_SUBC 0x20000000 /* subtraction with carry */ +#define PK_OPCODE_MULT 0x24000000 /* 2048bit multiplication */ +#define PK_OPCODE_SR 0x28000000 /* shift right */ +#define PK_OPCODE_SL 0x2c000000 /* shift left */ +#define PK_OPCODE_INC 0x30000000 /* increment */ +#define PK_OPCODE_DEC 0x34000000 /* decrement */ +#define PK_OPCODE_TAG 0x38000000 /* set length tag */ +#define PK_OPCODE_BRANCH 0x3c000000 /* jump to insn */ +#define PK_OPCODE_CALL 0x40000000 /* push addr and jump */ +#define PK_OPCODE_RETURN 0x44000000 /* pop addr and return */ + +#define PK_OP_RD_SHIFT 21 +#define PK_OP_RA_SHIFT 16 +#define PK_OP_RB_SHIFT 11 +#define PK_OP_RM_SHIFT 6 +#define PK_OP_R_MASK 0x1f +#define PK_OP_LEN_MASK 0xffff + +#define NOFN_PK_INSTR(done,op,rd,ra,rb,rm) \ + ((done) | (op) | \ + (((rd) & PK_OP_R_MASK) << PK_OP_RD_SHIFT) | \ + (((ra) & PK_OP_R_MASK) << PK_OP_RA_SHIFT) | \ + (((rb) & PK_OP_R_MASK) << PK_OP_RB_SHIFT) | \ + (((rm) & PK_OP_R_MASK) << PK_OP_RM_SHIFT)) + +/* shift left, shift right, tag */ +#define NOFN_PK_INSTR2(done,op,rd,ra,len) \ + ((done) | (op) | \ + (((rd) & PK_OP_R_MASK) << PK_OP_RD_SHIFT) | \ + (((ra) & PK_OP_R_MASK) << PK_OP_RA_SHIFT) | \ + ((len) & PK_OP_LEN_MASK)) diff --git a/sys/dev/pci/nofnvar.h b/sys/dev/pci/nofnvar.h new file mode 100644 index 00000000000..2e2dd6e11ae --- /dev/null +++ b/sys/dev/pci/nofnvar.h @@ -0,0 +1,80 @@ +/* $OpenBSD: nofnvar.h,v 1.3 2002/05/15 21:33:22 jason Exp $ */ + +/* + * Copyright (c) 2002 Jason L. Wright (jason@thought.net) + * 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 Jason L. Wright + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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. + */ + +struct nofn_softc { + struct device sc_dev; + void *sc_ih; + bus_space_handle_t sc_sh; + bus_space_tag_t sc_st; + bus_space_handle_t sc_pk_h; + bus_space_tag_t sc_pk_t; + bus_dma_tag_t sc_dmat; + int32_t sc_cid; + int sc_flags; + int sc_rngskip, sc_rngtick; + struct timeout sc_rngto; + u_int32_t sc_intrmask, sc_revid; + SIMPLEQ_HEAD(,nofn_pk_q) sc_pk_queue; + struct nofn_pk_q *sc_pk_current; + union nofn_pk_reg sc_pk_tmp, sc_pk_zero; +}; + +struct nofn_pk_q { + SIMPLEQ_ENTRY(nofn_pk_q) q_next; + int (*q_start)(struct nofn_softc *, struct nofn_pk_q *); + void (*q_finish)(struct nofn_softc *, struct nofn_pk_q *); + struct cryptkop *q_krp; +}; + +#define NOFN_FLAGS_RNG 0x01 +#define NOFN_FLAGS_PK 0x02 + +#define REG_WRITE_4(sc,r,v) \ + bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (r), (v)) +#define REG_READ_4(sc,r) \ + bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (r)) + +#define PK_WRITE_4(sc,r,v) \ + bus_space_write_4((sc)->sc_pk_t, (sc)->sc_pk_h, (r), (v)) +#define PK_READ_4(sc,r) \ + bus_space_read_4((sc)->sc_pk_t, (sc)->sc_pk_h, (r)) + +#ifndef PK_RNC_SCALER +#define PK_RNC_SCALER 0x00000700 +#endif + +/* C = M ^ E mod N */ +#define NOFN_MODEXP_PAR_M 0 +#define NOFN_MODEXP_PAR_E 1 +#define NOFN_MODEXP_PAR_N 2 +#define NOFN_MODEXP_PAR_C 3 |