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