Annotation of sys/dev/pci/ises.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ises.c,v 1.31 2006/06/29 21:34:51 deraadt Exp $ */
2:
3: /*
4: * Copyright (c) 2000, 2001 Håkan Olsson (ho@crt.se)
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:
29: /*
30: * PCC-ISES hardware crypto accelerator
31: */
32:
33: #include <sys/param.h>
34: #include <sys/systm.h>
35: #include <sys/proc.h>
36: #include <sys/errno.h>
37: #include <sys/malloc.h>
38: #include <sys/kernel.h>
39: #include <sys/mbuf.h>
40: #include <sys/timeout.h>
41: #include <sys/device.h>
42: #include <sys/queue.h>
43:
44: #include <crypto/cryptodev.h>
45: #include <crypto/cryptosoft.h>
46: #include <dev/rndvar.h>
47: #include <crypto/md5.h>
48: #include <crypto/sha1.h>
49: #include <crypto/rmd160.h>
50:
51: #include <dev/pci/pcireg.h>
52: #include <dev/pci/pcivar.h>
53: #include <dev/pci/pcidevs.h>
54:
55: #include <dev/pci/isesreg.h>
56: #include <dev/pci/isesvar.h>
57: #include <dev/microcode/ises/ises_fw.h>
58:
59: /*
60: * Prototypes and count for the pci_device structure
61: */
62: int ises_match(struct device *, void *, void *);
63: void ises_attach(struct device *, struct device *, void *);
64:
65: void ises_initstate(void *);
66: void ises_hrng_init(struct ises_softc *);
67: void ises_hrng(void *);
68: void ises_process_oqueue(struct ises_softc *);
69: int ises_queue_cmd(struct ises_softc *, u_int32_t, u_int32_t *,
70: u_int32_t (*)(struct ises_softc *, struct ises_cmd *));
71: u_int32_t ises_get_fwversion(struct ises_softc *);
72: int ises_assert_cmd_mode(struct ises_softc *);
73:
74: int ises_intr(void *);
75: int ises_newsession(u_int32_t *, struct cryptoini *);
76: int ises_freesession(u_int64_t);
77: int ises_process(struct cryptop *);
78: void ises_callback(struct ises_q *);
79: int ises_feed(struct ises_softc *);
80: int ises_bchu_switch_session(struct ises_softc *,
81: struct ises_session *, int);
82: u_int32_t ises_bchu_switch_final(struct ises_softc *, struct ises_cmd *);
83:
84: void ises_read_dma(struct ises_softc *);
85:
86: #define READ_REG(sc,r) \
87: bus_space_read_4((sc)->sc_memt, (sc)->sc_memh,r)
88:
89: #define WRITE_REG(sc,reg,val) \
90: bus_space_write_4((sc)->sc_memt, (sc)->sc_memh, reg, val)
91:
92: /* XXX This should probably be (x) = htole32((x)) */
93: #define SWAP32(x) ((x) = swap32((x)))
94:
95: #ifdef ISESDEBUG
96: # define DPRINTF(x) printf x
97: #else
98: # define DPRINTF(x)
99: #endif
100:
101: #ifdef ISESDEBUG
102: void ises_debug_init(struct ises_softc *);
103: void ises_debug_2(void);
104: void ises_debug_loop(void *);
105: void ises_showreg(void);
106: void ises_debug_parse_omr(struct ises_softc *);
107: void ises_debug_simple_cmd(struct ises_softc *, u_int32_t, u_int32_t);
108: struct ises_softc *ises_sc;
109: struct timeout ises_db_timeout;
110: int ises_db;
111: #endif
112:
113: /* For HRNG entropy collection, these values gather 1600 bytes/s */
114: #ifndef ISESRNGBITS
115: #define ISESRNGBITS 128 /* Bits per iteration (mult. of 32) */
116: #define ISESRNGIPS 100 /* Iterations per second */
117: #endif
118:
119: /* XXX Disable HRNG while debugging. */
120: #define ISES_HRNG_DISABLED
121:
122: /* Maximum number of times we try to download the firmware. */
123: #define ISES_MAX_DOWNLOAD_RETRIES 3
124:
125: struct cfattach ises_ca = {
126: sizeof(struct ises_softc), ises_match, ises_attach,
127: };
128:
129: struct cfdriver ises_cd = {
130: 0, "ises", DV_DULL
131: };
132:
133: struct ises_stats {
134: u_int64_t ibytes;
135: u_int64_t obytes;
136: u_int32_t ipkts;
137: u_int32_t opkts;
138: u_int32_t invalid;
139: u_int32_t nomem;
140: } isesstats;
141:
142: int
143: ises_match(struct device *parent, void *match, void *aux)
144: {
145: struct pci_attach_args *pa = (struct pci_attach_args *)aux;
146:
147: if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_PIJNENBURG &&
148: PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_PIJNENBURG_PCC_ISES)
149: return (1);
150:
151: return (0);
152: }
153:
154: void
155: ises_attach(struct device *parent, struct device *self, void *aux)
156: {
157: struct ises_softc *sc = (struct ises_softc *)self;
158: struct pci_attach_args *pa = aux;
159: pci_chipset_tag_t pc = pa->pa_pc;
160: pci_intr_handle_t ih;
161: const char *intrstr = NULL;
162: bus_size_t memsize;
163:
164: bus_dma_segment_t seg;
165: int nsegs, error, state;
166:
167: SIMPLEQ_INIT(&sc->sc_queue);
168: SIMPLEQ_INIT(&sc->sc_qchip);
169: SIMPLEQ_INIT(&sc->sc_cmdq);
170: state = 0;
171:
172: /* Map control/status registers. */
173: if (pci_mapreg_map(pa, PCI_MAPREG_START,
174: PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0, &sc->sc_memt,
175: &sc->sc_memh, NULL, &memsize, 0)) {
176: printf(": can't find mem space\n");
177: return;
178: }
179: state++;
180:
181: /* Map interrupt. */
182: if (pci_intr_map(pa, &ih)) {
183: printf(": couldn't map interrupt\n");
184: goto fail;
185: }
186: state++;
187:
188: intrstr = pci_intr_string(pc, ih);
189: sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, ises_intr, sc,
190: self->dv_xname);
191: if (sc->sc_ih == NULL) {
192: printf(": couldn't establish interrupt\n");
193: if (intrstr != NULL)
194: printf(" at %s", intrstr);
195: printf("\n");
196: goto fail;
197: }
198:
199: /* Initialize DMA map */
200: sc->sc_dmat = pa->pa_dmat;
201: error = bus_dmamap_create(sc->sc_dmat, 1 << PGSHIFT, 1, 1 << PGSHIFT,
202: 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_dmamap);
203: if (error) {
204: printf(": cannot create dma map (%d)\n", error);
205: goto fail;
206: }
207: state++;
208:
209: /* Allocate in DMAable memory. */
210: if (bus_dmamem_alloc(sc->sc_dmat, ISES_B_DATASIZE, 1, 0, &seg, 1,
211: &nsegs, BUS_DMA_NOWAIT)) {
212: printf(": can't alloc dma buffer space\n");
213: goto fail;
214: }
215: state++;
216:
217: if (bus_dmamem_map(sc->sc_dmat, &seg, nsegs, ISES_B_DATASIZE,
218: &sc->sc_dma_data, 0)) {
219: printf(": can't map dma buffer space\n");
220: goto fail;
221: }
222: state++;
223:
224: printf(": %s\n", intrstr);
225:
226: bzero(&isesstats, sizeof(isesstats));
227:
228: sc->sc_cid = crypto_get_driverid(0);
229:
230: if (sc->sc_cid < 0)
231: goto fail;
232:
233: /*
234: * Since none of the initialization steps generate interrupts
235: * for example, the hardware reset, we use a number of timeouts
236: * (or init states) to do the rest of the chip initialization.
237: */
238:
239: sc->sc_initstate = 0;
240: startuphook_establish(ises_initstate, sc);
241:
242: #ifdef ISESDEBUG
243: ises_debug_init(sc);
244: #endif
245: return;
246:
247: fail:
248: switch (state) { /* Always fallthrough here. */
249: case 5:
250: bus_dmamem_unmap(sc->sc_dmat, (caddr_t)&sc->sc_dma_data,
251: sizeof sc->sc_dma_data);
252: /* FALLTHROUGH */
253: case 4:
254: bus_dmamem_free(sc->sc_dmat, &seg, nsegs);
255: /* FALLTHROUGH */
256: case 3:
257: bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap);
258: /* FALLTHROUGH */
259: case 2:
260: pci_intr_disestablish(pc, sc->sc_ih);
261: /* FALLTHROUGH */
262: case 1:
263: bus_space_unmap(sc->sc_memt, sc->sc_memh, memsize);
264: /* FALLTHROUGH */
265: default: /* 0 */
266: break;
267: }
268: return;
269: }
270:
271: void
272: ises_initstate(void *v)
273: {
274: /*
275: * Step through chip initialization.
276: * sc->sc_initstate tells us what to do.
277: */
278: extern int hz;
279: struct ises_softc *sc = v;
280: char *dv = sc->sc_dv.dv_xname;
281: u_int32_t stat;
282: int p, ticks, algs[CRYPTO_ALGORITHM_MAX + 1];
283: static int retry_count = 0; /* XXX Should be in softc */
284:
285: ticks = hz * 3 / 2; /* 1.5s */
286:
287: p = ISES_STAT_IDP_STATE(READ_REG(sc, ISES_A_STAT));
288: DPRINTF(("%s: initstate %d, IDP state is %d \"%s\"\n", dv,
289: sc->sc_initstate, p, ises_idp_state[p]));
290:
291: switch (sc->sc_initstate) {
292: case 0:
293: /* Called by dostartuphooks(9). */
294: timeout_set(&sc->sc_timeout, ises_initstate, sc);
295: sc->sc_initstate++;
296:
297: /* FALLTHROUGH */
298: case 1:
299: /* Power up the chip (clear powerdown bit) */
300: stat = READ_REG(sc, ISES_BO_STAT);
301: if (stat & ISES_BO_STAT_POWERDOWN) {
302: stat &= ~ISES_BO_STAT_POWERDOWN;
303: WRITE_REG(sc, ISES_BO_STAT, stat);
304: /* Selftests will take 1 second. */
305: break;
306: }
307: #if 1
308: else {
309: /* Power down the chip for sane init, then rerun. */
310: stat |= ISES_BO_STAT_POWERDOWN;
311: WRITE_REG(sc, ISES_BO_STAT, stat);
312: sc->sc_initstate--; /* Rerun state 1. */
313: break;
314: }
315: #else
316: /* FALLTHROUGH (chip is already powered up) */
317: sc->sc_initstate++;
318: #endif
319:
320: case 2:
321: /* Perform a hardware reset */
322: stat = 0;
323:
324: printf ("%s: initializing...\n", dv);
325:
326: /* Clear all possible bypass bits. */
327: for (p = 0; p < 128; p++)
328: WRITE_REG(sc, ISES_B_BDATAOUT, 0L);
329:
330: stat |= ISES_BO_STAT_HWRESET;
331: WRITE_REG(sc, ISES_BO_STAT, stat);
332: stat &= ~ISES_BO_STAT_HWRESET;
333: WRITE_REG(sc, ISES_BO_STAT, stat);
334: /* Again, selftests will take 1 second. */
335: break;
336:
337: case 3:
338: /* Set AConf to zero, i.e 32-bits access to A-int. */
339: stat = READ_REG(sc, ISES_BO_STAT);
340: stat &= ~ISES_BO_STAT_ACONF;
341: WRITE_REG(sc, ISES_BO_STAT, stat);
342:
343: /* Is the firmware already loaded? */
344: if (READ_REG(sc, ISES_A_STAT) & ISES_STAT_HW_DA) {
345: /* Yes it is, jump ahead a bit */
346: ticks = 1;
347: sc->sc_initstate += 3; /* Next step --> 7 */
348: break;
349: }
350:
351: /*
352: * Download the Basic Functionality firmware.
353: */
354:
355: p = ISES_STAT_IDP_STATE(READ_REG(sc, ISES_A_STAT));
356: if (p == ISES_IDP_WFPL) {
357: /* We're ready to download. */
358: ticks = 1;
359: sc->sc_initstate += 2; /* Next step --> 6 */
360: break;
361: }
362:
363: /*
364: * Prior to downloading we need to reset the NSRAM.
365: * Setting the tamper bit will erase the contents
366: * in 1 microsecond.
367: */
368: stat = READ_REG(sc, ISES_BO_STAT);
369: stat |= ISES_BO_STAT_TAMPER;
370: WRITE_REG(sc, ISES_BO_STAT, stat);
371: ticks = 1;
372: break;
373:
374: case 4:
375: /* After tamper bit has been set, powerdown chip. */
376: stat = READ_REG(sc, ISES_BO_STAT);
377: stat |= ISES_BO_STAT_POWERDOWN;
378: WRITE_REG(sc, ISES_BO_STAT, stat);
379: /* Wait one second for power to dissipate. */
380: break;
381:
382: case 5:
383: /* Clear tamper and powerdown bits. */
384: stat = READ_REG(sc, ISES_BO_STAT);
385: stat &= ~(ISES_BO_STAT_TAMPER | ISES_BO_STAT_POWERDOWN);
386: WRITE_REG(sc, ISES_BO_STAT, stat);
387: /* Again we need to wait a second for selftests. */
388: break;
389:
390: case 6:
391: /*
392: * We'll need some space in the input queue (IQF)
393: * and we need to be in the 'waiting for program
394: * length' IDP state (0x4).
395: */
396: p = ISES_STAT_IDP_STATE(READ_REG(sc, ISES_A_STAT));
397: if (READ_REG(sc, ISES_A_IQF) < 4 || p != ISES_IDP_WFPL) {
398: if (retry_count++ < ISES_MAX_DOWNLOAD_RETRIES) {
399: /* Retry download. */
400: sc->sc_initstate -= 5; /* Next step --> 2 */
401: ticks = 1;
402: break;
403: }
404: retry_count = 0;
405: printf("%s: cannot download firmware, "
406: "IDP state is \"%s\"\n", dv, ises_idp_state[p]);
407: return;
408: }
409:
410: /* Write firmware length */
411: WRITE_REG(sc, ISES_A_IQD, ISES_BF_IDPLEN);
412:
413: /* Write firmware code */
414: for (p = 0; p < sizeof(ises_bf_fw)/sizeof(u_int32_t); p++) {
415: WRITE_REG(sc, ISES_A_IQD, ises_bf_fw[p]);
416: if (READ_REG(sc, ISES_A_IQF) < 4)
417: DELAY(10);
418: }
419:
420: /* Write firmware CRC */
421: WRITE_REG(sc, ISES_A_IQD, ISES_BF_IDPCRC);
422:
423: /* Wait 1s while chip resets and runs selftests */
424: break;
425:
426: case 7:
427: /* Did the download succed? */
428: if (READ_REG(sc, ISES_A_STAT) & ISES_STAT_HW_DA) {
429: ticks = 1;
430: break;
431: }
432:
433: /* We failed. */
434: goto fail;
435:
436: case 8:
437: if (ises_assert_cmd_mode(sc) < 0)
438: goto fail;
439:
440: /*
441: * Now that the basic functionality firmware should be
442: * up and running, try to get the firmware version.
443: */
444:
445: stat = ises_get_fwversion(sc);
446: if (stat == 0)
447: goto fail;
448:
449: printf("%s: firmware v%d.%d loaded (%d bytes)", dv,
450: stat & 0xffff, (stat >> 16) & 0xffff, ISES_BF_IDPLEN << 2);
451:
452: /* We can use firmware versions 1.x & 2.x */
453: switch (stat & 0xffff) {
454: case 0:
455: printf(" diagnostic, %s disabled\n", dv);
456: goto fail;
457: case 1: /* Basic Func "base" firmware */
458: case 2: /* Basic Func "ipsec" firmware, no ADP code */
459: break;
460: default:
461: printf(" unknown, %s disabled\n", dv);
462: goto fail;
463: }
464:
465: stat = READ_REG(sc, ISES_A_STAT);
466: DPRINTF((", mode %s",
467: ises_sw_mode[ISES_STAT_SW_MODE(stat)]));
468:
469: /* Reuse the timeout for HRNG entropy collection. */
470: timeout_del(&sc->sc_timeout);
471: ises_hrng_init(sc);
472:
473: /* Set the interrupt mask */
474: sc->sc_intrmask = ISES_STAT_BCHU_OAF | ISES_STAT_BCHU_ERR |
475: ISES_STAT_BCHU_OFHF | ISES_STAT_SW_OQSINC |
476: ISES_STAT_LNAU_BUSY_1 | ISES_STAT_LNAU_ERR_1 |
477: ISES_STAT_LNAU_BUSY_2 | ISES_STAT_LNAU_ERR_2;
478: #if 0
479: ISES_STAT_BCHU_ERR | ISES_STAT_BCHU_OAF |
480: ISES_STAT_BCHU_IFE | ISES_STAT_BCHU_IFHE |
481: ISES_STAT_BCHU_OFHF | ISES_STAT_BCHU_OFF;
482: #endif
483:
484: WRITE_REG(sc, ISES_A_INTE, sc->sc_intrmask);
485:
486: /* We're done. */
487: printf("\n");
488:
489: /* Register ourselves with crypto framework. */
490: bzero(algs, sizeof(algs));
491:
492: algs[CRYPTO_3DES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
493: algs[CRYPTO_DES_CBC] = CRYPTO_ALG_FLAG_SUPPORTED;
494: algs[CRYPTO_MD5_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
495: algs[CRYPTO_SHA1_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
496: algs[CRYPTO_RIPEMD160_HMAC] = CRYPTO_ALG_FLAG_SUPPORTED;
497:
498: crypto_register(sc->sc_cid, algs,
499: ises_newsession, ises_freesession, ises_process);
500: return;
501:
502: default:
503: printf("%s: entered unknown initstate %d\n", dv,
504: sc->sc_initstate);
505: goto fail;
506: }
507:
508: /* Increment state counter and schedule next step in 'ticks' ticks. */
509: sc->sc_initstate++;
510: timeout_add(&sc->sc_timeout, ticks);
511: return;
512:
513: fail:
514: printf("%s: firmware failure\n", dv);
515: timeout_del(&sc->sc_timeout);
516: return;
517: }
518:
519: /* Put a command on the A-interface queue. */
520: int
521: ises_queue_cmd(struct ises_softc *sc, u_int32_t cmd, u_int32_t *data,
522: u_int32_t (*callback)(struct ises_softc *, struct ises_cmd *))
523: {
524: struct ises_cmd *cq;
525: int p, len, s, code;
526:
527: len = cmd >> 24;
528: code = (cmd >> 16) & 0xFF;
529:
530: #ifdef ISESDEBUG
531: if (code != ISES_CMD_HBITS) /* ... since this happens 100 times/s */
532: DPRINTF(("%s: queueing cmd 0x%x len %d\n", sc->sc_dv.dv_xname,
533: code, len));
534: #endif
535:
536: s = splnet();
537:
538: if (len > READ_REG(sc, ISES_A_IQF)) {
539: splx(s);
540: return (EAGAIN); /* XXX ENOMEM ? */
541: }
542:
543: cq = (struct ises_cmd *)
544: malloc(sizeof (struct ises_cmd), M_DEVBUF, M_NOWAIT);
545: if (cq == NULL) {
546: splx(s);
547: isesstats.nomem++;
548: return (ENOMEM);
549: }
550: bzero(cq, sizeof (struct ises_cmd));
551: cq->cmd_code = code;
552: cq->cmd_cb = callback;
553: cq->cmd_session = sc->sc_cursession;
554: SIMPLEQ_INSERT_TAIL(&sc->sc_cmdq, cq, cmd_next);
555:
556: WRITE_REG(sc, ISES_A_IQD, cmd);
557:
558: /* LNAU register data should be written in reverse order */
559: if ((code >= ISES_CMD_LW_A_1 && code <= ISES_CMD_LW_U_1) || /* LNAU1 */
560: (code >= ISES_CMD_LW_A_2 && code <= ISES_CMD_LW_U_2)) /* LNAU2 */
561: for (p = len - 1; p >= 0; p--)
562: WRITE_REG(sc, ISES_A_IQD, *(data + p));
563: else
564: for (p = 0; p < len; p++)
565: WRITE_REG(sc, ISES_A_IQD, *(data + p));
566:
567: /* Signal 'command ready'. */
568: WRITE_REG(sc, ISES_A_IQS, 0);
569:
570: splx(s);
571: return (0);
572: }
573:
574: /* Process all completed responses in the output queue. */
575: void
576: ises_process_oqueue(struct ises_softc *sc)
577: {
578: #ifdef ISESDEBUG
579: char *dv = sc->sc_dv.dv_xname;
580: #endif
581: struct ises_cmd *cq;
582: struct ises_session *ses;
583: u_int32_t oqs, r, d;
584: int cmd, len, c, s;
585:
586: r = READ_REG(sc, ISES_A_OQS);
587: if (r > 1)
588: DPRINTF(("%s:process_oqueue: OQS=%d\n", dv, r));
589:
590: /* OQS gives us the number of responses we have to process. */
591: while ((oqs = READ_REG(sc, ISES_A_OQS)) > 0) {
592: /* Read command response. [ len(8) | cmd(8) | rc(16) ] */
593: r = READ_REG(sc, ISES_A_OQD);
594: len = (r >> 24);
595: cmd = (r >> 16) & 0xff;
596: r = r & 0xffff;
597:
598: s = splnet();
599: if (!SIMPLEQ_EMPTY(&sc->sc_cmdq)) {
600: cq = SIMPLEQ_FIRST(&sc->sc_cmdq);
601: SIMPLEQ_REMOVE_HEAD(&sc->sc_cmdq, cmd_next);
602: cq->cmd_rlen = len;
603: } else {
604: cq = NULL;
605: DPRINTF(("%s:process_oqueue: cmd queue empty!\n", dv));
606: }
607: splx(s);
608:
609: if (r) {
610: /* Ouch. This command generated an error */
611: DPRINTF(("%s:process_oqueue: cmd 0x%x err %d\n", dv,
612: cmd, (r & ISES_RC_MASK)));
613: /* Abort any running session switch to force a retry.*/
614: sc->sc_switching = 0;
615: /* Return to CMD mode. This will reset all queues. */
616: (void)ises_assert_cmd_mode(sc);
617: } else {
618: /* Use specified callback, if any */
619: if (cq && cq->cmd_cb) {
620: if (cmd == cq->cmd_code) {
621: cq->cmd_cb(sc, cq);
622: cmd = ISES_CMD_NONE;
623: } else {
624: DPRINTF(("%s:process_oqueue: expected"
625: " cmd 0x%x, got 0x%x\n", dv,
626: cq->cmd_code, cmd));
627: /* XXX Some error handling here? */
628: }
629: }
630:
631: switch (cmd) {
632: case ISES_CMD_NONE:
633: break;
634:
635: case ISES_CMD_HBITS:
636: /* XXX How about increasing the pool size? */
637: /* XXX Use add_entropy_words instead? */
638: /* XXX ... at proper spl */
639: /* Cmd generated by ises_rng() via timeouts */
640: while (len--) {
641: d = READ_REG(sc, ISES_A_OQD);
642: add_true_randomness(d);
643: }
644: break;
645:
646: case ISES_CMD_LUPLOAD_1:
647: /* Get result of LNAU 1 operation. */
648: DPRINTF(("%s:process_oqueue: LNAU 1 result "
649: "upload (len=%d)\n", dv, len));
650: sc->sc_lnau1_rlen = len;
651: bzero(sc->sc_lnau1_r, 2048 / 8);
652: while (len--) {
653: /* first word is LSW */
654: sc->sc_lnau1_r[len] =
655: READ_REG(sc, ISES_A_OQD);
656: }
657: break;
658:
659: case ISES_CMD_LUPLOAD_2:
660: /* Get result of LNAU 1 operation. */
661: DPRINTF(("%s:process_oqueue: LNAU 2 result "
662: "upload (len=%d)\n", dv, len));
663: sc->sc_lnau2_rlen = len;
664: bzero(sc->sc_lnau1_r, 2048 / 8);
665: while (len--) {
666: /* first word is LSW */
667: sc->sc_lnau2_r[len] =
668: READ_REG(sc, ISES_A_OQD);
669: }
670: break;
671:
672: case ISES_CMD_BR_OMR:
673: ses = &sc->sc_sessions[cq->cmd_session];
674: ses->omr = READ_REG(sc, ISES_A_OQD);
675: DPRINTF(("%s:process_oqueue: read OMR[%08x]\n",
676: dv, ses->omr));
677: #ifdef ISESDEBUG
678: ises_debug_parse_omr(sc);
679: #endif
680: break;
681:
682: case ISES_CMD_BSWITCH:
683: /* XXX Currently BSWITCH does not work. */
684: DPRINTF(("%s:process_oqueue: BCHU_SWITCH\n"));
685: /* Put switched BCHU session in cur session. */
686: ses = &sc->sc_sessions[cq->cmd_session];
687: for(c = 0; len > 0; len--, c++)
688: #if 0 /* Don't store the key, just drain the data */
689: *((u_int32_t *)&ses + c) =
690: #endif
691: READ_REG(sc, ISES_A_OQD);
692:
693: sc->sc_switching = 0;
694: ises_feed (sc);
695: break;
696:
697: case ISES_CMD_BW_HMLR:
698: /* XXX Obsoleted by ises_bchu_switch_final */
699: DPRINTF(("%s:process_oqueue: CMD_BW_HMLR !?\n",
700: dv));
701: break;
702:
703: default:
704: /* All other are ok (no response data) */
705: DPRINTF(("%s:process_oqueue cmd 0x%x len %d\n",
706: dv, cmd, len));
707: if (cq && cq->cmd_cb)
708: len -= cq->cmd_cb(sc, cq);
709: }
710: }
711:
712: if (cq)
713: free(cq, M_DEVBUF);
714:
715: /* This will drain any remaining data and ACK this reponse. */
716: while (len-- > 0)
717: d = READ_REG(sc, ISES_A_OQD);
718: WRITE_REG(sc, ISES_A_OQS, 0);
719: if (oqs > 1)
720: DELAY(1); /* Wait for fw to decrement OQS (8 clocks) */
721: }
722: }
723:
724: int
725: ises_intr(void *arg)
726: {
727: struct ises_softc *sc = arg;
728: u_int32_t ints, dma_status, cmd;
729: char *dv = sc->sc_dv.dv_xname;
730:
731: dma_status = READ_REG(sc, ISES_DMA_STATUS);
732:
733: if (!(dma_status & (ISES_DMA_STATUS_R_ERR | ISES_DMA_STATUS_W_ERR))) {
734: if ((sc->sc_dma_mask & ISES_DMA_STATUS_R_RUN) != 0 &&
735: (dma_status & ISES_DMA_STATUS_R_RUN) == 0) {
736: DPRINTF(("%s: DMA read complete\n", dv));
737:
738: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
739: sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
740:
741: /* XXX Pick up and return the data.*/
742:
743: WRITE_REG(sc, ISES_DMA_RESET, 0);
744: }
745: if ((sc->sc_dma_mask & ISES_DMA_STATUS_W_RUN) != 0 &&
746: (dma_status & ISES_DMA_STATUS_W_RUN) == 0) {
747: DPRINTF(("%s: DMA write complete\n", dv));
748:
749: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
750: sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
751:
752: WRITE_REG(sc, ISES_DMA_RESET, 0);
753: ises_feed(sc);
754: }
755: } else {
756: printf ("%s: DMA error\n", dv);
757: WRITE_REG(sc, ISES_DMA_RESET, 0);
758: }
759:
760: ints = READ_REG(sc, ISES_A_INTS);
761: if (!(ints & sc->sc_intrmask)) {
762: DPRINTF (("%s: other intr mask [%08x]\n", ints));
763: return (0); /* Not our interrupt. */
764: }
765:
766: /* Clear all set intr bits. */
767: WRITE_REG(sc, ISES_A_INTS, ints);
768:
769: #if 0
770: /* Check it we've got room for more data. */
771: if (READ_REG(sc, ISES_A_STAT) &
772: (ISES_STAT_BCHU_IFE | ISES_STAT_BCHU_IFHE))
773: ises_feed(sc);
774: #endif
775:
776: /* Does the A-intf output queue have data we need to process? */
777: if (ints & ISES_STAT_SW_OQSINC)
778: ises_process_oqueue(sc);
779:
780: if (ints & ISES_STAT_LNAU_BUSY_1) {
781: DPRINTF(("%s:ises_intr: LNAU 1 job complete\n", dv));
782: /* upload LNAU 1 result (into sc->sc_lnau1_r) */
783: cmd = ISES_MKCMD(ISES_CMD_LUPLOAD_1, 0);
784: ises_queue_cmd(sc, cmd, NULL, NULL);
785: }
786:
787: if (ints & ISES_STAT_LNAU_BUSY_2) {
788: DPRINTF(("%s:ises_intr: LNAU 2 job complete\n", dv));
789: /* upload LNAU 2 result (into sc->sc_lnau2_r) */
790: cmd = ISES_MKCMD(ISES_CMD_LUPLOAD_2, 0);
791: ises_queue_cmd(sc, cmd, NULL, NULL);
792: }
793:
794: if (ints & ISES_STAT_LNAU_ERR_1) {
795: DPRINTF(("%s:ises_intr: LNAU 1 error\n", dv));
796: sc->sc_lnau1_rlen = -1;
797: }
798:
799: if (ints & ISES_STAT_LNAU_ERR_2) {
800: DPRINTF(("%s:ises_intr: LNAU 2 error\n", dv));
801: sc->sc_lnau2_rlen = -1;
802: }
803:
804: if (ints & ISES_STAT_BCHU_OAF) { /* output data available */
805: DPRINTF(("%s:ises_intr: BCHU_OAF bit set\n", dv));
806: /* Read DMA data from B-interface. */
807: ises_read_dma (sc);
808: }
809:
810: if (ints & ISES_STAT_BCHU_ERR) { /* We got a BCHU error */
811: DPRINTF(("%s:ises_intr: BCHU error\n", dv));
812: /* XXX Error handling */
813: }
814:
815: if (ints & ISES_STAT_BCHU_OFHF) { /* Output is half full */
816: DPRINTF(("%s:ises_intr: BCHU output FIFO half full\n", dv));
817: /* XXX drain data? */
818: }
819:
820: #if 0 /* XXX Useful? */
821: if (ints & ISES_STAT_BCHU_OFF) { /* Output is full */
822: /* XXX drain data / error handling? */
823: }
824: #endif
825: return (1);
826: }
827:
828: int
829: ises_feed(struct ises_softc *sc)
830: {
831: struct ises_q *q;
832: bus_dma_segment_t *ds = &sc->sc_dmamap->dm_segs[0];
833: u_int32_t dma_status;
834: int s;
835: #ifdef ISESDEBUG
836: char *dv = sc->sc_dv.dv_xname;
837: #endif
838:
839: DPRINTF(("%s:ises_feed: called (sc = %p)\n", dv, sc));
840: DELAY(1000000);
841:
842: s = splnet();
843: /* Anything to do? */
844: if (SIMPLEQ_EMPTY(&sc->sc_queue) ||
845: (READ_REG(sc, ISES_A_STAT) & ISES_STAT_BCHU_IFF)) {
846: splx(s);
847: return (0);
848: }
849:
850: /* Pick the first */
851: q = SIMPLEQ_FIRST(&sc->sc_queue);
852: splx(s);
853:
854: /* If we're currently switching sessions, we'll have to wait. */
855: if (sc->sc_switching != 0) {
856: DPRINTF(("%s:ises_feed: waiting for session switch\n", dv));
857: return (0);
858: }
859:
860: /* If on-chip data is not correct for this data, switch session. */
861: if (sc->sc_cursession != q->q_sesn) {
862: /* Session switch required */
863: DPRINTF(("%s:ises_feed: initiating session switch\n", dv));
864: if (ises_bchu_switch_session (sc, &q->q_session, q->q_sesn))
865: sc->sc_cursession = q->q_sesn;
866: else
867: DPRINTF(("%s:ises_feed: session switch failed\n", dv));
868: return (0);
869: }
870:
871: DPRINTF(("%s:ises_feed: feed to chip (q = %p)\n", dv, q));
872: DELAY(2000000);
873:
874: s = splnet();
875: SIMPLEQ_REMOVE_HEAD(&sc->sc_queue, q_next);
876: SIMPLEQ_INSERT_TAIL(&sc->sc_qchip, q, q_next);
877: --sc->sc_nqueue;
878: splx(s);
879:
880: if (q->q_crp->crp_flags & CRYPTO_F_IMBUF)
881: bus_dmamap_load_mbuf(sc->sc_dmat, sc->sc_dmamap,
882: q->q_src.mbuf, BUS_DMA_NOWAIT);
883: else if (q->q_crp->crp_flags & CRYPTO_F_IOV)
884: bus_dmamap_load_uio(sc->sc_dmat, sc->sc_dmamap, q->q_src.uio,
885: BUS_DMA_NOWAIT);
886: /* ... else */
887:
888: /* Start writing data to the ises. */
889: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
890: sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
891:
892: DPRINTF(("%s:ises_feed: writing DMA\n", dv));
893: DELAY(1000000);
894:
895: sc->sc_dma_mask |= ISES_DMA_STATUS_W_RUN;
896:
897: WRITE_REG(sc, ISES_DMA_WRITE_START, ds->ds_addr);
898: WRITE_REG(sc, ISES_DMA_WRITE_COUNT, ISES_DMA_WCOUNT(ds->ds_len));
899:
900: dma_status = READ_REG(sc, ISES_DMA_STATUS);
901: dma_status |= ISES_DMA_CTRL_ILT | ISES_DMA_CTRL_RLINE;
902: WRITE_REG(sc, ISES_DMA_CTRL, dma_status);
903:
904: DPRINTF(("%s:ises_feed: done\n", dv));
905: return (0);
906: }
907:
908: /*
909: * Allocate a new 'session' and return an encoded session id. 'sidp'
910: * contains our registration id, and should contain an encoded session
911: * id on successful allocation.
912: */
913: int
914: ises_newsession(u_int32_t *sidp, struct cryptoini *cri)
915: {
916: struct cryptoini *c, *mac = NULL, *enc = NULL;
917: struct ises_softc *sc = NULL;
918: struct ises_session *ses;
919: MD5_CTX md5ctx;
920: SHA1_CTX sha1ctx;
921: RMD160_CTX rmd160ctx;
922: int i, sesn;
923: #ifdef ISESDEBUG
924: char *dv;
925: #endif
926:
927: if (sidp == NULL || cri == NULL)
928: return (EINVAL);
929:
930: for (i = 0; i < ises_cd.cd_ndevs; i++) {
931: sc = ises_cd.cd_devs[i];
932: if (sc == NULL || sc->sc_cid == (*sidp))
933: break;
934: }
935: if (sc == NULL)
936: return (EINVAL);
937: #ifdef ISESDEBUG
938: dv = sc->sc_dv.dv_xname;
939: #endif
940:
941: DPRINTF(("%s:ises_newsession: start\n", dv));
942:
943: for (c = cri; c != NULL; c = c->cri_next) {
944: if (c->cri_alg == CRYPTO_MD5_HMAC ||
945: c->cri_alg == CRYPTO_SHA1_HMAC ||
946: c->cri_alg == CRYPTO_RIPEMD160_HMAC) {
947: if (mac)
948: return (EINVAL);
949: mac = c;
950: } else if (c->cri_alg == CRYPTO_DES_CBC ||
951: c->cri_alg == CRYPTO_3DES_CBC) {
952: if (enc)
953: return (EINVAL);
954: enc = c;
955: } else
956: return (EINVAL);
957: }
958: if (mac == 0 && enc == 0)
959: return (EINVAL);
960:
961: #ifdef ISESDEBUG
962: printf ("%s:ises_newsession: mac=%p(%d) enc=%p(%d)\n",
963: dv, mac, (mac ? mac->cri_alg : -1), enc, (enc ? enc->cri_alg : -1));
964: #endif
965:
966: /* Allocate a new session */
967: if (sc->sc_sessions == NULL) {
968: ses = sc->sc_sessions = (struct ises_session *)
969: malloc(sizeof(struct ises_session), M_DEVBUF, M_NOWAIT);
970: if (ses == NULL) {
971: isesstats.nomem++;
972: return (ENOMEM);
973: }
974: sc->sc_cursession = -1;
975: sesn = 0;
976: sc->sc_nsessions = 1;
977: } else {
978: ses = NULL;
979: for (sesn = 0; sesn < sc->sc_nsessions; sesn++)
980: if (sc->sc_sessions[sesn].omr == 0) {
981: ses = &sc->sc_sessions[sesn];
982: sc->sc_cursession = sesn;
983: break;
984: }
985:
986: if (ses == NULL) {
987: i = sc->sc_nsessions * sizeof(struct ises_session);
988: ses = (struct ises_session *)
989: malloc(i + sizeof(struct ises_session), M_DEVBUF,
990: M_NOWAIT);
991: if (ses == NULL) {
992: isesstats.nomem++;
993: return (ENOMEM);
994: }
995:
996: bcopy(sc->sc_sessions, ses, i);
997: bzero(sc->sc_sessions, i);
998: free(sc->sc_sessions, M_DEVBUF);
999: sc->sc_sessions = ses;
1000: ses = &sc->sc_sessions[sc->sc_nsessions];
1001: sc->sc_cursession = sc->sc_nsessions;
1002: sc->sc_nsessions++;
1003: }
1004: }
1005:
1006: DPRINTF(("%s:ises_newsession: nsessions=%d cursession=%d\n", dv,
1007: sc->sc_nsessions, sc->sc_cursession));
1008:
1009: bzero(ses, sizeof(struct ises_session));
1010:
1011: /* Select data path through B-interface. */
1012: ses->omr |= ISES_SELR_BCHU_DIS;
1013:
1014: if (enc) {
1015: /* get an IV, network byte order */
1016: /* XXX switch to using builtin HRNG ! */
1017: get_random_bytes(ses->sccr, sizeof(ses->sccr));
1018:
1019: /* crypto key */
1020: if (enc->cri_alg == CRYPTO_DES_CBC) {
1021: bcopy(enc->cri_key, &ses->kr[0], 8);
1022: bcopy(enc->cri_key, &ses->kr[2], 8);
1023: bcopy(enc->cri_key, &ses->kr[4], 8);
1024: } else
1025: bcopy(enc->cri_key, &ses->kr[0], 24);
1026:
1027: SWAP32(ses->kr[0]);
1028: SWAP32(ses->kr[1]);
1029: SWAP32(ses->kr[2]);
1030: SWAP32(ses->kr[3]);
1031: SWAP32(ses->kr[4]);
1032: SWAP32(ses->kr[5]);
1033: }
1034:
1035: if (mac) {
1036: for (i = 0; i < mac->cri_klen / 8; i++)
1037: mac->cri_key[i] ^= HMAC_IPAD_VAL;
1038:
1039: switch (mac->cri_alg) {
1040: case CRYPTO_MD5_HMAC:
1041: MD5Init(&md5ctx);
1042: MD5Update(&md5ctx, mac->cri_key, mac->cri_klen / 8);
1043: MD5Update(&md5ctx, hmac_ipad_buffer, HMAC_BLOCK_LEN -
1044: (mac->cri_klen / 8));
1045: MD5Final((u_int8_t *)&ses->cvr, &md5ctx);
1046: break;
1047: case CRYPTO_SHA1_HMAC:
1048: SHA1Init(&sha1ctx);
1049: SHA1Update(&sha1ctx, mac->cri_key, mac->cri_klen / 8);
1050: SHA1Update(&sha1ctx, hmac_ipad_buffer, HMAC_BLOCK_LEN -
1051: (mac->cri_klen / 8));
1052: SHA1Final((u_int8_t *)ses->cvr, &sha1ctx);
1053: break;
1054: case CRYPTO_RIPEMD160_HMAC:
1055: default:
1056: RMD160Init(&rmd160ctx);
1057: RMD160Update(&rmd160ctx, mac->cri_key,
1058: mac->cri_klen / 8);
1059: RMD160Update(&rmd160ctx, hmac_ipad_buffer,
1060: HMAC_BLOCK_LEN - (mac->cri_klen / 8));
1061: RMD160Final((u_int8_t *)ses->cvr, &rmd160ctx);
1062: break;
1063: }
1064:
1065: for (i = 0; i < mac->cri_klen / 8; i++)
1066: mac->cri_key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
1067:
1068: switch (mac->cri_alg) {
1069: case CRYPTO_MD5_HMAC:
1070: MD5Init(&md5ctx);
1071: MD5Update(&md5ctx, mac->cri_key, mac->cri_klen / 8);
1072: MD5Update(&md5ctx, hmac_opad_buffer, HMAC_BLOCK_LEN -
1073: (mac->cri_klen / 8));
1074: MD5Update(&md5ctx, (u_int8_t *)ses->cvr,
1075: sizeof(md5ctx.state));
1076: MD5Final((u_int8_t *)ses->cvr, &md5ctx);
1077: break;
1078: case CRYPTO_SHA1_HMAC:
1079: SHA1Init(&sha1ctx);
1080: SHA1Update(&sha1ctx, mac->cri_key, mac->cri_klen / 8);
1081: SHA1Update(&sha1ctx, hmac_opad_buffer, HMAC_BLOCK_LEN -
1082: (mac->cri_klen / 8));
1083: SHA1Update(&sha1ctx, (u_int8_t *)ses->cvr,
1084: sizeof(sha1ctx.state));
1085: SHA1Final((u_int8_t *)ses->cvr, &sha1ctx);
1086: break;
1087: case CRYPTO_RIPEMD160_HMAC:
1088: default:
1089: RMD160Init(&rmd160ctx);
1090: RMD160Update(&rmd160ctx, mac->cri_key,
1091: mac->cri_klen / 8);
1092: RMD160Update(&rmd160ctx, hmac_opad_buffer,
1093: HMAC_BLOCK_LEN - (mac->cri_klen / 8));
1094: RMD160Update(&rmd160ctx, (u_int8_t *)ses->cvr,
1095: sizeof(rmd160ctx.state));
1096: RMD160Final((u_int8_t *)ses->cvr, &rmd160ctx);
1097: break;
1098: }
1099:
1100: for (i = 0; i < mac->cri_klen / 8; i++)
1101: mac->cri_key[i] ^= HMAC_OPAD_VAL;
1102: }
1103:
1104: DPRINTF(("%s:ises_newsession: done\n", dv));
1105: *sidp = ISES_SID(sc->sc_dv.dv_unit, sesn);
1106: return (0);
1107: }
1108:
1109: /* Deallocate a session. */
1110: int
1111: ises_freesession(u_int64_t tsid)
1112: {
1113: struct ises_softc *sc;
1114: int card, sesn;
1115: u_int32_t sid = ((u_int32_t)tsid) & 0xffffffff;
1116:
1117: card = ISES_CARD(sid);
1118: if (card >= ises_cd.cd_ndevs || ises_cd.cd_devs[card] == NULL)
1119: return (EINVAL);
1120:
1121: sc = ises_cd.cd_devs[card];
1122: sesn = ISES_SESSION(sid);
1123:
1124: DPRINTF(("%s:ises_freesession: freeing session %d\n",
1125: sc->sc_dv.dv_xname, sesn));
1126:
1127: if (sc->sc_cursession == sesn)
1128: sc->sc_cursession = -1;
1129:
1130: bzero(&sc->sc_sessions[sesn], sizeof(sc->sc_sessions[sesn]));
1131:
1132: return (0);
1133: }
1134:
1135: /* Called by the crypto framework, crypto(9). */
1136: int
1137: ises_process(struct cryptop *crp)
1138: {
1139: struct ises_softc *sc;
1140: struct ises_q *q;
1141: struct cryptodesc *maccrd, *enccrd, *crd;
1142: struct ises_session *ses;
1143: int card, s, err = EINVAL;
1144: int encoffset, macoffset, cpskip, sskip, dskip, stheend, dtheend;
1145: int cpoffset, coffset;
1146: #if 0
1147: int nicealign;
1148: #endif
1149: #ifdef ISESDEBUG
1150: char *dv;
1151: #endif
1152:
1153: if (crp == NULL || crp->crp_callback == NULL)
1154: return (EINVAL);
1155:
1156: card = ISES_CARD(crp->crp_sid);
1157: if (card >= ises_cd.cd_ndevs || ises_cd.cd_devs[card] == NULL)
1158: goto errout;
1159:
1160: sc = ises_cd.cd_devs[card];
1161: #ifdef ISESDEBUG
1162: dv = sc->sc_dv.dv_xname;
1163: #endif
1164:
1165: DPRINTF(("%s:ises_process: start (crp = %p)\n", dv, crp));
1166:
1167: s = splnet();
1168: if (sc->sc_nqueue == ISES_MAX_NQUEUE) {
1169: splx(s);
1170: goto memerr;
1171: }
1172: splx(s);
1173:
1174: q = (struct ises_q *)malloc(sizeof(struct ises_q), M_DEVBUF, M_NOWAIT);
1175: if (q == NULL)
1176: goto memerr;
1177: bzero(q, sizeof(struct ises_q));
1178:
1179: q->q_sesn = ISES_SESSION(crp->crp_sid);
1180: ses = &sc->sc_sessions[q->q_sesn];
1181:
1182: DPRINTF(("%s:ises_process: session %d selected\n", dv, q->q_sesn));
1183:
1184: q->q_sc = sc;
1185: q->q_crp = crp;
1186:
1187: if (crp->crp_flags & CRYPTO_F_IMBUF) {
1188: q->q_src.mbuf = (struct mbuf *)crp->crp_buf;
1189: q->q_dst.mbuf = (struct mbuf *)crp->crp_buf;
1190: } else if (crp->crp_flags & CRYPTO_F_IOV) {
1191: q->q_src.uio = (struct uio *)crp->crp_buf;
1192: q->q_dst.uio = (struct uio *)crp->crp_buf;
1193: } else {
1194: /* XXX for now... */
1195: goto errout;
1196: }
1197:
1198: /*
1199: * Check if the crypto descriptors are sane. We accept:
1200: * - just one crd; either auth or crypto
1201: * - two crds; must be one auth and one crypto, although now
1202: * for encryption we only want the first to be crypto, while
1203: * for decryption the second one should be crypto.
1204: */
1205: maccrd = enccrd = NULL;
1206: for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1207: switch (crd->crd_alg) {
1208: case CRYPTO_MD5_HMAC:
1209: case CRYPTO_SHA1_HMAC:
1210: case CRYPTO_RIPEMD160_HMAC:
1211: if (maccrd || (enccrd &&
1212: (enccrd->crd_flags & CRD_F_ENCRYPT) == 0))
1213: goto errout;
1214: maccrd = crd;
1215: break;
1216: case CRYPTO_DES_CBC:
1217: case CRYPTO_3DES_CBC:
1218: if (enccrd ||
1219: (maccrd && (crd->crd_flags & CRD_F_ENCRYPT)))
1220: goto errout;
1221: enccrd = crd;
1222: break;
1223: default:
1224: goto errout;
1225: }
1226: }
1227: if (!maccrd && !enccrd)
1228: goto errout;
1229:
1230: DPRINTF(("%s:ises_process: enc=%p mac=%p\n", dv, enccrd, maccrd));
1231:
1232: /* Select data path through B-interface. */
1233: q->q_session.omr |= ISES_SELR_BCHU_DIS;
1234:
1235: if (enccrd) {
1236: encoffset = enccrd->crd_skip;
1237:
1238: /* Select algorithm */
1239: if (enccrd->crd_alg == CRYPTO_3DES_CBC)
1240: q->q_session.omr |= ISES_SOMR_BOMR_3DES;
1241: else
1242: q->q_session.omr |= ISES_SOMR_BOMR_DES;
1243:
1244: /* Set CBC mode */
1245: q->q_session.omr |= ISES_SOMR_FMR_CBC;
1246:
1247: if (enccrd->crd_flags & CRD_F_ENCRYPT) {
1248: /* Set encryption bit */
1249: q->q_session.omr |= ISES_SOMR_EDR;
1250:
1251: if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
1252: bcopy(enccrd->crd_iv, q->q_session.sccr, 8);
1253: else {
1254: q->q_session.sccr[0] = ses->sccr[0];
1255: q->q_session.sccr[1] = ses->sccr[1];
1256: }
1257:
1258: if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
1259: if (crp->crp_flags & CRYPTO_F_IMBUF)
1260: m_copyback(q->q_src.mbuf,
1261: enccrd->crd_inject, 8,
1262: (caddr_t)q->q_session.sccr);
1263: else if (crp->crp_flags & CRYPTO_F_IOV)
1264: cuio_copyback(q->q_src.uio,
1265: enccrd->crd_inject, 8,
1266: (caddr_t)q->q_session.sccr);
1267: /* XXX else ... */
1268: }
1269: } else {
1270: /* Clear encryption bit == decrypt mode */
1271: q->q_session.omr &= ~ISES_SOMR_EDR;
1272:
1273: if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
1274: bcopy(enccrd->crd_iv, q->q_session.sccr, 8);
1275: else if (crp->crp_flags & CRYPTO_F_IMBUF)
1276: m_copydata(q->q_src.mbuf, enccrd->crd_inject,
1277: 8, (caddr_t)q->q_session.sccr);
1278: else if (crp->crp_flags & CRYPTO_F_IOV)
1279: cuio_copydata(q->q_src.uio,
1280: enccrd->crd_inject, 8,
1281: (caddr_t)q->q_session.sccr);
1282: /* XXX else ... */
1283: }
1284:
1285: q->q_session.kr[0] = ses->kr[0];
1286: q->q_session.kr[1] = ses->kr[1];
1287: q->q_session.kr[2] = ses->kr[2];
1288: q->q_session.kr[3] = ses->kr[3];
1289: q->q_session.kr[4] = ses->kr[4];
1290: q->q_session.kr[5] = ses->kr[5];
1291:
1292: SWAP32(q->q_session.sccr[0]);
1293: SWAP32(q->q_session.sccr[1]);
1294: }
1295:
1296: if (maccrd) {
1297: macoffset = maccrd->crd_skip;
1298:
1299: /* Select algorithm */
1300: switch (crd->crd_alg) {
1301: case CRYPTO_MD5_HMAC:
1302: q->q_session.omr |= ISES_HOMR_HFR_MD5;
1303: break;
1304: case CRYPTO_SHA1_HMAC:
1305: q->q_session.omr |= ISES_HOMR_HFR_SHA1;
1306: break;
1307: case CRYPTO_RIPEMD160_HMAC:
1308: default:
1309: q->q_session.omr |= ISES_HOMR_HFR_RMD160;
1310: break;
1311: }
1312:
1313: q->q_session.cvr[0] = ses->cvr[0];
1314: q->q_session.cvr[1] = ses->cvr[1];
1315: q->q_session.cvr[2] = ses->cvr[2];
1316: q->q_session.cvr[3] = ses->cvr[3];
1317: q->q_session.cvr[4] = ses->cvr[4];
1318: }
1319:
1320: if (enccrd && maccrd) {
1321: /* XXX Check if ises handles differing end of auth/enc etc */
1322: /* XXX For now, assume not (same as ubsec). */
1323: if (((encoffset + enccrd->crd_len) !=
1324: (macoffset + maccrd->crd_len)) ||
1325: (enccrd->crd_skip < maccrd->crd_skip)) {
1326: goto errout;
1327: }
1328:
1329: sskip = maccrd->crd_skip;
1330: cpskip = dskip = enccrd->crd_skip;
1331: stheend = maccrd->crd_len;
1332: dtheend = enccrd->crd_len;
1333: coffset = cpskip - sskip;
1334: cpoffset = cpskip + dtheend;
1335: /* XXX DEBUG ? */
1336: } else {
1337: cpskip = dskip = sskip = macoffset + encoffset;
1338: dtheend = enccrd ? enccrd->crd_len : maccrd->crd_len;
1339: stheend = dtheend;
1340: cpoffset = cpskip + dtheend;
1341: coffset = 0;
1342: }
1343: q->q_offset = coffset >> 2;
1344:
1345: #if 0 /* XXX not sure about this, in bus_dma context */
1346:
1347: if (crp->crp_flags & CRYPTO_F_IMBUF)
1348: q->q_src_l = mbuf2pages(q->q_src.mbuf, &q->q_src_npa,
1349: q->q_src_packp, q->q_src_packl, 1, &nicealign);
1350: else if (crp->crp_flags & CRYPTO_F_IOV)
1351: q->q_src_l = iov2pages(q->q_src.uio, &q->q_src_npa,
1352: q->q_src_packp, q->q_src_packl, 1, &nicealign);
1353: /* XXX else */
1354:
1355: DPRINTF(("%s:ises_process: foo2pages called!\n", dv));
1356:
1357: if (q->q_src_l == 0)
1358: goto memerr;
1359: else if (q->q_src_l > 0xfffc) {
1360: err = EIO;
1361: goto errout;
1362: }
1363:
1364: /* XXX ... */
1365:
1366: if (enccrd == NULL && maccrd != NULL) {
1367: /* XXX ... */
1368: } else {
1369: if (!nicealign && (crp->crp_flags & CRYPTO_F_IOV)) {
1370: goto errout;
1371: } else if (!nicealign && (crp->crp_flags & CRYPTO_F_IMBUF)) {
1372: int totlen, len;
1373: struct mbuf *m, *top, **mp;
1374:
1375: totlen = q->q_dst_l = q->q_src_l;
1376: if (q->q_src.mbuf->m_flags & M_PKTHDR) {
1377: MGETHDR(m, M_DONTWAIT, MT_DATA);
1378: M_DUP_PKTHDR(m, q->q_src.mbuf);
1379: len = MHLEN;
1380: } else {
1381: MGET(m, M_DONTWAIT, MT_DATA);
1382: len = MLEN;
1383: }
1384: if (m == NULL)
1385: goto memerr;
1386: if (totlen >= MINCLSIZE) {
1387: MCLGET(m, M_DONTWAIT);
1388: if (m->m_flags & M_EXT)
1389: len = MCLBYTES;
1390: }
1391: m->m_len = len;
1392: top = NULL;
1393: mp = ⊤
1394:
1395: while (totlen > 0) {
1396: if (top) {
1397: MGET(m, M_DONTWAIT, MT_DATA);
1398: if (m == NULL) {
1399: m_freem(top);
1400: goto memerr;
1401: }
1402: len = MLEN;
1403: }
1404: if (top && totlen >= MINCLSIZE) {
1405: MCLGET(m, M_DONTWAIT);
1406: if (m->m_flags & M_EXT)
1407: len = MCLBYTES;
1408: }
1409: m->m_len = len = min(totlen, len);
1410: totlen -= len;
1411: *mp = m;
1412:
1413: mp = &m->m_next;
1414: }
1415: q->q_dst.mbuf = top;
1416: #if notyet
1417: ubsec_mcopy(q->q_src.mbuf, q->q_dst.mbuf, cpskip, cpoffset);
1418: #endif
1419: } else
1420: q->q_dst.mbuf = q->q_src.mbuf;
1421:
1422: #if 0
1423: /* XXX ? */
1424: q->q_dst_l = mbuf2pages(q->q_dst.mbuf, &q->q_dst_npa,
1425: &q->q_dst_packp, &q->q_dst_packl, 1, NULL);
1426: #endif
1427: }
1428:
1429: #endif /* XXX */
1430:
1431: DPRINTF(("%s:ises_process: queueing request\n", dv));
1432:
1433: s = splnet();
1434: SIMPLEQ_INSERT_TAIL(&sc->sc_queue, q, q_next);
1435: sc->sc_nqueue++;
1436: splx(s);
1437: ises_feed(sc);
1438:
1439: return (0);
1440:
1441: memerr:
1442: err = ENOMEM;
1443: isesstats.nomem++;
1444: errout:
1445: DPRINTF(("%s:ises_process: an error occurred, err=%d, q=%p\n", dv,
1446: err, q));
1447:
1448: if (err == EINVAL)
1449: isesstats.invalid++;
1450:
1451: if (q) {
1452: if (q->q_src.mbuf != q->q_dst.mbuf)
1453: m_freem(q->q_dst.mbuf);
1454: free(q, M_DEVBUF);
1455: }
1456: crp->crp_etype = err;
1457: crypto_done(crp);
1458: return (0);
1459: }
1460:
1461: void
1462: ises_callback(struct ises_q *q)
1463: {
1464: struct cryptop *crp = (struct cryptop *)q->q_crp;
1465: struct cryptodesc *crd;
1466: struct ises_softc *sc = q->q_sc;
1467: u_int8_t *sccr;
1468:
1469: if ((crp->crp_flags & CRYPTO_F_IMBUF) &&
1470: (q->q_src.mbuf != q->q_dst.mbuf)) {
1471: m_freem(q->q_src.mbuf);
1472: crp->crp_buf = (caddr_t)q->q_dst.mbuf;
1473: }
1474:
1475: if (q->q_session.omr & ISES_SOMR_EDR) {
1476: /* Copy out IV after encryption. */
1477: sccr = (u_int8_t *)&sc->sc_sessions[q->q_sesn].sccr;
1478: for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1479: if (crd->crd_alg != CRYPTO_DES_CBC &&
1480: crd->crd_alg != CRYPTO_3DES_CBC)
1481: continue;
1482: if (crp->crp_flags & CRYPTO_F_IMBUF)
1483: m_copydata((struct mbuf *)crp->crp_buf,
1484: crd->crd_skip + crd->crd_len - 8, 8, sccr);
1485: else if (crp->crp_flags & CRYPTO_F_IOV)
1486: cuio_copydata((struct uio *)crp->crp_buf,
1487: crd->crd_skip + crd->crd_len - 8, 8, sccr);
1488: }
1489: }
1490:
1491: for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1492: if (crd->crd_alg != CRYPTO_MD5_HMAC &&
1493: crd->crd_alg != CRYPTO_SHA1_HMAC &&
1494: crd->crd_alg != CRYPTO_RIPEMD160_HMAC)
1495: continue;
1496: if (crp->crp_flags & CRYPTO_F_IMBUF)
1497: m_copyback((struct mbuf *)crp->crp_buf,
1498: crd->crd_inject, 12, (u_int8_t *)q->q_macbuf);
1499: else if (crp->crp_flags & CRYPTO_F_IOV)
1500: bcopy((u_int8_t *)q->q_macbuf, crp->crp_mac, 12);
1501: /* XXX else ... */
1502: break;
1503: }
1504:
1505: free(q, M_DEVBUF);
1506: DPRINTF(("%s:ises_callback: calling crypto_done\n",
1507: sc->sc_dv.dv_xname));
1508: crypto_done(crp);
1509: }
1510:
1511: /* Initilize the ISES hardware RNG, and set up timeouts. */
1512: void
1513: ises_hrng_init(struct ises_softc *sc)
1514: {
1515: u_int32_t cmd, r;
1516: int i;
1517: #ifdef ISESDEBUG
1518: struct timeval tv1, tv2;
1519: #endif
1520:
1521: /* Asking for random data will seed LFSR and start the RBG */
1522: cmd = ISES_MKCMD(ISES_CMD_HBITS, 1);
1523: r = 8; /* 8 * 32 = 256 bits */
1524:
1525: if (ises_queue_cmd(sc, cmd, &r, NULL))
1526: return;
1527:
1528: /* Wait until response arrives. */
1529: for (i = 1000; i && READ_REG(sc, ISES_A_OQS) == 0; i--)
1530: DELAY(10);
1531:
1532: if (!READ_REG(sc, ISES_A_OQS))
1533: return;
1534:
1535: /* Drain cmd response and 8*32 bits data */
1536: for (i = 0; i <= r; i++)
1537: (void)READ_REG(sc, ISES_A_OQD);
1538:
1539: /* ACK the response */
1540: WRITE_REG(sc, ISES_A_OQS, 0);
1541: DELAY(1);
1542: printf(", rng active");
1543:
1544: #ifdef ISESDEBUG
1545: /* Benchmark the HRNG. */
1546:
1547: /*
1548: * XXX These values gets surprisingly large. Docs state the
1549: * HNRG produces > 1 mbit/s of random data. The values I'm seeing
1550: * are much higher, ca 2.7-2.8 mbit/s. AFAICT the algorithm is sound.
1551: * Compiler optimization issues, perhaps?
1552: */
1553:
1554: #define ISES_WPR 250
1555: #define ISES_ROUNDS 100
1556: cmd = ISES_MKCMD(ISES_CMD_HBITS, 1);
1557: r = ISES_WPR;
1558:
1559: /* Queue 100 cmds; each generate 250 32-bit words of rnd data. */
1560: microtime(&tv1);
1561: for (i = 0; i < ISES_ROUNDS; i++)
1562: ises_queue_cmd(sc, cmd, &r, NULL);
1563: for (i = 0; i < ISES_ROUNDS; i++) {
1564: while (READ_REG(sc, ISES_A_OQS) == 0) ; /* Wait for response */
1565:
1566: (void)READ_REG(sc, ISES_A_OQD); /* read response */
1567: for (r = ISES_WPR; r--;)
1568: (void)READ_REG(sc, ISES_A_OQD); /* read data */
1569: WRITE_REG(sc, ISES_A_OQS, 0); /* ACK resp */
1570: DELAY(1); /* OQS needs 1us to decrement */
1571: }
1572: microtime(&tv2);
1573:
1574: timersub(&tv2, &tv1, &tv1);
1575: tv1.tv_usec += 1000000 * tv1.tv_sec;
1576: printf(", %dKb/sec",
1577: ISES_WPR * ISES_ROUNDS * 32 / 1024 * 1000000 / tv1.tv_usec);
1578: #endif
1579:
1580: timeout_set(&sc->sc_timeout, ises_hrng, sc);
1581: #ifndef ISES_HRNG_DISABLED
1582: ises_hrng(sc); /* Call first update */
1583: #endif
1584: }
1585:
1586: /* Called by timeout (and once by ises_init_hrng()). */
1587: void
1588: ises_hrng(void *v)
1589: {
1590: /*
1591: * Throw a HRNG read random bits command on the command queue.
1592: * The normal loop will manage the result and add it to the pool.
1593: */
1594: struct ises_softc *sc = v;
1595: u_int32_t cmd, n;
1596: extern int hz; /* from param.c */
1597:
1598: timeout_add(&sc->sc_timeout, hz / ISESRNGIPS);
1599:
1600: if (ises_assert_cmd_mode(sc) != 0)
1601: return;
1602:
1603: cmd = ISES_MKCMD(ISES_CMD_HBITS, 1);
1604: n = (ISESRNGBITS >> 5) & 0xff; /* ask for N 32 bit words */
1605:
1606: ises_queue_cmd(sc, cmd, &n, NULL);
1607: }
1608:
1609: u_int32_t
1610: ises_get_fwversion(struct ises_softc *sc)
1611: {
1612: u_int32_t r;
1613: int i;
1614:
1615: r = ISES_MKCMD(ISES_CMD_CHIP_ID, 0);
1616: WRITE_REG(sc, ISES_A_IQD, r);
1617: WRITE_REG(sc, ISES_A_IQS, 0);
1618:
1619: for (i = 100; i > 0 && READ_REG(sc, ISES_A_OQS) == 0; i--)
1620: DELAY(1);
1621:
1622: if (i < 1)
1623: return (0); /* No response */
1624:
1625: r = READ_REG(sc, ISES_A_OQD);
1626:
1627: /* Check validity. On error drain reponse data. */
1628: if (((r >> 16) & 0xff) != ISES_CMD_CHIP_ID ||
1629: ((r >> 24) & 0xff) != 3 || (r & ISES_RC_MASK) != ISES_RC_SUCCESS) {
1630: if ((r & ISES_RC_MASK) == ISES_RC_SUCCESS)
1631: for (i = ((r >> 24) & 0xff); i; i--)
1632: (void)READ_REG(sc, ISES_A_OQD);
1633: r = 0;
1634: goto out;
1635: }
1636:
1637: r = READ_REG(sc, ISES_A_OQD); /* read version */
1638: (void)READ_REG(sc, ISES_A_OQD); /* Discard 64bit "chip-id" */
1639: (void)READ_REG(sc, ISES_A_OQD);
1640: out:
1641: WRITE_REG(sc, ISES_A_OQS, 0); /* Ack the response */
1642: DELAY(1);
1643: return (r);
1644: }
1645:
1646: /*
1647: * ises_assert_cmd_mode() returns
1648: * -1 for failure to go to cmd
1649: * 0 if mode already was cmd
1650: * >0 if mode was other (WFC/WFR) but now is cmd (this has reset the queues)
1651: */
1652: int
1653: ises_assert_cmd_mode(struct ises_softc *sc)
1654: {
1655: switch (ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT))) {
1656: case 0x0: /* Selftest. XXX This is a transient state. */
1657: DELAY(1000000);
1658: if (ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT)) == 0)
1659: return (-1);
1660: return (ises_assert_cmd_mode(sc));
1661: case 0x1: /* Command mode */
1662: return (0);
1663: case 0x2: /* Waiting For Continue / WFC */
1664: bus_space_write_2(sc->sc_memt, sc->sc_memh, ISES_A_CTRL,
1665: ISES_A_CTRL_CONTINUE);
1666: DELAY(1);
1667: return ((ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT)) == 0) ?
1668: 1 : -1);
1669: case 0x3: /* Waiting For Reset / WFR */
1670: bus_space_write_2(sc->sc_memt, sc->sc_memh, ISES_A_CTRL,
1671: ISES_A_CTRL_RESET);
1672: DELAY(1000000);
1673: return ((ISES_STAT_SW_MODE(READ_REG(sc, ISES_A_STAT)) == 0) ?
1674: 2 : -1);
1675: default:
1676: return (-1); /* Unknown mode */
1677: }
1678: }
1679:
1680: int
1681: ises_bchu_switch_session (struct ises_softc *sc, struct ises_session *ss,
1682: int new_session)
1683: {
1684: /* It appears that the BCHU_SWITCH_SESSION command is broken. */
1685: /* We have to work around it. */
1686:
1687: u_int32_t cmd;
1688:
1689: /* Do we have enough in-queue space? Count cmds + data, 16bit words. */
1690: if ((8 * 2 + sizeof (*ss) / 2) > READ_REG(sc, ISES_A_IQF))
1691: return (0);
1692:
1693: /* Mark 'switch' in progress. */
1694: sc->sc_switching = new_session + 1;
1695:
1696: /* Write the key. */
1697: cmd = ISES_MKCMD(ISES_CMD_BW_KR0, 2);
1698: ises_queue_cmd(sc, cmd, &ss->kr[4], NULL);
1699: cmd = ISES_MKCMD(ISES_CMD_BW_KR1, 2);
1700: ises_queue_cmd(sc, cmd, &ss->kr[2], NULL);
1701: cmd = ISES_MKCMD(ISES_CMD_BW_KR2, 2);
1702: ises_queue_cmd(sc, cmd, &ss->kr[0], NULL);
1703:
1704: /* Write OMR - Operation Method Register, clears SCCR+CVR+DBCR+HMLR */
1705: cmd = ISES_MKCMD(ISES_CMD_BW_OMR, 1);
1706: ises_queue_cmd(sc, cmd, &ss->omr, NULL);
1707:
1708: /* Write SCCR - Symmetric Crypto Chaining Register (IV) */
1709: cmd = ISES_MKCMD(ISES_CMD_BW_SCCR, 2);
1710: ises_queue_cmd(sc, cmd, &ss->sccr[0], NULL);
1711:
1712: /* Write CVR - Chaining Variables Register (hash state) */
1713: cmd = ISES_MKCMD(ISES_CMD_BW_CVR, 5);
1714: ises_queue_cmd(sc, cmd, &ss->cvr[0], NULL);
1715:
1716: /* Write DBCR - Data Block Count Register */
1717: cmd = ISES_MKCMD(ISES_CMD_BW_DBCR, 2);
1718: ises_queue_cmd(sc, cmd, &ss->dbcr[0], NULL);
1719:
1720: /* Write HMLR - Hash Message Length Register - last cmd in switch */
1721: cmd = ISES_MKCMD(ISES_CMD_BW_HMLR, 2);
1722: ises_queue_cmd(sc, cmd, &ss->hmlr[0], ises_bchu_switch_final);
1723:
1724: return (1);
1725: }
1726:
1727: u_int32_t
1728: ises_bchu_switch_final (struct ises_softc *sc, struct ises_cmd *cmd)
1729: {
1730: /* Session switch is complete. */
1731:
1732: DPRINTF(("%s:ises_bchu_switch_final: switch complete\n",
1733: sc->sc_dv.dv_xname));
1734:
1735: sc->sc_cursession = sc->sc_switching - 1;
1736: sc->sc_switching = 0;
1737:
1738: /* Retry/restart feed. */
1739: ises_feed(sc);
1740:
1741: return (0);
1742: }
1743:
1744: /* XXX Currently unused. */
1745: void
1746: ises_read_dma (struct ises_softc *sc)
1747: {
1748: bus_dma_segment_t *ds = &sc->sc_dmamap->dm_segs[0];
1749: u_int32_t dma_status;
1750:
1751: bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
1752: sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
1753:
1754: WRITE_REG(sc, ISES_DMA_READ_START, ds->ds_addr);
1755: WRITE_REG(sc, ISES_DMA_READ_START, ISES_DMA_RCOUNT(ds->ds_len));
1756:
1757: dma_status = READ_REG(sc, ISES_DMA_STATUS);
1758: dma_status |= ISES_DMA_CTRL_ILT | ISES_DMA_CTRL_WRITE;
1759: WRITE_REG(sc, ISES_DMA_CTRL, dma_status);
1760: }
1761:
1762: #ifdef ISESDEBUG
1763: /*
1764: * Development code section below here.
1765: */
1766:
1767: void
1768: ises_debug_init (struct ises_softc *sc)
1769: {
1770: ises_sc = sc;
1771: ises_db = 0;
1772: timeout_set (&ises_db_timeout, ises_debug_loop, sc);
1773: timeout_add (&ises_db_timeout, 100);
1774: printf ("ises0: ISESDEBUG active (ises_sc = %p)\n", ises_sc);
1775: }
1776:
1777: void
1778: ises_debug_2 (void)
1779: {
1780: timeout_set (&ises_db_timeout, ises_debug_loop, ises_sc);
1781: timeout_add (&ises_db_timeout, 100);
1782: printf ("ises0: another debug timeout scheduled!\n");
1783: }
1784:
1785: void
1786: ises_debug_simple_cmd (struct ises_softc *sc, u_int32_t code, u_int32_t d)
1787: {
1788: u_int32_t cmd, data;
1789:
1790: cmd = ISES_MKCMD(code, (d ? 1 : 0));
1791: data = d;
1792: ises_queue_cmd(sc, cmd, &d, NULL);
1793: }
1794:
1795: void
1796: ises_debug_loop (void *v)
1797: {
1798: struct ises_softc *sc = (struct ises_softc *)v;
1799: struct ises_session ses;
1800: u_int32_t cmd, stat;
1801: int i;
1802:
1803: if (ises_db)
1804: printf ("ises0: ises_db = %d sc = %p\n", ises_db, sc);
1805:
1806: timeout_add (&ises_db_timeout, 300); /* Every 3 secs */
1807:
1808: stat = READ_REG(sc, ISES_A_OQS);
1809: cmd = READ_REG(sc, ISES_A_IQS);
1810: if (stat || cmd)
1811: printf ("ises0: IQS=%d OQS=%d / IQF=%d OQF=%d\n",
1812: cmd, stat, READ_REG(sc, ISES_A_IQF),
1813: READ_REG(sc, ISES_A_OQF));
1814:
1815: switch (ises_db) {
1816: default:
1817: /* 0 - do nothing (just loop) */
1818: break;
1819: case 1:
1820: /* Just dump register info */
1821: ises_showreg();
1822: break;
1823: case 2:
1824: /* Reset LNAU 1 registers */
1825: ises_debug_simple_cmd(sc, ISES_CMD_LRESET_1, 0);
1826:
1827: /* Compute R = (141 * 5623) % 117 (R should be 51 (0x33)) */
1828: ises_debug_simple_cmd(sc, ISES_CMD_LW_A_1, 141);
1829: ises_debug_simple_cmd(sc, ISES_CMD_LW_B_1, 5623);
1830: ises_debug_simple_cmd(sc, ISES_CMD_LW_N_1, 117);
1831:
1832: /* Launch LNAU operation. */
1833: ises_debug_simple_cmd(sc, ISES_CMD_LMULMOD_1, 0);
1834: break;
1835: case 3:
1836: /* Read result LNAU_1 R register (should not be necessary) */
1837: ises_debug_simple_cmd(sc, ISES_CMD_LUPLOAD_1, 0);
1838: break;
1839: case 4:
1840: /* Print result */
1841: printf ("LNAU_1 R length = %d\n", sc->sc_lnau1_rlen);
1842: for (i = 0; i < sc->sc_lnau1_rlen; i++)
1843: printf ("W%02d-[%08x]-(%u)\t%s", i, sc->sc_lnau1_r[i],
1844: sc->sc_lnau1_r[i], (i%4)==3 ? "\n" : "");
1845: printf ("%s", (i%4) ? "\n" : "");
1846: break;
1847: case 5:
1848: /* Crypto. */
1849:
1850: /* Load BCHU session data */
1851: bzero(&ses, sizeof ses);
1852: ses.kr[0] = 0xD0;
1853: ses.kr[1] = 0xD1;
1854: ses.kr[2] = 0xD2;
1855: ses.kr[3] = 0xD3;
1856: ses.kr[4] = 0xD4;
1857: ses.kr[5] = 0xD5;
1858:
1859: /* cipher data out is hash in, SHA1, 3DES, encrypt, ECB */
1860: ses.omr = ISES_SELR_BCHU_HISOF | ISES_HOMR_HFR_SHA1 |
1861: ISES_SOMR_BOMR_3DES | ISES_SOMR_EDR | ISES_SOMR_FMR_ECB;
1862:
1863: #if 1
1864: printf ("Queueing home-cooked session switch\n");
1865: ises_bchu_switch_session(sc, &ses, 0);
1866: #else /* switch session does not appear to work - it never returns */
1867: printf ("Queueing BCHU session switch\n");
1868: cmd = ISES_MKCMD(ISES_CMD_BSWITCH, sizeof ses / 4);
1869: printf ("session is %d 32bit words (== 18 ?), cmd = [%08x]\n",
1870: sizeof ses / 4, cmd);
1871: ises_queue_cmd(sc, cmd, (u_int32_t *)&ses, NULL);
1872: #endif
1873:
1874: break;
1875: case 96:
1876: printf ("Stopping HRNG data collection\n");
1877: timeout_del(&sc->sc_timeout);
1878: break;
1879: case 97:
1880: printf ("Restarting HRNG data collection\n");
1881: if (!timeout_pending(&sc->sc_timeout))
1882: timeout_add(&sc->sc_timeout, hz);
1883: break;
1884: case 98:
1885: printf ("Resetting (wait >1s before cont.)\n");
1886: stat = ISES_BO_STAT_HWRESET;
1887: WRITE_REG(sc, ISES_BO_STAT, stat);
1888: stat &= ~ISES_BO_STAT_HWRESET;
1889: WRITE_REG(sc, ISES_BO_STAT, stat);
1890: break;
1891: case 99:
1892: printf ("Resetting everything!\n");
1893: if (timeout_pending(&sc->sc_timeout))
1894: timeout_del(&sc->sc_timeout);
1895: timeout_set(&sc->sc_timeout, ises_initstate, sc);
1896: sc->sc_initstate = 0;
1897: ises_initstate(sc);
1898: break;
1899: }
1900:
1901: ises_db = 0;
1902: }
1903:
1904: void
1905: ises_showreg (void)
1906: {
1907: struct ises_softc *sc = ises_sc;
1908: u_int32_t stat, cmd;
1909:
1910: /* Board register */
1911:
1912: printf ("Board register: ");
1913: stat = READ_REG(sc, ISES_BO_STAT);
1914:
1915: if (stat & ISES_BO_STAT_LOOP)
1916: printf ("LoopMode ");
1917: if (stat & ISES_BO_STAT_TAMPER)
1918: printf ("Tamper ");
1919: if (stat & ISES_BO_STAT_POWERDOWN)
1920: printf ("PowerDown ");
1921: if (stat & ISES_BO_STAT_ACONF)
1922: printf ("16bitA-IF ");
1923: if (stat & ISES_BO_STAT_HWRESET)
1924: printf ("HWReset");
1925: if (stat & ISES_BO_STAT_AIRQ)
1926: printf ("A-IFintr");
1927: printf("\n");
1928:
1929: /* A interface */
1930:
1931: printf ("A Interface STAT register: \n\tLNAU-[");
1932: stat = READ_REG(sc, ISES_A_STAT);
1933: if (stat & ISES_STAT_LNAU_MASKED)
1934: printf ("masked");
1935: else {
1936: if (stat & ISES_STAT_LNAU_BUSY_1)
1937: printf ("busy1 ");
1938: if (stat & ISES_STAT_LNAU_ERR_1)
1939: printf ("err1 ");
1940: if (stat & ISES_STAT_LNAU_BUSY_2)
1941: printf ("busy2 ");
1942: if (stat & ISES_STAT_LNAU_ERR_2)
1943: printf ("err2 ");
1944: }
1945: printf ("]\n\tBCHU-[");
1946:
1947: if (stat & ISES_STAT_BCHU_MASKED)
1948: printf ("masked");
1949: else {
1950: if (stat & ISES_STAT_BCHU_BUSY)
1951: printf ("busy ");
1952: if (stat & ISES_STAT_BCHU_ERR)
1953: printf ("err ");
1954: if (stat & ISES_STAT_BCHU_SCIF)
1955: printf ("cr-inop ");
1956: if (stat & ISES_STAT_BCHU_HIF)
1957: printf ("ha-inop ");
1958: if (stat & ISES_STAT_BCHU_DDB)
1959: printf ("dscd-data ");
1960: if (stat & ISES_STAT_BCHU_IRF)
1961: printf ("inp-req ");
1962: if (stat & ISES_STAT_BCHU_OAF)
1963: printf ("out-avail ");
1964: if (stat & ISES_STAT_BCHU_DIE)
1965: printf ("inp-enabled ");
1966: if (stat & ISES_STAT_BCHU_UE)
1967: printf ("ififo-empty ");
1968: if (stat & ISES_STAT_BCHU_IFE)
1969: printf ("ififo-half ");
1970: if (stat & ISES_STAT_BCHU_IFHE)
1971: printf ("ififo-full ");
1972: if (stat & ISES_STAT_BCHU_OFE)
1973: printf ("ofifo-empty ");
1974: if (stat & ISES_STAT_BCHU_OFHF)
1975: printf ("ofifo-half ");
1976: if (stat & ISES_STAT_BCHU_OFF)
1977: printf ("ofifo-full ");
1978: }
1979: printf ("] \n\tmisc-[");
1980:
1981: if (stat & ISES_STAT_HW_DA)
1982: printf ("downloaded-appl ");
1983: if (stat & ISES_STAT_HW_ACONF)
1984: printf ("A-IF-conf ");
1985: if (stat & ISES_STAT_SW_WFOQ)
1986: printf ("OQ-wait ");
1987: if (stat & ISES_STAT_SW_OQSINC)
1988: printf ("OQS-increased ");
1989: printf ("]\n\t");
1990:
1991: if (stat & ISES_STAT_HW_DA)
1992: printf ("SW-mode is \"%s\"",
1993: ises_sw_mode[ISES_STAT_SW_MODE(stat)]);
1994: else
1995: printf ("IDP-state is \"%s\"",
1996: ises_idp_state[ISES_STAT_IDP_STATE(stat)]);
1997: printf ("\n");
1998:
1999: printf ("\tOQS = %d IQS = %d OQF = %d IQF = %d\n",
2000: READ_REG(sc, ISES_A_OQS), READ_REG(sc, ISES_A_IQS),
2001: READ_REG(sc, ISES_A_OQF), READ_REG(sc, ISES_A_IQF));
2002:
2003: /* B interface */
2004:
2005: printf ("B-interface status register contains [%08x]\n",
2006: READ_REG(sc, ISES_B_STAT));
2007:
2008: /* DMA */
2009:
2010: printf ("DMA read starts at 0x%x, length %d bytes\n",
2011: READ_REG(sc, ISES_DMA_READ_START),
2012: READ_REG(sc, ISES_DMA_READ_COUNT) >> 16);
2013:
2014: printf ("DMA write starts at 0x%x, length %d bytes\n",
2015: READ_REG(sc, ISES_DMA_WRITE_START),
2016: READ_REG(sc, ISES_DMA_WRITE_COUNT) & 0x00ff);
2017:
2018: stat = READ_REG(sc, ISES_DMA_STATUS);
2019: printf ("DMA status register contains [%08x]\n", stat);
2020:
2021: if (stat & ISES_DMA_CTRL_ILT)
2022: printf (" -- Ignore latency timer\n");
2023: if (stat & 0x0C000000)
2024: printf (" -- PCI Read - multiple\n");
2025: else if (stat & 0x08000000)
2026: printf (" -- PCI Read - line\n");
2027:
2028: if (stat & ISES_DMA_STATUS_R_RUN)
2029: printf (" -- PCI Read running/incomplete\n");
2030: else
2031: printf (" -- PCI Read complete\n");
2032: if (stat & ISES_DMA_STATUS_R_ERR)
2033: printf (" -- PCI Read DMA Error\n");
2034:
2035: if (stat & ISES_DMA_STATUS_W_RUN)
2036: printf (" -- PCI Write running/incomplete\n");
2037: else
2038: printf (" -- PCI Write complete\n");
2039: if (stat & ISES_DMA_STATUS_W_ERR)
2040: printf (" -- PCI Write DMA Error\n");
2041:
2042: /* OMR / HOMR / SOMR */
2043:
2044: /*
2045: * All these means throwing a cmd on to the A-interface, and then
2046: * reading the result.
2047: *
2048: * Currently, put debug output in process_oqueue...
2049: */
2050:
2051: printf ("Queueing Operation Method Register (OMR) READ cmd...\n");
2052: cmd = ISES_MKCMD(ISES_CMD_BR_OMR, 0);
2053: ises_queue_cmd(sc, cmd, NULL, NULL);
2054: }
2055:
2056: void
2057: ises_debug_parse_omr (struct ises_softc *sc)
2058: {
2059: u_int32_t omr = sc->sc_sessions[sc->sc_cursession].omr;
2060:
2061: printf ("SELR : ");
2062: if (omr & ISES_SELR_BCHU_EH)
2063: printf ("cont-on-error ");
2064: else
2065: printf ("stop-on-error ");
2066:
2067: if (omr & ISES_SELR_BCHU_HISOF)
2068: printf ("HU-input-is-SCU-output ");
2069:
2070: if (omr & ISES_SELR_BCHU_DIS)
2071: printf ("data-interface-select=B ");
2072: else
2073: printf ("data-interface-select=DataIn/DataOut ");
2074:
2075: printf ("\n");
2076:
2077: printf ("HOMR : ");
2078: if (omr & ISES_HOMR_HMTR)
2079: printf ("expect-padded-hash-msg ");
2080: else
2081: printf ("expect-plaintext-hash-msg ");
2082:
2083: printf ("ER=%d ", (omr & ISES_HOMR_ER) >> 20); /* ick */
2084:
2085: printf ("HFR=");
2086: switch (omr & ISES_HOMR_HFR) {
2087: case ISES_HOMR_HFR_NOP:
2088: printf ("inactive ");
2089: break;
2090: case ISES_HOMR_HFR_MD5:
2091: printf ("MD5 ");
2092: break;
2093: case ISES_HOMR_HFR_RMD160:
2094: printf ("RMD160 ");
2095: break;
2096: case ISES_HOMR_HFR_RMD128:
2097: printf ("RMD128 ");
2098: break;
2099: case ISES_HOMR_HFR_SHA1:
2100: printf ("SHA-1 ");
2101: break;
2102: default:
2103: printf ("reserved! ");
2104: break;
2105: }
2106: printf ("\nSOMR : ");
2107:
2108: switch (omr & ISES_SOMR_BOMR) {
2109: case ISES_SOMR_BOMR_NOP:
2110: printf ("NOP ");
2111: break;
2112: case ISES_SOMR_BOMR_TRANSPARENT:
2113: printf ("transparent ");
2114: break;
2115: case ISES_SOMR_BOMR_DES:
2116: printf ("DES ");
2117: break;
2118: case ISES_SOMR_BOMR_3DES2:
2119: printf ("3DES-2 ");
2120: break;
2121: case ISES_SOMR_BOMR_3DES:
2122: printf ("3DES-3 ");
2123: break;
2124: default:
2125: if (omr & ISES_SOMR_BOMR_SAFER)
2126: printf ("SAFER ");
2127: else
2128: printf ("reserved! ");
2129: break;
2130: }
2131:
2132: if (omr & ISES_SOMR_EDR)
2133: printf ("mode=encrypt ");
2134: else
2135: printf ("mode=decrypt ");
2136:
2137: switch (omr & ISES_SOMR_FMR) {
2138: case ISES_SOMR_FMR_ECB:
2139: printf ("ECB");
2140: break;
2141: case ISES_SOMR_FMR_CBC:
2142: printf ("CBC");
2143: break;
2144: case ISES_SOMR_FMR_CFB64:
2145: printf ("CFB64");
2146: break;
2147: case ISES_SOMR_FMR_OFB64:
2148: printf ("OFB64");
2149: break;
2150: default:
2151: /* Nada */
2152: }
2153: printf ("\n");
2154: }
2155:
2156: #endif /* ISESDEBUG */
CVSweb