[BACK]Return to nofn.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/nofn.c, Revision 1.1.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