Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / n8 / nsp.c
blob65a7d7c3ed142dc06c58a91c032bdc493d2089d8
1 /*-
2 * Copyright (c) 2008 The NetBSD Foundation, Inc.
3 * All rights reserved.
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Coyote Point Systems, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
30 /*-
31 * Copyright (C) 2001-2003 by NBMK Encryption Technologies.
32 * All rights reserved.
34 * NBMK Encryption Technologies provides no support of any kind for
35 * this software. Questions or concerns about it may be addressed to
36 * the members of the relevant open-source community at
37 * <tech-crypto@netbsd.org>.
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions are
41 * met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above
47 * copyright notice, this list of conditions and the following
48 * disclaimer in the documentation and/or other materials provided
49 * with the distribution.
51 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
52 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
53 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
54 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
55 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
56 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
57 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
61 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
66 * nsp.c - NetOctave NSP2000 NetBSD OpenCrypto Driver
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/proc.h>
73 #include <sys/endian.h>
74 #include <sys/errno.h>
75 #include <sys/malloc.h>
76 #include <sys/kernel.h>
77 #include <sys/mbuf.h>
78 #include <sys/device.h>
79 #include <sys/queue.h>
80 #include <sys/module.h>
81 #include <sys/bus.h>
83 #include <uvm/uvm_extern.h>
85 #include <opencrypto/cryptodev.h>
86 #include <opencrypto/xform.h>
87 #include <sys/rnd.h>
88 #include <sys/md5.h>
89 #include <sys/sha1.h>
91 #include <dev/pci/pcireg.h>
92 #include <dev/pci/pcivar.h>
93 #include <dev/pci/pcidevs.h>
95 #include "n8_driver_main.h"
96 #include "n8_driver_api.h"
97 #include "config.h"
98 #include "nsp.h"
99 #include "irq.h"
100 #include "n8_pub_rng.h"
101 #include "n8_pub_hash.h"
102 #include "n8_pub_symmetric.h"
103 #include "n8_pub_context.h"
104 #include "n8_pub_pk.h"
106 #include "nspvar.h"
108 static int nsp_probe(device_t parent, cfdata_t match, void *aux);
109 static void nsp_attach(device_t parent, device_t self, void *aux);
110 static int nsp_detach(device_t dev, int flags);
113 #ifdef _MODULE
114 CFATTACH_DECL(nsp2000, sizeof(struct nsp_softc), nsp_probe, nsp_attach, nsp_detach, NULL);
116 int nsp2000_lkmentry(struct lkm_table *lkmtp, int cmd, int ver);
117 CFDRIVER_DECL(nsp2000, DV_DULL, NULL);
118 extern struct cfdriver nsp2000_cd;
119 extern struct cfattach nsp2000_ca;
120 static int pciloc[] = { -1, -1 }; /* device, function */
121 static struct cfparent pciparent = {
122 "pci", "pci", DVUNIT_ANY
124 static struct cfdata nsp2000_cfdata[] = {
125 {"nsp2000", "nsp2000", 0, FSTATE_STAR, pciloc, 0, &pciparent},
126 { 0, 0, 0, 0, 0, 0, 0 }
129 static struct cfdriver *nsp2000_cfdrivers[] = {
130 &nsp2000_cd,
131 NULL
133 static struct cfattach *nsp2000_cfattachs[] = {
134 &nsp2000_ca,
135 NULL
137 static const struct cfattachlkminit nsp2000_cfattachinit[] = {
138 { "nsp2000", nsp2000_cfattachs },
139 { NULL, NULL }
142 MOD_DRV("nsp2000", nsp2000_cfdrivers, nsp2000_cfattachinit, nsp2000_cfdata);
145 nsp2000_lkmentry(struct lkm_table *lkmtp, int cmd, int ver)
147 /* LKM_DISPATCH(lkmtp, cmd, NULL, att, det, stat) */
148 LKM_DISPATCH(lkmtp, cmd, NULL, lkm_nofunc, lkm_nofunc, lkm_nofunc);
151 #else /* _MODULE */
152 CFATTACH_DECL(nsp, sizeof(struct nsp_softc), nsp_probe, nsp_attach, nsp_detach, NULL);
153 #endif
155 static int nsp_intr(void *arg);
156 static int n8_process(void *arg, struct cryptop *crp, int hint);
157 static int n8_kprocess(void *arg, struct cryptkop *krp, int hint);
158 static int n8_freesession(void *arg, u_int64_t tid);
159 static int n8_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri);
160 static void n8_callback(void *data, N8_Status_t status);
161 static int n8_do_crypt(struct nsp_softc *sc,
162 struct cryptop *crp,
163 struct cryptodesc *crd,
164 nsp_session_t *session);
165 static int n8_do_hash(struct nsp_softc *sc,
166 struct cryptop *crp,
167 struct cryptodesc *crd,
168 nsp_session_t *session);
169 static int n8_start_crd(struct nsp_softc *sc,
170 struct cryptop *crp,
171 struct cryptodesc *crd,
172 int crd_id,
173 nsp_session_t *session);
175 static nsp_session_t *n8_session_alloc(struct nsp_softc *sc);
176 static void n8_session_free(struct nsp_softc *sc,
177 nsp_session_t *session);
179 /* Supported crypto algorithms */
180 static struct {
181 int id;
182 const char *name;
183 } nsp_algo[] = {
184 { CRYPTO_DES_CBC, "CRYPTO_DES_CBC" },
185 { CRYPTO_3DES_CBC, "CRYPTO_3DES_CBC" },
186 { CRYPTO_MD5, "CRYPTO_MD5" },
187 { CRYPTO_SHA1, "CRYPTO_SHA1" },
188 { CRYPTO_MD5_HMAC, "CRYPTO_MD5_HMAC" },
189 { CRYPTO_SHA1_HMAC, "CRYPTO_SHA1_HMAC" },
190 { 0, NULL },
193 /* Supported key operations */
194 static struct {
195 int id;
196 const char *name;
197 } nsp_key[] = {
198 { CRK_MOD_EXP, "CRK_MOD_EXP" },
199 { CRK_DSA_SIGN, "CRK_DSA_SIGN" },
200 { CRK_DSA_VERIFY, "CRK_DSA_VERIFY" },
201 { CRK_DH_COMPUTE_KEY, "CRK_DH_COMPUTE_KEY" },
202 { CRK_MOD_ADD, "CRK_MOD_ADD" },
203 { CRK_MOD_ADDINV, "CRK_MOD_ADDINV" },
204 { CRK_MOD_SUB, "CRK_MOD_SUB" },
205 { CRK_MOD_MULT, "CRK_MOD_MULT" },
206 { CRK_MOD_MULTINV, "CRK_MOD_MULTINV" },
207 { CRK_MOD, "CRK_MOD" },
208 { 0, NULL },
211 /* parameter handling definitions for each supported crypto key operation */
212 static struct {
213 const char *name;
214 int iparmcount; /* number of input parameters */
215 int oparmcount; /* number of output parameters */
216 uint32_t bignums; /* bit mask of bignum parameters needing conversion */
217 } crk_def[CRK_ALGORITHM_MAX+1] = {
218 { "CRK_MOD_EXP", 3, 1, NSP_MOD_EXP_BIGNUMS },
219 { NULL, 6, 1, NSP_MOD_EXP_CRT_BIGNUMS }, /* N/A */
220 //{ "CRK_MOD_EXP_CRT", 6, 1, NSP_MOD_EXP_CRT_BIGNUMS },
221 { "CRK_DSA_SIGN", 5, 2, NSP_DSA_SIGN_BIGNUMS },
222 { "CRK_DSA_VERIFY", 7, 0, NSP_DSA_VERIFY_BIGNUMS },
223 { "CRK_DH_COMPUTE_KEY", 3, 1, NSP_DH_COMPUTE_KEY_BIGNUMS },
224 { "CRK_MOD_ADD", 3, 1, NSP_MOD_ADD_BIGNUMS },
225 { "CRK_MOD_ADDINV", 2, 1, NSP_MOD_ADDINV_BIGNUMS },
226 { "CRK_MOD_SUB", 3, 1, NSP_MOD_SUB_BIGNUMS },
227 { "CRK_MOD_MULT", 3, 1, NSP_MOD_MULT_BIGNUMS },
228 { "CRK_MOD_MULTINV", 2, 1, NSP_MOD_MULTINV_BIGNUMS },
229 { "CRK_MOD", 2, 1, NSP_MODULUS_BIGNUMS },
233 unsigned char N8_Debug_g = 0;
234 int NSPcount_g;
235 NspInstance_t NSPDeviceTable_g[NSP_MAX_INSTANCES];
237 static const struct nsp_product {
238 pci_vendor_id_t nsp_vendor;
239 pci_product_id_t nsp_product;
240 int nsp_flags;
241 const char *nsp_name;
242 } nsp_products[] = {
243 { PCI_VENDOR_NETOCTAVE, PCI_PRODUCT_NETOCTAVE_NSP2000,
245 "NetOctave NSP2000"
248 { 0, 0,
250 NULL
254 static const struct nsp_product *
255 nsp_lookup(const struct pci_attach_args *pa)
257 const struct nsp_product *nspp;
259 for (nspp = nsp_products; nspp->nsp_name != NULL; nspp++) {
260 if (PCI_VENDOR(pa->pa_id) == nspp->nsp_vendor &&
261 PCI_PRODUCT(pa->pa_id) == nspp->nsp_product)
262 return nspp;
264 return NULL;
267 static int
268 nsp_probe(device_t parent, cfdata_t match, void *aux)
270 static int once=0;
271 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
273 if (!once++) {
274 /* Here we set the NSPcount_g to be ONE so our NSP2k queue allocation */
275 /* multiplier will not be zero. The linux and FreeBSD drivers differ */
276 /* in WHEN they increment the NSPcount_g variable. The count is taken */
277 /* at module load time under linux, but during the attach() in FBSD. */
278 /* FBSD doesn't offer an interface to walk the existing PCI device */
279 /* tree to count each N8 device. Code can be added to the kernel in */
280 /* /usr/src/sys/pci/pci.c to perform this function and allow the NSP */
281 /* queue sizes to be dynamically allocated based on the number of */
282 /* installed chips or boards. See Docs for details */
283 #if 0
284 NSPcount_g = 1;
285 if (nsp_driverInit(N8_EA_POOL_SIZE, N8_PK_POOL_SIZE))
287 NSPcount_g = 0;
288 return ENOMEM;
290 #endif
291 NSPcount_g = 0; /* reset to zero since we increment in attach */
293 if (nsp_lookup(pa) != NULL)
294 return 1;
296 return 0;
300 /* initialize the session array into a free list of
301 * available sessions.
303 static void
304 n8_sessionInit(struct nsp_softc *sc)
306 int ind;
308 for (ind=0; ind<NSP_MAX_SESSION-1; ind++) {
309 sc->session[ind].next = &sc->session[ind+1];
311 sc->session[NSP_MAX_SESSION-1].next = NULL;
313 sc->freesession = &sc->session[0];
316 static void
317 nsp_attach(device_t parent, device_t self, void *aux)
319 struct nsp_softc *sc;
320 struct pci_attach_args *pa = aux;
321 const struct nsp_product *nspp;
322 pci_intr_handle_t ih;
323 const char *intrstr = NULL;
324 NspInstance_t *nip = &NSPDeviceTable_g[0]; /* can only attach once */
325 u_int32_t cmd;
326 int res;
327 int ind;
329 sc = device_private(self);
331 mutex_init(&sc->sc_intrlock, MUTEX_DEFAULT, IPL_NET);
333 sc->pa_pc = pa->pa_pc;
334 sc->pa_tag = pa->pa_tag;
335 sc->dma_tag = pa->pa_dmat;
337 DBG(("sc->dma_tag = 0x%x\n", (uint32_t)sc->dma_tag));
338 nspp = nsp_lookup(pa);
339 if (nspp == NULL) {
340 DBG(("\n"));
341 panic("nsp_attach: impossible");
344 sc->mem_mapped = 0;
345 nip->dev = self;
347 aprint_naive(": Crypto processor\n");
348 aprint_normal(": %s, rev. %d\n", nspp->nsp_name,
349 PCI_REVISION(pa->pa_class));
351 printf("NetOctave Encryption Processor - %s\n", device_xname(&sc->device));
353 n8_sessionInit(sc);
355 NSPcount_g = 1;
356 if (n8_driverInit(N8_EA_POOL_SIZE, N8_PK_POOL_SIZE)) {
357 DBG(("%s: Failed driver init\n", device_xname(&sc->device)));
358 NSPcount_g = 0;
359 return;
361 DBG(("n8_driverInit complete\n"));
362 /* reset to zero for rest of attach */
363 NSPcount_g = 0;
366 * Map control/status registers.
369 /* reset the TRDY timeout and RETRY timeout to reasonable values */
370 /* note: INSILICON_PCI_RETRY_TIMEOUT is the second byte */
371 cmd = pci_conf_read(sc->pa_pc, sc->pa_tag, INSILICON_PCI_TRDY_TIMEOUT);
372 cmd = (cmd & 0x0000FFFF); /* Zero TRDY_TIMEOUT and RETRY_TIMEOUT */
373 pci_conf_write(sc->pa_pc, sc->pa_tag, INSILICON_PCI_TRDY_TIMEOUT, cmd);
375 cmd = pci_conf_read(sc->pa_pc, sc->pa_tag, PCI_COMMAND_STATUS_REG);
376 cmd |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
377 pci_conf_write(sc->pa_pc, sc->pa_tag, PCI_COMMAND_STATUS_REG, cmd);
379 cmd = pci_conf_read(sc->pa_pc, sc->pa_tag, PCI_COMMAND_STATUS_REG);
381 if (!(cmd & PCI_COMMAND_MEM_ENABLE)) {
382 DBG(("nsp%d: failed to enable memory mapping!\n", sc->unit));
383 goto fail;
386 if (pci_mapreg_map(pa, NSP_BAR0, PCI_MAPREG_MEM_TYPE_64BIT, 0,
387 &sc->mem_tag, &sc->mem_handle, NULL, &sc->mem_size)) {
388 aprint_error_dev(&sc->device, "can't map mem space %d\n", 0);
389 return;
392 sc->mem_mapped = 1;
394 DBG(("nsp pci register space mapped\n"));
397 * Allocate interrupt.
399 if (pci_intr_map(pa, &ih)) {
400 aprint_error("nsp%d: couldn't map interrupt\n",
401 sc->unit);
402 goto fail;
404 intrstr = pci_intr_string(sc->pa_pc, ih);
405 sc->int_handle = pci_intr_establish(sc->pa_pc, ih, IPL_NET,
406 nsp_intr, sc);
407 if (sc->int_handle == NULL) {
408 aprint_error("nsp%d: couldn't establish interrupt", sc->unit);
409 if (intrstr != NULL)
410 aprint_normal(" at %s", intrstr);
411 aprint_normal("\n");
412 goto fail;
414 aprint_normal("nsp%d: interrupting at %s\n", sc->unit, intrstr);
416 /* setup card */
418 memset(nip, 0, sizeof (*nip));
420 sc->nip = nip;
421 nip->dev = sc;
422 nip->chip = NSPcount_g;
424 nip->PCIinfo.vendor_id = PCI_VENDOR(pa->pa_id);
425 nip->PCIinfo.device_id = PCI_PRODUCT(pa->pa_id);
426 nip->PCIinfo.revision_id =
427 PCI_REVISION(pci_conf_read(sc->pa_pc, sc->pa_tag, PCI_CLASS_REG));
429 #ifdef N8_ZERO_CACHE_LINE
430 /* ENSURE Cache line size is zero in PCI CONFIG SPACE */
431 /* This forces the chip to use PCI MEM_READ and not */
432 /* MEM_READ_MULTIPLE - this may impact performance */
434 pci_write_config(dev, PCIR_CACHELNSZ, 0x00, 1);
435 #endif
437 nip->PCIinfo.base_address[0] = sc->mem_handle;
438 nip->PCIinfo.base_range [0] = sc->mem_handle + DEF_ASIC_PCI_MEMORY_SIZE_2;
440 nip->NSPregs_base = nip->PCIinfo.base_address[0];
441 nip->NSPregs_p = (unsigned long*)nip->NSPregs_base;
443 DBG(("nsp%d: calling n8_chipInit\n", sc->unit));
444 if (!n8_chipInit(nip, nip->chip, N8_DEF_CMD_QUE_EXP, DEBUG_GENERAL)) {
445 DBG(("NSP2000: Failed to allocate resources for device #%d.\n",
446 nip->chip));
447 goto fail_int;
450 DBG(("NSP2000: Configured NSP2000 ASIC #%d @%08lx (%ld MB CtxMem).\n",
451 nip->chip, nip->NSPregs_base,
452 (nip->contextMemSize / 1024) / 1024));
455 sc->cid = crypto_get_driverid(0);
456 if (sc->cid < 0) {
457 DBG(("nsp%d: couldn't get crypto driver id\n",
458 sc->unit));
459 n8_driverRemove();
460 goto fail_int;
463 /* Increment our device count. */
464 NSPcount_g++;
466 /* Configure/enable interrupts. */
467 n8_enableInterrupts(N8_AMBA_TIMER_PRESET);
469 /* Register crypto support with opencrypto */
470 DBG(("nsp_attach: registering with opencrypto\n"));
471 for (ind=0; nsp_algo[ind].id != 0; ind++) {
472 res = crypto_register(sc->cid, nsp_algo[ind].id, 0, 0,
473 n8_newsession, n8_freesession, n8_process, sc);
474 if (res < 0) {
475 DBG(("nsp_attach: failed to register %s, err=%d\n",
476 nsp_algo[ind].name, res));
477 } else {
478 DBG(("nsp_attach: registered %s\n",
479 nsp_algo[ind].name));
483 /* XXX use crk_def instead, or combine nsp_key and crk_def */
484 for (ind=0; nsp_key[ind].name != NULL; ind++) {
485 res = crypto_kregister(sc->cid, nsp_key[ind].id, 0,
486 n8_kprocess, sc);
487 if (res < 0) {
488 DBG(("nsp_attach: failed to kregister %s, err=%d\n",
489 nsp_key[ind].name, res));
490 } else {
491 DBG(("nsp_attach: kregistered %s\n",
492 nsp_key[ind].name));
496 DBG(("nsp_attach: ready\n"));
497 return;
498 fail_int:
499 pci_intr_disestablish(sc->pa_pc, sc->int_handle);
500 sc->int_handle = NULL;
501 fail:
502 bus_space_unmap(sc->mem_tag, sc->mem_handle, sc->mem_size);
503 sc->mem_mapped = 0;
504 return;
509 nsp_detach(device_t dev, int flags)
511 struct nsp_softc *sc;
512 int res;
513 int ind;
515 sc = device_private(dev);
516 mutex_enter(&sc->sc_intrlock);
517 DBG(("nsp.%d detach\n", sc->unit));
519 DBG(("nsp_detach: unregistering with opencrypto\n"));
520 for (ind=0; nsp_algo[ind].id != 0; ind++) {
521 res = crypto_unregister(sc->cid, nsp_algo[ind].id);
522 if (res < 0) {
523 DBG(("nsp_attach: failed to unregister %s, err=%d\n",
524 nsp_algo[ind].name, res));
525 } else {
526 DBG(("nsp_attach: unregistered %s\n",
527 nsp_algo[ind].name));
531 n8_disableInterrupts();
532 if (sc->int_handle != NULL) {
533 pci_intr_disestablish(sc->pa_pc, sc->int_handle);
534 DBG(("nsp.%d intr disestablished\n", sc->unit));
535 } else {
536 DBG(("nsp.%d no intr registered\n", sc->unit));
539 DBG(("nsp.%d: calling n8_driverRemove()\n", sc->unit));
540 n8_driverRemove();
542 if (sc->mem_mapped) {
543 DBG(("nsp.%d unmapping PCI memory\n", sc->unit));
544 bus_space_unmap(sc->mem_tag, sc->mem_handle, sc->mem_size);
545 } else {
546 DBG(("nsp.%d no memory mapped\n", sc->unit));
548 mutex_exit(&sc->sc_intrlock);
549 return 0;
552 static int
553 nsp_intr(void *arg)
555 struct nsp_softc *sc = arg;
556 NspInstance_t *nip = sc->nip;
558 mutex_enter(&sc->sc_intrlock);
559 DBG(("nsp_intr: handler fired\n"));
560 n8_MainInterruptHandler(nip);
561 mutex_exit(&sc->sc_intrlock);
563 return 1;
566 N8_Status_t N8_GetRandomBytes(int num_bytes, char *buf_p, N8_Event_t *event_p)
568 RN_Request_t rn_request; /* RNG request structure */
569 N8_Status_t ret;
570 DBG(("N8_GetRandomBytes\n"));
572 /* check the number of bytes requested
573 it can't be less or equal to 0 or more than N8_RNG_MAX_REQUEST. */
574 if ((num_bytes <= 0) || (num_bytes > N8_RNG_MAX_REQUEST)) {
575 DBG(("Number of bytes requested is out of range : %d\n", num_bytes));
576 DBG(("N8_GetRandomBytes - return Error\n"));
577 return N8_INVALID_INPUT_SIZE;
580 rn_request.userRequest = N8_FALSE;
581 rn_request.userBuffer_p = buf_p;
582 rn_request.numBytesRequested = num_bytes;
584 /* we have a valid request. queue it up. */
585 ret = Queue_RN_request(&rn_request);
586 if (ret != N8_STATUS_OK) {
587 DBG(("Queue_RN_request failed\n"));
588 return ret;
591 if (event_p != NULL) {
592 event_p->unit = N8_RNG;
593 event_p->state = NULL;
594 event_p->status = N8_QUEUE_REQUEST_FINISHED;
597 return ret;
599 } /* N8_GetRandomBytes */
602 N8_Status_t
603 n8_gettime( n8_timeval_t *n8_timeResults_p )
606 struct timespec ts;
607 N8_Status_t returnResults = N8_STATUS_OK;
609 getnanotime(&ts);
611 /* Timespec has a seconds portion and a nano seconds portion. */
612 /* Thus we need to divide to convert nanoseconds to microseconds. */
613 n8_timeResults_p->tv_sec = ts.tv_sec;
614 n8_timeResults_p->tv_usec = ts.tv_nsec / 1000;
616 return returnResults;
618 } /* n8_gettime */
620 /* map an N8 Status error to a semi-appropriate errno */
621 static int
622 n8_map_errno(N8_Status_t error)
624 switch (error) {
625 case N8_STATUS_OK:
626 return 0;
627 case N8_INVALID_INPUT_SIZE:
628 case N8_INVALID_OUTPUT_SIZE:
629 case N8_INVALID_KEY_SIZE:
630 return ERANGE;
631 case N8_INVALID_ENUM:
632 return EDOM;
633 case N8_INVALID_PARAMETER:
634 case N8_INVALID_OBJECT:
635 /* coding bug */
636 break;
637 case N8_INVALID_PROTOCOL:
638 return EPROTOTYPE;
639 case N8_INVALID_KEY:
640 case N8_INVALID_CIPHER:
641 case N8_INVALID_HASH:
642 case N8_INVALID_VALUE:
643 return EINVAL;
644 case N8_WEAK_KEY:
645 break;
646 case N8_UNIMPLEMENTED_FUNCTION:
647 return ENODEV;
648 case N8_INCONSISTENT:
649 return EINVAL;
650 case N8_NO_MORE_RESOURCE:
651 return EBUSY;
653 case N8_MALLOC_FAILED:
654 return ENOMEM;
656 case N8_INVALID_VERSION:
657 case N8_NOT_INITIALIZED:
658 case N8_UNALLOCATED_CONTEXT:
659 case N8_HARDWARE_ERROR:
660 case N8_UNEXPECTED_ERROR:
661 return EIO;
662 default:
663 break;
666 return EINVAL;
670 /* allocate a session for a crypto op */
671 static nsp_session_t *
672 n8_session_alloc(struct nsp_softc *sc)
674 nsp_session_t *session;
676 mutex_enter(&sc->sc_intrlock);
677 session = sc->freesession;
678 if (sc->freesession == NULL) {
679 printf("n8_newsession(): out of sessions (max = %d)\n",
680 NSP_MAX_SESSION);
681 mutex_exit(&sc->sc_intrlock);
682 return NULL;
684 sc->freesession = session->next;
685 session->next = NULL;
686 session->magic = 0xDEADFEED;
687 mutex_exit(&sc->sc_intrlock);
689 session->contextAllocated = 0;
690 session->active = 0;
692 return session;
695 /* free a crypto op session */
696 static void
697 n8_session_free(struct nsp_softc *sc, nsp_session_t *session)
699 if (session->contextAllocated) {
700 N8_FreeContext(session->contextHandle, NULL);
701 session->contextAllocated = 0;
704 mutex_enter(&sc->sc_intrlock);
705 if (session == NULL) {
706 DBG(("n8_session_free: attempt to free NULL\n"));
707 mutex_exit(&sc->sc_intrlock);
708 return;
711 session->next = sc->freesession;
712 sc->freesession = session;
713 session->magic = 0xFEED;
714 mutex_exit(&sc->sc_intrlock);
718 /**********************************************************************
719 * FUNCTION: n8_newsession(*arg, *sidp, *cri)
720 * DESCRIPTION: The opencrypto new session handler. This function
721 * creates and initializes a new crypto session.
722 * The session can then be used to process crypto
723 * cipher and hash operations vi n8_process().
724 * Initial information is stored in the session
725 * at this time (e.g. keys, IVs).
726 * INPUTS: arg - N8 device softc
727 * cri - crypto cipher/hash initializtion info
728 * OUTPUTS: sidp - the id for the session. An arbitrary
729 * integer managed by us (in this case the
730 * index into the session array). This will
731 * be supplied to n8_process() to identify the
732 * session.
733 * RETURNS: 0 - ok
734 * else an errno value
735 * NOTES: This is a synchronous function - no async ops are
736 * started on the N8. These are all handled in the
737 * later n8_process() call.
738 **********************************************************************/
739 static int
740 n8_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
742 struct cryptoini *cinit;
743 struct cryptoini *cinit_crypto=NULL;
744 struct cryptoini *cinit_hash=NULL;
745 struct nsp_softc *sc = arg;
746 nsp_session_t *session;
747 int res;
749 if (sc == NULL) {
750 DBG(("n8_newsession(): sc == NULL\n"));
751 return EINVAL;
754 for (cinit=cri; cinit != NULL; cinit = cinit->cri_next) {
755 switch (cinit->cri_alg) {
756 case CRYPTO_MD5:
757 case CRYPTO_SHA1:
758 case CRYPTO_MD5_HMAC:
759 case CRYPTO_SHA1_HMAC:
760 if (cinit_hash != NULL) {
761 DBG(("n8_newsession(): ERROR - multiple hash requests\n"));
762 return EINVAL;
764 cinit_hash = cinit;
765 break;
766 case CRYPTO_AES_CBC:
767 DBG(("n8_newsession(): invalid crypto op %d\n", cinit->cri_alg));
768 return (EINVAL);
769 break;
770 case CRYPTO_DES_CBC:
771 case CRYPTO_3DES_CBC:
772 if (cinit_crypto != NULL) {
773 DBG(("n8_newsession(): ERROR - multiple crypto requests\n"));
774 return EINVAL;
776 cinit_crypto = cinit;
777 break;
778 default:
779 return (EINVAL);
782 if ((cinit_crypto == NULL) && (cinit_hash == NULL)) {
783 DBG(("n8_newsession(): no supported crypto ops\n"));
784 return EINVAL;
787 session = n8_session_alloc(sc);
788 if (session == NULL) {
789 DBG(("n8_newsession(): out of sessions (max = %d)\n",
790 NSP_MAX_SESSION));
791 return ENOMEM;
794 if (cinit_crypto != NULL) {
796 /* get a context for this session */
797 /* XXX not needed but faster with or without? */
798 res = N8_AllocateContext(&session->contextHandle, N8_ANY_UNIT);
799 if (res != N8_STATUS_OK) {
800 DBG(("%s.%d: failed to allocate context, err=%d\n",
801 __FILE__, __LINE__, res));
802 n8_session_free(sc, session);
803 return ENOMEM;
806 session->contextAllocated = 1;
808 /* use the same unit that the context came from */
809 session->cipherInfo.unitID = session->contextHandle.unitID;
810 DBG(("n8_newsession: 3DES assigned to n8 unit %d\n",
811 session->contextHandle.unitID));
812 session->cipherInfo.keySize = DES_KEY_SIZE_BYTES;
814 /* get IV and key for DES/3DES */
815 if (cinit_crypto->cri_klen > 0) {
817 memcpy(session->iv, &cinit_crypto->cri_iv[0], 8);
819 if (cinit_crypto->cri_alg == CRYPTO_DES_CBC) {
820 DBG(("n8_newsession: setup CRYPTO_DES_CBC\n"));
821 if (cinit_crypto->cri_klen != 64) {
822 DBG(("n8_newsession(): des key len %d != 64\n",
823 cinit_crypto->cri_klen));
824 n8_session_free(sc, session);
825 return EINVAL;
827 /* repeat the key 3 times for single DES */
828 memcpy(session->cipherInfo.key.keyDES.key1,
829 &cinit_crypto->cri_key[0], 8);
830 memcpy(session->cipherInfo.key.keyDES.key2,
831 &cinit_crypto->cri_key[0], 8);
832 memcpy(session->cipherInfo.key.keyDES.key3,
833 &cinit_crypto->cri_key[0], 8);
834 } else {
835 DBG(("n8_newsession: setup CRYPTO_3DES_CBC\n"));
836 if (cinit_crypto->cri_klen != 192) {
837 DBG(("n8_newsession(): 3des key len %d != 192\n",
838 cinit_crypto->cri_klen));
839 n8_session_free(sc, session);
840 return EINVAL;
842 memcpy(session->cipherInfo.key.keyDES.key1,
843 &cinit_crypto->cri_key[0], 8);
844 memcpy(session->cipherInfo.key.keyDES.key2,
845 &cinit_crypto->cri_key[8], 8);
846 memcpy(session->cipherInfo.key.keyDES.key3,
847 &cinit_crypto->cri_key[16], 8);
853 if (cinit_hash != NULL) {
854 /* setup for hashing */
855 if (cinit_hash->cri_key != NULL) {
856 /* take a copy of the key for hmac */
857 session->mackeylen = (cinit_hash->cri_klen+7)/8;
858 memcpy(session->mackey,
859 &cinit_hash->cri_key[0],
860 session->mackeylen);
861 DBG(("n8_newsession: stored hmac key %d bytes\n", session->mackeylen));
862 } else {
863 session->mackeylen = 0;
867 /* return the index for the session */
868 *sidp = session - sc->session;
869 session->sc = sc;
870 session->sid = *sidp;
872 DBG(("n8_newsession: completed - session %d\n", *sidp));
874 return 0;
878 /**********************************************************************
879 * FUNCTION: n8_freesession(*arg, *sidp, *cri)
880 * DESCRIPTION: The opencrypto free session handler. This function
881 * frees the specified session, releasing any
882 * associated resources (e.g. N8 context).
883 * INPUTS: arg - N8 device softc
884 * tid - The id of the session to free.
885 * RETURNS: 0 - ok
886 * else an errno value
887 * NOTES: XXX can this be called while the session is active?
888 **********************************************************************/
889 static int
890 n8_freesession(void *arg, u_int64_t tid)
892 struct nsp_softc *sc = arg;
893 uint32_t sid = ((uint32_t) tid) & 0xffffffff;
894 nsp_session_t *session;
896 if (sc == NULL) {
897 DBG(("n8_freesession(): sc == NULL\n"));
898 return EINVAL;
900 if (sid >= NSP_MAX_SESSION) {
901 DBG(("n8_freesession(): sid %d out of range\n",sid));
902 return EINVAL;
905 session = &sc->session[sid];
908 * Need to check if a partial operation is in progress
909 * and end it if so.
911 if (session->active) {
912 printf("n8_freesession: error - session 0x%04x is active. Not freeing.\n", sid);
913 //session->freePending = 1;
914 /* should be protected by the framework. If the session is
915 * freed while active nasty things will happen for all of the data
916 * references.
918 return 0;
921 n8_session_free(sc, session);
923 DBG(("n8_freesession: completed - session %d\n", sid));
924 return 0;
928 /**********************************************************************
929 * FUNCTION: n8_process(*arg, *crp, hint)
930 * DESCRIPTION: The opencrypto crypto operation handler. This function
931 * expects to be called when the user app requests a
932 * cipher or hash operation for a crypto session.
933 * It kicks off the appopriate N8 async operation
934 * to handle the request.
935 * INPUTS: arg - N8 device softc
936 * krp - opencrypto crypto operation description
937 * hint - not used.
938 * RETURNS: 0 - ok
939 * else an errno value
940 **********************************************************************/
941 static int
942 n8_process(void *arg, struct cryptop *crp, int hint)
944 struct nsp_softc *sc = arg;
945 struct cryptodesc *crd;
946 nsp_session_t *session;
947 uint32_t sid = (uint32_t)(crp->crp_sid & 0xFFFFFFFF);
948 int res=0;
949 int hash_seen, crypto_seen; /* booleans for error checking */
950 int crd_count=0; /* number of descriptors */
952 DBG(("n8_process: session %d\n", sid));
954 if (sc == NULL) {
955 DBG(("n8_process: sc == NULL\n"));
956 return EINVAL;
958 if (sid >= NSP_MAX_SESSION) {
959 DBG(("n8_process: sid %d out of range\n",sid));
960 return EINVAL;
962 session = &sc->session[sid];
963 session->crp = crp;
964 session->crd = NULL;
966 DBG(("n8_process: crp_ilen %d crp_olen %d crp_mac %p\n",
967 crp->crp_ilen, crp->crp_olen, crp->crp_mac));
969 #ifdef NBDEBUG
970 printf("n8_process: flags 0x%04x\n", crp->crp_flags);
971 for (flag=1; flag<=0x80; flag<<=1) {
972 if (flag & crp->crp_flags) {
973 switch (flag) {
974 case CRYPTO_F_IMBUF:
975 printf("\tCRYPTO_F_IMBUF\n");
976 break;
977 case CRYPTO_F_IOV:
978 printf("\tCRYPTO_F_IOV\n");
979 break;
980 case CRYPTO_F_REL:
981 printf("\tCRYPTO_F_REL\n");
982 break;
983 case CRYPTO_F_BATCH:
984 printf("\tCRYPTO_F_BATCH\n");
985 break;
986 case CRYPTO_F_CBIMM:
987 printf("\tCRYPTO_F_CBIMM\n");
988 break;
989 case CRYPTO_F_DONE:
990 printf("\tCRYPTO_F_DONE\n");
991 break;
992 case CRYPTO_F_CBIFSYNC:
993 printf("\tCRYPTO_F_CBIFSYNC\n");
994 break;
995 default:
996 printf("\tUnknown flag 0x%x\n", flag);
997 break;
1001 #endif
1002 /* set up source and dest */
1003 if (crp->crp_flags & CRYPTO_F_IMBUF) {
1004 session->src.mb = (struct mbuf *)crp->crp_buf;
1005 session->dst.mb = (struct mbuf *)crp->crp_buf;
1006 return EINVAL; /* XXX to be done */
1007 } else if (crp->crp_flags & CRYPTO_F_IOV) {
1008 session->src.io = (struct uio *)crp->crp_buf;
1009 session->dst.io = (struct uio *)crp->crp_buf;
1010 /* hash operations still use direct writes
1011 * for the digest.
1013 session->mac = (N8_Buffer_t *)crp->crp_mac;
1014 } else {
1015 /* contiguous buffer in memory */
1016 session->src.ptr = (N8_Buffer_t *)crp->crp_buf;
1017 session->dst.ptr = (N8_Buffer_t *)crp->crp_buf;
1018 /* the crd will specify an injection offset for
1019 * the hash operation */
1020 session->mac = (N8_Buffer_t *)crp->crp_buf;
1023 /* check data length */
1024 if (crp->crp_ilen > 0x4800) {
1025 /* not yet supported - will require segmenting the data
1026 * into multiple 18KB blocks, and multiple calls
1027 * to the card, and probable copies of the input
1028 * data to avoid overwriting the next block
1029 * with ciphertext expansion.
1031 printf("n8_process: crp_ilen %d too big\n", crp->crp_ilen);
1032 return EFBIG;
1034 if (crp->crp_olen > 0x4800) {
1035 /* not yet supported - will require segmenting the data
1036 * into multiple 18KB blocks, and multiple calls
1037 * to the card, and probable copies of the input
1038 * data to avoid overwriting the next block
1039 * with ciphertext expansion.
1041 printf("n8_process: crp_olen %d too big\n", crp->crp_olen);
1042 return EFBIG;
1045 /* check for supported set of operations */
1046 crypto_seen = 0;
1047 hash_seen = 0;
1048 for (crd=crp->crp_desc,crd_count=0; crd != NULL; crd=crd->crd_next, crd_count++) {
1049 #ifdef N8DEBUG
1050 printf("n8_process: crd %d - crd_flags 0x%04x\n", crd_count, crd->crd_flags);
1051 if (crd->crd_flags & CRD_F_ENCRYPT)
1052 printf("\tCRD_F_ENCRYPT\n");
1053 if (crd->crd_flags & CRD_F_IV_PRESENT)
1054 printf("\tCRD_F_IV_PRESENT\n");
1055 if (crd->crd_flags & CRD_F_IV_EXPLICIT)
1056 printf("\tCRD_F_IV_EXPLICIT\n");
1057 if (crd->crd_flags & CRD_F_DSA_SHA_NEEDED)
1058 printf("\tCRD_F_DSA_SHA_NEEDED \n");
1059 #endif
1061 switch (crd->crd_alg) {
1062 case CRYPTO_MD5:
1063 case CRYPTO_SHA1:
1064 case CRYPTO_MD5_HMAC:
1065 case CRYPTO_SHA1_HMAC:
1066 if (hash_seen) {
1067 printf("n8_newsession(): multiple hash requests\n");
1068 return EINVAL;
1070 hash_seen = 1;
1071 break;
1073 case CRYPTO_AES_CBC:
1074 printf("n8_newsession(): invalid crypto op %d\n", crd->crd_alg);
1075 return EINVAL;
1076 break;
1078 case CRYPTO_DES_CBC:
1079 case CRYPTO_3DES_CBC:
1080 if (crypto_seen) {
1081 printf("n8_newsession(): multiple crypto requests\n");
1082 return EINVAL;
1084 crypto_seen = 1;
1085 break;
1087 default:
1088 return EINVAL;
1092 /* kick off first operation */
1093 session->active = 1;
1094 res = n8_start_crd(sc, crp, crp->crp_desc, 0, session);
1096 if (res != 0) {
1097 /* op did not start, so session is not active */
1098 /* Note that the operation can complete before we
1099 * get to here, hence the session is flagged as
1100 * active before its started just in case.
1102 session->active = 0;
1105 return res;
1109 /**********************************************************************
1110 * FUNCTION: n8_callback(*arg, status)
1111 * DESCRIPTION: Called when a crypto or hash operation is completed by
1112 * the N8.
1113 * This function checks for any further operations
1114 * for the session and kicks the next one off.
1115 * If all operations have completed it returns
1116 * the results to the opencrypto framework.
1117 * INPUTS: arg - the session context
1118 * status - The result of the N8 operation.
1120 * RETURNS: none.
1121 **********************************************************************/
1122 static void
1123 n8_callback(void *arg, N8_Status_t status)
1125 nsp_session_t *session=arg;
1126 struct cryptop *crp;
1127 int res;
1129 crp = session->crp;
1130 DBG(("n8_callback: session %d(0x%x) crd %d done, status %d\n",
1131 (uint32_t)(crp->crp_sid & 0xFFFFFFFF),
1132 session->magic,
1133 session->crd_id,
1134 status));
1136 if (status != N8_STATUS_OK) {
1137 DBG(("n8_callback: operation (crd_alg %d) failed (res=%d)\n",
1138 session->crd->crd_alg, status));
1139 crp->crp_etype = n8_map_errno(status);
1140 session->active = 0;
1141 crypto_done(crp);
1142 return;
1145 /* Any more operations needed for this request? */
1146 if (session->crd->crd_next != NULL) {
1147 DBG(("n8_callback: starting next crd\n"));
1148 res = n8_start_crd(session->sc, session->crp,
1149 session->crd->crd_next,
1150 session->crd_id + 1,
1151 session);
1152 if (res != 0) {
1153 /* how do we let the user know? */
1154 DBG(("n8_callback: error %d starting crd\n", res));
1155 crp->crp_etype = res;
1156 session->active = 0;
1157 crypto_done(crp);
1159 } else {
1160 /* no more ops so this request is complete */
1161 DBG(("n8_callback: crypto_done, session %d -> inactive\n",
1162 (session - session->sc->session)));
1163 session->active = 0;
1164 crypto_done(crp);
1169 /**********************************************************************
1170 * FUNCTION: n8_start_crd(*sc, *crp, *crd, crd_id, *session)
1171 * DESCRIPTION: Start a crypto operation.
1172 * Kicks off a asynchronous crypto, or hash operation.
1173 * INPUTS: sc - device data
1174 * crp - crypto operation request
1175 * crd - crypto operation to start
1176 * crd_id - opencrypto crypto session id
1177 * session - session record to manage the operation.
1179 * RETURNS: 0 = success, else ERRNO value.
1180 **********************************************************************/
1181 static int
1182 n8_start_crd(struct nsp_softc *sc,
1183 struct cryptop *crp,
1184 struct cryptodesc *crd,
1185 int crd_id,
1186 nsp_session_t *session)
1188 int res = 0;
1190 #ifdef N8DEBUG
1191 printf("n8_start_crd: starting crd %d\n", crd_id);
1192 printf("n8_start_crd: crd_skip %d, crd_len %d, crd_inject %d\n",
1193 crd->crd_skip,
1194 crd->crd_len,
1195 crd->crd_inject);
1196 if (crd->crd_flags & CRD_F_ENCRYPT)
1197 printf("\tCRD_F_ENCRYPT\n");
1198 if (crd->crd_flags & CRD_F_IV_PRESENT)
1199 printf("\tCRD_F_IV_PRESENT\n");
1200 if (crd->crd_flags & CRD_F_IV_EXPLICIT)
1201 printf("\tCRD_F_IV_EXPLICIT\n");
1202 if (crd->crd_flags & CRD_F_DSA_SHA_NEEDED)
1203 printf("\tCRD_F_DSA_SHA_NEEDED \n");
1204 #endif
1206 session->crd = crd;
1207 session->crd_id = crd_id;
1209 /* note the errors should never occur since the crd list is
1210 * pre-checked for validity
1212 switch (crd->crd_alg) {
1213 case CRYPTO_MD5:
1214 case CRYPTO_SHA1:
1215 case CRYPTO_MD5_HMAC:
1216 case CRYPTO_SHA1_HMAC:
1217 res = n8_do_hash(sc, crp, crd, session);
1218 break;
1220 case CRYPTO_DES_CBC:
1221 case CRYPTO_3DES_CBC:
1222 res = n8_do_crypt(sc, crp, crd, session);
1223 break;
1225 default:
1226 printf("n8_start_crd: invalid crypto op %d\n", crd->crd_alg);
1227 return EINVAL;
1230 return res;
1234 /**********************************************************************
1235 * FUNCTION: n8_do_crypt(*sc, *crp, *crd, *session)
1236 * DESCRIPTION: Kick off an encrypt or decrypt operation for a session.
1237 * A session has one or more operations to perform on the
1238 * data. This function starts the operation specified
1239 * by the crd.
1240 * INPUTS: sc - the device state
1241 * crp - the crypto control data for the operation
1242 * crd - the crypto operation to start
1243 * session - session and context info for crypto ops
1245 * RETURNS: 0 - operation sucessfully started.
1246 * else ERRNO value.
1247 **********************************************************************/
1248 static int
1249 n8_do_crypt(struct nsp_softc *sc,
1250 struct cryptop *crp,
1251 struct cryptodesc *crd,
1252 nsp_session_t *session)
1254 N8_Event_t event;
1255 int res=0;
1256 int ivlen = 8; /* DES, 3DES CBC */
1258 /* IV Explicitly Provided? */
1259 if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
1260 /* yes: use it for the operation */
1261 memcpy(session->cipherInfo.key.keyDES.IV,
1262 crd->crd_iv, ivlen);
1263 } else {
1264 /* No: use the earlier setup one */
1265 memcpy(session->cipherInfo.key.keyDES.IV,
1266 session->iv, ivlen);
1269 /* IV not in place? */
1270 if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
1271 if (crp->crp_flags & CRYPTO_F_IMBUF) {
1272 m_copyback(session->src.mb, crd->crd_inject,
1273 ivlen,
1274 session->cipherInfo.key.keyDES.IV);
1275 } else if (crp->crp_flags & CRYPTO_F_IOV) {
1276 cuio_copyback(session->src.io, crd->crd_inject,
1277 ivlen,
1278 session->cipherInfo.key.keyDES.IV);
1282 res = N8_EncryptInitialize(&session->crypt, &session->contextHandle,
1283 N8_CIPHER_DES, &session->cipherInfo, NULL);
1284 if (res != N8_STATUS_OK) {
1285 printf("N8_EncryptInitialize: Failed - res=%d\n", res);
1286 return n8_map_errno(res);
1289 event.usrCallback = n8_callback;
1290 event.usrData = (void *)session;
1291 if (crd->crd_flags & CRD_F_ENCRYPT) {
1292 if (crp->crp_flags & CRYPTO_F_IOV) {
1293 res = N8_Encrypt_uio(&session->crypt, session->src.io,
1294 crd->crd_len, session->dst.io, &event);
1295 } else if (crp->crp_flags & CRYPTO_F_IMBUF) {
1296 printf("CRYPTO_F_IMBUF not implemented for Encrypt\n");
1297 } else {
1298 res = N8_Encrypt(&session->crypt,
1299 session->src.ptr+crd->crd_skip,
1300 crd->crd_len, session->dst.ptr+crd->crd_inject, &event);
1302 } else {
1303 if (crp->crp_flags & CRYPTO_F_IOV) {
1304 res = N8_Decrypt_uio(&session->crypt, session->src.io,
1305 crd->crd_len, session->dst.io, &event);
1306 } else if (crp->crp_flags & CRYPTO_F_IMBUF) {
1307 printf("CRYPTO_F_IMBUF not implemented for Decrypt\n");
1308 } else {
1309 res = N8_Decrypt(&session->crypt, session->src.ptr+crd->crd_skip,
1310 crd->crd_len, session->dst.ptr+crd->crd_inject, &event);
1314 return n8_map_errno(res);
1318 /**********************************************************************
1319 * FUNCTION: n8_do_hash(*sc, *crp, *crd, *session)
1320 * DESCRIPTION: Kick off a hash operation for a session.
1321 * A session has one or more operations to perform on the
1322 * data. This function starts the operation specified
1323 * by the crd.
1324 * INPUTS: sc - the device state
1325 * crp - the crypto control data for the operation
1326 * crd - the crypto hash operation to start
1327 * session - session and context info for crypto ops
1329 * RETURNS: 0 - operation sucessfully started.
1330 * else ERRNO value.
1331 **********************************************************************/
1332 static int
1333 n8_do_hash(struct nsp_softc *sc,
1334 struct cryptop *crp,
1335 struct cryptodesc *crd,
1336 nsp_session_t *session)
1338 N8_Event_t event;
1339 N8_HashInfo_t info;
1340 N8_HashAlgorithm_t alg;
1341 int res=0;
1343 info.unitID = N8_ANY_UNIT;
1344 info.keyLength = 0;
1346 switch (crd->crd_alg) {
1347 case CRYPTO_MD5:
1348 alg = N8_MD5;
1349 break;
1350 case CRYPTO_SHA1:
1351 alg = N8_SHA1;
1352 break;
1353 case CRYPTO_MD5_HMAC:
1354 alg = N8_HMAC_MD5;
1355 if (crd->crd_klen == 0) {
1356 DBG(("CRYPTO_MD5_HMAC: using session key, len %d\n",session->mackeylen));
1357 /* use the session key */
1358 info.keyLength = session->mackeylen;
1359 info.key_p = session->mackey;
1361 /* Sanity check */
1362 if (session->mackeylen == 0) {
1363 printf("No key provided for HMAC\n");
1364 return EINVAL;
1366 } else {
1367 info.keyLength = (crd->crd_klen+7)/8;
1368 info.key_p = crd->crd_key;
1369 DBG(("CRYPTO_MD5_HMAC: using crd key, len %d\n", info.keyLength));
1371 break;
1372 case CRYPTO_SHA1_HMAC:
1373 alg = N8_HMAC_SHA1;
1374 if (crd->crd_klen == 0) {
1375 DBG(("CRYPTO_SHA1_HMAC: using session key, len %d\n",session->mackeylen));
1376 /* use the session key */
1377 info.keyLength = session->mackeylen;
1378 info.key_p = session->mackey;
1380 /* Sanity check */
1381 if (session->mackeylen == 0) {
1382 printf("No key provided for HMAC\n");
1383 return EINVAL;
1385 } else {
1386 info.keyLength = (crd->crd_klen+7)/8;
1387 info.key_p = crd->crd_key;
1388 DBG(("CRYPTO_SHA1_HMAC: using crd key, len %d\n", info.keyLength));
1390 break;
1391 case CRYPTO_RIPEMD160_HMAC:
1392 return ENODEV;
1393 break;
1394 default:
1395 printf("n8_do_hash: invalid hash algorithm %d\n",
1396 crd->crd_alg);
1397 return ENODEV;
1400 res = N8_HashInitialize(&session->hash, alg, &info, NULL);
1401 if (res != N8_STATUS_OK) {
1402 printf("n8_do_hash: N8_HashInitialize failed, error=%d\n",
1403 res);
1404 return n8_map_errno(res);
1407 if ((crp->crp_flags & (CRYPTO_F_IOV | CRYPTO_F_IMBUF)) == 0) {
1408 /* use the crd's injection offset to obtain the output
1409 * address for the digest.
1411 session->mac = session->src.ptr + crd->crd_inject;
1414 DBG(("N8_HashInitialize: res=%d (crd_len=%d)\n", res, crd->crd_len));
1415 event.usrCallback = n8_callback;
1416 event.usrData = (void *)session;
1417 res = N8_HashCompleteMessage_uio(&session->hash, session->src.io,
1418 crd->crd_len, session->mac, &event);
1419 DBG(("N8_HashCompleteMessage_uio: res=%d\n", res));
1420 return n8_map_errno(res);
1424 /**********************************************************************
1425 * FUNCTION: bn_le_to_be(*le, numbits, *be)
1426 * DESCRIPTION: Return the big-endian representation of the
1427 * little-endian byte stream.
1428 * Basically a conversion from the opencrypto big-number format
1429 * to the N8 big-number format.
1430 * INPUTS: le - pointer to the little-endian byte-stream
1431 * numbits - number of bits to convert (this is rounded up
1432 * to be a multiple of 8).
1433 * OUTPUTS: be - big-endian byte stream conversion of *le
1434 * RETURNS: size of *be as number of bytes.
1435 * NOTE: assumes any remainder bits are zero, which is
1436 * true for OpenSSL bignum bit counts.
1437 **********************************************************************/
1438 static uint32_t
1439 bn_le_to_be(uint8_t *le, int numbits, N8_Buffer_t *be)
1441 int numbytes;
1442 int ind;
1444 numbytes = (numbits+7)/8;
1446 for (ind=0; ind<numbytes; ind++) {
1447 be[ind] = le[numbytes-ind-1];
1450 return numbytes;
1453 /**********************************************************************
1454 * FUNCTION: n8_kcallback_finish(void *arg, N8_Status_t status)
1455 * DESCRIPTION: Interrupt handler for N8 key operation completion.
1456 * This handler is called when the final N8 operation
1457 * completes for an asymmetric operation or modular
1458 * arithmetic operation.
1459 * If the status is ok, the results of the operation
1460 * are passed back to the application vi opencrypto.
1461 * Any bignum results are converted from big-endian
1462 * to little-endian before being passed back.
1464 * If the status was an error then it is noted for later.
1465 * This handler will be invoked a second time by the N8 once
1466 * the operation has been cleaned up (status will be ok),
1467 * at which time the error is passed back to the application.
1468 * INPUTS: arg - pointer to the key operation request data
1469 * to be a multiple of 8).
1470 * status - result of the operation.
1471 * RETURNS: none.
1472 **********************************************************************/
1473 static void
1474 n8_kcallback_finish(void *arg, N8_Status_t status)
1476 n8_kreq_t *req=arg;
1477 uint8_t data;
1479 DBG(("%s: status %d, req magic 0x%x\n", __func__, status, req->magic));
1481 if (req->krp == NULL) {
1482 printf("%s: called with NULL krp\n", __func__);
1483 return;
1486 if (status == N8_STATUS_OK) {
1487 int ind;
1488 int parm;
1489 int res;
1491 /* was there an earlier error? */
1492 if (req->error) {
1493 /* Yes - we're done then. */
1494 printf("%s: finishing op, error was %d\n", __func__, req->error);
1495 if (req->krp->krp_op == CRK_DSA_VERIFY) {
1496 /* the CRK_DSA_VERIFY result semantics
1497 * return 1 for verify ok, 0 for verify failed,
1498 * and -1 for any other errors
1500 req->krp->krp_status = -1;
1501 } else {
1502 /* the rest of the operations return an ERRNO */
1503 req->krp->krp_status = req->error; /* XXX translate to errno */
1506 /* clean up N8 operations */
1507 switch (req->krp->krp_op) {
1508 case CRK_DSA_VERIFY:
1509 case CRK_DSA_SIGN:
1510 N8_DSAFreeKey(&req->op.dsa.key);
1511 break;
1512 case CRK_DH_COMPUTE_KEY:
1513 N8_DHFreeKey(&req->op.dh.key);
1514 break;
1515 case CRK_MOD_EXP_CRT:
1516 N8_RSAFreeKey(&req->op.rsa.key);
1517 break;
1518 default:
1519 /* nothing to clean up */
1520 break;
1524 crypto_kdone(req->krp);
1525 req->krp = NULL;
1526 free(req, M_DEVBUF); /* XXX use a pool... */
1527 return;
1530 /* convert any bignum results to little-endian */
1531 for (parm=crk_def[req->krp->krp_op].iparmcount;
1532 parm < (crk_def[req->krp->krp_op].iparmcount +
1533 crk_def[req->krp->krp_op].oparmcount);
1534 parm++) {
1536 int numbytes = req->parm[parm].lengthBytes;
1538 /* need to convert bignum to little-endian? */
1539 if (crk_def[req->krp->krp_op].bignums & BN_ARG(parm)) {
1541 /* convert the big-endian result to little-endian */
1542 for (ind=0; ind<numbytes/2; ind++) {
1543 data = req->parm[parm].value_p[ind];
1544 req->parm[parm].value_p[ind] = req->parm[parm].value_p[numbytes-ind-1];
1545 req->parm[parm].value_p[numbytes-ind-1] = data;
1548 req->krp->krp_param[parm].crp_nbits = numbytes*8;
1551 /* Deal with any special results and cleanups */
1552 switch (req->krp->krp_op) {
1553 case CRK_DSA_VERIFY:
1554 DBG(("CRK_DSA_VERIFY: result=%d\n", req->op.dsa.verifyok));
1555 /* return 0 for verify ok, 1 for verify failed */
1556 req->krp->krp_status = req->op.dsa.verifyok ? 0 : 1;
1557 res = N8_DSAFreeKey(&req->op.dsa.key);
1558 if (res != N8_STATUS_OK) {
1559 printf("%s: N8_DSAFreeKey failed, error=%d\n",
1560 __func__, res);
1562 break;
1564 case CRK_DSA_SIGN:
1565 res = N8_DSAFreeKey(&req->op.dsa.key);
1566 if (res != N8_STATUS_OK) {
1567 printf("%s: N8_DSAFreeKey failed, error=%d\n",
1568 __func__, res);
1570 req->krp->krp_status = 0;
1571 break;
1573 case CRK_DH_COMPUTE_KEY:
1574 res = N8_DHFreeKey(&req->op.dh.key);
1575 if (res != N8_STATUS_OK) {
1576 printf("%s: N8_DHFreeKey failed, error=%d\n",
1577 __func__, res);
1579 req->krp->krp_status = 0;
1580 break;
1582 case CRK_MOD_EXP_CRT:
1583 res = N8_RSAFreeKey(&req->op.rsa.key);
1584 if (res != N8_STATUS_OK) {
1585 printf("%s: N8_RSAFreeKey failed, error=%d\n",
1586 __func__, res);
1588 req->krp->krp_status = 0;
1589 break;
1591 default:
1592 req->krp->krp_status = 0;
1593 break;
1596 /* Done - let the user app know */
1597 crypto_kdone(req->krp);
1598 req->krp = NULL;
1599 free(req, M_DEVBUF); /* XXX replace with pool */
1600 } else {
1601 printf("%s: op failed, status=%d\n", __func__, status);
1602 req->krp->krp_status = n8_map_errno(status);
1603 req->error = status;
1608 /**********************************************************************
1609 * FUNCTION: n8_kcallback_setup(void *arg, N8_Status_t status)
1610 * DESCRIPTION: Interrupt handler for N8 key operation setup.
1611 * This handler is called when the N8 key initialization
1612 * operation completes. If the initialization was
1613 * successful then the final N8 operation is started
1614 * with the n8_kcallback_finish() handler set to be called
1615 * on completion.
1617 * If the status was an error then it is noted for later.
1618 * This handler will be invoked a second time by the N8 once
1619 * the operation has been cleaned up (status will be ok),
1620 * at which time the error is passed back to the application.
1621 * INPUTS: arg - pointer to the key operation request data
1622 * to be a multiple of 8).
1623 * status - result of the operation.
1624 * RETURNS: none.
1625 **********************************************************************/
1626 static void
1627 n8_kcallback_setup(void *arg, N8_Status_t status)
1629 n8_kreq_t *req=arg;
1630 N8_Event_t event;
1631 int res;
1633 DBG(("%s status %d\n", __func__, status));
1635 if (req->krp == NULL) {
1636 printf("%s called with NULL krp\n", __func__);
1637 return;
1640 if (status == N8_STATUS_OK) {
1641 /* was there an earlier error? */
1642 if (req->error) {
1643 /* Yes - we're done then. */
1644 printf("%s: finishing op, error was %d\n", __func__, req->error);
1645 if (req->krp->krp_op == CRK_DSA_VERIFY) {
1646 /* the CRK_DSA_VERIFY result semantics
1647 * return 1 for verify ok, 0 for verify failed,
1648 * and -1 for any other errors
1650 req->krp->krp_status = -1;
1651 } else {
1652 /* the rest of the operations return an ERRNO */
1653 req->krp->krp_status = n8_map_errno(req->error);
1655 crypto_kdone(req->krp);
1656 req->krp = NULL;
1657 free(req, M_DEVBUF); /* use a pool... */
1658 return;
1661 /* kick off the finishing op */
1662 event.usrCallback = n8_kcallback_finish;
1663 event.usrData = (void *)req;
1664 switch (req->krp->krp_op) {
1665 case CRK_DSA_SIGN:
1666 res = N8_DSASign(&req->op.dsa.key,
1667 req->parm[NSP_DSA_SIGN_DIGEST].value_p,
1668 req->parm[NSP_DSA_SIGN_RVALUE].value_p,
1669 req->parm[NSP_DSA_SIGN_SVALUE].value_p,
1670 &event);
1671 if (res != N8_STATUS_OK) {
1672 printf("%s: N8_DSASign failed, error = %d\n", __func__, res);
1673 req->krp->krp_status = n8_map_errno(res);
1674 crypto_kdone(req->krp);
1675 req->krp = NULL;
1676 free(req, M_DEVBUF); /* XXX use a pool... */
1678 break;
1680 case CRK_DSA_VERIFY:
1681 res = N8_DSAVerify(&req->op.dsa.key,
1682 req->parm[NSP_DSA_VERIFY_DIGEST].value_p,
1683 req->parm[NSP_DSA_VERIFY_RVALUE].value_p,
1684 req->parm[NSP_DSA_VERIFY_SVALUE].value_p,
1685 &req->op.dsa.verifyok,
1686 &event);
1687 if (res != N8_STATUS_OK) {
1688 printf("%s: N8_DSAVerify failed, error = %d\n", __func__, res);
1689 req->krp->krp_status = n8_map_errno(res);
1690 crypto_kdone(req->krp);
1691 req->krp = NULL;
1692 free(req, M_DEVBUF); /* XXX use a pool... */
1694 break;
1696 case CRK_DH_COMPUTE_KEY:
1697 DBG(("N8_DHCompute: PRIV=%08x %08x\n",
1698 ((uint32_t *)req->parm[NSP_DH_COMPUTE_KEY_PRIV].value_p)[0],
1699 ((uint32_t *)req->parm[NSP_DH_COMPUTE_KEY_PRIV].value_p)[1]));
1700 /* KEY = B^a % p, a and p already in dh.key */
1701 res = N8_DHCompute(&req->op.dh.key,
1702 NULL, /* already have PUB key from init */
1703 req->parm[NSP_DH_COMPUTE_KEY_PRIV].value_p,
1704 req->parm[NSP_DH_COMPUTE_KEY_K].value_p,
1705 &event);
1706 if (res != N8_STATUS_OK) {
1707 printf("%s: N8_DHCompute failed, error = %d\n", __func__, res);
1708 req->krp->krp_status = n8_map_errno(res);
1709 crypto_kdone(req->krp);
1710 req->krp = NULL;
1711 free(req, M_DEVBUF); /* XXX use a pool... */
1713 break;
1715 default: /* coding error - shouldn't reach here */
1716 printf("%s: got unexpected krp_op %d\n", __func__, req->krp->krp_op);
1717 req->krp->krp_status = ENODEV;
1718 crypto_kdone(req->krp);
1719 req->krp = NULL;
1720 free(req, M_DEVBUF); /* XXX use a pool... */
1722 } else {
1723 printf("n8_kcallback: op failed, status=%d\n", status);
1724 req->krp->krp_status = status; /* XXX translate to errno */
1725 req->error = status;
1730 /**********************************************************************
1731 * FUNCTION: check_key_parms(*krp)
1732 * DESCRIPTION: Check that each of the bignum parameters supplied by the
1733 * key operation are valid for the operation.
1734 * i.e. the number of input and output parameters is correct,
1735 * and all of the bignum parameters are with the appropraite
1736 * size range.
1737 * INPUTS: krp - opencrypto key operation description
1738 * RETURNS: 0 - ok
1739 * ENODEV - invalid key operation
1740 * EINVAL - invalid number of input or output parameters
1741 * ERANGE - one or more parameters are outside
1742 * the range supported for big-numbers.
1743 **********************************************************************/
1744 static int
1745 check_key_parms(struct cryptkop *krp)
1747 int ind;
1749 if (krp->krp_op > CRK_ALGORITHM_MAX) {
1750 printf("nsp: invalid crypto key op %d\n", krp->krp_op);
1751 return ENODEV;
1753 if (krp->krp_iparams != crk_def[krp->krp_op].iparmcount) {
1754 printf("nsp: %s input params %d != %d\n",
1755 crk_def[krp->krp_op].name,
1756 krp->krp_iparams,
1757 crk_def[krp->krp_op].iparmcount);
1758 return EINVAL;
1761 if (krp->krp_oparams != crk_def[krp->krp_op].oparmcount) {
1762 printf("nsp: %s output params %d != %d\n",
1763 crk_def[krp->krp_op].name,
1764 krp->krp_oparams,
1765 crk_def[krp->krp_op].oparmcount);
1766 return EINVAL;
1769 for (ind=0; ind<(krp->krp_iparams + krp->krp_oparams); ind++) {
1770 /* is the parameter a bignum? */
1771 if (crk_def[krp->krp_op].bignums & BN_ARG(ind)) {
1772 /* check its size */
1773 if (krp->krp_param[ind].crp_nbits > (NSP_MAX_KEYLEN*8)) {
1774 printf("n8_kprocess: %s - param %d too large (%d bits)\n",
1775 crk_def[krp->krp_op].name,
1776 ind,
1777 krp->krp_param[ind].crp_nbits);
1778 return ERANGE;
1783 return 0;
1787 /**********************************************************************
1788 * FUNCTION: n8_kprocess(*arg, *krp, hint)
1789 * DESCRIPTION: The opencrypto key operation handler. This function
1790 * expects to be called when the user app requests a
1791 * key operation.
1792 * It kicks off the appopriate N8 async operation
1793 * to handle the request.
1794 * INPUTS: arg - N8 device softc
1795 * krp - opencrypto key operation description
1796 * hint - not used.
1797 * RETURNS: 0 - ok
1798 * else an errno value
1799 **********************************************************************/
1800 static int
1801 n8_kprocess(void *arg, struct cryptkop *krp, int hint)
1803 struct nsp_softc *sc;
1805 N8_Event_t event;
1806 n8_kreq_t *req; /* to hold result data */
1807 int res=0;
1808 int ind;
1810 sc = arg;
1812 if ((krp == NULL) || (krp->krp_callback == NULL))
1813 return (EINVAL);
1815 if (sc == NULL) {
1816 printf("n8_kprocess: error - sc == NULL\n");
1817 return EINVAL;
1820 DBG(("n8_kprocess op %d, iparams %d, oparams %d, hid 0x%x\n",
1821 krp->krp_op,
1822 krp->krp_iparams,
1823 krp->krp_oparams,
1824 krp->krp_hid));
1826 /* Q. Does the final byte need to be masked?
1827 * Q. Does the number need to be re-aligned?
1830 /* opencrypto bignum format:
1831 * possibly a little-endian byte stream.
1833 * N8 bignum format:
1834 * an array of 256 words by 128 bits per operand
1836 * N8 api bignum format:
1837 * a network byte order string (big-endian).
1840 * OpenSSL bignum:
1841 * an array n of integers, with element n[0]
1842 * containing the least-significant word of
1843 * the bignum (word size is BN_BITS2 bits,
1844 * which is 64, 32, 16, or 8 depending on machine
1845 * architecture size of ulong).
1846 * The elements are in little-endian byte order.
1847 * The bignum includes a boolean to flag the number
1848 * as negative (bn.neg).
1851 * So, conversion from little-endian OpenSSL bignum
1852 * to N8 api bignum requires the OpenSSL elements to be
1853 * reversed, and the bytes in each element to be swapped.
1855 * opencrypto BN -> N8 api BN:
1856 * reverse the byte stream.
1857 * If the number of bits is not a multiple of 8,
1858 * will need to shift the final byte and pad with
1859 * 0 bits.
1861 res = check_key_parms(krp);
1862 if (res != 0) {
1863 krp->krp_status = res;
1864 crypto_kdone(krp);
1865 return 0;
1868 /* setup a buffer to track this request and provide the callback handler
1869 * with what it needs to complete it.
1871 req = (n8_kreq_t *)malloc(sizeof(n8_kreq_t), M_DEVBUF, M_NOWAIT);
1872 if (req == NULL) {
1873 printf("n8_kprocess: failed to alloc req (size=%d)\n", sizeof(n8_kreq_t));
1874 krp->krp_status = ENOMEM;
1875 crypto_kdone(krp);
1876 return 0;
1878 req->magic = 0xFEEDFEED;
1880 /* convert input arguments from little-endian to big-endian */
1881 /* what about has values (e.g. DSA digests, etc) */
1882 DBG(("op %s, %d input %d output, bignums 0x%02x\n",
1883 crk_def[krp->krp_op].name,
1884 crk_def[krp->krp_op].iparmcount,
1885 crk_def[krp->krp_op].oparmcount,
1886 crk_def[krp->krp_op].bignums));
1887 for (ind=0; ind<krp->krp_iparams; ind++) {
1888 req->parm[ind].value_p = &req->value[ind][0];
1889 if (crk_def[krp->krp_op].bignums & BN_ARG(ind)) {
1890 req->parm[ind].lengthBytes =
1891 bn_le_to_be(krp->krp_param[ind].crp_p,
1892 krp->krp_param[ind].crp_nbits,
1893 req->parm[ind].value_p);
1894 } else {
1895 /* unknown - defined by key algorithm */
1896 req->parm[ind].lengthBytes = 0;
1898 DBG(("iparm %d length %d, ptr %p\n",
1899 ind, req->parm[ind].lengthBytes,
1900 req->parm[ind].value_p));
1903 /* fill in output bignums */
1904 /* Results are converted to little-endian after the op completes. */
1905 for (ind=krp->krp_iparams;
1906 ind < (krp->krp_iparams + krp->krp_oparams);
1907 ind++) {
1908 req->parm[ind].value_p = krp->krp_param[ind].crp_p;
1909 req->parm[ind].lengthBytes =
1910 (krp->krp_param[ind].crp_nbits+7)/8;
1911 DBG(("oparm %d bits -> %d bytes\n",
1912 krp->krp_param[ind].crp_nbits,
1913 req->parm[ind].lengthBytes));
1914 DBG(("oparm %d length %d, ptr %p\n",
1915 ind, req->parm[ind].lengthBytes,
1916 req->parm[ind].value_p));
1919 /* this only supports a single result... DSA_SIGN needs two */
1920 req->error = N8_STATUS_OK;
1921 req->krp = krp;
1922 /* setup N8 call to call n8_kcallback with the request */
1924 switch (krp->krp_op) {
1925 case CRK_DSA_SIGN:
1926 /* inputs: dgst dsa->p dsa->q dsa->g dsa->priv_key */
1927 event.usrCallback = n8_kcallback_setup;
1928 event.usrData = (void *)req;
1931 * N8_DSAInitializeKey()
1932 * 1) Put p in the parameter block.
1933 * 2) Put q in the Parameter block.
1934 * 3) Put privateKey in the parameter block.
1935 * 4) Compute gR mod p and put it in the parameter block.
1936 * 5) Compute cp = -(p[0]^-1 mod 2^128 and
1937 * put it in the parameter block.
1939 req->op.dsa.keymaterial.privateKey = req->parm[NSP_DSA_SIGN_X];
1940 req->op.dsa.keymaterial.p = req->parm[NSP_DSA_SIGN_P];
1941 req->op.dsa.keymaterial.q = req->parm[NSP_DSA_SIGN_Q];
1942 req->op.dsa.keymaterial.g = req->parm[NSP_DSA_SIGN_G];
1943 req->op.dsa.keymaterial.unitID = N8_ANY_UNIT;
1944 res = N8_DSAInitializeKey(&req->op.dsa.key, N8_PRIVATE,
1945 &req->op.dsa.keymaterial, &event);
1946 if (res != N8_STATUS_OK) {
1947 free(req, M_DEVBUF);
1948 printf("%s: N8_DSAInitializeKey failed, err=%d\n", __func__, res);
1949 krp->krp_status = res;
1950 crypto_kdone(krp);
1951 return 0;
1953 break;
1955 case CRK_DSA_VERIFY:
1956 /* inputs: dgst dsa->p dsa->q dsa->g dsa->pub_key sig->r sig->s */
1957 event.usrCallback = n8_kcallback_setup;
1958 event.usrData = (void *)req;
1961 * N8_DSAInitializeKey()
1962 * 1) Put p in the parameter block.
1963 * 2) Put q in the Parameter block.
1964 * 3) Put privateKey in the parameter block.
1965 * 4) Compute gR mod p and put it in the parameter block.
1966 * 5) Compute cp = -(p[0]^-1 mod 2^128 and
1967 * put it in the parameter block.
1969 req->op.dsa.keymaterial.publicKey = req->parm[NSP_DSA_VERIFY_Y];
1970 req->op.dsa.keymaterial.p = req->parm[NSP_DSA_VERIFY_P];
1971 req->op.dsa.keymaterial.q = req->parm[NSP_DSA_VERIFY_Q];
1972 req->op.dsa.keymaterial.g = req->parm[NSP_DSA_VERIFY_G];
1973 req->op.dsa.keymaterial.unitID = N8_ANY_UNIT;
1974 res = N8_DSAInitializeKey(&req->op.dsa.key, N8_PUBLIC,
1975 &req->op.dsa.keymaterial, &event);
1976 if (res != N8_STATUS_OK) {
1977 free(req, M_DEVBUF);
1978 printf("%s: N8_DSAInitializeKey failed, err=%d\n", __func__, res);
1979 krp->krp_status = n8_map_errno(res);
1980 crypto_kdone(krp);
1981 return 0;
1983 break;
1985 case CRK_DH_COMPUTE_KEY:
1987 /* inputs: dh->priv_key pub_key dh->p (prime modulus) key output g^x */
1988 /* key = pub_key ^ priv_key % p,
1989 * where pub_key is from second party, derived as pub_key = g^b % p,
1990 * where b is the second parties private key
1993 event.usrCallback = n8_kcallback_setup;
1994 event.usrData = (void *)req;
1996 req->op.dh.keymaterial.p =
1997 req->parm[NSP_DH_COMPUTE_KEY_P].value_p;
1998 req->op.dh.keymaterial.g =
1999 req->parm[NSP_DH_COMPUTE_KEY_PUB].value_p;
2000 req->op.dh.keymaterial.modulusSize =
2001 req->parm[NSP_DH_COMPUTE_KEY_P].lengthBytes;
2002 req->op.dh.keymaterial.unitID = N8_ANY_UNIT;
2004 DBG(("N8_DHInitializeKey: P=%08x %08x, PUB=%08x %08x\n",
2005 ((uint32_t *)req->parm[NSP_DH_COMPUTE_KEY_P].value_p)[0],
2006 ((uint32_t *)req->parm[NSP_DH_COMPUTE_KEY_P].value_p)[1],
2007 ((uint32_t *)req->parm[NSP_DH_COMPUTE_KEY_PUB].value_p)[0],
2008 ((uint32_t *)req->parm[NSP_DH_COMPUTE_KEY_PUB].value_p)[1]));
2010 res = N8_DHInitializeKey(&req->op.dh.key,
2011 &req->op.dh.keymaterial, &event);
2012 if (res != N8_STATUS_OK) {
2013 free(req, M_DEVBUF);
2014 printf("%s: N8_DHInitializeKey failed, err=%d\n", __func__, res);
2015 krp->krp_status = n8_map_errno(res);
2016 crypto_kdone(krp);
2017 return 0;
2019 break;
2022 case CRK_MOD_EXP:
2023 /* inputs: a^p % m */
2024 event.usrCallback = n8_kcallback_finish;
2025 event.usrData = (void *)req;
2026 res = N8_ModExponentiate(
2027 &req->parm[NSP_MOD_EXP_A],
2028 &req->parm[NSP_MOD_EXP_B],
2029 &req->parm[NSP_MOD_EXP_M],
2030 &req->parm[NSP_MOD_EXP_R0],
2031 N8_ANY_UNIT,
2032 &event);
2033 if (res != N8_STATUS_OK) {
2034 free(req, M_DEVBUF);
2035 printf("N8_ModExponentiate failed, err=%d\n",res);
2037 krp->krp_status = n8_map_errno(res);
2038 crypto_kdone(krp);
2039 return 0;
2041 break;
2043 case CRK_MOD_EXP_CRT:
2044 /* inputs: rsa->p rsa->q I rsa->dmp1 rsa->dmq1 rsa->iqmp */
2046 /* compute r0 = r0 ^ I mod rsa->n
2047 * inputs from OpenSSL:rsa_mod_exp(r0, I, rsa)
2048 * are p, q, I, dmp1 (DP), dmq1 (DQ), iqmp (QINV), r0.
2050 * N8 requires at least N to do this operation,
2051 * and N is not passed in by OpenSSL.
2052 * Q. Can OpenSSL provide it?
2053 * Q. Add another opencrypto op for this?
2056 /* Try doing this from a higher level so that N and D can
2057 * be passed in?
2058 * Construct the operation from smaller operations (slower)?
2061 krp->krp_status = EOPNOTSUPP;
2062 crypto_kdone(krp);
2063 break;
2065 case CRK_MOD_ADD:
2067 * inputs: A B Modulus
2068 * result = (A + B) mod Modulus
2070 event.usrCallback = n8_kcallback_finish;
2071 event.usrData = (void *)req;
2072 res = N8_ModAdd(
2073 &req->parm[NSP_MOD_ADD_A],
2074 &req->parm[NSP_MOD_ADD_B],
2075 &req->parm[NSP_MOD_ADD_M],
2076 &req->parm[NSP_MOD_ADD_R0],
2077 N8_ANY_UNIT,
2078 &event);
2079 if (res != N8_STATUS_OK) {
2080 free(req, M_DEVBUF);
2081 printf("N8_ModAdd failed, err=%d\n",res);
2083 krp->krp_status = n8_map_errno(res);
2084 crypto_kdone(krp);
2085 return 0;
2087 break;
2089 case CRK_MOD_ADDINV:
2091 * inputs: A Modulus
2092 * result = -A mod Modulus
2094 event.usrCallback = n8_kcallback_finish;
2095 event.usrData = (void *)req;
2096 res = N8_ModAdditiveInverse(
2097 &req->parm[NSP_MOD_ADDINV_A],
2098 &req->parm[NSP_MOD_ADDINV_M],
2099 &req->parm[NSP_MOD_ADDINV_R0],
2100 N8_ANY_UNIT,
2101 &event);
2102 if (res != N8_STATUS_OK) {
2103 free(req, M_DEVBUF);
2104 printf("N8_ModAdditiveInverse failed, err=%d\n",res);
2106 krp->krp_status = n8_map_errno(res);
2107 crypto_kdone(krp);
2108 return 0;
2110 break;
2112 case CRK_MOD_SUB:
2114 * inputs: A B Modulus
2115 * result = (A - B) mod Modulus
2117 event.usrCallback = n8_kcallback_finish;
2118 event.usrData = (void *)req;
2119 res = N8_ModSubtract(
2120 &req->parm[NSP_MOD_SUB_A],
2121 &req->parm[NSP_MOD_SUB_B],
2122 &req->parm[NSP_MOD_SUB_M],
2123 &req->parm[NSP_MOD_SUB_R0],
2124 N8_ANY_UNIT,
2125 &event);
2126 if (res != N8_STATUS_OK) {
2127 free(req, M_DEVBUF);
2128 printf("N8_ModSubtract failed, err=%d\n",res);
2130 krp->krp_status = n8_map_errno(res);
2131 crypto_kdone(krp);
2132 return 0;
2134 break;
2136 case CRK_MOD_MULT:
2138 * inputs: A B Modulus
2139 * result = (A * B) mod Modulus
2141 event.usrCallback = n8_kcallback_finish;
2142 event.usrData = (void *)req;
2143 res = N8_ModMultiply(
2144 &req->parm[NSP_MOD_MULT_A],
2145 &req->parm[NSP_MOD_MULT_B],
2146 &req->parm[NSP_MOD_MULT_M],
2147 &req->parm[NSP_MOD_MULT_R0],
2148 N8_ANY_UNIT,
2149 &event);
2150 if (res != N8_STATUS_OK) {
2151 free(req, M_DEVBUF);
2152 printf("N8_ModMultiply failed, err=%d\n",res);
2154 krp->krp_status = n8_map_errno(res);
2155 crypto_kdone(krp);
2156 return 0;
2158 break;
2160 case CRK_MOD_MULTINV:
2162 * inputs: A Modulus
2163 * result = (A ^ -1) mod Modulus
2165 event.usrCallback = n8_kcallback_finish;
2166 event.usrData = (void *)req;
2167 res = N8_ModMultiplicativeInverse(
2168 &req->parm[NSP_MOD_MULTINV_A],
2169 &req->parm[NSP_MOD_MULTINV_M],
2170 &req->parm[NSP_MOD_MULTINV_R0],
2171 N8_ANY_UNIT,
2172 &event);
2173 if (res != N8_STATUS_OK) {
2174 free(req, M_DEVBUF);
2175 printf("N8_ModMultiplicativeInverse failed, err=%d\n",res);
2177 krp->krp_status = n8_map_errno(res);
2178 crypto_kdone(krp);
2179 return 0;
2181 break;
2183 case CRK_MOD:
2185 * inputs: A Modulus
2186 * result = A mod Modulus
2188 event.usrCallback = n8_kcallback_finish;
2189 event.usrData = (void *)req;
2190 res = N8_Modulus(
2191 &req->parm[NSP_MODULUS_A],
2192 &req->parm[NSP_MODULUS_M],
2193 &req->parm[NSP_MODULUS_R0],
2194 N8_ANY_UNIT,
2195 &event);
2196 if (res != N8_STATUS_OK) {
2197 free(req, M_DEVBUF);
2198 printf("N8_Modulus failed, err=%d\n",res);
2200 krp->krp_status = n8_map_errno(res);
2201 crypto_kdone(krp);
2202 return 0;
2204 break;
2206 default:
2207 printf("nsp: n8_kprocess: invalid op %d\n", krp->krp_op);
2208 krp->krp_status = EOPNOTSUPP;
2209 crypto_kdone(krp);
2210 break;
2212 return res;