2 * Copyright (c) 2008 The NetBSD Foundation, Inc.
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
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.
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
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>
73 #include <sys/endian.h>
74 #include <sys/errno.h>
75 #include <sys/malloc.h>
76 #include <sys/kernel.h>
78 #include <sys/device.h>
79 #include <sys/queue.h>
80 #include <sys/module.h>
83 #include <uvm/uvm_extern.h>
85 #include <opencrypto/cryptodev.h>
86 #include <opencrypto/xform.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"
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"
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
);
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
[] = {
133 static struct cfattach
*nsp2000_cfattachs
[] = {
137 static const struct cfattachlkminit nsp2000_cfattachinit
[] = {
138 { "nsp2000", nsp2000_cfattachs
},
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
);
152 CFATTACH_DECL(nsp
, sizeof(struct nsp_softc
), nsp_probe
, nsp_attach
, nsp_detach
, NULL
);
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
,
163 struct cryptodesc
*crd
,
164 nsp_session_t
*session
);
165 static int n8_do_hash(struct nsp_softc
*sc
,
167 struct cryptodesc
*crd
,
168 nsp_session_t
*session
);
169 static int n8_start_crd(struct nsp_softc
*sc
,
171 struct cryptodesc
*crd
,
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 */
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" },
193 /* Supported key operations */
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" },
211 /* parameter handling definitions for each supported crypto key operation */
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;
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
;
241 const char *nsp_name
;
243 { PCI_VENDOR_NETOCTAVE
, PCI_PRODUCT_NETOCTAVE_NSP2000
,
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
)
268 nsp_probe(device_t parent
, cfdata_t match
, void *aux
)
271 struct pci_attach_args
*pa
= (struct pci_attach_args
*)aux
;
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 */
285 if (nsp_driverInit(N8_EA_POOL_SIZE
, N8_PK_POOL_SIZE
))
291 NSPcount_g
= 0; /* reset to zero since we increment in attach */
293 if (nsp_lookup(pa
) != NULL
)
300 /* initialize the session array into a free list of
301 * available sessions.
304 n8_sessionInit(struct nsp_softc
*sc
)
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];
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 */
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
);
341 panic("nsp_attach: impossible");
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
));
356 if (n8_driverInit(N8_EA_POOL_SIZE
, N8_PK_POOL_SIZE
)) {
357 DBG(("%s: Failed driver init\n", device_xname(&sc
->device
)));
361 DBG(("n8_driverInit complete\n"));
362 /* reset to zero for rest of attach */
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
));
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);
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",
404 intrstr
= pci_intr_string(sc
->pa_pc
, ih
);
405 sc
->int_handle
= pci_intr_establish(sc
->pa_pc
, ih
, IPL_NET
,
407 if (sc
->int_handle
== NULL
) {
408 aprint_error("nsp%d: couldn't establish interrupt", sc
->unit
);
410 aprint_normal(" at %s", intrstr
);
414 aprint_normal("nsp%d: interrupting at %s\n", sc
->unit
, intrstr
);
418 memset(nip
, 0, sizeof (*nip
));
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);
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",
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);
457 DBG(("nsp%d: couldn't get crypto driver id\n",
463 /* Increment our device count. */
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
);
475 DBG(("nsp_attach: failed to register %s, err=%d\n",
476 nsp_algo
[ind
].name
, res
));
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,
488 DBG(("nsp_attach: failed to kregister %s, err=%d\n",
489 nsp_key
[ind
].name
, res
));
491 DBG(("nsp_attach: kregistered %s\n",
496 DBG(("nsp_attach: ready\n"));
499 pci_intr_disestablish(sc
->pa_pc
, sc
->int_handle
);
500 sc
->int_handle
= NULL
;
502 bus_space_unmap(sc
->mem_tag
, sc
->mem_handle
, sc
->mem_size
);
509 nsp_detach(device_t dev
, int flags
)
511 struct nsp_softc
*sc
;
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
);
523 DBG(("nsp_attach: failed to unregister %s, err=%d\n",
524 nsp_algo
[ind
].name
, res
));
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
));
536 DBG(("nsp.%d no intr registered\n", sc
->unit
));
539 DBG(("nsp.%d: calling n8_driverRemove()\n", sc
->unit
));
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
);
546 DBG(("nsp.%d no memory mapped\n", sc
->unit
));
548 mutex_exit(&sc
->sc_intrlock
);
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
);
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 */
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"));
591 if (event_p
!= NULL
) {
592 event_p
->unit
= N8_RNG
;
593 event_p
->state
= NULL
;
594 event_p
->status
= N8_QUEUE_REQUEST_FINISHED
;
599 } /* N8_GetRandomBytes */
603 n8_gettime( n8_timeval_t
*n8_timeResults_p
)
607 N8_Status_t returnResults
= N8_STATUS_OK
;
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
;
620 /* map an N8 Status error to a semi-appropriate errno */
622 n8_map_errno(N8_Status_t error
)
627 case N8_INVALID_INPUT_SIZE
:
628 case N8_INVALID_OUTPUT_SIZE
:
629 case N8_INVALID_KEY_SIZE
:
631 case N8_INVALID_ENUM
:
633 case N8_INVALID_PARAMETER
:
634 case N8_INVALID_OBJECT
:
637 case N8_INVALID_PROTOCOL
:
640 case N8_INVALID_CIPHER
:
641 case N8_INVALID_HASH
:
642 case N8_INVALID_VALUE
:
646 case N8_UNIMPLEMENTED_FUNCTION
:
648 case N8_INCONSISTENT
:
650 case N8_NO_MORE_RESOURCE
:
653 case N8_MALLOC_FAILED
:
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
:
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",
681 mutex_exit(&sc
->sc_intrlock
);
684 sc
->freesession
= session
->next
;
685 session
->next
= NULL
;
686 session
->magic
= 0xDEADFEED;
687 mutex_exit(&sc
->sc_intrlock
);
689 session
->contextAllocated
= 0;
695 /* free a crypto op session */
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
);
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
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 **********************************************************************/
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
;
750 DBG(("n8_newsession(): sc == NULL\n"));
754 for (cinit
=cri
; cinit
!= NULL
; cinit
= cinit
->cri_next
) {
755 switch (cinit
->cri_alg
) {
758 case CRYPTO_MD5_HMAC
:
759 case CRYPTO_SHA1_HMAC
:
760 if (cinit_hash
!= NULL
) {
761 DBG(("n8_newsession(): ERROR - multiple hash requests\n"));
767 DBG(("n8_newsession(): invalid crypto op %d\n", cinit
->cri_alg
));
771 case CRYPTO_3DES_CBC
:
772 if (cinit_crypto
!= NULL
) {
773 DBG(("n8_newsession(): ERROR - multiple crypto requests\n"));
776 cinit_crypto
= cinit
;
782 if ((cinit_crypto
== NULL
) && (cinit_hash
== NULL
)) {
783 DBG(("n8_newsession(): no supported crypto ops\n"));
787 session
= n8_session_alloc(sc
);
788 if (session
== NULL
) {
789 DBG(("n8_newsession(): out of sessions (max = %d)\n",
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
);
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
);
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);
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
);
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],
861 DBG(("n8_newsession: stored hmac key %d bytes\n", session
->mackeylen
));
863 session
->mackeylen
= 0;
867 /* return the index for the session */
868 *sidp
= session
- sc
->session
;
870 session
->sid
= *sidp
;
872 DBG(("n8_newsession: completed - session %d\n", *sidp
));
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.
886 * else an errno value
887 * NOTES: XXX can this be called while the session is active?
888 **********************************************************************/
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
;
897 DBG(("n8_freesession(): sc == NULL\n"));
900 if (sid
>= NSP_MAX_SESSION
) {
901 DBG(("n8_freesession(): sid %d out of range\n",sid
));
905 session
= &sc
->session
[sid
];
908 * Need to check if a partial operation is in progress
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
921 n8_session_free(sc
, session
);
923 DBG(("n8_freesession: completed - session %d\n", sid
));
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
939 * else an errno value
940 **********************************************************************/
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);
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
));
955 DBG(("n8_process: sc == NULL\n"));
958 if (sid
>= NSP_MAX_SESSION
) {
959 DBG(("n8_process: sid %d out of range\n",sid
));
962 session
= &sc
->session
[sid
];
966 DBG(("n8_process: crp_ilen %d crp_olen %d crp_mac %p\n",
967 crp
->crp_ilen
, crp
->crp_olen
, crp
->crp_mac
));
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
) {
975 printf("\tCRYPTO_F_IMBUF\n");
978 printf("\tCRYPTO_F_IOV\n");
981 printf("\tCRYPTO_F_REL\n");
984 printf("\tCRYPTO_F_BATCH\n");
987 printf("\tCRYPTO_F_CBIMM\n");
990 printf("\tCRYPTO_F_DONE\n");
992 case CRYPTO_F_CBIFSYNC
:
993 printf("\tCRYPTO_F_CBIFSYNC\n");
996 printf("\tUnknown flag 0x%x\n", flag
);
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
1013 session
->mac
= (N8_Buffer_t
*)crp
->crp_mac
;
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
);
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
);
1045 /* check for supported set of operations */
1048 for (crd
=crp
->crp_desc
,crd_count
=0; crd
!= NULL
; crd
=crd
->crd_next
, crd_count
++) {
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");
1061 switch (crd
->crd_alg
) {
1064 case CRYPTO_MD5_HMAC
:
1065 case CRYPTO_SHA1_HMAC
:
1067 printf("n8_newsession(): multiple hash requests\n");
1073 case CRYPTO_AES_CBC
:
1074 printf("n8_newsession(): invalid crypto op %d\n", crd
->crd_alg
);
1078 case CRYPTO_DES_CBC
:
1079 case CRYPTO_3DES_CBC
:
1081 printf("n8_newsession(): multiple crypto requests\n");
1092 /* kick off first operation */
1093 session
->active
= 1;
1094 res
= n8_start_crd(sc
, crp
, crp
->crp_desc
, 0, session
);
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;
1109 /**********************************************************************
1110 * FUNCTION: n8_callback(*arg, status)
1111 * DESCRIPTION: Called when a crypto or hash operation is completed by
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.
1121 **********************************************************************/
1123 n8_callback(void *arg
, N8_Status_t status
)
1125 nsp_session_t
*session
=arg
;
1126 struct cryptop
*crp
;
1130 DBG(("n8_callback: session %d(0x%x) crd %d done, status %d\n",
1131 (uint32_t)(crp
->crp_sid
& 0xFFFFFFFF),
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;
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,
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;
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;
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 **********************************************************************/
1182 n8_start_crd(struct nsp_softc
*sc
,
1183 struct cryptop
*crp
,
1184 struct cryptodesc
*crd
,
1186 nsp_session_t
*session
)
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",
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");
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
) {
1215 case CRYPTO_MD5_HMAC
:
1216 case CRYPTO_SHA1_HMAC
:
1217 res
= n8_do_hash(sc
, crp
, crd
, session
);
1220 case CRYPTO_DES_CBC
:
1221 case CRYPTO_3DES_CBC
:
1222 res
= n8_do_crypt(sc
, crp
, crd
, session
);
1226 printf("n8_start_crd: invalid crypto op %d\n", crd
->crd_alg
);
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
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.
1247 **********************************************************************/
1249 n8_do_crypt(struct nsp_softc
*sc
,
1250 struct cryptop
*crp
,
1251 struct cryptodesc
*crd
,
1252 nsp_session_t
*session
)
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
);
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
,
1274 session
->cipherInfo
.key
.keyDES
.IV
);
1275 } else if (crp
->crp_flags
& CRYPTO_F_IOV
) {
1276 cuio_copyback(session
->src
.io
, crd
->crd_inject
,
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");
1298 res
= N8_Encrypt(&session
->crypt
,
1299 session
->src
.ptr
+crd
->crd_skip
,
1300 crd
->crd_len
, session
->dst
.ptr
+crd
->crd_inject
, &event
);
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");
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
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.
1331 **********************************************************************/
1333 n8_do_hash(struct nsp_softc
*sc
,
1334 struct cryptop
*crp
,
1335 struct cryptodesc
*crd
,
1336 nsp_session_t
*session
)
1340 N8_HashAlgorithm_t alg
;
1343 info
.unitID
= N8_ANY_UNIT
;
1346 switch (crd
->crd_alg
) {
1353 case CRYPTO_MD5_HMAC
:
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
;
1362 if (session
->mackeylen
== 0) {
1363 printf("No key provided for HMAC\n");
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
));
1372 case CRYPTO_SHA1_HMAC
:
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
;
1381 if (session
->mackeylen
== 0) {
1382 printf("No key provided for HMAC\n");
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
));
1391 case CRYPTO_RIPEMD160_HMAC
:
1395 printf("n8_do_hash: invalid hash algorithm %d\n",
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",
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 **********************************************************************/
1439 bn_le_to_be(uint8_t *le
, int numbits
, N8_Buffer_t
*be
)
1444 numbytes
= (numbits
+7)/8;
1446 for (ind
=0; ind
<numbytes
; ind
++) {
1447 be
[ind
] = le
[numbytes
-ind
-1];
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.
1472 **********************************************************************/
1474 n8_kcallback_finish(void *arg
, N8_Status_t status
)
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__
);
1486 if (status
== N8_STATUS_OK
) {
1491 /* was there an earlier 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;
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
:
1510 N8_DSAFreeKey(&req
->op
.dsa
.key
);
1512 case CRK_DH_COMPUTE_KEY
:
1513 N8_DHFreeKey(&req
->op
.dh
.key
);
1515 case CRK_MOD_EXP_CRT
:
1516 N8_RSAFreeKey(&req
->op
.rsa
.key
);
1519 /* nothing to clean up */
1524 crypto_kdone(req
->krp
);
1526 free(req
, M_DEVBUF
); /* XXX use a pool... */
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
);
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",
1565 res
= N8_DSAFreeKey(&req
->op
.dsa
.key
);
1566 if (res
!= N8_STATUS_OK
) {
1567 printf("%s: N8_DSAFreeKey failed, error=%d\n",
1570 req
->krp
->krp_status
= 0;
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",
1579 req
->krp
->krp_status
= 0;
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",
1588 req
->krp
->krp_status
= 0;
1592 req
->krp
->krp_status
= 0;
1596 /* Done - let the user app know */
1597 crypto_kdone(req
->krp
);
1599 free(req
, M_DEVBUF
); /* XXX replace with pool */
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
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.
1625 **********************************************************************/
1627 n8_kcallback_setup(void *arg
, N8_Status_t status
)
1633 DBG(("%s status %d\n", __func__
, status
));
1635 if (req
->krp
== NULL
) {
1636 printf("%s called with NULL krp\n", __func__
);
1640 if (status
== N8_STATUS_OK
) {
1641 /* was there an earlier 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;
1652 /* the rest of the operations return an ERRNO */
1653 req
->krp
->krp_status
= n8_map_errno(req
->error
);
1655 crypto_kdone(req
->krp
);
1657 free(req
, M_DEVBUF
); /* use a pool... */
1661 /* kick off the finishing op */
1662 event
.usrCallback
= n8_kcallback_finish
;
1663 event
.usrData
= (void *)req
;
1664 switch (req
->krp
->krp_op
) {
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
,
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
);
1676 free(req
, M_DEVBUF
); /* XXX use a pool... */
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
,
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
);
1692 free(req
, M_DEVBUF
); /* XXX use a pool... */
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
,
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
);
1711 free(req
, M_DEVBUF
); /* XXX use a pool... */
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
);
1720 free(req
, M_DEVBUF
); /* XXX use a pool... */
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
1737 * INPUTS: krp - opencrypto key operation description
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 **********************************************************************/
1745 check_key_parms(struct cryptkop
*krp
)
1749 if (krp
->krp_op
> CRK_ALGORITHM_MAX
) {
1750 printf("nsp: invalid crypto key op %d\n", krp
->krp_op
);
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
,
1757 crk_def
[krp
->krp_op
].iparmcount
);
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
,
1765 crk_def
[krp
->krp_op
].oparmcount
);
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
,
1777 krp
->krp_param
[ind
].crp_nbits
);
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
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
1798 * else an errno value
1799 **********************************************************************/
1801 n8_kprocess(void *arg
, struct cryptkop
*krp
, int hint
)
1803 struct nsp_softc
*sc
;
1806 n8_kreq_t
*req
; /* to hold result data */
1812 if ((krp
== NULL
) || (krp
->krp_callback
== NULL
))
1816 printf("n8_kprocess: error - sc == NULL\n");
1820 DBG(("n8_kprocess op %d, iparams %d, oparams %d, hid 0x%x\n",
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.
1834 * an array of 256 words by 128 bits per operand
1836 * N8 api bignum format:
1837 * a network byte order string (big-endian).
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
1861 res
= check_key_parms(krp
);
1863 krp
->krp_status
= res
;
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
);
1873 printf("n8_kprocess: failed to alloc req (size=%d)\n", sizeof(n8_kreq_t
));
1874 krp
->krp_status
= ENOMEM
;
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
);
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
);
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
;
1922 /* setup N8 call to call n8_kcallback with the request */
1924 switch (krp
->krp_op
) {
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
;
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
);
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
);
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
],
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
);
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
2058 * Construct the operation from smaller operations (slower)?
2061 krp
->krp_status
= EOPNOTSUPP
;
2067 * inputs: A B Modulus
2068 * result = (A + B) mod Modulus
2070 event
.usrCallback
= n8_kcallback_finish
;
2071 event
.usrData
= (void *)req
;
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
],
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
);
2089 case CRK_MOD_ADDINV
:
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
],
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
);
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
],
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
);
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
],
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
);
2160 case CRK_MOD_MULTINV
:
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
],
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
);
2186 * result = A mod Modulus
2188 event
.usrCallback
= n8_kcallback_finish
;
2189 event
.usrData
= (void *)req
;
2191 &req
->parm
[NSP_MODULUS_A
],
2192 &req
->parm
[NSP_MODULUS_M
],
2193 &req
->parm
[NSP_MODULUS_R0
],
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
);
2207 printf("nsp: n8_kprocess: invalid op %d\n", krp
->krp_op
);
2208 krp
->krp_status
= EOPNOTSUPP
;