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