summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorJason Wright <jason@cvs.openbsd.org>2003-08-20 16:28:36 +0000
committerJason Wright <jason@cvs.openbsd.org>2003-08-20 16:28:36 +0000
commit081a7b677351d2522fe49ee563b546c059729d29 (patch)
tree30e366e7e1b00250e181c4148e3ac1b315348d89 /sys/dev
parent4a9331a4d5ec0960cf3c1adb263a86577c02fe86 (diff)
most of the infrastructure to support public key operation. This is just
a snapshot of work in progress (doesn't work correctly yet).
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/safe.c289
-rw-r--r--sys/dev/pci/safereg.h21
-rw-r--r--sys/dev/pci/safevar.h16
3 files changed, 304 insertions, 22 deletions
diff --git a/sys/dev/pci/safe.c b/sys/dev/pci/safe.c
index 9d6024132e1..ff1bc73da35 100644
--- a/sys/dev/pci/safe.c
+++ b/sys/dev/pci/safe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: safe.c,v 1.6 2003/08/14 18:46:41 jason Exp $ */
+/* $OpenBSD: safe.c,v 1.7 2003/08/20 16:28:35 jason Exp $ */
/*-
* Copyright (c) 2003 Sam Leffler, Errno Consulting
@@ -85,6 +85,14 @@ int safe_intr(void *);
int safe_newsession(u_int32_t *, struct cryptoini *);
int safe_freesession(u_int64_t);
int safe_process(struct cryptop *);
+int safe_kprocess(struct cryptkop *);
+int safe_kstart(struct safe_softc *);
+void safe_kload_reg(struct safe_softc *, u_int32_t, u_int32_t,
+ struct crparam *);
+struct safe_softc *safe_kfind(struct cryptkop *);
+void safe_kpoll(void *);
+void safe_kfeed(struct safe_softc *);
+int safe_ksigbits(struct crparam *cr);
void safe_callback(struct safe_softc *, struct safe_ringentry *);
void safe_feed(struct safe_softc *, struct safe_ringentry *);
void safe_mcopy(struct mbuf *, struct mbuf *, u_int);
@@ -158,6 +166,7 @@ safe_attach(struct device *parent, struct device *self, void *aux)
/* XXX handle power management */
+ SIMPLEQ_INIT(&sc->sc_pkq);
sc->sc_dmat = pa->pa_dmat;
cmd = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
@@ -270,17 +279,17 @@ safe_attach(struct device *parent, struct device *self, void *aux)
if (devinfo & SAFE_DEVINFO_RNG)
printf(" rng");
- bzero(algs, sizeof(algs));
#ifdef notyet
- /* Key ops not supported yet */
+ bzero(algs, sizeof(algs));
if (devinfo & SAFE_DEVINFO_PKEY) {
printf(" 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);
+ algs[CRK_MOD_EXP] = CRYPTO_ALG_FLAG_SUPPORTED;
+ crypto_kregister(sc->sc_cid, algs, safe_kprocess);
+ timeout_set(&sc->sc_pkto, safe_kpoll, sc);
}
#endif
+
+ bzero(algs, sizeof(algs));
if (devinfo & SAFE_DEVINFO_DES) {
printf(" des/3des");
algs[CRYPTO_3DES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
@@ -935,10 +944,10 @@ safe_process(struct cryptop *crp)
*/
sa->sa_cmd0 = cmd0 | SAFE_SA_CMD0_IPCI | SAFE_SA_CMD0_OPCI;
sa->sa_cmd1 = cmd1
- | (coffset << SAFE_SA_CMD1_OFFSET_S)
- | SAFE_SA_CMD1_SAREV1 /* Rev 1 SA data structure */
- | SAFE_SA_CMD1_SRPCI
- ;
+ | (coffset << SAFE_SA_CMD1_OFFSET_S)
+ | SAFE_SA_CMD1_SAREV1 /* Rev 1 SA data structure */
+ | SAFE_SA_CMD1_SRPCI;
+
/*
* NB: the order of writes is important here. In case the
* chip is scanning the ring because of an outstanding request
@@ -1026,6 +1035,9 @@ safe_init_board(struct safe_softc *sc)
;
WRITE_REG(sc, SAFE_PE_DMACFG, v);
+ WRITE_REG(sc, SAFE_CRYPTO_CTRL, SAFE_CRYPTO_CTRL_PKEY |
+ SAFE_CRYPTO_CTRL_3DES | SAFE_CRYPTO_CTRL_RNG);
+
#if BYTE_ORDER == LITTLE_ENDIAN
WRITE_REG(sc, SAFE_ENDIAN, SAFE_ENDIAN_TGT_PASS|SAFE_ENDIAN_DMA_PASS);
#elif BYTE_ORDER == BIG_ENDIAN
@@ -1072,7 +1084,7 @@ safe_init_board(struct safe_softc *sc)
*/
WRITE_REG(sc, SAFE_PE_PARTCFG, SAFE_MAX_DSIZE);
-/*XXX*/ WRITE_REG(sc, SAFE_HI_CLR, SAFE_INT_PE_CDONE | SAFE_INT_PE_DDONE |
+ WRITE_REG(sc, SAFE_HI_CLR, SAFE_INT_PE_CDONE | SAFE_INT_PE_DDONE |
SAFE_INT_PE_ERROR | SAFE_INT_PE_ODONE);
/* it's now safe to enable PE mode, do it */
@@ -1790,6 +1802,259 @@ safe_intr(void *arg)
return (1);
}
+struct safe_softc *
+safe_kfind(struct cryptkop *krp)
+{
+ struct safe_softc *sc;
+ int i;
+
+ for (i = 0; i < safe_cd.cd_ndevs; i++) {
+ sc = safe_cd.cd_devs[i];
+ if (sc == NULL)
+ continue;
+ if (sc->sc_cid == krp->krp_hid)
+ return (sc);
+ }
+ return (NULL);
+}
+
+int
+safe_kprocess(struct cryptkop *krp)
+{
+ struct safe_softc *sc;
+ struct safe_pkq *q;
+ int s;
+
+ if ((sc = safe_kfind(krp)) == NULL) {
+ krp->krp_status = EINVAL;
+ goto err;
+ }
+
+ if (krp->krp_op != CRK_MOD_EXP) {
+ krp->krp_status = EOPNOTSUPP;
+ goto err;
+ }
+
+ q = (struct safe_pkq *)malloc(sizeof(*q), M_DEVBUF, M_NOWAIT);
+ if (q == NULL) {
+ krp->krp_status = ENOMEM;
+ goto err;
+ }
+ q->pkq_krp = krp;
+
+ s = splnet();
+ SIMPLEQ_INSERT_TAIL(&sc->sc_pkq, q, pkq_next);
+ safe_kfeed(sc);
+ splx(s);
+ return (0);
+
+err:
+ crypto_kdone(krp);
+ return (0);
+}
+
+#define SAFE_CRK_PARAM_BASE 0
+#define SAFE_CRK_PARAM_EXP 1
+#define SAFE_CRK_PARAM_MOD 2
+
+int
+safe_kstart(struct safe_softc *sc)
+{
+ struct cryptkop *krp = sc->sc_pkq_cur->pkq_krp;
+ int exp_bits, mod_bits, base_bits;
+ u_int32_t op, a_off, b_off, c_off, d_off;
+
+ if (krp->krp_iparams < 3 || krp->krp_oparams != 1) {
+ krp->krp_status = EINVAL;
+ return (1);
+ }
+
+ base_bits = safe_ksigbits(&krp->krp_param[SAFE_CRK_PARAM_BASE]);
+ if (base_bits > 2048)
+ goto too_big;
+ if (base_bits <= 0) /* 5. base not zero */
+ goto too_small;
+
+ exp_bits = safe_ksigbits(&krp->krp_param[SAFE_CRK_PARAM_EXP]);
+ if (exp_bits > 2048)
+ goto too_big;
+ if (exp_bits <= 0) /* 1. exponent word length > 0 */
+ goto too_small; /* 4. exponent not zero */
+
+ mod_bits = safe_ksigbits(&krp->krp_param[SAFE_CRK_PARAM_MOD]);
+ if (mod_bits > 2048)
+ goto too_big;
+ if (mod_bits <= 32) /* 2. modulus word length > 1 */
+ goto too_small; /* 8. MSW of modulus != zero */
+ if (mod_bits < exp_bits) /* 3 modulus len >= exponent len */
+ goto too_small;
+ if ((krp->krp_param[SAFE_CRK_PARAM_MOD].crp_p[0] & 1) == 0)
+ goto bad_domain; /* 6. modulus is odd */
+ if (mod_bits > krp->krp_param[krp->krp_iparams].crp_nbits)
+ goto too_small; /* make sure result will fit */
+
+ /* 7. modulus > base */
+ if (mod_bits < base_bits)
+ goto too_small;
+ if (mod_bits == base_bits) {
+ u_int8_t *basep, *modp;
+ int i;
+
+ basep = krp->krp_param[SAFE_CRK_PARAM_BASE].crp_p +
+ ((base_bits + 7) / 8) - 1;
+ modp = krp->krp_param[SAFE_CRK_PARAM_MOD].crp_p +
+ ((mod_bits + 7) / 8) - 1;
+
+ for (i = 0; i < (mod_bits + 7) / 8; i++, basep--, modp--) {
+ if (*modp < *basep)
+ goto too_small;
+ if (*modp > *basep)
+ break;
+ }
+ }
+
+ /* And on the 9th step, he rested. */
+
+ WRITE_REG(sc, SAFE_PK_A_LEN, (exp_bits + 31) / 32);
+ WRITE_REG(sc, SAFE_PK_B_LEN, (mod_bits + 31) / 32);
+ if (mod_bits > 1024) {
+ op = SAFE_PK_FUNC_EXP4;
+ a_off = 0x000;
+ b_off = 0x100;
+ c_off = 0x200;
+ d_off = 0x300;
+ } else {
+ op = SAFE_PK_FUNC_EXP16;
+ a_off = 0x000;
+ b_off = 0x080;
+ c_off = 0x100;
+ d_off = 0x180;
+ }
+ sc->sc_pk_reslen = b_off - a_off;
+ sc->sc_pk_resoff = d_off;
+
+ /* A is exponent, B is modulus, C is base, D is result */
+ safe_kload_reg(sc, a_off, b_off - a_off,
+ &krp->krp_param[SAFE_CRK_PARAM_EXP]);
+ WRITE_REG(sc, SAFE_PK_A_ADDR, a_off >> 2);
+ safe_kload_reg(sc, a_off, b_off - a_off,
+ &krp->krp_param[SAFE_CRK_PARAM_MOD]);
+ WRITE_REG(sc, SAFE_PK_B_ADDR, b_off >> 2);
+ safe_kload_reg(sc, a_off, b_off - a_off,
+ &krp->krp_param[SAFE_CRK_PARAM_BASE]);
+ WRITE_REG(sc, SAFE_PK_C_ADDR, c_off >> 2);
+ WRITE_REG(sc, SAFE_PK_D_ADDR, d_off >> 2);
+
+ WRITE_REG(sc, SAFE_PK_FUNC, op | SAFE_PK_FUNC_RUN);
+
+ return (0);
+
+too_big:
+ krp->krp_status = E2BIG;
+ return (1);
+too_small:
+ krp->krp_status = ERANGE;
+ return (1);
+bad_domain:
+ krp->krp_status = EDOM;
+ return (1);
+}
+
+int
+safe_ksigbits(struct crparam *cr)
+{
+ u_int plen = (cr->crp_nbits + 7) / 8;
+ int i, sig = plen * 8;
+ u_int8_t c, *p = cr->crp_p;
+
+ 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);
+}
+
+void
+safe_kfeed(struct safe_softc *sc)
+{
+ if (SIMPLEQ_EMPTY(&sc->sc_pkq) && sc->sc_pkq_cur == NULL)
+ return;
+ if (sc->sc_pkq_cur != NULL)
+ return;
+ while (!SIMPLEQ_EMPTY(&sc->sc_pkq)) {
+ struct safe_pkq *q = SIMPLEQ_FIRST(&sc->sc_pkq);
+
+ sc->sc_pkq_cur = q;
+ SIMPLEQ_REMOVE_HEAD(&sc->sc_pkq, q, pkq_next);
+ if (safe_kstart(sc) != 0) {
+ crypto_kdone(q->pkq_krp);
+ free(q, M_DEVBUF);
+ sc->sc_pkq_cur = NULL;
+ } else {
+ /* op started, start polling */
+ timeout_add(&sc->sc_pkto, 1);
+ break;
+ }
+ }
+}
+
+void
+safe_kpoll(void *vsc)
+{
+ struct safe_softc *sc = vsc;
+ struct safe_pkq *q;
+ struct crparam *res;
+ int s, i;
+ u_int32_t buf[64];
+
+ if (sc->sc_pkq_cur == NULL)
+ return;
+ if (READ_REG(sc, SAFE_PK_FUNC) & SAFE_PK_FUNC_RUN) {
+ /* still running, check back later */
+ timeout_add(&sc->sc_pkto, 1);
+ return;
+ }
+
+ q = sc->sc_pkq_cur;
+ res = &q->pkq_krp->krp_param[q->pkq_krp->krp_iparams];
+ bzero(buf, sizeof(buf));
+ bzero(res->crp_p, (res->crp_nbits + 7) / 8);
+ for (i = 0; i < sc->sc_pk_reslen >> 2; i++)
+ buf[i] = READ_REG(sc, SAFE_PK_RAM_START + sc->sc_pk_resoff +
+ (i << 2));
+ bcopy(buf, res->crp_p, sc->sc_pk_reslen);
+ res->crp_nbits = sc->sc_pk_reslen * 8;
+ res->crp_nbits = safe_ksigbits(res);
+
+ crypto_kdone(q->pkq_krp);
+ free(q, M_DEVBUF);
+ sc->sc_pkq_cur = NULL;
+
+ s = splnet();
+ safe_kfeed(sc);
+ splx(s);
+}
+
+void
+safe_kload_reg(struct safe_softc *sc, u_int32_t off, u_int32_t len,
+ struct crparam *n)
+{
+ u_int32_t buf[64], i;
+
+ bzero(buf, sizeof(buf));
+ bcopy(n->crp_p, buf, (n->crp_nbits + 7) / 8);
+
+ for (i = 0; i < len >> 2; i++)
+ WRITE_REG(sc, SAFE_PK_RAM_START + off + (i << 2), buf[i]);
+}
+
#ifdef SAFE_DEBUG
void
diff --git a/sys/dev/pci/safereg.h b/sys/dev/pci/safereg.h
index ca4d406e6e9..a3ea0fc0908 100644
--- a/sys/dev/pci/safereg.h
+++ b/sys/dev/pci/safereg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: safereg.h,v 1.3 2003/08/14 18:53:36 jason Exp $ */
+/* $OpenBSD: safereg.h,v 1.4 2003/08/20 16:28:35 jason Exp $ */
/*-
* Copyright (c) 2003 Sam Leffler, Errno Consulting
@@ -77,14 +77,6 @@
#define SAFE_DMA_STAT 0x00cc /* DMA Current Status */
#define SAFE_DMA_CFG 0x00d4 /* DMA Configuration/Status */
#define SAFE_ENDIAN 0x00e0 /* Endian Configuration */
-#define SAFE_PK_A_ADDR 0x0800 /* Public Key A Address */
-#define SAFE_PK_B_ADDR 0x0804 /* Public Key B Address */
-#define SAFE_PK_C_ADDR 0x0808 /* Public Key C Address */
-#define SAFE_PK_D_ADDR 0x080c /* Public Key D Address */
-#define SAFE_PK_A_LEN 0x0810 /* Public Key A Length */
-#define SAFE_PK_B_LEN 0x0814 /* Public Key B Length */
-#define SAFE_PK_SHIFT 0x0818 /* Public Key Shift */
-#define SAFE_PK_FUNC 0x081c /* Public Key Function */
#define SAFE_RNG_OUT 0x0100 /* RNG Output */
#define SAFE_RNG_STAT 0x0104 /* RNG Status */
#define SAFE_RNG_CTRL 0x0108 /* RNG Control */
@@ -100,6 +92,16 @@
#define SAFE_RNG_LFSR1_HI 0x0130 /* RNG LFSR1 [47:32] */
#define SAFE_RNG_LFSR2_LO 0x0134 /* RNG LFSR1 [31:0] */
#define SAFE_RNG_LFSR2_HI 0x0138 /* RNG LFSR1 [47:32] */
+#define SAFE_PK_A_ADDR 0x0800 /* Public Key A Address */
+#define SAFE_PK_B_ADDR 0x0804 /* Public Key B Address */
+#define SAFE_PK_C_ADDR 0x0808 /* Public Key C Address */
+#define SAFE_PK_D_ADDR 0x080c /* Public Key D Address */
+#define SAFE_PK_A_LEN 0x0810 /* Public Key A Length */
+#define SAFE_PK_B_LEN 0x0814 /* Public Key B Length */
+#define SAFE_PK_SHIFT 0x0818 /* Public Key Shift */
+#define SAFE_PK_FUNC 0x081c /* Public Key Function */
+#define SAFE_PK_RAM_START 0x1000 /* Public Key RAM start address */
+#define SAFE_PK_RAM_END 0x1fff /* Public Key RAM end address */
#define SAFE_PE_CSR_READY 0x00000001 /* ready for processing */
#define SAFE_PE_CSR_DONE 0x00000002 /* h/w completed processing */
@@ -265,6 +267,7 @@
#define SAFE_PK_FUNC_COPY 0x00000800 /* Copy function */
#define SAFE_PK_FUNC_EXP16 0x00002000 /* Exponentiate (4-bit ACT) */
#define SAFE_PK_FUNC_EXP4 0x00004000 /* Exponentiate (2-bit ACT) */
+#define SAFE_PK_FUNC_RUN 0x00008000 /* start/status */
#define SAFE_RNG_STAT_BUSY 0x00000001 /* busy, data not valid */
diff --git a/sys/dev/pci/safevar.h b/sys/dev/pci/safevar.h
index 794857f621e..7b9fed21f69 100644
--- a/sys/dev/pci/safevar.h
+++ b/sys/dev/pci/safevar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: safevar.h,v 1.4 2003/08/14 15:26:03 jason Exp $ */
+/* $OpenBSD: safevar.h,v 1.5 2003/08/20 16:28:35 jason Exp $ */
/*-
* Copyright (c) 2003 Sam Leffler, Errno Consulting
@@ -31,6 +31,11 @@
#ifndef _SAFE_SAFEVAR_H_
#define _SAFE_SAFEVAR_H_
+/* public key parameter locations */
+#define SAFE_CRK_PARAM_BASE 0
+#define SAFE_CRK_PARAM_EXP 1
+#define SAFE_CRK_PARAM_MOD 2
+
/* Maximum queue length */
#ifndef SAFE_MAX_NQUEUE
#define SAFE_MAX_NQUEUE 60
@@ -137,6 +142,11 @@ struct safe_session {
u_int32_t ses_iv[4]; /* DES/3DES/AES iv */
};
+struct safe_pkq {
+ SIMPLEQ_ENTRY(safe_pkq) pkq_next;
+ struct cryptkop *pkq_krp;
+};
+
struct safe_softc {
struct device sc_dev; /* device backpointer */
struct resource *sc_irq;
@@ -167,6 +177,10 @@ struct safe_softc {
struct safe_session *sc_sessions; /* sessions */
struct timeout sc_rngto; /* rng timeout */
+ struct timeout sc_pkto; /* pk timeout */
+ SIMPLEQ_HEAD(, safe_pkq) sc_pkq;
+ struct safe_pkq *sc_pkq_cur;
+ u_int32_t sc_pk_reslen, sc_pk_resoff;
};
#endif /* _KERNEL */