Annotation of sys/dev/pci/nofn.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: nofn.c,v 1.15 2006/06/29 21:34:51 deraadt Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
! 5: * All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 19: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 22: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 25: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 26: * POSSIBILITY OF SUCH DAMAGE.
! 27: *
! 28: * Effort sponsored in part by the Defense Advanced Research Projects
! 29: * Agency (DARPA) and Air Force Research Laboratory, Air Force
! 30: * Materiel Command, USAF, under agreement number F30602-01-2-0537.
! 31: *
! 32: */
! 33:
! 34: /*
! 35: * Driver for the Hifn 7814/7851/7854 HIPP1 processor.
! 36: */
! 37:
! 38: #include <sys/param.h>
! 39: #include <sys/systm.h>
! 40: #include <sys/proc.h>
! 41: #include <sys/errno.h>
! 42: #include <sys/malloc.h>
! 43: #include <sys/kernel.h>
! 44: #include <sys/mbuf.h>
! 45: #include <sys/device.h>
! 46: #include <sys/queue.h>
! 47:
! 48: #include <crypto/cryptodev.h>
! 49: #include <crypto/cryptosoft.h>
! 50: #include <dev/rndvar.h>
! 51: #include <crypto/md5.h>
! 52: #include <crypto/sha1.h>
! 53:
! 54: #include <dev/pci/pcireg.h>
! 55: #include <dev/pci/pcivar.h>
! 56: #include <dev/pci/pcidevs.h>
! 57:
! 58: #include <dev/pci/nofnreg.h>
! 59: #include <dev/pci/nofnvar.h>
! 60:
! 61: int nofn_match(struct device *, void *, void *);
! 62: void nofn_attach(struct device *, struct device *, void *);
! 63: int nofn_intr(void *);
! 64:
! 65: void nofn_rng_enable(struct nofn_softc *);
! 66: void nofn_rng_disable(struct nofn_softc *);
! 67: void nofn_rng_tick(void *);
! 68: int nofn_rng_intr(struct nofn_softc *);
! 69: int nofn_rng_read(struct nofn_softc *);
! 70:
! 71: int nofn_pk_process(struct cryptkop *);
! 72: void nofn_pk_enable(struct nofn_softc *);
! 73: void nofn_pk_feed(struct nofn_softc *);
! 74: struct nofn_softc *nofn_pk_find(struct cryptkop *);
! 75: void nofn_pk_write_reg(struct nofn_softc *, int, union nofn_pk_reg *);
! 76: void nofn_pk_read_reg(struct nofn_softc *, int, union nofn_pk_reg *);
! 77: void nofn_pk_zero_reg(struct nofn_softc *, int);
! 78: int nofn_modexp_start(struct nofn_softc *, struct nofn_pk_q *);
! 79: void nofn_modexp_finish(struct nofn_softc *, struct nofn_pk_q *);
! 80: int nofn_pk_sigbits(const u_int8_t *, u_int);
! 81:
! 82: struct cfattach nofn_ca = {
! 83: sizeof(struct nofn_softc), nofn_match, nofn_attach
! 84: };
! 85:
! 86: struct cfdriver nofn_cd = {
! 87: 0, "nofn", DV_DULL
! 88: };
! 89:
! 90: int
! 91: nofn_match(parent, match, aux)
! 92: struct device *parent;
! 93: void *match, *aux;
! 94: {
! 95: struct pci_attach_args *pa = (struct pci_attach_args *)aux;
! 96:
! 97: if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_HIFN &&
! 98: PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_HIFN_78XX)
! 99: return (1);
! 100: return (0);
! 101: }
! 102:
! 103: void
! 104: nofn_attach(parent, self, aux)
! 105: struct device *parent, *self;
! 106: void *aux;
! 107: {
! 108: struct nofn_softc *sc = (struct nofn_softc *)self;
! 109: struct pci_attach_args *pa = aux;
! 110: pci_chipset_tag_t pc = pa->pa_pc;
! 111: pci_intr_handle_t ih;
! 112: const char *intrstr = NULL;
! 113: bus_size_t bar0size = 0, bar3size = 0;
! 114:
! 115: sc->sc_dmat = pa->pa_dmat;
! 116:
! 117: if (pci_mapreg_map(pa, NOFN_BAR0_REGS, PCI_MAPREG_TYPE_MEM, 0,
! 118: &sc->sc_st, &sc->sc_sh, NULL, &bar0size, 0)) {
! 119: printf(": can't map bar0 regs\n");
! 120: goto fail;
! 121: }
! 122:
! 123: if (pci_intr_map(pa, &ih)) {
! 124: printf(": couldn't map interrupt\n");
! 125: bus_space_unmap(sc->sc_st, sc->sc_sh, bar0size);
! 126: goto fail;
! 127: }
! 128:
! 129: intrstr = pci_intr_string(pc, ih);
! 130: sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, nofn_intr, sc,
! 131: self->dv_xname);
! 132: if (sc->sc_ih == NULL) {
! 133: printf(": couldn't establish interrupt");
! 134: if (intrstr != NULL)
! 135: printf(" at %s", intrstr);
! 136: printf("\n");
! 137: goto fail;
! 138: }
! 139:
! 140: sc->sc_revid = REG_READ_4(sc, NOFN_REVID);
! 141:
! 142: switch (sc->sc_revid) {
! 143: case REVID_7814_7854_1:
! 144: case REVID_8154_1:/* XXX ? */
! 145: case REVID_8065_1:/* XXX ? */
! 146: case REVID_8165_1:/* XXX ? */
! 147: if (pci_mapreg_map(pa, NOFN_BAR3_PK, PCI_MAPREG_TYPE_MEM, 0,
! 148: &sc->sc_pk_t, &sc->sc_pk_h, NULL, &bar3size, 0)) {
! 149: printf(": can't map bar3 regs\n");
! 150: goto fail;
! 151: }
! 152: nofn_rng_enable(sc);
! 153: nofn_pk_enable(sc);
! 154: break;
! 155: case REVID_7851_1:
! 156: case REVID_7851_2:
! 157: break;
! 158: default:
! 159: printf(": unknown revid %x\n", sc->sc_revid);
! 160: break;
! 161: }
! 162:
! 163: printf(":");
! 164: if (sc->sc_flags & NOFN_FLAGS_PK)
! 165: printf(" PK");
! 166: if (sc->sc_flags & NOFN_FLAGS_RNG)
! 167: printf(" RNG");
! 168: printf(", %s\n", intrstr);
! 169:
! 170: REG_WRITE_4(sc, NOFN_PCI_INT_MASK, sc->sc_intrmask);
! 171:
! 172: return;
! 173:
! 174: fail:
! 175: if (bar3size != 0)
! 176: bus_space_unmap(sc->sc_pk_t, sc->sc_pk_h, bar3size);
! 177: if (bar0size != 0)
! 178: bus_space_unmap(sc->sc_st, sc->sc_sh, bar0size);
! 179: }
! 180:
! 181: int
! 182: nofn_intr(vsc)
! 183: void *vsc;
! 184: {
! 185: struct nofn_softc *sc = vsc;
! 186: u_int32_t stat;
! 187: int r = 0;
! 188:
! 189: stat = REG_READ_4(sc, NOFN_PCI_INT_STAT) & sc->sc_intrmask;
! 190:
! 191: if (stat & PCIINTSTAT_RNGRDY)
! 192: r |= nofn_rng_intr(sc);
! 193:
! 194: if (stat & PCIINTSTAT_PK) {
! 195: struct nofn_pk_q *q;
! 196: u_int32_t sr;
! 197:
! 198: r = 1;
! 199: sr = PK_READ_4(sc, NOFN_PK_SR);
! 200: if (sr & PK_SR_DONE && sc->sc_pk_current != NULL) {
! 201: q = sc->sc_pk_current;
! 202: sc->sc_pk_current = NULL;
! 203: q->q_finish(sc, q);
! 204: free(q, M_DEVBUF);
! 205: nofn_pk_feed(sc);
! 206: }
! 207: }
! 208:
! 209: return (r);
! 210: }
! 211:
! 212: int
! 213: nofn_rng_read(sc)
! 214: struct nofn_softc *sc;
! 215: {
! 216: u_int32_t buf[8], reg;
! 217: int ret = 0, i;
! 218:
! 219: for (;;) {
! 220: reg = PK_READ_4(sc, NOFN_PK_SR);
! 221: if (reg & PK_SR_UFLOW) {
! 222: ret = -1;
! 223: printf("%s: rng underflow, disabling.\n",
! 224: sc->sc_dev.dv_xname);
! 225: nofn_rng_disable(sc);
! 226: break;
! 227: }
! 228:
! 229: if ((reg & PK_SR_RRDY) == 0)
! 230: break;
! 231:
! 232: ret = 1;
! 233: bus_space_read_region_4(sc->sc_pk_t, sc->sc_pk_h,
! 234: NOFN_PK_RNGFIFO_BEGIN, buf, 8);
! 235: if (sc->sc_rngskip > 0)
! 236: sc->sc_rngskip -= 8;
! 237: else
! 238: for (i = 0; i < 8; i++)
! 239: add_true_randomness(buf[i]);
! 240: }
! 241:
! 242: return (ret);
! 243: }
! 244:
! 245: int
! 246: nofn_rng_intr(sc)
! 247: struct nofn_softc *sc;
! 248: {
! 249: int r;
! 250:
! 251: r = nofn_rng_read(sc);
! 252: if (r == 0)
! 253: return (0);
! 254: return (1);
! 255: }
! 256:
! 257: void
! 258: nofn_rng_tick(vsc)
! 259: void *vsc;
! 260: {
! 261: struct nofn_softc *sc = vsc;
! 262: int s, r;
! 263:
! 264: s = splnet();
! 265: r = nofn_rng_read(sc);
! 266: if (r != -1)
! 267: timeout_add(&sc->sc_rngto, sc->sc_rngtick);
! 268: splx(s);
! 269: }
! 270:
! 271: void
! 272: nofn_rng_disable(sc)
! 273: struct nofn_softc *sc;
! 274: {
! 275: u_int32_t r;
! 276:
! 277: /* disable rng unit */
! 278: r = PK_READ_4(sc, NOFN_PK_CFG2);
! 279: r &= PK_CFG2_ALU_ENA; /* preserve */
! 280: PK_WRITE_4(sc, NOFN_PK_CFG2, r);
! 281:
! 282: switch (sc->sc_revid) {
! 283: case REVID_7814_7854_1:
! 284: if (timeout_pending(&sc->sc_rngto))
! 285: timeout_del(&sc->sc_rngto);
! 286: break;
! 287: case REVID_8154_1:
! 288: case REVID_8065_1:
! 289: case REVID_8165_1:
! 290: /* disable rng interrupts */
! 291: r = PK_READ_4(sc, NOFN_PK_IER);
! 292: r &= PK_IER_DONE; /* preserve */
! 293: PK_WRITE_4(sc, NOFN_PK_IER, r);
! 294:
! 295: sc->sc_intrmask &= ~PCIINTMASK_RNGRDY;
! 296: REG_WRITE_4(sc, NOFN_PCI_INT_MASK, sc->sc_intrmask);
! 297: break;
! 298: default:
! 299: printf("%s: nofn_rng_disable: unknown rev %x\n",
! 300: sc->sc_dev.dv_xname, sc->sc_revid);
! 301: break;
! 302: }
! 303:
! 304: sc->sc_flags &= ~NOFN_FLAGS_RNG;
! 305: }
! 306:
! 307: void
! 308: nofn_rng_enable(sc)
! 309: struct nofn_softc *sc;
! 310: {
! 311: u_int32_t r;
! 312:
! 313: /* setup scalar */
! 314: PK_WRITE_4(sc, NOFN_PK_RNC, PK_RNC_SCALER);
! 315:
! 316: /* enable rng unit */
! 317: r = PK_READ_4(sc, NOFN_PK_CFG2);
! 318: r &= PK_CFG2_ALU_ENA; /* preserve */
! 319: r |= PK_CFG2_RNG_ENA;
! 320: PK_WRITE_4(sc, NOFN_PK_CFG2, r);
! 321:
! 322: /* 78xx chips cannot use interrupts to gather rng's */
! 323: switch (sc->sc_revid) {
! 324: case REVID_7814_7854_1:
! 325: timeout_set(&sc->sc_rngto, nofn_rng_tick, sc);
! 326: if (hz < 100)
! 327: sc->sc_rngtick = 1;
! 328: else
! 329: sc->sc_rngtick = hz / 100;
! 330: timeout_add(&sc->sc_rngto, sc->sc_rngtick);
! 331: break;
! 332: case REVID_8154_1:
! 333: case REVID_8065_1:
! 334: case REVID_8165_1:
! 335: /* enable rng interrupts */
! 336: r = PK_READ_4(sc, NOFN_PK_IER);
! 337: r &= PK_IER_DONE; /* preserve */
! 338: r |= PK_IER_RRDY;
! 339: PK_WRITE_4(sc, NOFN_PK_IER, r);
! 340: sc->sc_intrmask |= PCIINTMASK_RNGRDY;
! 341: break;
! 342: default:
! 343: printf("%s: nofn_rng_enable: unknown rev %x\n",
! 344: sc->sc_dev.dv_xname, sc->sc_revid);
! 345: break;
! 346: }
! 347:
! 348: sc->sc_flags |= NOFN_FLAGS_RNG;
! 349: }
! 350:
! 351: void
! 352: nofn_pk_enable(sc)
! 353: struct nofn_softc *sc;
! 354: {
! 355: u_int32_t r;
! 356: int algs[CRK_ALGORITHM_MAX + 1];
! 357:
! 358: if ((sc->sc_cid = crypto_get_driverid(0)) < 0) {
! 359: printf(": failed to register cid\n");
! 360: return;
! 361: }
! 362:
! 363: SIMPLEQ_INIT(&sc->sc_pk_queue);
! 364: sc->sc_pk_current = NULL;
! 365:
! 366: bzero(algs, sizeof(algs));
! 367: algs[CRK_MOD_EXP] = CRYPTO_ALG_FLAG_SUPPORTED;
! 368: crypto_kregister(sc->sc_cid, algs, nofn_pk_process);
! 369:
! 370: /* enable ALU */
! 371: r = PK_READ_4(sc, NOFN_PK_CFG2);
! 372: r &= PK_CFG2_RNG_ENA; /* preserve */
! 373: r |= PK_CFG2_ALU_ENA;
! 374: PK_WRITE_4(sc, NOFN_PK_CFG2, r);
! 375:
! 376: sc->sc_intrmask |= PCIINTMASK_PK;
! 377: sc->sc_flags |= NOFN_FLAGS_PK;
! 378: }
! 379:
! 380: void
! 381: nofn_pk_feed(sc)
! 382: struct nofn_softc *sc;
! 383: {
! 384: struct nofn_pk_q *q;
! 385: u_int32_t r;
! 386:
! 387: /* Queue is empty and nothing being processed, turn off interrupt */
! 388: if (SIMPLEQ_EMPTY(&sc->sc_pk_queue) &&
! 389: sc->sc_pk_current == NULL) {
! 390: r = PK_READ_4(sc, NOFN_PK_IER);
! 391: r &= PK_IER_RRDY; /* preserve */
! 392: PK_WRITE_4(sc, NOFN_PK_IER, r);
! 393: return;
! 394: }
! 395:
! 396: /* Operation already pending, wait. */
! 397: if (sc->sc_pk_current != NULL)
! 398: return;
! 399:
! 400: while (!SIMPLEQ_EMPTY(&sc->sc_pk_queue)) {
! 401: q = SIMPLEQ_FIRST(&sc->sc_pk_queue);
! 402: if (q->q_start(sc, q) == 0) {
! 403: sc->sc_pk_current = q;
! 404: SIMPLEQ_REMOVE_HEAD(&sc->sc_pk_queue, q_next);
! 405:
! 406: r = PK_READ_4(sc, NOFN_PK_IER);
! 407: r &= PK_IER_RRDY; /* preserve */
! 408: r |= PK_IER_DONE;
! 409: PK_WRITE_4(sc, NOFN_PK_IER, r);
! 410: break;
! 411: } else {
! 412: SIMPLEQ_REMOVE_HEAD(&sc->sc_pk_queue, q_next);
! 413: free(q, M_DEVBUF);
! 414: }
! 415: }
! 416: }
! 417:
! 418: int
! 419: nofn_pk_process(krp)
! 420: struct cryptkop *krp;
! 421: {
! 422: struct nofn_softc *sc;
! 423: struct nofn_pk_q *q;
! 424: int s;
! 425:
! 426: if (krp == NULL || krp->krp_callback == NULL)
! 427: return (EINVAL);
! 428: if ((sc = nofn_pk_find(krp)) == NULL) {
! 429: krp->krp_status = EINVAL;
! 430: crypto_kdone(krp);
! 431: return (0);
! 432: }
! 433:
! 434: q = (struct nofn_pk_q *)malloc(sizeof(*q), M_DEVBUF, M_NOWAIT);
! 435: if (q == NULL) {
! 436: krp->krp_status = ENOMEM;
! 437: crypto_kdone(krp);
! 438: return (0);
! 439: }
! 440:
! 441: switch (krp->krp_op) {
! 442: case CRK_MOD_EXP:
! 443: q->q_start = nofn_modexp_start;
! 444: q->q_finish = nofn_modexp_finish;
! 445: q->q_krp = krp;
! 446: s = splnet();
! 447: SIMPLEQ_INSERT_TAIL(&sc->sc_pk_queue, q, q_next);
! 448: nofn_pk_feed(sc);
! 449: splx(s);
! 450: return (0);
! 451: default:
! 452: printf("%s: kprocess: invalid op 0x%x\n",
! 453: sc->sc_dev.dv_xname, krp->krp_op);
! 454: krp->krp_status = EOPNOTSUPP;
! 455: crypto_kdone(krp);
! 456: free(q, M_DEVBUF);
! 457: return (0);
! 458: }
! 459: }
! 460:
! 461: struct nofn_softc *
! 462: nofn_pk_find(krp)
! 463: struct cryptkop *krp;
! 464: {
! 465: struct nofn_softc *sc;
! 466: int i;
! 467:
! 468: for (i = 0; i < nofn_cd.cd_ndevs; i++) {
! 469: sc = nofn_cd.cd_devs[i];
! 470: if (sc == NULL)
! 471: continue;
! 472: if (sc->sc_cid == krp->krp_hid)
! 473: return (sc);
! 474: }
! 475: return (NULL);
! 476: }
! 477:
! 478: void
! 479: nofn_pk_read_reg(sc, ridx, rp)
! 480: struct nofn_softc *sc;
! 481: int ridx;
! 482: union nofn_pk_reg *rp;
! 483: {
! 484: #if BYTE_ORDER == BIG_ENDIAN
! 485: bus_space_read_region_4(sc->sc_pk_t, sc->sc_pk_h,
! 486: NOFN_PK_REGADDR(NOFN_PK_WIN_0, ridx, 0), rp->w, 1024/32);
! 487: #else
! 488: bus_space_read_region_4(sc->sc_pk_t, sc->sc_pk_h,
! 489: NOFN_PK_REGADDR(NOFN_PK_WIN_2, ridx, 0), rp->w, 1024/32);
! 490: #endif
! 491: }
! 492:
! 493: void
! 494: nofn_pk_write_reg(sc, ridx, rp)
! 495: struct nofn_softc *sc;
! 496: int ridx;
! 497: union nofn_pk_reg *rp;
! 498: {
! 499: #if BYTE_ORDER == BIG_ENDIAN
! 500: bus_space_write_region_4(sc->sc_pk_t, sc->sc_pk_h,
! 501: NOFN_PK_REGADDR(NOFN_PK_WIN_0, ridx, 0), rp->w, 1024/32);
! 502: #else
! 503: bus_space_write_region_4(sc->sc_pk_t, sc->sc_pk_h,
! 504: NOFN_PK_REGADDR(NOFN_PK_WIN_2, ridx, 0), rp->w, 1024/32);
! 505: #endif
! 506: }
! 507:
! 508: void
! 509: nofn_pk_zero_reg(sc, ridx)
! 510: struct nofn_softc *sc;
! 511: int ridx;
! 512: {
! 513: nofn_pk_write_reg(sc, ridx, &sc->sc_pk_zero);
! 514: }
! 515:
! 516: int
! 517: nofn_modexp_start(sc, q)
! 518: struct nofn_softc *sc;
! 519: struct nofn_pk_q *q;
! 520: {
! 521: struct cryptkop *krp = q->q_krp;
! 522: int ip = 0, err = 0;
! 523: int mshift, eshift, nshift;
! 524: int mbits, ebits, nbits;
! 525:
! 526: if (krp->krp_param[NOFN_MODEXP_PAR_M].crp_nbits > 1024) {
! 527: err = ERANGE;
! 528: goto errout;
! 529: }
! 530:
! 531: /* Zero out registers. */
! 532: nofn_pk_zero_reg(sc, 0);
! 533: nofn_pk_zero_reg(sc, 1);
! 534: nofn_pk_zero_reg(sc, 2);
! 535: nofn_pk_zero_reg(sc, 3);
! 536:
! 537: /* Write out N... */
! 538: nbits = nofn_pk_sigbits(krp->krp_param[NOFN_MODEXP_PAR_N].crp_p,
! 539: krp->krp_param[NOFN_MODEXP_PAR_N].crp_nbits);
! 540: if (nbits > 1024) {
! 541: err = E2BIG;
! 542: goto errout;
! 543: }
! 544: if (nbits < 5) {
! 545: err = ERANGE;
! 546: goto errout;
! 547: }
! 548: bzero(&sc->sc_pk_tmp, sizeof(sc->sc_pk_tmp));
! 549: bcopy(krp->krp_param[NOFN_MODEXP_PAR_N].crp_p, &sc->sc_pk_tmp,
! 550: (nbits + 7) / 8);
! 551: nofn_pk_write_reg(sc, 2, &sc->sc_pk_tmp);
! 552:
! 553: nshift = 1024 - nbits;
! 554: PK_WRITE_4(sc, NOFN_PK_LENADDR(2), 1024);
! 555: if (nshift != 0) {
! 556: PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip,
! 557: NOFN_PK_INSTR2(0, PK_OPCODE_SL, 2, 2, nshift));
! 558: ip += 4;
! 559:
! 560: PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip,
! 561: NOFN_PK_INSTR2(0, PK_OPCODE_TAG, 2, 2, nbits));
! 562: ip += 4;
! 563: }
! 564:
! 565: /* Write out M... */
! 566: mbits = nofn_pk_sigbits(krp->krp_param[NOFN_MODEXP_PAR_M].crp_p,
! 567: krp->krp_param[NOFN_MODEXP_PAR_M].crp_nbits);
! 568: if (mbits > 1024 || mbits > nbits) {
! 569: err = E2BIG;
! 570: goto errout;
! 571: }
! 572: bzero(&sc->sc_pk_tmp, sizeof(sc->sc_pk_tmp));
! 573: bcopy(krp->krp_param[NOFN_MODEXP_PAR_M].crp_p, &sc->sc_pk_tmp,
! 574: (mbits + 7) / 8);
! 575: nofn_pk_write_reg(sc, 0, &sc->sc_pk_tmp);
! 576:
! 577: mshift = 1024 - nbits;
! 578: PK_WRITE_4(sc, NOFN_PK_LENADDR(0), 1024);
! 579: if (mshift != 0) {
! 580: PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip,
! 581: NOFN_PK_INSTR2(0, PK_OPCODE_SL, 0, 0, mshift));
! 582: ip += 4;
! 583:
! 584: PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip,
! 585: NOFN_PK_INSTR2(0, PK_OPCODE_TAG, 0, 0, nbits));
! 586: ip += 4;
! 587: }
! 588:
! 589: /* Write out E... */
! 590: ebits = nofn_pk_sigbits(krp->krp_param[NOFN_MODEXP_PAR_E].crp_p,
! 591: krp->krp_param[NOFN_MODEXP_PAR_E].crp_nbits);
! 592: if (ebits > 1024 || ebits > nbits) {
! 593: err = E2BIG;
! 594: goto errout;
! 595: }
! 596: if (ebits < 1) {
! 597: err = ERANGE;
! 598: goto errout;
! 599: }
! 600: bzero(&sc->sc_pk_tmp, sizeof(sc->sc_pk_tmp));
! 601: bcopy(krp->krp_param[NOFN_MODEXP_PAR_E].crp_p, &sc->sc_pk_tmp,
! 602: (ebits + 7) / 8);
! 603: nofn_pk_write_reg(sc, 1, &sc->sc_pk_tmp);
! 604:
! 605: eshift = 1024 - nbits;
! 606: PK_WRITE_4(sc, NOFN_PK_LENADDR(1), 1024);
! 607: if (eshift != 0) {
! 608: PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip,
! 609: NOFN_PK_INSTR2(0, PK_OPCODE_SL, 1, 1, eshift));
! 610: ip += 4;
! 611:
! 612: PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip,
! 613: NOFN_PK_INSTR2(0, PK_OPCODE_TAG, 1, 1, nbits));
! 614: ip += 4;
! 615: }
! 616:
! 617: if (nshift == 0) {
! 618: PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip,
! 619: NOFN_PK_INSTR(PK_OP_DONE, PK_OPCODE_MODEXP, 3, 0, 1, 2));
! 620: ip += 4;
! 621: } else {
! 622: PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip,
! 623: NOFN_PK_INSTR(0, PK_OPCODE_MODEXP, 3, 0, 1, 2));
! 624: ip += 4;
! 625:
! 626: PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip,
! 627: NOFN_PK_INSTR2(0, PK_OPCODE_SR, 3, 3, nshift));
! 628: ip += 4;
! 629:
! 630: PK_WRITE_4(sc, NOFN_PK_INSTR_BEGIN + ip,
! 631: NOFN_PK_INSTR2(PK_OP_DONE, PK_OPCODE_TAG, 3, 3, nbits));
! 632: ip += 4;
! 633: }
! 634:
! 635: /* Start microprogram */
! 636: PK_WRITE_4(sc, NOFN_PK_CR, 0 << PK_CR_OFFSET_S);
! 637:
! 638: return (0);
! 639:
! 640: errout:
! 641: bzero(&sc->sc_pk_tmp, sizeof(sc->sc_pk_tmp));
! 642: nofn_pk_zero_reg(sc, 0);
! 643: nofn_pk_zero_reg(sc, 1);
! 644: nofn_pk_zero_reg(sc, 2);
! 645: nofn_pk_zero_reg(sc, 3);
! 646: krp->krp_status = err;
! 647: crypto_kdone(krp);
! 648: return (1);
! 649: }
! 650:
! 651: void
! 652: nofn_modexp_finish(sc, q)
! 653: struct nofn_softc *sc;
! 654: struct nofn_pk_q *q;
! 655: {
! 656: struct cryptkop *krp = q->q_krp;
! 657: int reglen, crplen;
! 658:
! 659: nofn_pk_read_reg(sc, 3, &sc->sc_pk_tmp);
! 660:
! 661: reglen = ((PK_READ_4(sc, NOFN_PK_LENADDR(3)) & NOFN_PK_LENMASK) + 7)
! 662: / 8;
! 663: crplen = (krp->krp_param[krp->krp_iparams].crp_nbits + 7) / 8;
! 664:
! 665: if (crplen <= reglen)
! 666: bcopy(sc->sc_pk_tmp.b, krp->krp_param[krp->krp_iparams].crp_p,
! 667: reglen);
! 668: else {
! 669: bcopy(sc->sc_pk_tmp.b, krp->krp_param[krp->krp_iparams].crp_p,
! 670: reglen);
! 671: bzero(krp->krp_param[krp->krp_iparams].crp_p + reglen,
! 672: crplen - reglen);
! 673: }
! 674: bzero(&sc->sc_pk_tmp, sizeof(sc->sc_pk_tmp));
! 675: nofn_pk_zero_reg(sc, 0);
! 676: nofn_pk_zero_reg(sc, 1);
! 677: nofn_pk_zero_reg(sc, 2);
! 678: nofn_pk_zero_reg(sc, 3);
! 679: crypto_kdone(krp);
! 680: }
! 681:
! 682: /*
! 683: * Return the number of significant bits of a little endian big number.
! 684: */
! 685: int
! 686: nofn_pk_sigbits(p, pbits)
! 687: const u_int8_t *p;
! 688: u_int pbits;
! 689: {
! 690: u_int plen = (pbits + 7) / 8;
! 691: int i, sig = plen * 8;
! 692: u_int8_t c;
! 693:
! 694: for (i = plen - 1; i >= 0; i--) {
! 695: c = p[i];
! 696: if (c != 0) {
! 697: while ((c & 0x80) == 0) {
! 698: sig--;
! 699: c <<= 1;
! 700: }
! 701: break;
! 702: }
! 703: sig -= 8;
! 704: }
! 705: return (sig);
! 706: }
CVSweb