ubsec.c revision 1.7 1 /* $NetBSD: ubsec.c,v 1.7 2005/06/28 00:28:42 thorpej Exp $ */
2 /* $FreeBSD: src/sys/dev/ubsec/ubsec.c,v 1.6.2.6 2003/01/23 21:06:43 sam Exp $ */
3 /* $OpenBSD: ubsec.c,v 1.127 2003/06/04 14:04:58 jason Exp $ */
4
5 /*
6 * Copyright (c) 2000 Jason L. Wright (jason (at) thought.net)
7 * Copyright (c) 2000 Theo de Raadt (deraadt (at) openbsd.org)
8 * Copyright (c) 2001 Patrik Lindergren (patrik (at) ipunplugged.com)
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * Effort sponsored in part by the Defense Advanced Research Projects
32 * Agency (DARPA) and Air Force Research Laboratory, Air Force
33 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
34 *
35 */
36
37 #undef UBSEC_DEBUG
38
39 /*
40 * uBsec 5[56]01, bcm580xx, bcm582x hardware crypto accelerator
41 */
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/proc.h>
46 #include <sys/endian.h>
47 #ifdef __NetBSD__
48 #define letoh16 htole16
49 #define letoh32 htole32
50 #define UBSEC_NO_RNG /* until statistically tested */
51 #endif
52 #include <sys/errno.h>
53 #include <sys/malloc.h>
54 #include <sys/kernel.h>
55 #include <sys/mbuf.h>
56 #include <sys/device.h>
57 #include <sys/queue.h>
58
59 #include <uvm/uvm_extern.h>
60
61 #include <opencrypto/cryptodev.h>
62 #include <opencrypto/cryptosoft.h>
63 #ifdef __OpenBSD__
64 #include <dev/rndvar.h>
65 #include <sys/md5k.h>
66 #else
67 #include <sys/rnd.h>
68 #include <sys/md5.h>
69 #endif
70 #include <sys/sha1.h>
71
72 #include <dev/pci/pcireg.h>
73 #include <dev/pci/pcivar.h>
74 #include <dev/pci/pcidevs.h>
75
76 #include <dev/pci/ubsecreg.h>
77 #include <dev/pci/ubsecvar.h>
78
79 /*
80 * Prototypes and count for the pci_device structure
81 */
82 static int ubsec_probe(struct device *, struct cfdata *, void *);
83 static void ubsec_attach(struct device *, struct device *, void *);
84 static void ubsec_reset_board(struct ubsec_softc *);
85 static void ubsec_init_board(struct ubsec_softc *);
86 static void ubsec_init_pciregs(struct pci_attach_args *pa);
87 static void ubsec_cleanchip(struct ubsec_softc *);
88 static void ubsec_totalreset(struct ubsec_softc *);
89 static int ubsec_free_q(struct ubsec_softc*, struct ubsec_q *);
90
91 #ifdef __OpenBSD__
92 struct cfattach ubsec_ca = {
93 sizeof(struct ubsec_softc), ubsec_probe, ubsec_attach,
94 };
95
96 struct cfdriver ubsec_cd = {
97 0, "ubsec", DV_DULL
98 };
99 #else
100 CFATTACH_DECL(ubsec, sizeof(struct ubsec_softc), ubsec_probe, ubsec_attach,
101 NULL, NULL);
102 extern struct cfdriver ubsec_cd;
103 #endif
104
105 /* patchable */
106 #ifdef UBSEC_DEBUG
107 extern int ubsec_debug;
108 int ubsec_debug=1;
109 #endif
110
111 static int ubsec_intr(void *);
112 static int ubsec_newsession(void*, u_int32_t *, struct cryptoini *);
113 static int ubsec_freesession(void*, u_int64_t);
114 static int ubsec_process(void*, struct cryptop *, int hint);
115 static void ubsec_callback(struct ubsec_softc *, struct ubsec_q *);
116 static void ubsec_feed(struct ubsec_softc *);
117 static void ubsec_mcopy(struct mbuf *, struct mbuf *, int, int);
118 static void ubsec_callback2(struct ubsec_softc *, struct ubsec_q2 *);
119 static void ubsec_feed2(struct ubsec_softc *);
120 #ifndef UBSEC_NO_RNG
121 static void ubsec_rng(void *);
122 #endif /* UBSEC_NO_RNG */
123 static int ubsec_dma_malloc(struct ubsec_softc *, bus_size_t,
124 struct ubsec_dma_alloc *, int);
125 static void ubsec_dma_free(struct ubsec_softc *, struct ubsec_dma_alloc *);
126 static int ubsec_dmamap_aligned(bus_dmamap_t);
127
128 static int ubsec_kprocess(void*, struct cryptkop *, int);
129 static int ubsec_kprocess_modexp_sw(struct ubsec_softc *,
130 struct cryptkop *, int);
131 static int ubsec_kprocess_modexp_hw(struct ubsec_softc *,
132 struct cryptkop *, int);
133 static int ubsec_kprocess_rsapriv(struct ubsec_softc *,
134 struct cryptkop *, int);
135 static void ubsec_kfree(struct ubsec_softc *, struct ubsec_q2 *);
136 static int ubsec_ksigbits(struct crparam *);
137 static void ubsec_kshift_r(u_int, u_int8_t *, u_int, u_int8_t *, u_int);
138 static void ubsec_kshift_l(u_int, u_int8_t *, u_int, u_int8_t *, u_int);
139
140 #ifdef UBSEC_DEBUG
141 static void ubsec_dump_pb(volatile struct ubsec_pktbuf *);
142 static void ubsec_dump_mcr(struct ubsec_mcr *);
143 static void ubsec_dump_ctx2(volatile struct ubsec_ctx_keyop *);
144 #endif
145
146 #define READ_REG(sc,r) \
147 bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (r))
148
149 #define WRITE_REG(sc,reg,val) \
150 bus_space_write_4((sc)->sc_st, (sc)->sc_sh, reg, val)
151
152 #define SWAP32(x) (x) = htole32(ntohl((x)))
153 #ifndef HTOLE32
154 #define HTOLE32(x) (x) = htole32(x)
155 #endif
156
157 struct ubsec_stats ubsecstats;
158
159 /*
160 * ubsec_maxbatch controls the number of crypto ops to voluntarily
161 * collect into one submission to the hardware. This batching happens
162 * when ops are dispatched from the crypto subsystem with a hint that
163 * more are to follow immediately. These ops must also not be marked
164 * with a ``no delay'' flag.
165 */
166 static int ubsec_maxbatch = 1;
167 #ifdef SYSCTL_INT
168 SYSCTL_INT(_kern, OID_AUTO, ubsec_maxbatch, CTLFLAG_RW, &ubsec_maxbatch,
169 0, "Broadcom driver: max ops to batch w/o interrupt");
170 #endif
171
172 /*
173 * ubsec_maxaggr controls the number of crypto ops to submit to the
174 * hardware as a unit. This aggregation reduces the number of interrupts
175 * to the host at the expense of increased latency (for all but the last
176 * operation). For network traffic setting this to one yields the highest
177 * performance but at the expense of more interrupt processing.
178 */
179 static int ubsec_maxaggr = 1;
180 #ifdef SYSCTL_INT
181 SYSCTL_INT(_kern, OID_AUTO, ubsec_maxaggr, CTLFLAG_RW, &ubsec_maxaggr,
182 0, "Broadcom driver: max ops to aggregate under one interrupt");
183 #endif
184
185 static const struct ubsec_product {
186 pci_vendor_id_t ubsec_vendor;
187 pci_product_id_t ubsec_product;
188 int ubsec_flags;
189 int ubsec_statmask;
190 const char *ubsec_name;
191 } ubsec_products[] = {
192 { PCI_VENDOR_BLUESTEEL, PCI_PRODUCT_BLUESTEEL_5501,
193 0,
194 BS_STAT_MCR1_DONE | BS_STAT_DMAERR,
195 "Bluesteel 5501"
196 },
197 { PCI_VENDOR_BLUESTEEL, PCI_PRODUCT_BLUESTEEL_5601,
198 UBS_FLAGS_KEY | UBS_FLAGS_RNG,
199 BS_STAT_MCR1_DONE | BS_STAT_DMAERR,
200 "Bluesteel 5601"
201 },
202
203 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5801,
204 0,
205 BS_STAT_MCR1_DONE | BS_STAT_DMAERR,
206 "Broadcom BCM5801"
207 },
208
209 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5802,
210 UBS_FLAGS_KEY | UBS_FLAGS_RNG,
211 BS_STAT_MCR1_DONE | BS_STAT_DMAERR,
212 "Broadcom BCM5802"
213 },
214
215 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5805,
216 UBS_FLAGS_KEY | UBS_FLAGS_RNG,
217 BS_STAT_MCR1_DONE | BS_STAT_DMAERR,
218 "Broadcom BCM5805"
219 },
220
221 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5820,
222 UBS_FLAGS_KEY | UBS_FLAGS_RNG | UBS_FLAGS_LONGCTX |
223 UBS_FLAGS_HWNORM | UBS_FLAGS_BIGKEY,
224 BS_STAT_MCR1_DONE | BS_STAT_DMAERR,
225 "Broadcom BCM5820"
226 },
227
228 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5821,
229 UBS_FLAGS_KEY | UBS_FLAGS_RNG | UBS_FLAGS_LONGCTX |
230 UBS_FLAGS_HWNORM | UBS_FLAGS_BIGKEY,
231 BS_STAT_MCR1_DONE | BS_STAT_DMAERR |
232 BS_STAT_MCR1_ALLEMPTY | BS_STAT_MCR2_ALLEMPTY,
233 "Broadcom BCM5821"
234 },
235 { PCI_VENDOR_SUN, PCI_PRODUCT_SUN_SCA1K,
236 UBS_FLAGS_KEY | UBS_FLAGS_RNG | UBS_FLAGS_LONGCTX |
237 UBS_FLAGS_HWNORM | UBS_FLAGS_BIGKEY,
238 BS_STAT_MCR1_DONE | BS_STAT_DMAERR |
239 BS_STAT_MCR1_ALLEMPTY | BS_STAT_MCR2_ALLEMPTY,
240 "Sun Crypto Accelerator 1000"
241 },
242 { PCI_VENDOR_SUN, PCI_PRODUCT_SUN_5821,
243 UBS_FLAGS_KEY | UBS_FLAGS_RNG | UBS_FLAGS_LONGCTX |
244 UBS_FLAGS_HWNORM | UBS_FLAGS_BIGKEY,
245 BS_STAT_MCR1_DONE | BS_STAT_DMAERR |
246 BS_STAT_MCR1_ALLEMPTY | BS_STAT_MCR2_ALLEMPTY,
247 "Broadcom BCM5821 (Sun)"
248 },
249
250 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5822,
251 UBS_FLAGS_KEY | UBS_FLAGS_RNG | UBS_FLAGS_LONGCTX |
252 UBS_FLAGS_HWNORM | UBS_FLAGS_BIGKEY,
253 BS_STAT_MCR1_DONE | BS_STAT_DMAERR |
254 BS_STAT_MCR1_ALLEMPTY | BS_STAT_MCR2_ALLEMPTY,
255 "Broadcom BCM5822"
256 },
257
258 { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_5823,
259 UBS_FLAGS_KEY | UBS_FLAGS_RNG | UBS_FLAGS_LONGCTX |
260 UBS_FLAGS_HWNORM | UBS_FLAGS_BIGKEY,
261 BS_STAT_MCR1_DONE | BS_STAT_DMAERR |
262 BS_STAT_MCR1_ALLEMPTY | BS_STAT_MCR2_ALLEMPTY,
263 "Broadcom BCM5823"
264 },
265
266 { 0, 0,
267 0,
268 0,
269 NULL
270 }
271 };
272
273 static const struct ubsec_product *
274 ubsec_lookup(const struct pci_attach_args *pa)
275 {
276 const struct ubsec_product *up;
277
278 for (up = ubsec_products; up->ubsec_name != NULL; up++) {
279 if (PCI_VENDOR(pa->pa_id) == up->ubsec_vendor &&
280 PCI_PRODUCT(pa->pa_id) == up->ubsec_product)
281 return (up);
282 }
283 return (NULL);
284 }
285
286 static int
287 ubsec_probe(struct device *parent, struct cfdata *match, void *aux)
288 {
289 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
290
291 if (ubsec_lookup(pa) != NULL)
292 return (1);
293
294 return (0);
295 }
296
297 static void
298 ubsec_attach(struct device *parent, struct device *self, void *aux)
299 {
300 struct ubsec_softc *sc = (struct ubsec_softc *)self;
301 struct pci_attach_args *pa = aux;
302 const struct ubsec_product *up;
303 pci_chipset_tag_t pc = pa->pa_pc;
304 pci_intr_handle_t ih;
305 const char *intrstr = NULL;
306 struct ubsec_dma *dmap;
307 u_int32_t cmd, i;
308
309 up = ubsec_lookup(pa);
310 if (up == NULL) {
311 printf("\n");
312 panic("ubsec_attach: impossible");
313 }
314
315 aprint_naive(": Crypto processor\n");
316 aprint_normal(": %s, rev. %d\n", up->ubsec_name,
317 PCI_REVISION(pa->pa_class));
318
319 SIMPLEQ_INIT(&sc->sc_queue);
320 SIMPLEQ_INIT(&sc->sc_qchip);
321 SIMPLEQ_INIT(&sc->sc_queue2);
322 SIMPLEQ_INIT(&sc->sc_qchip2);
323 SIMPLEQ_INIT(&sc->sc_q2free);
324
325 sc->sc_flags = up->ubsec_flags;
326 sc->sc_statmask = up->ubsec_statmask;
327
328 cmd = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
329 cmd |= PCI_COMMAND_MASTER_ENABLE;
330 pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, cmd);
331
332 if (pci_mapreg_map(pa, BS_BAR, PCI_MAPREG_TYPE_MEM, 0,
333 &sc->sc_st, &sc->sc_sh, NULL, NULL)) {
334 aprint_error("%s: can't find mem space",
335 sc->sc_dv.dv_xname);
336 return;
337 }
338
339 sc->sc_dmat = pa->pa_dmat;
340
341 if (pci_intr_map(pa, &ih)) {
342 aprint_error("%s: couldn't map interrupt\n",
343 sc->sc_dv.dv_xname);
344 return;
345 }
346 intrstr = pci_intr_string(pc, ih);
347 sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, ubsec_intr, sc);
348 if (sc->sc_ih == NULL) {
349 aprint_error("%s: couldn't establish interrupt",
350 sc->sc_dv.dv_xname);
351 if (intrstr != NULL)
352 aprint_normal(" at %s", intrstr);
353 aprint_normal("\n");
354 return;
355 }
356 aprint_normal("%s: interrupting at %s\n", sc->sc_dv.dv_xname, intrstr);
357
358 sc->sc_cid = crypto_get_driverid(0);
359 if (sc->sc_cid < 0) {
360 aprint_error("%s: couldn't get crypto driver id\n",
361 sc->sc_dv.dv_xname);
362 pci_intr_disestablish(pc, sc->sc_ih);
363 return;
364 }
365
366 SIMPLEQ_INIT(&sc->sc_freequeue);
367 dmap = sc->sc_dmaa;
368 for (i = 0; i < UBS_MAX_NQUEUE; i++, dmap++) {
369 struct ubsec_q *q;
370
371 q = (struct ubsec_q *)malloc(sizeof(struct ubsec_q),
372 M_DEVBUF, M_NOWAIT);
373 if (q == NULL) {
374 aprint_error("%s: can't allocate queue buffers\n",
375 sc->sc_dv.dv_xname);
376 break;
377 }
378
379 if (ubsec_dma_malloc(sc, sizeof(struct ubsec_dmachunk),
380 &dmap->d_alloc, 0)) {
381 aprint_error("%s: can't allocate dma buffers\n",
382 sc->sc_dv.dv_xname);
383 free(q, M_DEVBUF);
384 break;
385 }
386 dmap->d_dma = (struct ubsec_dmachunk *)dmap->d_alloc.dma_vaddr;
387
388 q->q_dma = dmap;
389 sc->sc_queuea[i] = q;
390
391 SIMPLEQ_INSERT_TAIL(&sc->sc_freequeue, q, q_next);
392 }
393
394 crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0,
395 ubsec_newsession, ubsec_freesession, ubsec_process, sc);
396 crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0,
397 ubsec_newsession, ubsec_freesession, ubsec_process, sc);
398 crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0,
399 ubsec_newsession, ubsec_freesession, ubsec_process, sc);
400 crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0,
401 ubsec_newsession, ubsec_freesession, ubsec_process, sc);
402
403 /*
404 * Reset Broadcom chip
405 */
406 ubsec_reset_board(sc);
407
408 /*
409 * Init Broadcom specific PCI settings
410 */
411 ubsec_init_pciregs(pa);
412
413 /*
414 * Init Broadcom chip
415 */
416 ubsec_init_board(sc);
417
418 #ifndef UBSEC_NO_RNG
419 if (sc->sc_flags & UBS_FLAGS_RNG) {
420 sc->sc_statmask |= BS_STAT_MCR2_DONE;
421
422 if (ubsec_dma_malloc(sc, sizeof(struct ubsec_mcr),
423 &sc->sc_rng.rng_q.q_mcr, 0))
424 goto skip_rng;
425
426 if (ubsec_dma_malloc(sc, sizeof(struct ubsec_ctx_rngbypass),
427 &sc->sc_rng.rng_q.q_ctx, 0)) {
428 ubsec_dma_free(sc, &sc->sc_rng.rng_q.q_mcr);
429 goto skip_rng;
430 }
431
432 if (ubsec_dma_malloc(sc, sizeof(u_int32_t) *
433 UBSEC_RNG_BUFSIZ, &sc->sc_rng.rng_buf, 0)) {
434 ubsec_dma_free(sc, &sc->sc_rng.rng_q.q_ctx);
435 ubsec_dma_free(sc, &sc->sc_rng.rng_q.q_mcr);
436 goto skip_rng;
437 }
438
439 if (hz >= 100)
440 sc->sc_rnghz = hz / 100;
441 else
442 sc->sc_rnghz = 1;
443 #ifdef __OpenBSD__
444 timeout_set(&sc->sc_rngto, ubsec_rng, sc);
445 timeout_add(&sc->sc_rngto, sc->sc_rnghz);
446 #else
447 callout_init(&sc->sc_rngto);
448 callout_reset(&sc->sc_rngto, sc->sc_rnghz, ubsec_rng, sc);
449 #endif
450 skip_rng:
451 if (sc->sc_rnghz)
452 aprint_normal("%s: random number generator enabled\n",
453 sc->sc_dv.dv_xname);
454 else
455 aprint_error("%s: WARNING: random number generator "
456 "disabled\n", sc->sc_dv.dv_xname);
457 }
458 #endif /* UBSEC_NO_RNG */
459
460 if (sc->sc_flags & UBS_FLAGS_KEY) {
461 sc->sc_statmask |= BS_STAT_MCR2_DONE;
462
463 crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0,
464 ubsec_kprocess, sc);
465 #if 0
466 crypto_kregister(sc->sc_cid, CRK_MOD_EXP_CRT, 0,
467 ubsec_kprocess, sc);
468 #endif
469 }
470 }
471
472 /*
473 * UBSEC Interrupt routine
474 */
475 static int
476 ubsec_intr(void *arg)
477 {
478 struct ubsec_softc *sc = arg;
479 volatile u_int32_t stat;
480 struct ubsec_q *q;
481 struct ubsec_dma *dmap;
482 int npkts = 0, i;
483
484 stat = READ_REG(sc, BS_STAT);
485 stat &= sc->sc_statmask;
486 if (stat == 0) {
487 return (0);
488 }
489
490 WRITE_REG(sc, BS_STAT, stat); /* IACK */
491
492 /*
493 * Check to see if we have any packets waiting for us
494 */
495 if ((stat & BS_STAT_MCR1_DONE)) {
496 while (!SIMPLEQ_EMPTY(&sc->sc_qchip)) {
497 q = SIMPLEQ_FIRST(&sc->sc_qchip);
498 dmap = q->q_dma;
499
500 if ((dmap->d_dma->d_mcr.mcr_flags & htole16(UBS_MCR_DONE)) == 0)
501 break;
502
503 q = SIMPLEQ_FIRST(&sc->sc_qchip);
504 SIMPLEQ_REMOVE_HEAD(&sc->sc_qchip, /*q,*/ q_next);
505
506 npkts = q->q_nstacked_mcrs;
507 sc->sc_nqchip -= 1+npkts;
508 /*
509 * search for further sc_qchip ubsec_q's that share
510 * the same MCR, and complete them too, they must be
511 * at the top.
512 */
513 for (i = 0; i < npkts; i++) {
514 if(q->q_stacked_mcr[i])
515 ubsec_callback(sc, q->q_stacked_mcr[i]);
516 else
517 break;
518 }
519 ubsec_callback(sc, q);
520 }
521
522 /*
523 * Don't send any more packet to chip if there has been
524 * a DMAERR.
525 */
526 if (!(stat & BS_STAT_DMAERR))
527 ubsec_feed(sc);
528 }
529
530 /*
531 * Check to see if we have any key setups/rng's waiting for us
532 */
533 if ((sc->sc_flags & (UBS_FLAGS_KEY|UBS_FLAGS_RNG)) &&
534 (stat & BS_STAT_MCR2_DONE)) {
535 struct ubsec_q2 *q2;
536 struct ubsec_mcr *mcr;
537
538 while (!SIMPLEQ_EMPTY(&sc->sc_qchip2)) {
539 q2 = SIMPLEQ_FIRST(&sc->sc_qchip2);
540
541 bus_dmamap_sync(sc->sc_dmat, q2->q_mcr.dma_map,
542 0, q2->q_mcr.dma_map->dm_mapsize,
543 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
544
545 mcr = (struct ubsec_mcr *)q2->q_mcr.dma_vaddr;
546 if ((mcr->mcr_flags & htole16(UBS_MCR_DONE)) == 0) {
547 bus_dmamap_sync(sc->sc_dmat,
548 q2->q_mcr.dma_map, 0,
549 q2->q_mcr.dma_map->dm_mapsize,
550 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
551 break;
552 }
553 q2 = SIMPLEQ_FIRST(&sc->sc_qchip2);
554 SIMPLEQ_REMOVE_HEAD(&sc->sc_qchip2, /*q2,*/ q_next);
555 ubsec_callback2(sc, q2);
556 /*
557 * Don't send any more packet to chip if there has been
558 * a DMAERR.
559 */
560 if (!(stat & BS_STAT_DMAERR))
561 ubsec_feed2(sc);
562 }
563 }
564
565 /*
566 * Check to see if we got any DMA Error
567 */
568 if (stat & BS_STAT_DMAERR) {
569 #ifdef UBSEC_DEBUG
570 if (ubsec_debug) {
571 volatile u_int32_t a = READ_REG(sc, BS_ERR);
572
573 printf("%s: dmaerr %s@%08x\n", sc->sc_dv.dv_xname,
574 (a & BS_ERR_READ) ? "read" : "write",
575 a & BS_ERR_ADDR);
576 }
577 #endif /* UBSEC_DEBUG */
578 ubsecstats.hst_dmaerr++;
579 ubsec_totalreset(sc);
580 ubsec_feed(sc);
581 }
582
583 if (sc->sc_needwakeup) { /* XXX check high watermark */
584 int wkeup = sc->sc_needwakeup & (CRYPTO_SYMQ|CRYPTO_ASYMQ);
585 #ifdef UBSEC_DEBUG
586 if (ubsec_debug)
587 printf("%s: wakeup crypto (%x)\n", sc->sc_dv.dv_xname,
588 sc->sc_needwakeup);
589 #endif /* UBSEC_DEBUG */
590 sc->sc_needwakeup &= ~wkeup;
591 crypto_unblock(sc->sc_cid, wkeup);
592 }
593 return (1);
594 }
595
596 /*
597 * ubsec_feed() - aggregate and post requests to chip
598 * OpenBSD comments:
599 * It is assumed that the caller set splnet()
600 */
601 static void
602 ubsec_feed(struct ubsec_softc *sc)
603 {
604 struct ubsec_q *q, *q2;
605 int npkts, i;
606 void *v;
607 u_int32_t stat;
608 #ifdef UBSEC_DEBUG
609 static int max;
610 #endif /* UBSEC_DEBUG */
611
612 npkts = sc->sc_nqueue;
613 if (npkts > ubsecstats.hst_maxqueue)
614 ubsecstats.hst_maxqueue = npkts;
615 if (npkts < 2)
616 goto feed1;
617
618 /*
619 * Decide how many ops to combine in a single MCR. We cannot
620 * aggregate more than UBS_MAX_AGGR because this is the number
621 * of slots defined in the data structure. Otherwise we clamp
622 * based on the tunable parameter ubsec_maxaggr. Note that
623 * aggregation can happen in two ways: either by batching ops
624 * from above or because the h/w backs up and throttles us.
625 * Aggregating ops reduces the number of interrupts to the host
626 * but also (potentially) increases the latency for processing
627 * completed ops as we only get an interrupt when all aggregated
628 * ops have completed.
629 */
630 if (npkts > UBS_MAX_AGGR)
631 npkts = UBS_MAX_AGGR;
632 if (npkts > ubsec_maxaggr)
633 npkts = ubsec_maxaggr;
634 if (npkts > ubsecstats.hst_maxbatch)
635 ubsecstats.hst_maxbatch = npkts;
636 if (npkts < 2)
637 goto feed1;
638 ubsecstats.hst_totbatch += npkts-1;
639
640 if ((stat = READ_REG(sc, BS_STAT)) & (BS_STAT_MCR1_FULL | BS_STAT_DMAERR)) {
641 if (stat & BS_STAT_DMAERR) {
642 ubsec_totalreset(sc);
643 ubsecstats.hst_dmaerr++;
644 } else {
645 ubsecstats.hst_mcr1full++;
646 }
647 return;
648 }
649
650 #ifdef UBSEC_DEBUG
651 if (ubsec_debug)
652 printf("merging %d records\n", npkts);
653 /* XXX temporary aggregation statistics reporting code */
654 if (max < npkts) {
655 max = npkts;
656 printf("%s: new max aggregate %d\n", sc->sc_dv.dv_xname, max);
657 }
658 #endif /* UBSEC_DEBUG */
659
660 q = SIMPLEQ_FIRST(&sc->sc_queue);
661 SIMPLEQ_REMOVE_HEAD(&sc->sc_queue, /*q,*/ q_next);
662 --sc->sc_nqueue;
663
664 bus_dmamap_sync(sc->sc_dmat, q->q_src_map,
665 0, q->q_src_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
666 if (q->q_dst_map != NULL)
667 bus_dmamap_sync(sc->sc_dmat, q->q_dst_map,
668 0, q->q_dst_map->dm_mapsize, BUS_DMASYNC_PREREAD);
669
670 q->q_nstacked_mcrs = npkts - 1; /* Number of packets stacked */
671
672 for (i = 0; i < q->q_nstacked_mcrs; i++) {
673 q2 = SIMPLEQ_FIRST(&sc->sc_queue);
674 bus_dmamap_sync(sc->sc_dmat, q2->q_src_map,
675 0, q2->q_src_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
676 if (q2->q_dst_map != NULL)
677 bus_dmamap_sync(sc->sc_dmat, q2->q_dst_map,
678 0, q2->q_dst_map->dm_mapsize, BUS_DMASYNC_PREREAD);
679 q2= SIMPLEQ_FIRST(&sc->sc_queue);
680 SIMPLEQ_REMOVE_HEAD(&sc->sc_queue, /*q2,*/ q_next);
681 --sc->sc_nqueue;
682
683 v = ((void *)&q2->q_dma->d_dma->d_mcr);
684 v = (char*)v + (sizeof(struct ubsec_mcr) -
685 sizeof(struct ubsec_mcr_add));
686 bcopy(v, &q->q_dma->d_dma->d_mcradd[i], sizeof(struct ubsec_mcr_add));
687 q->q_stacked_mcr[i] = q2;
688 }
689 q->q_dma->d_dma->d_mcr.mcr_pkts = htole16(npkts);
690 SIMPLEQ_INSERT_TAIL(&sc->sc_qchip, q, q_next);
691 sc->sc_nqchip += npkts;
692 if (sc->sc_nqchip > ubsecstats.hst_maxqchip)
693 ubsecstats.hst_maxqchip = sc->sc_nqchip;
694 bus_dmamap_sync(sc->sc_dmat, q->q_dma->d_alloc.dma_map,
695 0, q->q_dma->d_alloc.dma_map->dm_mapsize,
696 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
697 WRITE_REG(sc, BS_MCR1, q->q_dma->d_alloc.dma_paddr +
698 offsetof(struct ubsec_dmachunk, d_mcr));
699 return;
700
701 feed1:
702 while (!SIMPLEQ_EMPTY(&sc->sc_queue)) {
703 if ((stat = READ_REG(sc, BS_STAT)) & (BS_STAT_MCR1_FULL | BS_STAT_DMAERR)) {
704 if (stat & BS_STAT_DMAERR) {
705 ubsec_totalreset(sc);
706 ubsecstats.hst_dmaerr++;
707 } else {
708 ubsecstats.hst_mcr1full++;
709 }
710 break;
711 }
712
713 q = SIMPLEQ_FIRST(&sc->sc_queue);
714
715 bus_dmamap_sync(sc->sc_dmat, q->q_src_map,
716 0, q->q_src_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
717 if (q->q_dst_map != NULL)
718 bus_dmamap_sync(sc->sc_dmat, q->q_dst_map,
719 0, q->q_dst_map->dm_mapsize, BUS_DMASYNC_PREREAD);
720 bus_dmamap_sync(sc->sc_dmat, q->q_dma->d_alloc.dma_map,
721 0, q->q_dma->d_alloc.dma_map->dm_mapsize,
722 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
723
724 WRITE_REG(sc, BS_MCR1, q->q_dma->d_alloc.dma_paddr +
725 offsetof(struct ubsec_dmachunk, d_mcr));
726 #ifdef UBSEC_DEBUG
727 if (ubsec_debug)
728 printf("feed: q->chip %p %08x stat %08x\n",
729 q, (u_int32_t)q->q_dma->d_alloc.dma_paddr,
730 stat);
731 #endif /* UBSEC_DEBUG */
732 q = SIMPLEQ_FIRST(&sc->sc_queue);
733 SIMPLEQ_REMOVE_HEAD(&sc->sc_queue, /*q,*/ q_next);
734 --sc->sc_nqueue;
735 SIMPLEQ_INSERT_TAIL(&sc->sc_qchip, q, q_next);
736 sc->sc_nqchip++;
737 }
738 if (sc->sc_nqchip > ubsecstats.hst_maxqchip)
739 ubsecstats.hst_maxqchip = sc->sc_nqchip;
740 }
741
742 /*
743 * Allocate a new 'session' and return an encoded session id. 'sidp'
744 * contains our registration id, and should contain an encoded session
745 * id on successful allocation.
746 */
747 static int
748 ubsec_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
749 {
750 struct cryptoini *c, *encini = NULL, *macini = NULL;
751 struct ubsec_softc *sc;
752 struct ubsec_session *ses = NULL;
753 MD5_CTX md5ctx;
754 SHA1_CTX sha1ctx;
755 int i, sesn;
756
757 sc = arg;
758 KASSERT(sc != NULL /*, ("ubsec_newsession: null softc")*/);
759
760 if (sidp == NULL || cri == NULL || sc == NULL)
761 return (EINVAL);
762
763 for (c = cri; c != NULL; c = c->cri_next) {
764 if (c->cri_alg == CRYPTO_MD5_HMAC ||
765 c->cri_alg == CRYPTO_SHA1_HMAC) {
766 if (macini)
767 return (EINVAL);
768 macini = c;
769 } else if (c->cri_alg == CRYPTO_DES_CBC ||
770 c->cri_alg == CRYPTO_3DES_CBC) {
771 if (encini)
772 return (EINVAL);
773 encini = c;
774 } else
775 return (EINVAL);
776 }
777 if (encini == NULL && macini == NULL)
778 return (EINVAL);
779
780 if (sc->sc_sessions == NULL) {
781 ses = sc->sc_sessions = (struct ubsec_session *)malloc(
782 sizeof(struct ubsec_session), M_DEVBUF, M_NOWAIT);
783 if (ses == NULL)
784 return (ENOMEM);
785 sesn = 0;
786 sc->sc_nsessions = 1;
787 } else {
788 for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
789 if (sc->sc_sessions[sesn].ses_used == 0) {
790 ses = &sc->sc_sessions[sesn];
791 break;
792 }
793 }
794
795 if (ses == NULL) {
796 sesn = sc->sc_nsessions;
797 ses = (struct ubsec_session *)malloc((sesn + 1) *
798 sizeof(struct ubsec_session), M_DEVBUF, M_NOWAIT);
799 if (ses == NULL)
800 return (ENOMEM);
801 bcopy(sc->sc_sessions, ses, sesn *
802 sizeof(struct ubsec_session));
803 bzero(sc->sc_sessions, sesn *
804 sizeof(struct ubsec_session));
805 free(sc->sc_sessions, M_DEVBUF);
806 sc->sc_sessions = ses;
807 ses = &sc->sc_sessions[sesn];
808 sc->sc_nsessions++;
809 }
810 }
811
812 bzero(ses, sizeof(struct ubsec_session));
813 ses->ses_used = 1;
814 if (encini) {
815 /* get an IV, network byte order */
816 #ifdef __NetBSD__
817 rnd_extract_data(ses->ses_iv,
818 sizeof(ses->ses_iv), RND_EXTRACT_ANY);
819 #else
820 get_random_bytes(ses->ses_iv, sizeof(ses->ses_iv));
821 #endif
822
823 /* Go ahead and compute key in ubsec's byte order */
824 if (encini->cri_alg == CRYPTO_DES_CBC) {
825 bcopy(encini->cri_key, &ses->ses_deskey[0], 8);
826 bcopy(encini->cri_key, &ses->ses_deskey[2], 8);
827 bcopy(encini->cri_key, &ses->ses_deskey[4], 8);
828 } else
829 bcopy(encini->cri_key, ses->ses_deskey, 24);
830
831 SWAP32(ses->ses_deskey[0]);
832 SWAP32(ses->ses_deskey[1]);
833 SWAP32(ses->ses_deskey[2]);
834 SWAP32(ses->ses_deskey[3]);
835 SWAP32(ses->ses_deskey[4]);
836 SWAP32(ses->ses_deskey[5]);
837 }
838
839 if (macini) {
840 for (i = 0; i < macini->cri_klen / 8; i++)
841 macini->cri_key[i] ^= HMAC_IPAD_VAL;
842
843 if (macini->cri_alg == CRYPTO_MD5_HMAC) {
844 MD5Init(&md5ctx);
845 MD5Update(&md5ctx, macini->cri_key,
846 macini->cri_klen / 8);
847 MD5Update(&md5ctx, hmac_ipad_buffer,
848 HMAC_BLOCK_LEN - (macini->cri_klen / 8));
849 bcopy(md5ctx.state, ses->ses_hminner,
850 sizeof(md5ctx.state));
851 } else {
852 SHA1Init(&sha1ctx);
853 SHA1Update(&sha1ctx, macini->cri_key,
854 macini->cri_klen / 8);
855 SHA1Update(&sha1ctx, hmac_ipad_buffer,
856 HMAC_BLOCK_LEN - (macini->cri_klen / 8));
857 bcopy(sha1ctx.state, ses->ses_hminner,
858 sizeof(sha1ctx.state));
859 }
860
861 for (i = 0; i < macini->cri_klen / 8; i++)
862 macini->cri_key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
863
864 if (macini->cri_alg == CRYPTO_MD5_HMAC) {
865 MD5Init(&md5ctx);
866 MD5Update(&md5ctx, macini->cri_key,
867 macini->cri_klen / 8);
868 MD5Update(&md5ctx, hmac_opad_buffer,
869 HMAC_BLOCK_LEN - (macini->cri_klen / 8));
870 bcopy(md5ctx.state, ses->ses_hmouter,
871 sizeof(md5ctx.state));
872 } else {
873 SHA1Init(&sha1ctx);
874 SHA1Update(&sha1ctx, macini->cri_key,
875 macini->cri_klen / 8);
876 SHA1Update(&sha1ctx, hmac_opad_buffer,
877 HMAC_BLOCK_LEN - (macini->cri_klen / 8));
878 bcopy(sha1ctx.state, ses->ses_hmouter,
879 sizeof(sha1ctx.state));
880 }
881
882 for (i = 0; i < macini->cri_klen / 8; i++)
883 macini->cri_key[i] ^= HMAC_OPAD_VAL;
884 }
885
886 *sidp = UBSEC_SID(sc->sc_dv.dv_unit, sesn);
887 return (0);
888 }
889
890 /*
891 * Deallocate a session.
892 */
893 static int
894 ubsec_freesession(void *arg, u_int64_t tid)
895 {
896 struct ubsec_softc *sc;
897 int session;
898 u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
899
900 sc = arg;
901 KASSERT(sc != NULL /*, ("ubsec_freesession: null softc")*/);
902
903 session = UBSEC_SESSION(sid);
904 if (session >= sc->sc_nsessions)
905 return (EINVAL);
906
907 bzero(&sc->sc_sessions[session], sizeof(sc->sc_sessions[session]));
908 return (0);
909 }
910
911 #ifdef __FreeBSD__ /* Ugly gratuitous changes to bus_dma */
912 static void
913 ubsec_op_cb(void *arg, bus_dma_segment_t *seg, int nsegs, bus_size_t mapsize, int error)
914 {
915 struct ubsec_operand *op = arg;
916
917 KASSERT(nsegs <= UBS_MAX_SCATTER
918 /*, ("Too many DMA segments returned when mapping operand")*/);
919 #ifdef UBSEC_DEBUG
920 if (ubsec_debug)
921 printf("ubsec_op_cb: mapsize %u nsegs %d\n",
922 (u_int) mapsize, nsegs);
923 #endif
924 op->mapsize = mapsize;
925 op->nsegs = nsegs;
926 bcopy(seg, op->segs, nsegs * sizeof (seg[0]));
927 }
928 #endif
929
930 static int
931 ubsec_process(void *arg, struct cryptop *crp, int hint)
932 {
933 struct ubsec_q *q = NULL;
934 #ifdef __OpenBSD__
935 int card;
936 #endif
937 int err = 0, i, j, s, nicealign;
938 struct ubsec_softc *sc;
939 struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
940 int encoffset = 0, macoffset = 0, cpskip, cpoffset;
941 int sskip, dskip, stheend, dtheend;
942 int16_t coffset;
943 struct ubsec_session *ses;
944 struct ubsec_pktctx ctx;
945 struct ubsec_dma *dmap = NULL;
946
947 sc = arg;
948 KASSERT(sc != NULL /*, ("ubsec_process: null softc")*/);
949
950 if (crp == NULL || crp->crp_callback == NULL || sc == NULL) {
951 ubsecstats.hst_invalid++;
952 return (EINVAL);
953 }
954 if (UBSEC_SESSION(crp->crp_sid) >= sc->sc_nsessions) {
955 ubsecstats.hst_badsession++;
956 return (EINVAL);
957 }
958
959 s = splnet();
960
961 if (SIMPLEQ_EMPTY(&sc->sc_freequeue)) {
962 ubsecstats.hst_queuefull++;
963 sc->sc_needwakeup |= CRYPTO_SYMQ;
964 splx(s);
965 return(ERESTART);
966 }
967
968 q = SIMPLEQ_FIRST(&sc->sc_freequeue);
969 SIMPLEQ_REMOVE_HEAD(&sc->sc_freequeue, /*q,*/ q_next);
970 splx(s);
971
972 dmap = q->q_dma; /* Save dma pointer */
973 bzero(q, sizeof(struct ubsec_q));
974 bzero(&ctx, sizeof(ctx));
975
976 q->q_sesn = UBSEC_SESSION(crp->crp_sid);
977 q->q_dma = dmap;
978 ses = &sc->sc_sessions[q->q_sesn];
979
980 if (crp->crp_flags & CRYPTO_F_IMBUF) {
981 q->q_src_m = (struct mbuf *)crp->crp_buf;
982 q->q_dst_m = (struct mbuf *)crp->crp_buf;
983 } else if (crp->crp_flags & CRYPTO_F_IOV) {
984 q->q_src_io = (struct uio *)crp->crp_buf;
985 q->q_dst_io = (struct uio *)crp->crp_buf;
986 } else {
987 ubsecstats.hst_badflags++;
988 err = EINVAL;
989 goto errout; /* XXX we don't handle contiguous blocks! */
990 }
991
992 bzero(&dmap->d_dma->d_mcr, sizeof(struct ubsec_mcr));
993
994 dmap->d_dma->d_mcr.mcr_pkts = htole16(1);
995 dmap->d_dma->d_mcr.mcr_flags = 0;
996 q->q_crp = crp;
997
998 crd1 = crp->crp_desc;
999 if (crd1 == NULL) {
1000 ubsecstats.hst_nodesc++;
1001 err = EINVAL;
1002 goto errout;
1003 }
1004 crd2 = crd1->crd_next;
1005
1006 if (crd2 == NULL) {
1007 if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
1008 crd1->crd_alg == CRYPTO_SHA1_HMAC) {
1009 maccrd = crd1;
1010 enccrd = NULL;
1011 } else if (crd1->crd_alg == CRYPTO_DES_CBC ||
1012 crd1->crd_alg == CRYPTO_3DES_CBC) {
1013 maccrd = NULL;
1014 enccrd = crd1;
1015 } else {
1016 ubsecstats.hst_badalg++;
1017 err = EINVAL;
1018 goto errout;
1019 }
1020 } else {
1021 if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
1022 crd1->crd_alg == CRYPTO_SHA1_HMAC) &&
1023 (crd2->crd_alg == CRYPTO_DES_CBC ||
1024 crd2->crd_alg == CRYPTO_3DES_CBC) &&
1025 ((crd2->crd_flags & CRD_F_ENCRYPT) == 0)) {
1026 maccrd = crd1;
1027 enccrd = crd2;
1028 } else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
1029 crd1->crd_alg == CRYPTO_3DES_CBC) &&
1030 (crd2->crd_alg == CRYPTO_MD5_HMAC ||
1031 crd2->crd_alg == CRYPTO_SHA1_HMAC) &&
1032 (crd1->crd_flags & CRD_F_ENCRYPT)) {
1033 enccrd = crd1;
1034 maccrd = crd2;
1035 } else {
1036 /*
1037 * We cannot order the ubsec as requested
1038 */
1039 ubsecstats.hst_badalg++;
1040 err = EINVAL;
1041 goto errout;
1042 }
1043 }
1044
1045 if (enccrd) {
1046 encoffset = enccrd->crd_skip;
1047 ctx.pc_flags |= htole16(UBS_PKTCTX_ENC_3DES);
1048
1049 if (enccrd->crd_flags & CRD_F_ENCRYPT) {
1050 q->q_flags |= UBSEC_QFLAGS_COPYOUTIV;
1051
1052 if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
1053 bcopy(enccrd->crd_iv, ctx.pc_iv, 8);
1054 else {
1055 ctx.pc_iv[0] = ses->ses_iv[0];
1056 ctx.pc_iv[1] = ses->ses_iv[1];
1057 }
1058
1059 if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
1060 if (crp->crp_flags & CRYPTO_F_IMBUF)
1061 m_copyback(q->q_src_m,
1062 enccrd->crd_inject,
1063 8, (caddr_t)ctx.pc_iv);
1064 else if (crp->crp_flags & CRYPTO_F_IOV)
1065 cuio_copyback(q->q_src_io,
1066 enccrd->crd_inject,
1067 8, (caddr_t)ctx.pc_iv);
1068 }
1069 } else {
1070 ctx.pc_flags |= htole16(UBS_PKTCTX_INBOUND);
1071
1072 if (enccrd->crd_flags & CRD_F_IV_EXPLICIT)
1073 bcopy(enccrd->crd_iv, ctx.pc_iv, 8);
1074 else if (crp->crp_flags & CRYPTO_F_IMBUF)
1075 m_copydata(q->q_src_m, enccrd->crd_inject,
1076 8, (caddr_t)ctx.pc_iv);
1077 else if (crp->crp_flags & CRYPTO_F_IOV)
1078 cuio_copydata(q->q_src_io,
1079 enccrd->crd_inject, 8,
1080 (caddr_t)ctx.pc_iv);
1081 }
1082
1083 ctx.pc_deskey[0] = ses->ses_deskey[0];
1084 ctx.pc_deskey[1] = ses->ses_deskey[1];
1085 ctx.pc_deskey[2] = ses->ses_deskey[2];
1086 ctx.pc_deskey[3] = ses->ses_deskey[3];
1087 ctx.pc_deskey[4] = ses->ses_deskey[4];
1088 ctx.pc_deskey[5] = ses->ses_deskey[5];
1089 SWAP32(ctx.pc_iv[0]);
1090 SWAP32(ctx.pc_iv[1]);
1091 }
1092
1093 if (maccrd) {
1094 macoffset = maccrd->crd_skip;
1095
1096 if (maccrd->crd_alg == CRYPTO_MD5_HMAC)
1097 ctx.pc_flags |= htole16(UBS_PKTCTX_AUTH_MD5);
1098 else
1099 ctx.pc_flags |= htole16(UBS_PKTCTX_AUTH_SHA1);
1100
1101 for (i = 0; i < 5; i++) {
1102 ctx.pc_hminner[i] = ses->ses_hminner[i];
1103 ctx.pc_hmouter[i] = ses->ses_hmouter[i];
1104
1105 HTOLE32(ctx.pc_hminner[i]);
1106 HTOLE32(ctx.pc_hmouter[i]);
1107 }
1108 }
1109
1110 if (enccrd && maccrd) {
1111 /*
1112 * ubsec cannot handle packets where the end of encryption
1113 * and authentication are not the same, or where the
1114 * encrypted part begins before the authenticated part.
1115 */
1116 if ((encoffset + enccrd->crd_len) !=
1117 (macoffset + maccrd->crd_len)) {
1118 ubsecstats.hst_lenmismatch++;
1119 err = EINVAL;
1120 goto errout;
1121 }
1122 if (enccrd->crd_skip < maccrd->crd_skip) {
1123 ubsecstats.hst_skipmismatch++;
1124 err = EINVAL;
1125 goto errout;
1126 }
1127 sskip = maccrd->crd_skip;
1128 cpskip = dskip = enccrd->crd_skip;
1129 stheend = maccrd->crd_len;
1130 dtheend = enccrd->crd_len;
1131 coffset = enccrd->crd_skip - maccrd->crd_skip;
1132 cpoffset = cpskip + dtheend;
1133 #ifdef UBSEC_DEBUG
1134 if (ubsec_debug) {
1135 printf("mac: skip %d, len %d, inject %d\n",
1136 maccrd->crd_skip, maccrd->crd_len, maccrd->crd_inject);
1137 printf("enc: skip %d, len %d, inject %d\n",
1138 enccrd->crd_skip, enccrd->crd_len, enccrd->crd_inject);
1139 printf("src: skip %d, len %d\n", sskip, stheend);
1140 printf("dst: skip %d, len %d\n", dskip, dtheend);
1141 printf("ubs: coffset %d, pktlen %d, cpskip %d, cpoffset %d\n",
1142 coffset, stheend, cpskip, cpoffset);
1143 }
1144 #endif
1145 } else {
1146 cpskip = dskip = sskip = macoffset + encoffset;
1147 dtheend = stheend = (enccrd)?enccrd->crd_len:maccrd->crd_len;
1148 cpoffset = cpskip + dtheend;
1149 coffset = 0;
1150 }
1151 ctx.pc_offset = htole16(coffset >> 2);
1152
1153 /* XXX FIXME: jonathan asks, what the heck's that 0xfff0? */
1154 if (bus_dmamap_create(sc->sc_dmat, 0xfff0, UBS_MAX_SCATTER,
1155 0xfff0, 0, BUS_DMA_NOWAIT, &q->q_src_map) != 0) {
1156 err = ENOMEM;
1157 goto errout;
1158 }
1159 if (crp->crp_flags & CRYPTO_F_IMBUF) {
1160 if (bus_dmamap_load_mbuf(sc->sc_dmat, q->q_src_map,
1161 q->q_src_m, BUS_DMA_NOWAIT) != 0) {
1162 bus_dmamap_destroy(sc->sc_dmat, q->q_src_map);
1163 q->q_src_map = NULL;
1164 ubsecstats.hst_noload++;
1165 err = ENOMEM;
1166 goto errout;
1167 }
1168 } else if (crp->crp_flags & CRYPTO_F_IOV) {
1169 if (bus_dmamap_load_uio(sc->sc_dmat, q->q_src_map,
1170 q->q_src_io, BUS_DMA_NOWAIT) != 0) {
1171 bus_dmamap_destroy(sc->sc_dmat, q->q_src_map);
1172 q->q_src_map = NULL;
1173 ubsecstats.hst_noload++;
1174 err = ENOMEM;
1175 goto errout;
1176 }
1177 }
1178 nicealign = ubsec_dmamap_aligned(q->q_src_map);
1179
1180 dmap->d_dma->d_mcr.mcr_pktlen = htole16(stheend);
1181
1182 #ifdef UBSEC_DEBUG
1183 if (ubsec_debug)
1184 printf("src skip: %d nicealign: %u\n", sskip, nicealign);
1185 #endif
1186 for (i = j = 0; i < q->q_src_map->dm_nsegs; i++) {
1187 struct ubsec_pktbuf *pb;
1188 bus_size_t packl = q->q_src_map->dm_segs[i].ds_len;
1189 bus_addr_t packp = q->q_src_map->dm_segs[i].ds_addr;
1190
1191 if (sskip >= packl) {
1192 sskip -= packl;
1193 continue;
1194 }
1195
1196 packl -= sskip;
1197 packp += sskip;
1198 sskip = 0;
1199
1200 if (packl > 0xfffc) {
1201 err = EIO;
1202 goto errout;
1203 }
1204
1205 if (j == 0)
1206 pb = &dmap->d_dma->d_mcr.mcr_ipktbuf;
1207 else
1208 pb = &dmap->d_dma->d_sbuf[j - 1];
1209
1210 pb->pb_addr = htole32(packp);
1211
1212 if (stheend) {
1213 if (packl > stheend) {
1214 pb->pb_len = htole32(stheend);
1215 stheend = 0;
1216 } else {
1217 pb->pb_len = htole32(packl);
1218 stheend -= packl;
1219 }
1220 } else
1221 pb->pb_len = htole32(packl);
1222
1223 if ((i + 1) == q->q_src_map->dm_nsegs)
1224 pb->pb_next = 0;
1225 else
1226 pb->pb_next = htole32(dmap->d_alloc.dma_paddr +
1227 offsetof(struct ubsec_dmachunk, d_sbuf[j]));
1228 j++;
1229 }
1230
1231 if (enccrd == NULL && maccrd != NULL) {
1232 dmap->d_dma->d_mcr.mcr_opktbuf.pb_addr = 0;
1233 dmap->d_dma->d_mcr.mcr_opktbuf.pb_len = 0;
1234 dmap->d_dma->d_mcr.mcr_opktbuf.pb_next = htole32(dmap->d_alloc.dma_paddr +
1235 offsetof(struct ubsec_dmachunk, d_macbuf[0]));
1236 #ifdef UBSEC_DEBUG
1237 if (ubsec_debug)
1238 printf("opkt: %x %x %x\n",
1239 dmap->d_dma->d_mcr.mcr_opktbuf.pb_addr,
1240 dmap->d_dma->d_mcr.mcr_opktbuf.pb_len,
1241 dmap->d_dma->d_mcr.mcr_opktbuf.pb_next);
1242
1243 #endif
1244 } else {
1245 if (crp->crp_flags & CRYPTO_F_IOV) {
1246 if (!nicealign) {
1247 ubsecstats.hst_iovmisaligned++;
1248 err = EINVAL;
1249 goto errout;
1250 }
1251 /* XXX: ``what the heck's that'' 0xfff0? */
1252 if (bus_dmamap_create(sc->sc_dmat, 0xfff0,
1253 UBS_MAX_SCATTER, 0xfff0, 0, BUS_DMA_NOWAIT,
1254 &q->q_dst_map) != 0) {
1255 ubsecstats.hst_nomap++;
1256 err = ENOMEM;
1257 goto errout;
1258 }
1259 if (bus_dmamap_load_uio(sc->sc_dmat, q->q_dst_map,
1260 q->q_dst_io, BUS_DMA_NOWAIT) != 0) {
1261 bus_dmamap_destroy(sc->sc_dmat, q->q_dst_map);
1262 q->q_dst_map = NULL;
1263 ubsecstats.hst_noload++;
1264 err = ENOMEM;
1265 goto errout;
1266 }
1267 } else if (crp->crp_flags & CRYPTO_F_IMBUF) {
1268 if (nicealign) {
1269 q->q_dst_m = q->q_src_m;
1270 q->q_dst_map = q->q_src_map;
1271 } else {
1272 int totlen, len;
1273 struct mbuf *m, *top, **mp;
1274
1275 ubsecstats.hst_unaligned++;
1276 totlen = q->q_src_map->dm_mapsize;
1277 if (q->q_src_m->m_flags & M_PKTHDR) {
1278 len = MHLEN;
1279 MGETHDR(m, M_DONTWAIT, MT_DATA);
1280 /*XXX FIXME: m_dup_pkthdr */
1281 if (m && 1 /*!m_dup_pkthdr(m, q->q_src_m, M_DONTWAIT)*/) {
1282 m_free(m);
1283 m = NULL;
1284 }
1285 } else {
1286 len = MLEN;
1287 MGET(m, M_DONTWAIT, MT_DATA);
1288 }
1289 if (m == NULL) {
1290 ubsecstats.hst_nombuf++;
1291 err = sc->sc_nqueue ? ERESTART : ENOMEM;
1292 goto errout;
1293 }
1294 if (len == MHLEN)
1295 /*XXX was M_DUP_PKTHDR*/
1296 M_COPY_PKTHDR(m, q->q_src_m);
1297 if (totlen >= MINCLSIZE) {
1298 MCLGET(m, M_DONTWAIT);
1299 if ((m->m_flags & M_EXT) == 0) {
1300 m_free(m);
1301 ubsecstats.hst_nomcl++;
1302 err = sc->sc_nqueue ? ERESTART : ENOMEM;
1303 goto errout;
1304 }
1305 len = MCLBYTES;
1306 }
1307 m->m_len = len;
1308 top = NULL;
1309 mp = ⊤
1310
1311 while (totlen > 0) {
1312 if (top) {
1313 MGET(m, M_DONTWAIT, MT_DATA);
1314 if (m == NULL) {
1315 m_freem(top);
1316 ubsecstats.hst_nombuf++;
1317 err = sc->sc_nqueue ? ERESTART : ENOMEM;
1318 goto errout;
1319 }
1320 len = MLEN;
1321 }
1322 if (top && totlen >= MINCLSIZE) {
1323 MCLGET(m, M_DONTWAIT);
1324 if ((m->m_flags & M_EXT) == 0) {
1325 *mp = m;
1326 m_freem(top);
1327 ubsecstats.hst_nomcl++;
1328 err = sc->sc_nqueue ? ERESTART : ENOMEM;
1329 goto errout;
1330 }
1331 len = MCLBYTES;
1332 }
1333 m->m_len = len = min(totlen, len);
1334 totlen -= len;
1335 *mp = m;
1336 mp = &m->m_next;
1337 }
1338 q->q_dst_m = top;
1339 ubsec_mcopy(q->q_src_m, q->q_dst_m,
1340 cpskip, cpoffset);
1341 /* XXX again, what the heck is that 0xfff0? */
1342 if (bus_dmamap_create(sc->sc_dmat, 0xfff0,
1343 UBS_MAX_SCATTER, 0xfff0, 0, BUS_DMA_NOWAIT,
1344 &q->q_dst_map) != 0) {
1345 ubsecstats.hst_nomap++;
1346 err = ENOMEM;
1347 goto errout;
1348 }
1349 if (bus_dmamap_load_mbuf(sc->sc_dmat,
1350 q->q_dst_map, q->q_dst_m,
1351 BUS_DMA_NOWAIT) != 0) {
1352 bus_dmamap_destroy(sc->sc_dmat,
1353 q->q_dst_map);
1354 q->q_dst_map = NULL;
1355 ubsecstats.hst_noload++;
1356 err = ENOMEM;
1357 goto errout;
1358 }
1359 }
1360 } else {
1361 ubsecstats.hst_badflags++;
1362 err = EINVAL;
1363 goto errout;
1364 }
1365
1366 #ifdef UBSEC_DEBUG
1367 if (ubsec_debug)
1368 printf("dst skip: %d\n", dskip);
1369 #endif
1370 for (i = j = 0; i < q->q_dst_map->dm_nsegs; i++) {
1371 struct ubsec_pktbuf *pb;
1372 bus_size_t packl = q->q_dst_map->dm_segs[i].ds_len;
1373 bus_addr_t packp = q->q_dst_map->dm_segs[i].ds_addr;
1374
1375 if (dskip >= packl) {
1376 dskip -= packl;
1377 continue;
1378 }
1379
1380 packl -= dskip;
1381 packp += dskip;
1382 dskip = 0;
1383
1384 if (packl > 0xfffc) {
1385 err = EIO;
1386 goto errout;
1387 }
1388
1389 if (j == 0)
1390 pb = &dmap->d_dma->d_mcr.mcr_opktbuf;
1391 else
1392 pb = &dmap->d_dma->d_dbuf[j - 1];
1393
1394 pb->pb_addr = htole32(packp);
1395
1396 if (dtheend) {
1397 if (packl > dtheend) {
1398 pb->pb_len = htole32(dtheend);
1399 dtheend = 0;
1400 } else {
1401 pb->pb_len = htole32(packl);
1402 dtheend -= packl;
1403 }
1404 } else
1405 pb->pb_len = htole32(packl);
1406
1407 if ((i + 1) == q->q_dst_map->dm_nsegs) {
1408 if (maccrd)
1409 pb->pb_next = htole32(dmap->d_alloc.dma_paddr +
1410 offsetof(struct ubsec_dmachunk, d_macbuf[0]));
1411 else
1412 pb->pb_next = 0;
1413 } else
1414 pb->pb_next = htole32(dmap->d_alloc.dma_paddr +
1415 offsetof(struct ubsec_dmachunk, d_dbuf[j]));
1416 j++;
1417 }
1418 }
1419
1420 dmap->d_dma->d_mcr.mcr_cmdctxp = htole32(dmap->d_alloc.dma_paddr +
1421 offsetof(struct ubsec_dmachunk, d_ctx));
1422
1423 if (sc->sc_flags & UBS_FLAGS_LONGCTX) {
1424 struct ubsec_pktctx_long *ctxl;
1425
1426 ctxl = (struct ubsec_pktctx_long *)(dmap->d_alloc.dma_vaddr +
1427 offsetof(struct ubsec_dmachunk, d_ctx));
1428
1429 /* transform small context into long context */
1430 ctxl->pc_len = htole16(sizeof(struct ubsec_pktctx_long));
1431 ctxl->pc_type = htole16(UBS_PKTCTX_TYPE_IPSEC);
1432 ctxl->pc_flags = ctx.pc_flags;
1433 ctxl->pc_offset = ctx.pc_offset;
1434 for (i = 0; i < 6; i++)
1435 ctxl->pc_deskey[i] = ctx.pc_deskey[i];
1436 for (i = 0; i < 5; i++)
1437 ctxl->pc_hminner[i] = ctx.pc_hminner[i];
1438 for (i = 0; i < 5; i++)
1439 ctxl->pc_hmouter[i] = ctx.pc_hmouter[i];
1440 ctxl->pc_iv[0] = ctx.pc_iv[0];
1441 ctxl->pc_iv[1] = ctx.pc_iv[1];
1442 } else
1443 bcopy(&ctx, dmap->d_alloc.dma_vaddr +
1444 offsetof(struct ubsec_dmachunk, d_ctx),
1445 sizeof(struct ubsec_pktctx));
1446
1447 s = splnet();
1448 SIMPLEQ_INSERT_TAIL(&sc->sc_queue, q, q_next);
1449 sc->sc_nqueue++;
1450 ubsecstats.hst_ipackets++;
1451 ubsecstats.hst_ibytes += dmap->d_alloc.dma_map->dm_mapsize;
1452 if ((hint & CRYPTO_HINT_MORE) == 0 || sc->sc_nqueue >= ubsec_maxbatch)
1453 ubsec_feed(sc);
1454 splx(s);
1455 return (0);
1456
1457 errout:
1458 if (q != NULL) {
1459 if ((q->q_dst_m != NULL) && (q->q_src_m != q->q_dst_m))
1460 m_freem(q->q_dst_m);
1461
1462 if (q->q_dst_map != NULL && q->q_dst_map != q->q_src_map) {
1463 bus_dmamap_unload(sc->sc_dmat, q->q_dst_map);
1464 bus_dmamap_destroy(sc->sc_dmat, q->q_dst_map);
1465 }
1466 if (q->q_src_map != NULL) {
1467 bus_dmamap_unload(sc->sc_dmat, q->q_src_map);
1468 bus_dmamap_destroy(sc->sc_dmat, q->q_src_map);
1469 }
1470
1471 s = splnet();
1472 SIMPLEQ_INSERT_TAIL(&sc->sc_freequeue, q, q_next);
1473 splx(s);
1474 }
1475 #if 0 /* jonathan says: this openbsd code seems to be subsumed elsewhere */
1476 if (err == EINVAL)
1477 ubsecstats.hst_invalid++;
1478 else
1479 ubsecstats.hst_nomem++;
1480 #endif
1481 if (err != ERESTART) {
1482 crp->crp_etype = err;
1483 crypto_done(crp);
1484 } else {
1485 sc->sc_needwakeup |= CRYPTO_SYMQ;
1486 }
1487 return (err);
1488 }
1489
1490 static void
1491 ubsec_callback(struct ubsec_softc *sc, struct ubsec_q *q)
1492 {
1493 struct cryptop *crp = (struct cryptop *)q->q_crp;
1494 struct cryptodesc *crd;
1495 struct ubsec_dma *dmap = q->q_dma;
1496
1497 ubsecstats.hst_opackets++;
1498 ubsecstats.hst_obytes += dmap->d_alloc.dma_size;
1499
1500 bus_dmamap_sync(sc->sc_dmat, dmap->d_alloc.dma_map, 0,
1501 dmap->d_alloc.dma_map->dm_mapsize,
1502 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1503 if (q->q_dst_map != NULL && q->q_dst_map != q->q_src_map) {
1504 bus_dmamap_sync(sc->sc_dmat, q->q_dst_map,
1505 0, q->q_dst_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
1506 bus_dmamap_unload(sc->sc_dmat, q->q_dst_map);
1507 bus_dmamap_destroy(sc->sc_dmat, q->q_dst_map);
1508 }
1509 bus_dmamap_sync(sc->sc_dmat, q->q_src_map,
1510 0, q->q_src_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1511 bus_dmamap_unload(sc->sc_dmat, q->q_src_map);
1512 bus_dmamap_destroy(sc->sc_dmat, q->q_src_map);
1513
1514 if ((crp->crp_flags & CRYPTO_F_IMBUF) && (q->q_src_m != q->q_dst_m)) {
1515 m_freem(q->q_src_m);
1516 crp->crp_buf = (caddr_t)q->q_dst_m;
1517 }
1518
1519 /* copy out IV for future use */
1520 if (q->q_flags & UBSEC_QFLAGS_COPYOUTIV) {
1521 for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1522 if (crd->crd_alg != CRYPTO_DES_CBC &&
1523 crd->crd_alg != CRYPTO_3DES_CBC)
1524 continue;
1525 if (crp->crp_flags & CRYPTO_F_IMBUF)
1526 m_copydata((struct mbuf *)crp->crp_buf,
1527 crd->crd_skip + crd->crd_len - 8, 8,
1528 (caddr_t)sc->sc_sessions[q->q_sesn].ses_iv);
1529 else if (crp->crp_flags & CRYPTO_F_IOV) {
1530 cuio_copydata((struct uio *)crp->crp_buf,
1531 crd->crd_skip + crd->crd_len - 8, 8,
1532 (caddr_t)sc->sc_sessions[q->q_sesn].ses_iv);
1533 }
1534 break;
1535 }
1536 }
1537
1538 for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1539 if (crd->crd_alg != CRYPTO_MD5_HMAC &&
1540 crd->crd_alg != CRYPTO_SHA1_HMAC)
1541 continue;
1542 if (crp->crp_flags & CRYPTO_F_IMBUF)
1543 m_copyback((struct mbuf *)crp->crp_buf,
1544 crd->crd_inject, 12,
1545 (caddr_t)dmap->d_dma->d_macbuf);
1546 else if (crp->crp_flags & CRYPTO_F_IOV && crp->crp_mac)
1547 bcopy((caddr_t)dmap->d_dma->d_macbuf,
1548 crp->crp_mac, 12);
1549 break;
1550 }
1551 SIMPLEQ_INSERT_TAIL(&sc->sc_freequeue, q, q_next);
1552 crypto_done(crp);
1553 }
1554
1555 static void
1556 ubsec_mcopy(struct mbuf *srcm, struct mbuf *dstm, int hoffset, int toffset)
1557 {
1558 int i, j, dlen, slen;
1559 caddr_t dptr, sptr;
1560
1561 j = 0;
1562 sptr = srcm->m_data;
1563 slen = srcm->m_len;
1564 dptr = dstm->m_data;
1565 dlen = dstm->m_len;
1566
1567 while (1) {
1568 for (i = 0; i < min(slen, dlen); i++) {
1569 if (j < hoffset || j >= toffset)
1570 *dptr++ = *sptr++;
1571 slen--;
1572 dlen--;
1573 j++;
1574 }
1575 if (slen == 0) {
1576 srcm = srcm->m_next;
1577 if (srcm == NULL)
1578 return;
1579 sptr = srcm->m_data;
1580 slen = srcm->m_len;
1581 }
1582 if (dlen == 0) {
1583 dstm = dstm->m_next;
1584 if (dstm == NULL)
1585 return;
1586 dptr = dstm->m_data;
1587 dlen = dstm->m_len;
1588 }
1589 }
1590 }
1591
1592 /*
1593 * feed the key generator, must be called at splnet() or higher.
1594 */
1595 static void
1596 ubsec_feed2(struct ubsec_softc *sc)
1597 {
1598 struct ubsec_q2 *q;
1599
1600 while (!SIMPLEQ_EMPTY(&sc->sc_queue2)) {
1601 if (READ_REG(sc, BS_STAT) & BS_STAT_MCR2_FULL)
1602 break;
1603 q = SIMPLEQ_FIRST(&sc->sc_queue2);
1604
1605 bus_dmamap_sync(sc->sc_dmat, q->q_mcr.dma_map, 0,
1606 q->q_mcr.dma_map->dm_mapsize,
1607 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1608 bus_dmamap_sync(sc->sc_dmat, q->q_ctx.dma_map, 0,
1609 q->q_ctx.dma_map->dm_mapsize,
1610 BUS_DMASYNC_PREWRITE);
1611
1612 WRITE_REG(sc, BS_MCR2, q->q_mcr.dma_paddr);
1613 q = SIMPLEQ_FIRST(&sc->sc_queue2);
1614 SIMPLEQ_REMOVE_HEAD(&sc->sc_queue2, /*q,*/ q_next);
1615 --sc->sc_nqueue2;
1616 SIMPLEQ_INSERT_TAIL(&sc->sc_qchip2, q, q_next);
1617 }
1618 }
1619
1620 /*
1621 * Callback for handling random numbers
1622 */
1623 static void
1624 ubsec_callback2(struct ubsec_softc *sc, struct ubsec_q2 *q)
1625 {
1626 struct cryptkop *krp;
1627 struct ubsec_ctx_keyop *ctx;
1628
1629 ctx = (struct ubsec_ctx_keyop *)q->q_ctx.dma_vaddr;
1630 bus_dmamap_sync(sc->sc_dmat, q->q_ctx.dma_map, 0,
1631 q->q_ctx.dma_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1632
1633 switch (q->q_type) {
1634 #ifndef UBSEC_NO_RNG
1635 case UBS_CTXOP_RNGSHA1:
1636 case UBS_CTXOP_RNGBYPASS: {
1637 struct ubsec_q2_rng *rng = (struct ubsec_q2_rng *)q;
1638 u_int32_t *p;
1639 int i;
1640
1641 bus_dmamap_sync(sc->sc_dmat, rng->rng_buf.dma_map, 0,
1642 rng->rng_buf.dma_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
1643 p = (u_int32_t *)rng->rng_buf.dma_vaddr;
1644 #ifndef __NetBSD__
1645 for (i = 0; i < UBSEC_RNG_BUFSIZ; p++, i++)
1646 add_true_randomness(letoh32(*p));
1647 rng->rng_used = 0;
1648 #else
1649 /* XXX NetBSD rnd subsystem too weak */
1650 i = 0; (void)i; /* shut off gcc warnings */
1651 #endif
1652 #ifdef __OpenBSD__
1653 timeout_add(&sc->sc_rngto, sc->sc_rnghz);
1654 #else
1655 callout_reset(&sc->sc_rngto, sc->sc_rnghz, ubsec_rng, sc);
1656 #endif
1657 break;
1658 }
1659 #endif
1660 case UBS_CTXOP_MODEXP: {
1661 struct ubsec_q2_modexp *me = (struct ubsec_q2_modexp *)q;
1662 u_int rlen, clen;
1663
1664 krp = me->me_krp;
1665 rlen = (me->me_modbits + 7) / 8;
1666 clen = (krp->krp_param[krp->krp_iparams].crp_nbits + 7) / 8;
1667
1668 bus_dmamap_sync(sc->sc_dmat, me->me_M.dma_map,
1669 0, me->me_M.dma_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1670 bus_dmamap_sync(sc->sc_dmat, me->me_E.dma_map,
1671 0, me->me_E.dma_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1672 bus_dmamap_sync(sc->sc_dmat, me->me_C.dma_map,
1673 0, me->me_C.dma_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
1674 bus_dmamap_sync(sc->sc_dmat, me->me_epb.dma_map,
1675 0, me->me_epb.dma_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1676
1677 if (clen < rlen)
1678 krp->krp_status = E2BIG;
1679 else {
1680 if (sc->sc_flags & UBS_FLAGS_HWNORM) {
1681 bzero(krp->krp_param[krp->krp_iparams].crp_p,
1682 (krp->krp_param[krp->krp_iparams].crp_nbits
1683 + 7) / 8);
1684 bcopy(me->me_C.dma_vaddr,
1685 krp->krp_param[krp->krp_iparams].crp_p,
1686 (me->me_modbits + 7) / 8);
1687 } else
1688 ubsec_kshift_l(me->me_shiftbits,
1689 me->me_C.dma_vaddr, me->me_normbits,
1690 krp->krp_param[krp->krp_iparams].crp_p,
1691 krp->krp_param[krp->krp_iparams].crp_nbits);
1692 }
1693
1694 crypto_kdone(krp);
1695
1696 /* bzero all potentially sensitive data */
1697 bzero(me->me_E.dma_vaddr, me->me_E.dma_size);
1698 bzero(me->me_M.dma_vaddr, me->me_M.dma_size);
1699 bzero(me->me_C.dma_vaddr, me->me_C.dma_size);
1700 bzero(me->me_q.q_ctx.dma_vaddr, me->me_q.q_ctx.dma_size);
1701
1702 /* Can't free here, so put us on the free list. */
1703 SIMPLEQ_INSERT_TAIL(&sc->sc_q2free, &me->me_q, q_next);
1704 break;
1705 }
1706 case UBS_CTXOP_RSAPRIV: {
1707 struct ubsec_q2_rsapriv *rp = (struct ubsec_q2_rsapriv *)q;
1708 u_int len;
1709
1710 krp = rp->rpr_krp;
1711 bus_dmamap_sync(sc->sc_dmat, rp->rpr_msgin.dma_map, 0,
1712 rp->rpr_msgin.dma_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1713 bus_dmamap_sync(sc->sc_dmat, rp->rpr_msgout.dma_map, 0,
1714 rp->rpr_msgout.dma_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
1715
1716 len = (krp->krp_param[UBS_RSAPRIV_PAR_MSGOUT].crp_nbits + 7) / 8;
1717 bcopy(rp->rpr_msgout.dma_vaddr,
1718 krp->krp_param[UBS_RSAPRIV_PAR_MSGOUT].crp_p, len);
1719
1720 crypto_kdone(krp);
1721
1722 bzero(rp->rpr_msgin.dma_vaddr, rp->rpr_msgin.dma_size);
1723 bzero(rp->rpr_msgout.dma_vaddr, rp->rpr_msgout.dma_size);
1724 bzero(rp->rpr_q.q_ctx.dma_vaddr, rp->rpr_q.q_ctx.dma_size);
1725
1726 /* Can't free here, so put us on the free list. */
1727 SIMPLEQ_INSERT_TAIL(&sc->sc_q2free, &rp->rpr_q, q_next);
1728 break;
1729 }
1730 default:
1731 printf("%s: unknown ctx op: %x\n", sc->sc_dv.dv_xname,
1732 letoh16(ctx->ctx_op));
1733 break;
1734 }
1735 }
1736
1737 #ifndef UBSEC_NO_RNG
1738 static void
1739 ubsec_rng(void *vsc)
1740 {
1741 struct ubsec_softc *sc = vsc;
1742 struct ubsec_q2_rng *rng = &sc->sc_rng;
1743 struct ubsec_mcr *mcr;
1744 struct ubsec_ctx_rngbypass *ctx;
1745 int s;
1746
1747 s = splnet();
1748 if (rng->rng_used) {
1749 splx(s);
1750 return;
1751 }
1752 sc->sc_nqueue2++;
1753 if (sc->sc_nqueue2 >= UBS_MAX_NQUEUE)
1754 goto out;
1755
1756 mcr = (struct ubsec_mcr *)rng->rng_q.q_mcr.dma_vaddr;
1757 ctx = (struct ubsec_ctx_rngbypass *)rng->rng_q.q_ctx.dma_vaddr;
1758
1759 mcr->mcr_pkts = htole16(1);
1760 mcr->mcr_flags = 0;
1761 mcr->mcr_cmdctxp = htole32(rng->rng_q.q_ctx.dma_paddr);
1762 mcr->mcr_ipktbuf.pb_addr = mcr->mcr_ipktbuf.pb_next = 0;
1763 mcr->mcr_ipktbuf.pb_len = 0;
1764 mcr->mcr_reserved = mcr->mcr_pktlen = 0;
1765 mcr->mcr_opktbuf.pb_addr = htole32(rng->rng_buf.dma_paddr);
1766 mcr->mcr_opktbuf.pb_len = htole32(((sizeof(u_int32_t) * UBSEC_RNG_BUFSIZ)) &
1767 UBS_PKTBUF_LEN);
1768 mcr->mcr_opktbuf.pb_next = 0;
1769
1770 ctx->rbp_len = htole16(sizeof(struct ubsec_ctx_rngbypass));
1771 ctx->rbp_op = htole16(UBS_CTXOP_RNGSHA1);
1772 rng->rng_q.q_type = UBS_CTXOP_RNGSHA1;
1773
1774 bus_dmamap_sync(sc->sc_dmat, rng->rng_buf.dma_map, 0,
1775 rng->rng_buf.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD);
1776
1777 SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &rng->rng_q, q_next);
1778 rng->rng_used = 1;
1779 ubsec_feed2(sc);
1780 ubsecstats.hst_rng++;
1781 splx(s);
1782
1783 return;
1784
1785 out:
1786 /*
1787 * Something weird happened, generate our own call back.
1788 */
1789 sc->sc_nqueue2--;
1790 splx(s);
1791 #ifdef __OpenBSD__
1792 timeout_add(&sc->sc_rngto, sc->sc_rnghz);
1793 #else
1794 callout_reset(&sc->sc_rngto, sc->sc_rnghz, ubsec_rng, sc);
1795 #endif
1796 }
1797 #endif /* UBSEC_NO_RNG */
1798
1799 static int
1800 ubsec_dma_malloc(struct ubsec_softc *sc, bus_size_t size,
1801 struct ubsec_dma_alloc *dma,int mapflags)
1802 {
1803 int r;
1804
1805 if ((r = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0,
1806 &dma->dma_seg, 1, &dma->dma_nseg, BUS_DMA_NOWAIT)) != 0)
1807 goto fail_0;
1808
1809 if ((r = bus_dmamem_map(sc->sc_dmat, &dma->dma_seg, dma->dma_nseg,
1810 size, &dma->dma_vaddr, mapflags | BUS_DMA_NOWAIT)) != 0)
1811 goto fail_1;
1812
1813 if ((r = bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
1814 BUS_DMA_NOWAIT, &dma->dma_map)) != 0)
1815 goto fail_2;
1816
1817 if ((r = bus_dmamap_load(sc->sc_dmat, dma->dma_map, dma->dma_vaddr,
1818 size, NULL, BUS_DMA_NOWAIT)) != 0)
1819 goto fail_3;
1820
1821 dma->dma_paddr = dma->dma_map->dm_segs[0].ds_addr;
1822 dma->dma_size = size;
1823 return (0);
1824
1825 fail_3:
1826 bus_dmamap_destroy(sc->sc_dmat, dma->dma_map);
1827 fail_2:
1828 bus_dmamem_unmap(sc->sc_dmat, dma->dma_vaddr, size);
1829 fail_1:
1830 bus_dmamem_free(sc->sc_dmat, &dma->dma_seg, dma->dma_nseg);
1831 fail_0:
1832 dma->dma_map = NULL;
1833 return (r);
1834 }
1835
1836 static void
1837 ubsec_dma_free(struct ubsec_softc *sc, struct ubsec_dma_alloc *dma)
1838 {
1839 bus_dmamap_unload(sc->sc_dmat, dma->dma_map);
1840 bus_dmamem_unmap(sc->sc_dmat, dma->dma_vaddr, dma->dma_size);
1841 bus_dmamem_free(sc->sc_dmat, &dma->dma_seg, dma->dma_nseg);
1842 bus_dmamap_destroy(sc->sc_dmat, dma->dma_map);
1843 }
1844
1845 /*
1846 * Resets the board. Values in the regesters are left as is
1847 * from the reset (i.e. initial values are assigned elsewhere).
1848 */
1849 static void
1850 ubsec_reset_board(struct ubsec_softc *sc)
1851 {
1852 volatile u_int32_t ctrl;
1853
1854 ctrl = READ_REG(sc, BS_CTRL);
1855 ctrl |= BS_CTRL_RESET;
1856 WRITE_REG(sc, BS_CTRL, ctrl);
1857
1858 /*
1859 * Wait aprox. 30 PCI clocks = 900 ns = 0.9 us
1860 */
1861 DELAY(10);
1862 }
1863
1864 /*
1865 * Init Broadcom registers
1866 */
1867 static void
1868 ubsec_init_board(struct ubsec_softc *sc)
1869 {
1870 u_int32_t ctrl;
1871
1872 ctrl = READ_REG(sc, BS_CTRL);
1873 ctrl &= ~(BS_CTRL_BE32 | BS_CTRL_BE64);
1874 ctrl |= BS_CTRL_LITTLE_ENDIAN | BS_CTRL_MCR1INT;
1875
1876 /*
1877 * XXX: Sam Leffler's code has (UBS_FLAGS_KEY|UBS_FLAGS_RNG)).
1878 * anyone got hw docs?
1879 */
1880 if (sc->sc_flags & UBS_FLAGS_KEY)
1881 ctrl |= BS_CTRL_MCR2INT;
1882 else
1883 ctrl &= ~BS_CTRL_MCR2INT;
1884
1885 if (sc->sc_flags & UBS_FLAGS_HWNORM)
1886 ctrl &= ~BS_CTRL_SWNORM;
1887
1888 WRITE_REG(sc, BS_CTRL, ctrl);
1889 }
1890
1891 /*
1892 * Init Broadcom PCI registers
1893 */
1894 static void
1895 ubsec_init_pciregs(struct pci_attach_args *pa)
1896 {
1897 pci_chipset_tag_t pc = pa->pa_pc;
1898 u_int32_t misc;
1899
1900 /*
1901 * This will set the cache line size to 1, this will
1902 * force the BCM58xx chip just to do burst read/writes.
1903 * Cache line read/writes are to slow
1904 */
1905 misc = pci_conf_read(pc, pa->pa_tag, PCI_BHLC_REG);
1906 misc = (misc & ~(PCI_CACHELINE_MASK << PCI_CACHELINE_SHIFT))
1907 | ((UBS_DEF_CACHELINE & 0xff) << PCI_CACHELINE_SHIFT);
1908 pci_conf_write(pc, pa->pa_tag, PCI_BHLC_REG, misc);
1909 }
1910
1911 /*
1912 * Clean up after a chip crash.
1913 * It is assumed that the caller in splnet()
1914 */
1915 static void
1916 ubsec_cleanchip(struct ubsec_softc *sc)
1917 {
1918 struct ubsec_q *q;
1919
1920 while (!SIMPLEQ_EMPTY(&sc->sc_qchip)) {
1921 q = SIMPLEQ_FIRST(&sc->sc_qchip);
1922 SIMPLEQ_REMOVE_HEAD(&sc->sc_qchip, /*q,*/ q_next);
1923 ubsec_free_q(sc, q);
1924 }
1925 sc->sc_nqchip = 0;
1926 }
1927
1928 /*
1929 * free a ubsec_q
1930 * It is assumed that the caller is within splnet()
1931 */
1932 static int
1933 ubsec_free_q(struct ubsec_softc *sc, struct ubsec_q *q)
1934 {
1935 struct ubsec_q *q2;
1936 struct cryptop *crp;
1937 int npkts;
1938 int i;
1939
1940 npkts = q->q_nstacked_mcrs;
1941
1942 for (i = 0; i < npkts; i++) {
1943 if(q->q_stacked_mcr[i]) {
1944 q2 = q->q_stacked_mcr[i];
1945
1946 if ((q2->q_dst_m != NULL) && (q2->q_src_m != q2->q_dst_m))
1947 m_freem(q2->q_dst_m);
1948
1949 crp = (struct cryptop *)q2->q_crp;
1950
1951 SIMPLEQ_INSERT_TAIL(&sc->sc_freequeue, q2, q_next);
1952
1953 crp->crp_etype = EFAULT;
1954 crypto_done(crp);
1955 } else {
1956 break;
1957 }
1958 }
1959
1960 /*
1961 * Free header MCR
1962 */
1963 if ((q->q_dst_m != NULL) && (q->q_src_m != q->q_dst_m))
1964 m_freem(q->q_dst_m);
1965
1966 crp = (struct cryptop *)q->q_crp;
1967
1968 SIMPLEQ_INSERT_TAIL(&sc->sc_freequeue, q, q_next);
1969
1970 crp->crp_etype = EFAULT;
1971 crypto_done(crp);
1972 return(0);
1973 }
1974
1975 /*
1976 * Routine to reset the chip and clean up.
1977 * It is assumed that the caller is in splnet()
1978 */
1979 static void
1980 ubsec_totalreset(struct ubsec_softc *sc)
1981 {
1982 ubsec_reset_board(sc);
1983 ubsec_init_board(sc);
1984 ubsec_cleanchip(sc);
1985 }
1986
1987 static int
1988 ubsec_dmamap_aligned(bus_dmamap_t map)
1989 {
1990 int i;
1991
1992 for (i = 0; i < map->dm_nsegs; i++) {
1993 if (map->dm_segs[i].ds_addr & 3)
1994 return (0);
1995 if ((i != (map->dm_nsegs - 1)) &&
1996 (map->dm_segs[i].ds_len & 3))
1997 return (0);
1998 }
1999 return (1);
2000 }
2001
2002 #ifdef __OpenBSD__
2003 struct ubsec_softc *
2004 ubsec_kfind(struct cryptkop *krp)
2005 {
2006 struct ubsec_softc *sc;
2007 int i;
2008
2009 for (i = 0; i < ubsec_cd.cd_ndevs; i++) {
2010 sc = ubsec_cd.cd_devs[i];
2011 if (sc == NULL)
2012 continue;
2013 if (sc->sc_cid == krp->krp_hid)
2014 return (sc);
2015 }
2016 return (NULL);
2017 }
2018 #endif
2019
2020 static void
2021 ubsec_kfree(struct ubsec_softc *sc, struct ubsec_q2 *q)
2022 {
2023 switch (q->q_type) {
2024 case UBS_CTXOP_MODEXP: {
2025 struct ubsec_q2_modexp *me = (struct ubsec_q2_modexp *)q;
2026
2027 ubsec_dma_free(sc, &me->me_q.q_mcr);
2028 ubsec_dma_free(sc, &me->me_q.q_ctx);
2029 ubsec_dma_free(sc, &me->me_M);
2030 ubsec_dma_free(sc, &me->me_E);
2031 ubsec_dma_free(sc, &me->me_C);
2032 ubsec_dma_free(sc, &me->me_epb);
2033 free(me, M_DEVBUF);
2034 break;
2035 }
2036 case UBS_CTXOP_RSAPRIV: {
2037 struct ubsec_q2_rsapriv *rp = (struct ubsec_q2_rsapriv *)q;
2038
2039 ubsec_dma_free(sc, &rp->rpr_q.q_mcr);
2040 ubsec_dma_free(sc, &rp->rpr_q.q_ctx);
2041 ubsec_dma_free(sc, &rp->rpr_msgin);
2042 ubsec_dma_free(sc, &rp->rpr_msgout);
2043 free(rp, M_DEVBUF);
2044 break;
2045 }
2046 default:
2047 printf("%s: invalid kfree 0x%x\n", sc->sc_dv.dv_xname,
2048 q->q_type);
2049 break;
2050 }
2051 }
2052
2053 static int
2054 ubsec_kprocess(void *arg, struct cryptkop *krp, int hint)
2055 {
2056 struct ubsec_softc *sc;
2057 int r;
2058
2059 if (krp == NULL || krp->krp_callback == NULL)
2060 return (EINVAL);
2061 #ifdef __OpenBSD__
2062 if ((sc = ubsec_kfind(krp)) == NULL)
2063 return (EINVAL);
2064 #else
2065 sc = arg;
2066 KASSERT(sc != NULL /*, ("ubsec_kprocess: null softc")*/);
2067 #endif
2068
2069 while (!SIMPLEQ_EMPTY(&sc->sc_q2free)) {
2070 struct ubsec_q2 *q;
2071
2072 q = SIMPLEQ_FIRST(&sc->sc_q2free);
2073 SIMPLEQ_REMOVE_HEAD(&sc->sc_q2free, /*q,*/ q_next);
2074 ubsec_kfree(sc, q);
2075 }
2076
2077 switch (krp->krp_op) {
2078 case CRK_MOD_EXP:
2079 if (sc->sc_flags & UBS_FLAGS_HWNORM)
2080 r = ubsec_kprocess_modexp_hw(sc, krp, hint);
2081 else
2082 r = ubsec_kprocess_modexp_sw(sc, krp, hint);
2083 break;
2084 case CRK_MOD_EXP_CRT:
2085 r = ubsec_kprocess_rsapriv(sc, krp, hint);
2086 break;
2087 default:
2088 printf("%s: kprocess: invalid op 0x%x\n",
2089 sc->sc_dv.dv_xname, krp->krp_op);
2090 krp->krp_status = EOPNOTSUPP;
2091 crypto_kdone(krp);
2092 r = 0;
2093 }
2094 return (r);
2095 }
2096
2097 /*
2098 * Start computation of cr[C] = (cr[M] ^ cr[E]) mod cr[N] (sw normalization)
2099 */
2100 static int
2101 ubsec_kprocess_modexp_sw(struct ubsec_softc *sc, struct cryptkop *krp,
2102 int hint)
2103 {
2104 struct ubsec_q2_modexp *me;
2105 struct ubsec_mcr *mcr;
2106 struct ubsec_ctx_modexp *ctx;
2107 struct ubsec_pktbuf *epb;
2108 int s, err = 0;
2109 u_int nbits, normbits, mbits, shiftbits, ebits;
2110
2111 me = (struct ubsec_q2_modexp *)malloc(sizeof *me, M_DEVBUF, M_NOWAIT);
2112 if (me == NULL) {
2113 err = ENOMEM;
2114 goto errout;
2115 }
2116 bzero(me, sizeof *me);
2117 me->me_krp = krp;
2118 me->me_q.q_type = UBS_CTXOP_MODEXP;
2119
2120 nbits = ubsec_ksigbits(&krp->krp_param[UBS_MODEXP_PAR_N]);
2121 if (nbits <= 512)
2122 normbits = 512;
2123 else if (nbits <= 768)
2124 normbits = 768;
2125 else if (nbits <= 1024)
2126 normbits = 1024;
2127 else if (sc->sc_flags & UBS_FLAGS_BIGKEY && nbits <= 1536)
2128 normbits = 1536;
2129 else if (sc->sc_flags & UBS_FLAGS_BIGKEY && nbits <= 2048)
2130 normbits = 2048;
2131 else {
2132 err = E2BIG;
2133 goto errout;
2134 }
2135
2136 shiftbits = normbits - nbits;
2137
2138 me->me_modbits = nbits;
2139 me->me_shiftbits = shiftbits;
2140 me->me_normbits = normbits;
2141
2142 /* Sanity check: result bits must be >= true modulus bits. */
2143 if (krp->krp_param[krp->krp_iparams].crp_nbits < nbits) {
2144 err = ERANGE;
2145 goto errout;
2146 }
2147
2148 if (ubsec_dma_malloc(sc, sizeof(struct ubsec_mcr),
2149 &me->me_q.q_mcr, 0)) {
2150 err = ENOMEM;
2151 goto errout;
2152 }
2153 mcr = (struct ubsec_mcr *)me->me_q.q_mcr.dma_vaddr;
2154
2155 if (ubsec_dma_malloc(sc, sizeof(struct ubsec_ctx_modexp),
2156 &me->me_q.q_ctx, 0)) {
2157 err = ENOMEM;
2158 goto errout;
2159 }
2160
2161 mbits = ubsec_ksigbits(&krp->krp_param[UBS_MODEXP_PAR_M]);
2162 if (mbits > nbits) {
2163 err = E2BIG;
2164 goto errout;
2165 }
2166 if (ubsec_dma_malloc(sc, normbits / 8, &me->me_M, 0)) {
2167 err = ENOMEM;
2168 goto errout;
2169 }
2170 ubsec_kshift_r(shiftbits,
2171 krp->krp_param[UBS_MODEXP_PAR_M].crp_p, mbits,
2172 me->me_M.dma_vaddr, normbits);
2173
2174 if (ubsec_dma_malloc(sc, normbits / 8, &me->me_C, 0)) {
2175 err = ENOMEM;
2176 goto errout;
2177 }
2178 bzero(me->me_C.dma_vaddr, me->me_C.dma_size);
2179
2180 ebits = ubsec_ksigbits(&krp->krp_param[UBS_MODEXP_PAR_E]);
2181 if (ebits > nbits) {
2182 err = E2BIG;
2183 goto errout;
2184 }
2185 if (ubsec_dma_malloc(sc, normbits / 8, &me->me_E, 0)) {
2186 err = ENOMEM;
2187 goto errout;
2188 }
2189 ubsec_kshift_r(shiftbits,
2190 krp->krp_param[UBS_MODEXP_PAR_E].crp_p, ebits,
2191 me->me_E.dma_vaddr, normbits);
2192
2193 if (ubsec_dma_malloc(sc, sizeof(struct ubsec_pktbuf),
2194 &me->me_epb, 0)) {
2195 err = ENOMEM;
2196 goto errout;
2197 }
2198 epb = (struct ubsec_pktbuf *)me->me_epb.dma_vaddr;
2199 epb->pb_addr = htole32(me->me_E.dma_paddr);
2200 epb->pb_next = 0;
2201 epb->pb_len = htole32(normbits / 8);
2202
2203 #ifdef UBSEC_DEBUG
2204 if (ubsec_debug) {
2205 printf("Epb ");
2206 ubsec_dump_pb(epb);
2207 }
2208 #endif
2209
2210 mcr->mcr_pkts = htole16(1);
2211 mcr->mcr_flags = 0;
2212 mcr->mcr_cmdctxp = htole32(me->me_q.q_ctx.dma_paddr);
2213 mcr->mcr_reserved = 0;
2214 mcr->mcr_pktlen = 0;
2215
2216 mcr->mcr_ipktbuf.pb_addr = htole32(me->me_M.dma_paddr);
2217 mcr->mcr_ipktbuf.pb_len = htole32(normbits / 8);
2218 mcr->mcr_ipktbuf.pb_next = htole32(me->me_epb.dma_paddr);
2219
2220 mcr->mcr_opktbuf.pb_addr = htole32(me->me_C.dma_paddr);
2221 mcr->mcr_opktbuf.pb_next = 0;
2222 mcr->mcr_opktbuf.pb_len = htole32(normbits / 8);
2223
2224 #ifdef DIAGNOSTIC
2225 /* Misaligned output buffer will hang the chip. */
2226 if ((letoh32(mcr->mcr_opktbuf.pb_addr) & 3) != 0)
2227 panic("%s: modexp invalid addr 0x%x",
2228 sc->sc_dv.dv_xname, letoh32(mcr->mcr_opktbuf.pb_addr));
2229 if ((letoh32(mcr->mcr_opktbuf.pb_len) & 3) != 0)
2230 panic("%s: modexp invalid len 0x%x",
2231 sc->sc_dv.dv_xname, letoh32(mcr->mcr_opktbuf.pb_len));
2232 #endif
2233
2234 ctx = (struct ubsec_ctx_modexp *)me->me_q.q_ctx.dma_vaddr;
2235 bzero(ctx, sizeof(*ctx));
2236 ubsec_kshift_r(shiftbits,
2237 krp->krp_param[UBS_MODEXP_PAR_N].crp_p, nbits,
2238 ctx->me_N, normbits);
2239 ctx->me_len = htole16((normbits / 8) + (4 * sizeof(u_int16_t)));
2240 ctx->me_op = htole16(UBS_CTXOP_MODEXP);
2241 ctx->me_E_len = htole16(nbits);
2242 ctx->me_N_len = htole16(nbits);
2243
2244 #ifdef UBSEC_DEBUG
2245 if (ubsec_debug) {
2246 ubsec_dump_mcr(mcr);
2247 ubsec_dump_ctx2((struct ubsec_ctx_keyop *)ctx);
2248 }
2249 #endif
2250
2251 /*
2252 * ubsec_feed2 will sync mcr and ctx, we just need to sync
2253 * everything else.
2254 */
2255 bus_dmamap_sync(sc->sc_dmat, me->me_M.dma_map,
2256 0, me->me_M.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
2257 bus_dmamap_sync(sc->sc_dmat, me->me_E.dma_map,
2258 0, me->me_E.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
2259 bus_dmamap_sync(sc->sc_dmat, me->me_C.dma_map,
2260 0, me->me_C.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD);
2261 bus_dmamap_sync(sc->sc_dmat, me->me_epb.dma_map,
2262 0, me->me_epb.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
2263
2264 /* Enqueue and we're done... */
2265 s = splnet();
2266 SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &me->me_q, q_next);
2267 ubsec_feed2(sc);
2268 ubsecstats.hst_modexp++;
2269 splx(s);
2270
2271 return (0);
2272
2273 errout:
2274 if (me != NULL) {
2275 if (me->me_q.q_mcr.dma_map != NULL)
2276 ubsec_dma_free(sc, &me->me_q.q_mcr);
2277 if (me->me_q.q_ctx.dma_map != NULL) {
2278 bzero(me->me_q.q_ctx.dma_vaddr, me->me_q.q_ctx.dma_size);
2279 ubsec_dma_free(sc, &me->me_q.q_ctx);
2280 }
2281 if (me->me_M.dma_map != NULL) {
2282 bzero(me->me_M.dma_vaddr, me->me_M.dma_size);
2283 ubsec_dma_free(sc, &me->me_M);
2284 }
2285 if (me->me_E.dma_map != NULL) {
2286 bzero(me->me_E.dma_vaddr, me->me_E.dma_size);
2287 ubsec_dma_free(sc, &me->me_E);
2288 }
2289 if (me->me_C.dma_map != NULL) {
2290 bzero(me->me_C.dma_vaddr, me->me_C.dma_size);
2291 ubsec_dma_free(sc, &me->me_C);
2292 }
2293 if (me->me_epb.dma_map != NULL)
2294 ubsec_dma_free(sc, &me->me_epb);
2295 free(me, M_DEVBUF);
2296 }
2297 krp->krp_status = err;
2298 crypto_kdone(krp);
2299 return (0);
2300 }
2301
2302 /*
2303 * Start computation of cr[C] = (cr[M] ^ cr[E]) mod cr[N] (hw normalization)
2304 */
2305 static int
2306 ubsec_kprocess_modexp_hw(struct ubsec_softc *sc, struct cryptkop *krp,
2307 int hint)
2308 {
2309 struct ubsec_q2_modexp *me;
2310 struct ubsec_mcr *mcr;
2311 struct ubsec_ctx_modexp *ctx;
2312 struct ubsec_pktbuf *epb;
2313 int s, err = 0;
2314 u_int nbits, normbits, mbits, shiftbits, ebits;
2315
2316 me = (struct ubsec_q2_modexp *)malloc(sizeof *me, M_DEVBUF, M_NOWAIT);
2317 if (me == NULL) {
2318 err = ENOMEM;
2319 goto errout;
2320 }
2321 bzero(me, sizeof *me);
2322 me->me_krp = krp;
2323 me->me_q.q_type = UBS_CTXOP_MODEXP;
2324
2325 nbits = ubsec_ksigbits(&krp->krp_param[UBS_MODEXP_PAR_N]);
2326 if (nbits <= 512)
2327 normbits = 512;
2328 else if (nbits <= 768)
2329 normbits = 768;
2330 else if (nbits <= 1024)
2331 normbits = 1024;
2332 else if (sc->sc_flags & UBS_FLAGS_BIGKEY && nbits <= 1536)
2333 normbits = 1536;
2334 else if (sc->sc_flags & UBS_FLAGS_BIGKEY && nbits <= 2048)
2335 normbits = 2048;
2336 else {
2337 err = E2BIG;
2338 goto errout;
2339 }
2340
2341 shiftbits = normbits - nbits;
2342
2343 /* XXX ??? */
2344 me->me_modbits = nbits;
2345 me->me_shiftbits = shiftbits;
2346 me->me_normbits = normbits;
2347
2348 /* Sanity check: result bits must be >= true modulus bits. */
2349 if (krp->krp_param[krp->krp_iparams].crp_nbits < nbits) {
2350 err = ERANGE;
2351 goto errout;
2352 }
2353
2354 if (ubsec_dma_malloc(sc, sizeof(struct ubsec_mcr),
2355 &me->me_q.q_mcr, 0)) {
2356 err = ENOMEM;
2357 goto errout;
2358 }
2359 mcr = (struct ubsec_mcr *)me->me_q.q_mcr.dma_vaddr;
2360
2361 if (ubsec_dma_malloc(sc, sizeof(struct ubsec_ctx_modexp),
2362 &me->me_q.q_ctx, 0)) {
2363 err = ENOMEM;
2364 goto errout;
2365 }
2366
2367 mbits = ubsec_ksigbits(&krp->krp_param[UBS_MODEXP_PAR_M]);
2368 if (mbits > nbits) {
2369 err = E2BIG;
2370 goto errout;
2371 }
2372 if (ubsec_dma_malloc(sc, normbits / 8, &me->me_M, 0)) {
2373 err = ENOMEM;
2374 goto errout;
2375 }
2376 bzero(me->me_M.dma_vaddr, normbits / 8);
2377 bcopy(krp->krp_param[UBS_MODEXP_PAR_M].crp_p,
2378 me->me_M.dma_vaddr, (mbits + 7) / 8);
2379
2380 if (ubsec_dma_malloc(sc, normbits / 8, &me->me_C, 0)) {
2381 err = ENOMEM;
2382 goto errout;
2383 }
2384 bzero(me->me_C.dma_vaddr, me->me_C.dma_size);
2385
2386 ebits = ubsec_ksigbits(&krp->krp_param[UBS_MODEXP_PAR_E]);
2387 if (ebits > nbits) {
2388 err = E2BIG;
2389 goto errout;
2390 }
2391 if (ubsec_dma_malloc(sc, normbits / 8, &me->me_E, 0)) {
2392 err = ENOMEM;
2393 goto errout;
2394 }
2395 bzero(me->me_E.dma_vaddr, normbits / 8);
2396 bcopy(krp->krp_param[UBS_MODEXP_PAR_E].crp_p,
2397 me->me_E.dma_vaddr, (ebits + 7) / 8);
2398
2399 if (ubsec_dma_malloc(sc, sizeof(struct ubsec_pktbuf),
2400 &me->me_epb, 0)) {
2401 err = ENOMEM;
2402 goto errout;
2403 }
2404 epb = (struct ubsec_pktbuf *)me->me_epb.dma_vaddr;
2405 epb->pb_addr = htole32(me->me_E.dma_paddr);
2406 epb->pb_next = 0;
2407 epb->pb_len = htole32((ebits + 7) / 8);
2408
2409 #ifdef UBSEC_DEBUG
2410 if (ubsec_debug) {
2411 printf("Epb ");
2412 ubsec_dump_pb(epb);
2413 }
2414 #endif
2415
2416 mcr->mcr_pkts = htole16(1);
2417 mcr->mcr_flags = 0;
2418 mcr->mcr_cmdctxp = htole32(me->me_q.q_ctx.dma_paddr);
2419 mcr->mcr_reserved = 0;
2420 mcr->mcr_pktlen = 0;
2421
2422 mcr->mcr_ipktbuf.pb_addr = htole32(me->me_M.dma_paddr);
2423 mcr->mcr_ipktbuf.pb_len = htole32(normbits / 8);
2424 mcr->mcr_ipktbuf.pb_next = htole32(me->me_epb.dma_paddr);
2425
2426 mcr->mcr_opktbuf.pb_addr = htole32(me->me_C.dma_paddr);
2427 mcr->mcr_opktbuf.pb_next = 0;
2428 mcr->mcr_opktbuf.pb_len = htole32(normbits / 8);
2429
2430 #ifdef DIAGNOSTIC
2431 /* Misaligned output buffer will hang the chip. */
2432 if ((letoh32(mcr->mcr_opktbuf.pb_addr) & 3) != 0)
2433 panic("%s: modexp invalid addr 0x%x",
2434 sc->sc_dv.dv_xname, letoh32(mcr->mcr_opktbuf.pb_addr));
2435 if ((letoh32(mcr->mcr_opktbuf.pb_len) & 3) != 0)
2436 panic("%s: modexp invalid len 0x%x",
2437 sc->sc_dv.dv_xname, letoh32(mcr->mcr_opktbuf.pb_len));
2438 #endif
2439
2440 ctx = (struct ubsec_ctx_modexp *)me->me_q.q_ctx.dma_vaddr;
2441 bzero(ctx, sizeof(*ctx));
2442 bcopy(krp->krp_param[UBS_MODEXP_PAR_N].crp_p, ctx->me_N,
2443 (nbits + 7) / 8);
2444 ctx->me_len = htole16((normbits / 8) + (4 * sizeof(u_int16_t)));
2445 ctx->me_op = htole16(UBS_CTXOP_MODEXP);
2446 ctx->me_E_len = htole16(ebits);
2447 ctx->me_N_len = htole16(nbits);
2448
2449 #ifdef UBSEC_DEBUG
2450 if (ubsec_debug) {
2451 ubsec_dump_mcr(mcr);
2452 ubsec_dump_ctx2((struct ubsec_ctx_keyop *)ctx);
2453 }
2454 #endif
2455
2456 /*
2457 * ubsec_feed2 will sync mcr and ctx, we just need to sync
2458 * everything else.
2459 */
2460 bus_dmamap_sync(sc->sc_dmat, me->me_M.dma_map,
2461 0, me->me_M.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
2462 bus_dmamap_sync(sc->sc_dmat, me->me_E.dma_map,
2463 0, me->me_E.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
2464 bus_dmamap_sync(sc->sc_dmat, me->me_C.dma_map,
2465 0, me->me_C.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD);
2466 bus_dmamap_sync(sc->sc_dmat, me->me_epb.dma_map,
2467 0, me->me_epb.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
2468
2469 /* Enqueue and we're done... */
2470 s = splnet();
2471 SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &me->me_q, q_next);
2472 ubsec_feed2(sc);
2473 splx(s);
2474
2475 return (0);
2476
2477 errout:
2478 if (me != NULL) {
2479 if (me->me_q.q_mcr.dma_map != NULL)
2480 ubsec_dma_free(sc, &me->me_q.q_mcr);
2481 if (me->me_q.q_ctx.dma_map != NULL) {
2482 bzero(me->me_q.q_ctx.dma_vaddr, me->me_q.q_ctx.dma_size);
2483 ubsec_dma_free(sc, &me->me_q.q_ctx);
2484 }
2485 if (me->me_M.dma_map != NULL) {
2486 bzero(me->me_M.dma_vaddr, me->me_M.dma_size);
2487 ubsec_dma_free(sc, &me->me_M);
2488 }
2489 if (me->me_E.dma_map != NULL) {
2490 bzero(me->me_E.dma_vaddr, me->me_E.dma_size);
2491 ubsec_dma_free(sc, &me->me_E);
2492 }
2493 if (me->me_C.dma_map != NULL) {
2494 bzero(me->me_C.dma_vaddr, me->me_C.dma_size);
2495 ubsec_dma_free(sc, &me->me_C);
2496 }
2497 if (me->me_epb.dma_map != NULL)
2498 ubsec_dma_free(sc, &me->me_epb);
2499 free(me, M_DEVBUF);
2500 }
2501 krp->krp_status = err;
2502 crypto_kdone(krp);
2503 return (0);
2504 }
2505
2506 static int
2507 ubsec_kprocess_rsapriv(struct ubsec_softc *sc, struct cryptkop *krp,
2508 int hint)
2509 {
2510 struct ubsec_q2_rsapriv *rp = NULL;
2511 struct ubsec_mcr *mcr;
2512 struct ubsec_ctx_rsapriv *ctx;
2513 int s, err = 0;
2514 u_int padlen, msglen;
2515
2516 msglen = ubsec_ksigbits(&krp->krp_param[UBS_RSAPRIV_PAR_P]);
2517 padlen = ubsec_ksigbits(&krp->krp_param[UBS_RSAPRIV_PAR_Q]);
2518 if (msglen > padlen)
2519 padlen = msglen;
2520
2521 if (padlen <= 256)
2522 padlen = 256;
2523 else if (padlen <= 384)
2524 padlen = 384;
2525 else if (padlen <= 512)
2526 padlen = 512;
2527 else if (sc->sc_flags & UBS_FLAGS_BIGKEY && padlen <= 768)
2528 padlen = 768;
2529 else if (sc->sc_flags & UBS_FLAGS_BIGKEY && padlen <= 1024)
2530 padlen = 1024;
2531 else {
2532 err = E2BIG;
2533 goto errout;
2534 }
2535
2536 if (ubsec_ksigbits(&krp->krp_param[UBS_RSAPRIV_PAR_DP]) > padlen) {
2537 err = E2BIG;
2538 goto errout;
2539 }
2540
2541 if (ubsec_ksigbits(&krp->krp_param[UBS_RSAPRIV_PAR_DQ]) > padlen) {
2542 err = E2BIG;
2543 goto errout;
2544 }
2545
2546 if (ubsec_ksigbits(&krp->krp_param[UBS_RSAPRIV_PAR_PINV]) > padlen) {
2547 err = E2BIG;
2548 goto errout;
2549 }
2550
2551 rp = (struct ubsec_q2_rsapriv *)malloc(sizeof *rp, M_DEVBUF, M_NOWAIT);
2552 if (rp == NULL)
2553 return (ENOMEM);
2554 bzero(rp, sizeof *rp);
2555 rp->rpr_krp = krp;
2556 rp->rpr_q.q_type = UBS_CTXOP_RSAPRIV;
2557
2558 if (ubsec_dma_malloc(sc, sizeof(struct ubsec_mcr),
2559 &rp->rpr_q.q_mcr, 0)) {
2560 err = ENOMEM;
2561 goto errout;
2562 }
2563 mcr = (struct ubsec_mcr *)rp->rpr_q.q_mcr.dma_vaddr;
2564
2565 if (ubsec_dma_malloc(sc, sizeof(struct ubsec_ctx_rsapriv),
2566 &rp->rpr_q.q_ctx, 0)) {
2567 err = ENOMEM;
2568 goto errout;
2569 }
2570 ctx = (struct ubsec_ctx_rsapriv *)rp->rpr_q.q_ctx.dma_vaddr;
2571 bzero(ctx, sizeof *ctx);
2572
2573 /* Copy in p */
2574 bcopy(krp->krp_param[UBS_RSAPRIV_PAR_P].crp_p,
2575 &ctx->rpr_buf[0 * (padlen / 8)],
2576 (krp->krp_param[UBS_RSAPRIV_PAR_P].crp_nbits + 7) / 8);
2577
2578 /* Copy in q */
2579 bcopy(krp->krp_param[UBS_RSAPRIV_PAR_Q].crp_p,
2580 &ctx->rpr_buf[1 * (padlen / 8)],
2581 (krp->krp_param[UBS_RSAPRIV_PAR_Q].crp_nbits + 7) / 8);
2582
2583 /* Copy in dp */
2584 bcopy(krp->krp_param[UBS_RSAPRIV_PAR_DP].crp_p,
2585 &ctx->rpr_buf[2 * (padlen / 8)],
2586 (krp->krp_param[UBS_RSAPRIV_PAR_DP].crp_nbits + 7) / 8);
2587
2588 /* Copy in dq */
2589 bcopy(krp->krp_param[UBS_RSAPRIV_PAR_DQ].crp_p,
2590 &ctx->rpr_buf[3 * (padlen / 8)],
2591 (krp->krp_param[UBS_RSAPRIV_PAR_DQ].crp_nbits + 7) / 8);
2592
2593 /* Copy in pinv */
2594 bcopy(krp->krp_param[UBS_RSAPRIV_PAR_PINV].crp_p,
2595 &ctx->rpr_buf[4 * (padlen / 8)],
2596 (krp->krp_param[UBS_RSAPRIV_PAR_PINV].crp_nbits + 7) / 8);
2597
2598 msglen = padlen * 2;
2599
2600 /* Copy in input message (aligned buffer/length). */
2601 if (ubsec_ksigbits(&krp->krp_param[UBS_RSAPRIV_PAR_MSGIN]) > msglen) {
2602 /* Is this likely? */
2603 err = E2BIG;
2604 goto errout;
2605 }
2606 if (ubsec_dma_malloc(sc, (msglen + 7) / 8, &rp->rpr_msgin, 0)) {
2607 err = ENOMEM;
2608 goto errout;
2609 }
2610 bzero(rp->rpr_msgin.dma_vaddr, (msglen + 7) / 8);
2611 bcopy(krp->krp_param[UBS_RSAPRIV_PAR_MSGIN].crp_p,
2612 rp->rpr_msgin.dma_vaddr,
2613 (krp->krp_param[UBS_RSAPRIV_PAR_MSGIN].crp_nbits + 7) / 8);
2614
2615 /* Prepare space for output message (aligned buffer/length). */
2616 if (ubsec_ksigbits(&krp->krp_param[UBS_RSAPRIV_PAR_MSGOUT]) < msglen) {
2617 /* Is this likely? */
2618 err = E2BIG;
2619 goto errout;
2620 }
2621 if (ubsec_dma_malloc(sc, (msglen + 7) / 8, &rp->rpr_msgout, 0)) {
2622 err = ENOMEM;
2623 goto errout;
2624 }
2625 bzero(rp->rpr_msgout.dma_vaddr, (msglen + 7) / 8);
2626
2627 mcr->mcr_pkts = htole16(1);
2628 mcr->mcr_flags = 0;
2629 mcr->mcr_cmdctxp = htole32(rp->rpr_q.q_ctx.dma_paddr);
2630 mcr->mcr_ipktbuf.pb_addr = htole32(rp->rpr_msgin.dma_paddr);
2631 mcr->mcr_ipktbuf.pb_next = 0;
2632 mcr->mcr_ipktbuf.pb_len = htole32(rp->rpr_msgin.dma_size);
2633 mcr->mcr_reserved = 0;
2634 mcr->mcr_pktlen = htole16(msglen);
2635 mcr->mcr_opktbuf.pb_addr = htole32(rp->rpr_msgout.dma_paddr);
2636 mcr->mcr_opktbuf.pb_next = 0;
2637 mcr->mcr_opktbuf.pb_len = htole32(rp->rpr_msgout.dma_size);
2638
2639 #ifdef DIAGNOSTIC
2640 if (rp->rpr_msgin.dma_paddr & 3 || rp->rpr_msgin.dma_size & 3) {
2641 panic("%s: rsapriv: invalid msgin 0x%lx(0x%lx)",
2642 sc->sc_dv.dv_xname, (u_long) rp->rpr_msgin.dma_paddr,
2643 (u_long) rp->rpr_msgin.dma_size);
2644 }
2645 if (rp->rpr_msgout.dma_paddr & 3 || rp->rpr_msgout.dma_size & 3) {
2646 panic("%s: rsapriv: invalid msgout 0x%lx(0x%lx)",
2647 sc->sc_dv.dv_xname, (u_long) rp->rpr_msgout.dma_paddr,
2648 (u_long) rp->rpr_msgout.dma_size);
2649 }
2650 #endif
2651
2652 ctx->rpr_len = (sizeof(u_int16_t) * 4) + (5 * (padlen / 8));
2653 ctx->rpr_op = htole16(UBS_CTXOP_RSAPRIV);
2654 ctx->rpr_q_len = htole16(padlen);
2655 ctx->rpr_p_len = htole16(padlen);
2656
2657 /*
2658 * ubsec_feed2 will sync mcr and ctx, we just need to sync
2659 * everything else.
2660 */
2661 bus_dmamap_sync(sc->sc_dmat, rp->rpr_msgin.dma_map,
2662 0, rp->rpr_msgin.dma_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
2663 bus_dmamap_sync(sc->sc_dmat, rp->rpr_msgout.dma_map,
2664 0, rp->rpr_msgout.dma_map->dm_mapsize, BUS_DMASYNC_PREREAD);
2665
2666 /* Enqueue and we're done... */
2667 s = splnet();
2668 SIMPLEQ_INSERT_TAIL(&sc->sc_queue2, &rp->rpr_q, q_next);
2669 ubsec_feed2(sc);
2670 ubsecstats.hst_modexpcrt++;
2671 splx(s);
2672 return (0);
2673
2674 errout:
2675 if (rp != NULL) {
2676 if (rp->rpr_q.q_mcr.dma_map != NULL)
2677 ubsec_dma_free(sc, &rp->rpr_q.q_mcr);
2678 if (rp->rpr_msgin.dma_map != NULL) {
2679 bzero(rp->rpr_msgin.dma_vaddr, rp->rpr_msgin.dma_size);
2680 ubsec_dma_free(sc, &rp->rpr_msgin);
2681 }
2682 if (rp->rpr_msgout.dma_map != NULL) {
2683 bzero(rp->rpr_msgout.dma_vaddr, rp->rpr_msgout.dma_size);
2684 ubsec_dma_free(sc, &rp->rpr_msgout);
2685 }
2686 free(rp, M_DEVBUF);
2687 }
2688 krp->krp_status = err;
2689 crypto_kdone(krp);
2690 return (0);
2691 }
2692
2693 #ifdef UBSEC_DEBUG
2694 static void
2695 ubsec_dump_pb(volatile struct ubsec_pktbuf *pb)
2696 {
2697 printf("addr 0x%x (0x%x) next 0x%x\n",
2698 pb->pb_addr, pb->pb_len, pb->pb_next);
2699 }
2700
2701 static void
2702 ubsec_dump_ctx2(volatile struct ubsec_ctx_keyop *c)
2703 {
2704 printf("CTX (0x%x):\n", c->ctx_len);
2705 switch (letoh16(c->ctx_op)) {
2706 case UBS_CTXOP_RNGBYPASS:
2707 case UBS_CTXOP_RNGSHA1:
2708 break;
2709 case UBS_CTXOP_MODEXP:
2710 {
2711 struct ubsec_ctx_modexp *cx = (void *)c;
2712 int i, len;
2713
2714 printf(" Elen %u, Nlen %u\n",
2715 letoh16(cx->me_E_len), letoh16(cx->me_N_len));
2716 len = (cx->me_N_len + 7)/8;
2717 for (i = 0; i < len; i++)
2718 printf("%s%02x", (i == 0) ? " N: " : ":", cx->me_N[i]);
2719 printf("\n");
2720 break;
2721 }
2722 default:
2723 printf("unknown context: %x\n", c->ctx_op);
2724 }
2725 printf("END CTX\n");
2726 }
2727
2728 static void
2729 ubsec_dump_mcr(struct ubsec_mcr *mcr)
2730 {
2731 volatile struct ubsec_mcr_add *ma;
2732 int i;
2733
2734 printf("MCR:\n");
2735 printf(" pkts: %u, flags 0x%x\n",
2736 letoh16(mcr->mcr_pkts), letoh16(mcr->mcr_flags));
2737 ma = (volatile struct ubsec_mcr_add *)&mcr->mcr_cmdctxp;
2738 for (i = 0; i < letoh16(mcr->mcr_pkts); i++) {
2739 printf(" %d: ctx 0x%x len 0x%x rsvd 0x%x\n", i,
2740 letoh32(ma->mcr_cmdctxp), letoh16(ma->mcr_pktlen),
2741 letoh16(ma->mcr_reserved));
2742 printf(" %d: ipkt ", i);
2743 ubsec_dump_pb(&ma->mcr_ipktbuf);
2744 printf(" %d: opkt ", i);
2745 ubsec_dump_pb(&ma->mcr_opktbuf);
2746 ma++;
2747 }
2748 printf("END MCR\n");
2749 }
2750 #endif /* UBSEC_DEBUG */
2751
2752 /*
2753 * Return the number of significant bits of a big number.
2754 */
2755 static int
2756 ubsec_ksigbits(struct crparam *cr)
2757 {
2758 u_int plen = (cr->crp_nbits + 7) / 8;
2759 int i, sig = plen * 8;
2760 u_int8_t c, *p = cr->crp_p;
2761
2762 for (i = plen - 1; i >= 0; i--) {
2763 c = p[i];
2764 if (c != 0) {
2765 while ((c & 0x80) == 0) {
2766 sig--;
2767 c <<= 1;
2768 }
2769 break;
2770 }
2771 sig -= 8;
2772 }
2773 return (sig);
2774 }
2775
2776 static void
2777 ubsec_kshift_r(u_int shiftbits, u_int8_t *src, u_int srcbits,
2778 u_int8_t *dst, u_int dstbits)
2779 {
2780 u_int slen, dlen;
2781 int i, si, di, n;
2782
2783 slen = (srcbits + 7) / 8;
2784 dlen = (dstbits + 7) / 8;
2785
2786 for (i = 0; i < slen; i++)
2787 dst[i] = src[i];
2788 for (i = 0; i < dlen - slen; i++)
2789 dst[slen + i] = 0;
2790
2791 n = shiftbits / 8;
2792 if (n != 0) {
2793 si = dlen - n - 1;
2794 di = dlen - 1;
2795 while (si >= 0)
2796 dst[di--] = dst[si--];
2797 while (di >= 0)
2798 dst[di--] = 0;
2799 }
2800
2801 n = shiftbits % 8;
2802 if (n != 0) {
2803 for (i = dlen - 1; i > 0; i--)
2804 dst[i] = (dst[i] << n) |
2805 (dst[i - 1] >> (8 - n));
2806 dst[0] = dst[0] << n;
2807 }
2808 }
2809
2810 static void
2811 ubsec_kshift_l(u_int shiftbits, u_int8_t *src, u_int srcbits,
2812 u_int8_t *dst, u_int dstbits)
2813 {
2814 int slen, dlen, i, n;
2815
2816 slen = (srcbits + 7) / 8;
2817 dlen = (dstbits + 7) / 8;
2818
2819 n = shiftbits / 8;
2820 for (i = 0; i < slen; i++)
2821 dst[i] = src[i + n];
2822 for (i = 0; i < dlen - slen; i++)
2823 dst[slen + i] = 0;
2824
2825 n = shiftbits % 8;
2826 if (n != 0) {
2827 for (i = 0; i < (dlen - 1); i++)
2828 dst[i] = (dst[i] >> n) | (dst[i + 1] << (8 - n));
2829 dst[dlen - 1] = dst[dlen - 1] >> n;
2830 }
2831 }
2832