diff options
author | sam <sam@FreeBSD.org> | 2002-10-07 20:02:34 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2002-10-07 20:02:34 +0000 |
commit | ee6c62e3fe91046d73b33ed1081c46c0e7f58ea0 (patch) | |
tree | 7ebc3a43bea2929701830f397b9330dd7877f3d1 /sys/dev/ubsec/ubsec.c | |
parent | 6bb1507f12d490730bbfe3406fff9c62ff193f91 (diff) | |
download | FreeBSD-src-ee6c62e3fe91046d73b33ed1081c46c0e7f58ea0.zip FreeBSD-src-ee6c62e3fe91046d73b33ed1081c46c0e7f58ea0.tar.gz |
Track openbsd changes that don't affect us yet (PK supoprt is
currently disabled):
o Don't use constants for the output parameter, use the iparam count as a
pointer to the first result location.
o Fix bits vs bytes counting problems.
o Split out the hardware and software normalization versions of modexp.
o Enable hardware normalization for chips that support it.
o On reset, disable hardware normalization for 582x and make sure the
chip is in little endian mode.
o Since sw normalization is now the only option, simplify normalization
handling.
Also fix RNG harvesting: disabling PK support (for the moment) had disabled
the MCR2 interrupt; consider both KEY support and RNG support when deciding
whether or not to enable it.
Obtained from: openbsd
Diffstat (limited to 'sys/dev/ubsec/ubsec.c')
-rw-r--r-- | sys/dev/ubsec/ubsec.c | 271 |
1 files changed, 249 insertions, 22 deletions
diff --git a/sys/dev/ubsec/ubsec.c b/sys/dev/ubsec/ubsec.c index 9d13681..415bd49 100644 --- a/sys/dev/ubsec/ubsec.c +++ b/sys/dev/ubsec/ubsec.c @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $OpenBSD: ubsec.c,v 1.103 2002/06/17 08:05:47 deraadt Exp $ */ +/* $OpenBSD: ubsec.c,v 1.115 2002/09/24 18:33:26 jason Exp $ */ /* * Copyright (c) 2000 Jason L. Wright (jason@thought.net) @@ -148,7 +148,8 @@ 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(struct ubsec_softc *, 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); static void ubsec_kfree(struct ubsec_softc *, struct ubsec_q2 *); static int ubsec_ksigbits(struct crparam *); @@ -437,8 +438,10 @@ skip_rng: crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0, ubsec_kprocess, sc); +#if 0 crypto_kregister(sc->sc_cid, CRK_MOD_EXP_CRT, 0, ubsec_kprocess, sc); +#endif } return (0); bad: @@ -1618,7 +1621,7 @@ ubsec_callback2(struct ubsec_softc *sc, struct ubsec_q2 *q) krp = me->me_krp; rlen = (me->me_modbits + 7) / 8; - clen = (krp->krp_param[UBS_MODEXP_PAR_C].crp_nbits + 7) / 8; + clen = (krp->krp_param[krp->krp_iparams].crp_nbits + 7) / 8; bus_dmamap_sync(sc->sc_dmat, me->me_M.dma_map, BUS_DMASYNC_POSTWRITE); @@ -1631,11 +1634,20 @@ ubsec_callback2(struct ubsec_softc *sc, struct ubsec_q2 *q) if (clen < rlen) krp->krp_status = E2BIG; - else - ubsec_kshift_l(me->me_shiftbits, - me->me_C.dma_vaddr, me->me_modbits, - krp->krp_param[UBS_MODEXP_PAR_C].crp_p, - krp->krp_param[UBS_MODEXP_PAR_C].crp_nbits); + else { + if (sc->sc_flags & UBS_FLAGS_HWNORM) { + bzero(krp->krp_param[krp->krp_iparams].crp_p, + (krp->krp_param[krp->krp_iparams].crp_nbits + + 7) / 8); + bcopy(me->me_C.dma_vaddr, + krp->krp_param[krp->krp_iparams].crp_p, + (me->me_modbits + 7) / 8); + } else + ubsec_kshift_l(me->me_shiftbits, + me->me_C.dma_vaddr, me->me_normbits, + krp->krp_param[krp->krp_iparams].crp_p, + krp->krp_param[krp->krp_iparams].crp_nbits); + } crypto_kdone(krp); @@ -1816,9 +1828,21 @@ ubsec_reset_board(struct ubsec_softc *sc) static void ubsec_init_board(struct ubsec_softc *sc) { - WRITE_REG(sc, BS_CTRL, - READ_REG(sc, BS_CTRL) | BS_CTRL_MCR1INT | BS_CTRL_DMAERR | - ((sc->sc_flags & UBS_FLAGS_KEY) ? BS_CTRL_MCR2INT : 0)); + u_int32_t ctrl; + + ctrl = READ_REG(sc, BS_CTRL); + ctrl &= ~(BS_CTRL_BE32 | BS_CTRL_BE64); + ctrl |= BS_CTRL_LITTLE_ENDIAN | BS_CTRL_MCR1INT; + + if (sc->sc_flags & (UBS_FLAGS_KEY|UBS_FLAGS_RNG)) + ctrl |= BS_CTRL_MCR2INT; + else + ctrl &= ~BS_CTRL_MCR2INT; + + if (sc->sc_flags & UBS_FLAGS_HWNORM) + ctrl &= ~BS_CTRL_SWNORM; + + WRITE_REG(sc, BS_CTRL, ctrl); } /* @@ -1972,6 +1996,7 @@ static int ubsec_kprocess(void *arg, struct cryptkop *krp, int hint) { struct ubsec_softc *sc = arg; + int r; if (krp == NULL || krp->krp_callback == NULL) return (EINVAL); @@ -1986,7 +2011,11 @@ ubsec_kprocess(void *arg, struct cryptkop *krp, int hint) switch (krp->krp_op) { case CRK_MOD_EXP: - return (ubsec_kprocess_modexp(sc, krp, hint)); + if (sc->sc_flags & UBS_FLAGS_HWNORM) + r = ubsec_kprocess_modexp_hw(sc, krp, hint); + else + r = ubsec_kprocess_modexp_sw(sc, krp, hint); + break; case CRK_MOD_EXP_CRT: return (ubsec_kprocess_rsapriv(sc, krp, hint)); default: @@ -1996,13 +2025,14 @@ ubsec_kprocess(void *arg, struct cryptkop *krp, int hint) crypto_kdone(krp); return (0); } + return (0); /* silence compiler */ } /* - * Start computation of cr[C] = (cr[M] ^ cr[E]) mod cr[N] + * Start computation of cr[C] = (cr[M] ^ cr[E]) mod cr[N] (sw normalization) */ static int -ubsec_kprocess_modexp(struct ubsec_softc *sc, struct cryptkop *krp, int hint) +ubsec_kprocess_modexp_sw(struct ubsec_softc *sc, struct cryptkop *krp, int hint) { struct ubsec_q2_modexp *me; struct ubsec_mcr *mcr; @@ -2036,16 +2066,14 @@ ubsec_kprocess_modexp(struct ubsec_softc *sc, struct cryptkop *krp, int hint) goto errout; } - if (sc->sc_flags & UBS_FLAGS_HWNORM) - shiftbits = 0; - else - shiftbits = normbits - nbits; + shiftbits = normbits - nbits; - me->me_modbits = normbits; + me->me_modbits = nbits; me->me_shiftbits = shiftbits; + me->me_normbits = normbits; /* Sanity check: result bits must be >= true modulus bits. */ - if (krp->krp_param[UBS_MODEXP_PAR_C].crp_nbits < nbits) { + if (krp->krp_param[krp->krp_iparams].crp_nbits < nbits) { err = ERANGE; goto errout; } @@ -2145,8 +2173,8 @@ ubsec_kprocess_modexp(struct ubsec_softc *sc, struct cryptkop *krp, int hint) ctx->me_N, normbits); ctx->me_len = htole16((normbits / 8) + (4 * sizeof(u_int16_t))); ctx->me_op = htole16(UBS_CTXOP_MODEXP); - ctx->me_E_len = htole16(normbits - shiftbits); - ctx->me_N_len = htole16(normbits - shiftbits); + ctx->me_E_len = htole16(nbits); + ctx->me_N_len = htole16(nbits); #ifdef UBSEC_DEBUG if (ubsec_debug) { @@ -2202,6 +2230,205 @@ errout: return (0); } +/* + * Start computation of cr[C] = (cr[M] ^ cr[E]) mod cr[N] (hw normalization) + */ +int +ubsec_kprocess_modexp_hw(struct ubsec_softc *sc, struct cryptkop *krp, int hint) +{ + struct ubsec_q2_modexp *me; + struct ubsec_mcr *mcr; + struct ubsec_ctx_modexp *ctx; + struct ubsec_pktbuf *epb; + int err = 0; + u_int nbits, normbits, mbits, shiftbits, ebits; + + me = (struct ubsec_q2_modexp *)malloc(sizeof *me, M_DEVBUF, M_NOWAIT); + if (me == NULL) { + err = ENOMEM; + goto errout; + } + bzero(me, sizeof *me); + me->me_krp = krp; + me->me_q.q_type = UBS_CTXOP_MODEXP; + + nbits = ubsec_ksigbits(&krp->krp_param[UBS_MODEXP_PAR_N]); + if (nbits <= 512) + normbits = 512; + else if (nbits <= 768) + normbits = 768; + else if (nbits <= 1024) + normbits = 1024; + else if (sc->sc_flags & UBS_FLAGS_BIGKEY && nbits <= 1536) + normbits = 1536; + else if (sc->sc_flags & UBS_FLAGS_BIGKEY && nbits <= 2048) + normbits = 2048; + else { + err = E2BIG; + goto errout; + } + + shiftbits = normbits - nbits; + + /* XXX ??? */ + me->me_modbits = nbits; + me->me_shiftbits = shiftbits; + me->me_normbits = normbits; + + /* Sanity check: result bits must be >= true modulus bits. */ + if (krp->krp_param[krp->krp_iparams].crp_nbits < nbits) { + err = ERANGE; + goto errout; + } + + if (ubsec_dma_malloc(sc, sizeof(struct ubsec_mcr), + &me->me_q.q_mcr, 0)) { + err = ENOMEM; + goto errout; + } + mcr = (struct ubsec_mcr *)me->me_q.q_mcr.dma_vaddr; + + if (ubsec_dma_malloc(sc, sizeof(struct ubsec_ctx_modexp), + &me->me_q.q_ctx, 0)) { + err = ENOMEM; + goto errout; + } + + mbits = ubsec_ksigbits(&krp->krp_param[UBS_MODEXP_PAR_M]); + if (mbits > nbits) { + err = E2BIG; + goto errout; + } + if (ubsec_dma_malloc(sc, normbits / 8, &me->me_M, 0)) { + err = ENOMEM; + goto errout; + } + bzero(me->me_M.dma_vaddr, normbits / 8); + bcopy(krp->krp_param[UBS_MODEXP_PAR_M].crp_p, + me->me_M.dma_vaddr, (mbits + 7) / 8); + + if (ubsec_dma_malloc(sc, normbits / 8, &me->me_C, 0)) { + err = ENOMEM; + goto errout; + } + bzero(me->me_C.dma_vaddr, me->me_C.dma_size); + + ebits = ubsec_ksigbits(&krp->krp_param[UBS_MODEXP_PAR_E]); + if (ebits > nbits) { + err = E2BIG; + goto errout; + } + if (ubsec_dma_malloc(sc, normbits / 8, &me->me_E, 0)) { + err = ENOMEM; + goto errout; + } + bzero(me->me_E.dma_vaddr, normbits / 8); + bcopy(krp->krp_param[UBS_MODEXP_PAR_E].crp_p, + me->me_E.dma_vaddr, (ebits + 7) / 8); + + if (ubsec_dma_malloc(sc, sizeof(struct ubsec_pktbuf), + &me->me_epb, 0)) { + err = ENOMEM; + goto errout; + } + epb = (struct ubsec_pktbuf *)me->me_epb.dma_vaddr; + epb->pb_addr = htole32(me->me_E.dma_paddr); + epb->pb_next = 0; + epb->pb_len = htole32((ebits + 7) / 8); + +#ifdef UBSEC_DEBUG + printf("Epb "); + ubsec_dump_pb(epb); +#endif + + mcr->mcr_pkts = htole16(1); + mcr->mcr_flags = 0; + mcr->mcr_cmdctxp = htole32(me->me_q.q_ctx.dma_paddr); + mcr->mcr_reserved = 0; + mcr->mcr_pktlen = 0; + + mcr->mcr_ipktbuf.pb_addr = htole32(me->me_M.dma_paddr); + mcr->mcr_ipktbuf.pb_len = htole32(normbits / 8); + mcr->mcr_ipktbuf.pb_next = htole32(me->me_epb.dma_paddr); + + mcr->mcr_opktbuf.pb_addr = htole32(me->me_C.dma_paddr); + mcr->mcr_opktbuf.pb_next = 0; + mcr->mcr_opktbuf.pb_len = htole32(normbits / 8); + +#ifdef DIAGNOSTIC + /* Misaligned output buffer will hang the chip. */ + if ((letoh32(mcr->mcr_opktbuf.pb_addr) & 3) != 0) + panic("%s: modexp invalid addr 0x%x\n", + device_get_nameunit(sc->sc_dev), + letoh32(mcr->mcr_opktbuf.pb_addr)); + if ((letoh32(mcr->mcr_opktbuf.pb_len) & 3) != 0) + panic("%s: modexp invalid len 0x%x\n", + device_get_nameunit(sc->sc_dev), + letoh32(mcr->mcr_opktbuf.pb_len)); +#endif + + ctx = (struct ubsec_ctx_modexp *)me->me_q.q_ctx.dma_vaddr; + bzero(ctx, sizeof(*ctx)); + bcopy(krp->krp_param[UBS_MODEXP_PAR_N].crp_p, ctx->me_N, + (nbits + 7) / 8); + ctx->me_len = htole16((normbits / 8) + (4 * sizeof(u_int16_t))); + ctx->me_op = htole16(UBS_CTXOP_MODEXP); + ctx->me_E_len = htole16(ebits); + ctx->me_N_len = htole16(nbits); + +#ifdef UBSEC_DEBUG + if (ubsec_debug) { + ubsec_dump_mcr(mcr); + ubsec_dump_ctx2((struct ubsec_ctx_keyop *)ctx); + } +#endif + + /* + * ubsec_feed2 will sync mcr and ctx, we just need to sync + * everything else. + */ + bus_dmamap_sync(sc->sc_dmat, me->me_M.dma_map, BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(sc->sc_dmat, me->me_E.dma_map, BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(sc->sc_dmat, me->me_C.dma_map, BUS_DMASYNC_PREREAD); + bus_dmamap_sync(sc->sc_dmat, me->me_epb.dma_map, BUS_DMASYNC_PREWRITE); + + /* Enqueue and we're done... */ + UBSEC_LOCK(sc); + SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &me->me_q, q_next); + ubsec_feed2(sc); + UBSEC_UNLOCK(sc); + + return (0); + +errout: + if (me != NULL) { + if (me->me_q.q_mcr.dma_map != NULL) + ubsec_dma_free(sc, &me->me_q.q_mcr); + if (me->me_q.q_ctx.dma_map != NULL) { + bzero(me->me_q.q_ctx.dma_vaddr, me->me_q.q_ctx.dma_size); + ubsec_dma_free(sc, &me->me_q.q_ctx); + } + if (me->me_M.dma_map != NULL) { + bzero(me->me_M.dma_vaddr, me->me_M.dma_size); + ubsec_dma_free(sc, &me->me_M); + } + if (me->me_E.dma_map != NULL) { + bzero(me->me_E.dma_vaddr, me->me_E.dma_size); + ubsec_dma_free(sc, &me->me_E); + } + if (me->me_C.dma_map != NULL) { + bzero(me->me_C.dma_vaddr, me->me_C.dma_size); + ubsec_dma_free(sc, &me->me_C); + } + if (me->me_epb.dma_map != NULL) + ubsec_dma_free(sc, &me->me_epb); + free(me, M_DEVBUF); + } + krp->krp_status = err; + crypto_kdone(krp); + return (0); +} + static int ubsec_kprocess_rsapriv(struct ubsec_softc *sc, struct cryptkop *krp, int hint) { |