summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/mips/conf/std.XLP10
-rw-r--r--sys/mips/nlm/dev/sec/nlmrsa.c556
-rw-r--r--sys/mips/nlm/dev/sec/nlmrsalib.h68
-rw-r--r--sys/mips/nlm/dev/sec/nlmsec.c850
-rw-r--r--sys/mips/nlm/dev/sec/nlmseclib.c307
-rw-r--r--sys/mips/nlm/dev/sec/nlmseclib.h157
-rw-r--r--sys/mips/nlm/dev/sec/rsa_ucode.h956
-rw-r--r--sys/mips/nlm/files.xlp6
-rw-r--r--sys/mips/nlm/hal/iomap.h1
-rw-r--r--sys/mips/nlm/hal/nlmsaelib.h607
10 files changed, 3518 insertions, 0 deletions
diff --git a/sys/mips/conf/std.XLP b/sys/mips/conf/std.XLP
index e998734..2d867c2 100644
--- a/sys/mips/conf/std.XLP
+++ b/sys/mips/conf/std.XLP
@@ -95,3 +95,13 @@ device iic
device iicbus
device iicoc
device ds1374 # RTC on XLP boards
+
+# Crypto
+device crypto
+device cryptodev
+device nlmsec
+device nlmrsa
+
+# Options that use crypto
+options IPSEC
+options GEOM_ELI
diff --git a/sys/mips/nlm/dev/sec/nlmrsa.c b/sys/mips/nlm/dev/sec/nlmrsa.c
new file mode 100644
index 0000000..2438fdf
--- /dev/null
+++ b/sys/mips/nlm/dev/sec/nlmrsa.c
@@ -0,0 +1,556 @@
+/*-
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/errno.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/mbuf.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sysctl.h>
+#include <sys/bus.h>
+#include <sys/random.h>
+#include <sys/rman.h>
+#include <sys/uio.h>
+#include <sys/kobj.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <opencrypto/cryptodev.h>
+
+#include "cryptodev_if.h"
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <mips/nlm/hal/haldefs.h>
+#include <mips/nlm/hal/iomap.h>
+#include <mips/nlm/xlp.h>
+#include <mips/nlm/hal/sys.h>
+#include <mips/nlm/hal/fmn.h>
+#include <mips/nlm/hal/nlmsaelib.h>
+#include <mips/nlm/dev/sec/nlmrsalib.h>
+#include <mips/nlm/dev/sec/rsa_ucode.h>
+#include <mips/nlm/hal/cop2.h>
+#include <mips/nlm/hal/mips-extns.h>
+#include <mips/nlm/msgring.h>
+
+#ifdef NLM_RSA_DEBUG
+int print_krp_params(struct cryptkop *krp);
+#endif
+
+static int xlp_rsa_init(struct xlp_rsa_softc *sc, int node);
+static int xlp_rsa_newsession(device_t , uint32_t *, struct cryptoini *);
+static int xlp_rsa_freesession(device_t , uint64_t);
+static int xlp_rsa_kprocess(device_t , struct cryptkop *, int);
+static int xlp_get_rsa_opsize(struct xlp_rsa_command *cmd, unsigned int bits);
+static void xlp_free_cmd_params(struct xlp_rsa_command *cmd);
+static int xlp_rsa_inp2hwformat(uint8_t *src, uint8_t *dst,
+ uint32_t paramsize, uint8_t result);
+
+static int xlp_rsa_probe(device_t);
+static int xlp_rsa_attach(device_t);
+static int xlp_rsa_detach(device_t);
+
+static device_method_t xlp_rsa_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, xlp_rsa_probe),
+ DEVMETHOD(device_attach, xlp_rsa_attach),
+ DEVMETHOD(device_detach, xlp_rsa_detach),
+
+ /* bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+
+ /* crypto device methods */
+ DEVMETHOD(cryptodev_newsession, xlp_rsa_newsession),
+ DEVMETHOD(cryptodev_freesession,xlp_rsa_freesession),
+ DEVMETHOD(cryptodev_kprocess, xlp_rsa_kprocess),
+
+ DEVMETHOD_END
+};
+
+static driver_t xlp_rsa_driver = {
+ "nlmrsa",
+ xlp_rsa_methods,
+ sizeof(struct xlp_rsa_softc)
+};
+static devclass_t xlp_rsa_devclass;
+
+DRIVER_MODULE(nlmrsa, pci, xlp_rsa_driver, xlp_rsa_devclass, 0, 0);
+MODULE_DEPEND(nlmrsa, crypto, 1, 1, 1);
+
+void
+nlm_xlprsaecc_msgring_handler(int vc, int size, int code, int src_id,
+ struct nlm_fmn_msg *msg, void *data);
+
+#ifdef NLM_RSA_DEBUG
+int
+print_krp_params(struct cryptkop *krp)
+{
+ int i;
+
+ printf("krp->krp_op :%d\n",krp->krp_op);
+ printf("krp->krp_status :%d\n",krp->krp_status);
+ printf("krp->krp_iparams:%d\n",krp->krp_iparams);
+ printf("krp->krp_oparams:%d\n",krp->krp_oparams);
+ for (i=0;i<krp->krp_iparams+krp->krp_oparams;i++) {
+ printf("krp->krp_param[%d].crp_p :0x%llx\n",i,
+ (unsigned long long)krp->krp_param[i].crp_p);
+ printf("krp->krp_param[%d].crp_nbits :%d\n",i,
+ krp->krp_param[i].crp_nbits);
+ printf("krp->krp_param[%d].crp_nbytes :%d\n",i,
+ (krp->krp_param[i].crp_nbits+7)/8);
+ }
+ return 0;
+}
+#endif
+
+static int
+xlp_rsa_init(struct xlp_rsa_softc *sc, int node)
+{
+ struct xlp_rsa_command *cmd = NULL;
+ uint32_t size, fbvc, dstvc, endsel, regval;
+ struct nlm_fmn_msg m;
+ int err, ret, i;
+ uint64_t base;
+
+ /* Register interrupt handler for the RSA/ECC CMS messages */
+ if (register_msgring_handler(sc->rsaecc_vc_start,
+ sc->rsaecc_vc_end, nlm_xlprsaecc_msgring_handler, sc) != 0) {
+ err = -1;
+ printf("Couldn't register rsa/ecc msgring handler\n");
+ goto errout;
+ }
+ m.msg[0] = m.msg[1] = m.msg[2] = m.msg[3] = 0;
+ fbvc = nlm_cpuid() / CMS_MAX_VCPU_VC;
+ /* Do the CMS credit initialization */
+ /* Currently it is configured by default to 50 when kernel comes up */
+
+ if ((cmd = malloc(sizeof(struct xlp_rsa_command), M_DEVBUF,
+ M_NOWAIT | M_ZERO)) == NULL) {
+ err = ENOMEM;
+ printf("Failed to allocate mem for cmd\n");
+ goto errout;
+ }
+ size = sizeof(nlm_rsa_ucode_data);
+ if ((cmd->rsasrc = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
+ err = ENOMEM;
+ printf("Failed to allocate mem for cmd->rsasrc\n");
+ goto errout;
+ }
+ if (((uintptr_t)cmd->rsasrc & (XLP_L2L3_CACHELINE_SIZE - 1))) {
+ err = EINVAL;
+ printf("cmd->rsasrc is not cacheline aligned\n");
+ goto errout;
+ }
+ memcpy(cmd->rsasrc, (uint8_t *)nlm_rsa_ucode_data, size);
+ m.msg[0] = nlm_crypto_form_rsa_ecc_fmn_entry0(1, 0x70, 0,
+ vtophys(cmd->rsasrc));
+ m.msg[1] = nlm_crypto_form_rsa_ecc_fmn_entry1(0, 1, fbvc,
+ vtophys(cmd->rsasrc));
+ /* Software scratch pad */
+ m.msg[2] = (uintptr_t)cmd;
+
+ for (dstvc = sc->rsaecc_vc_start; dstvc <= sc->rsaecc_vc_end; dstvc++) {
+ ret = nlm_fmn_msgsend(dstvc, 3, FMN_SWCODE_RSA, &m);
+ if (ret != 0) {
+ err = -1;
+ printf("%s: msgsnd failed (%x)\n", __func__, ret);
+ goto errout;
+ }
+ }
+ /* Configure so that all VCs send request to all RSA pipes */
+ base = nlm_get_rsa_regbase(node);
+ if (nlm_is_xlp3xx()) {
+ endsel = 1;
+ regval = 0xFFFF;
+ } else {
+ endsel = 3;
+ regval = 0x07FFFFFF;
+ }
+ for (i = 0; i < endsel; i++)
+ nlm_write_rsa_reg(base, RSA_ENG_SEL_0 + i, regval);
+ return (0);
+errout:
+ xlp_free_cmd_params(cmd);
+ return (err);
+}
+
+/* This function is called from an interrupt handler */
+void
+nlm_xlprsaecc_msgring_handler(int vc, int size, int code, int src_id,
+ struct nlm_fmn_msg *msg, void *data)
+{
+ struct xlp_rsa_command *cmd = NULL;
+ struct xlp_rsa_softc *sc = NULL;
+
+ KASSERT(code == FMN_SWCODE_RSA,
+ ("%s: bad code = %d, expected code = %d\n", __FUNCTION__, code,
+ FMN_SWCODE_RSA));
+
+ sc = (struct xlp_rsa_softc *)data;
+ KASSERT(src_id >= sc->rsaecc_vc_start && src_id <= sc->rsaecc_vc_end,
+ ("%s: bad src_id = %d, expect %d - %d\n", __FUNCTION__,
+ src_id, sc->rsaecc_vc_start, sc->rsaecc_vc_end));
+
+ cmd = (struct xlp_rsa_command *)(uintptr_t)msg->msg[1];
+ KASSERT(cmd != NULL, ("%s:cmd not received properly\n",
+ __FUNCTION__));
+
+ KASSERT(RSA_ERROR(msg->msg[0]) == 0,
+ ("%s: Message rcv msg0 %llx msg1 %llx err %x \n", __FUNCTION__,
+ (unsigned long long)msg->msg[0], (unsigned long long)msg->msg[1],
+ (int)RSA_ERROR(msg->msg[0])));
+
+ xlp_rsa_inp2hwformat(((uint8_t *)cmd->rsasrc+
+ (cmd->rsaopsize*cmd->krp->krp_iparams)),
+ cmd->krp->krp_param[cmd->krp->krp_iparams].crp_p,
+ ((cmd->krp->krp_param[cmd->krp->krp_iparams].crp_nbits+7)/8), 1);
+
+ if (cmd->krp != NULL)
+ crypto_kdone(cmd->krp);
+
+ xlp_free_cmd_params(cmd);
+
+ return;
+}
+
+static int
+xlp_rsa_probe(device_t dev)
+{
+ struct xlp_rsa_softc *sc;
+
+ if (pci_get_vendor(dev) == PCI_VENDOR_NETLOGIC &&
+ pci_get_device(dev) == PCI_DEVICE_ID_NLM_RSA) {
+ sc = device_get_softc(dev);
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+/*
+ * Attach an interface that successfully probed.
+ */
+static int
+xlp_rsa_attach(device_t dev)
+{
+ struct xlp_rsa_softc *sc = device_get_softc(dev);
+ uint64_t base;
+ int qstart, qnum;
+ int freq, node;
+
+ sc->sc_dev = dev;
+
+ node = nlm_get_device_node(pci_get_slot(dev));
+ freq = nlm_set_device_frequency(node, DFS_DEVICE_RSA, 250);
+ if (bootverbose)
+ device_printf(dev, "RSA Freq: %dMHz\n", freq);
+ if(pci_get_device(dev) == PCI_DEVICE_ID_NLM_RSA) {
+ device_set_desc(dev, "XLP RSA/ECC Accelerator");
+ if ((sc->sc_cid = crypto_get_driverid(dev,
+ CRYPTOCAP_F_HARDWARE)) < 0) {
+ printf("xlp_rsaecc-err:couldn't get the driver id\n");
+ goto error_exit;
+ }
+ if (crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0) != 0)
+ printf("register failed for CRK_MOD_EXP\n");
+
+ base = nlm_get_rsa_pcibase(node);
+ qstart = nlm_qidstart(base);
+ qnum = nlm_qnum(base);
+ sc->rsaecc_vc_start = qstart;
+ sc->rsaecc_vc_end = qstart + qnum - 1;
+ }
+ if (xlp_rsa_init(sc, node) != 0)
+ goto error_exit;
+ device_printf(dev, "RSA Initialization complete!\n");
+ return (0);
+
+error_exit:
+ return (ENXIO);
+
+}
+
+/*
+ * Detach an interface that successfully probed.
+ */
+static int
+xlp_rsa_detach(device_t dev)
+{
+ return (0);
+}
+
+/*
+ * Allocate a new 'session' and return an encoded session id. 'sidp'
+ * contains our registration id, and should contain an encoded session
+ * id on successful allocation.
+ */
+static int
+xlp_rsa_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
+{
+ struct xlp_rsa_softc *sc = device_get_softc(dev);
+ int sesn;
+ struct xlp_rsa_session *ses = NULL;
+
+ if (sidp == NULL || cri == NULL || sc == NULL)
+ return (EINVAL);
+
+ if (sc->sc_sessions == NULL) {
+ ses = sc->sc_sessions = malloc(sizeof(struct xlp_rsa_session),
+ M_DEVBUF, M_NOWAIT);
+ if (ses == NULL)
+ return (ENOMEM);
+ sesn = 0;
+ sc->sc_nsessions = 1;
+ } else {
+ for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
+ if (!sc->sc_sessions[sesn].hs_used) {
+ ses = &sc->sc_sessions[sesn];
+ break;
+ }
+ }
+
+ if (ses == NULL) {
+ sesn = sc->sc_nsessions;
+ ses = malloc((sesn + 1)*sizeof(struct xlp_rsa_session),
+ M_DEVBUF, M_NOWAIT);
+ if (ses == NULL)
+ return (ENOMEM);
+ bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
+ bzero(sc->sc_sessions, sesn * sizeof(*ses));
+ free(sc->sc_sessions, M_DEVBUF);
+ sc->sc_sessions = ses;
+ ses = &sc->sc_sessions[sesn];
+ sc->sc_nsessions++;
+ }
+ }
+ bzero(ses, sizeof(*ses));
+ ses->sessionid = sesn;
+ ses->hs_used = 1;
+
+ *sidp = XLP_RSA_SID(device_get_unit(sc->sc_dev), sesn);
+ return (0);
+}
+
+/*
+ * Deallocate a session.
+ * XXX this routine should run a zero'd mac/encrypt key into context ram.
+ * XXX to blow away any keys already stored there.
+ */
+static int
+xlp_rsa_freesession(device_t dev, u_int64_t tid)
+{
+ struct xlp_rsa_softc *sc = device_get_softc(dev);
+ int session;
+ u_int32_t sid = CRYPTO_SESID2LID(tid);
+
+ if (sc == NULL)
+ return (EINVAL);
+
+ session = XLP_RSA_SESSION(sid);
+ if (session >= sc->sc_nsessions)
+ return (EINVAL);
+
+ sc->sc_sessions[session].hs_used = 0;
+ return (0);
+}
+
+static void
+xlp_free_cmd_params(struct xlp_rsa_command *cmd)
+{
+ if (cmd->rsasrc != NULL)
+ free(cmd->rsasrc, M_DEVBUF);
+ if (cmd != NULL)
+ free(cmd, M_DEVBUF);
+ return;
+}
+
+static int
+xlp_get_rsa_opsize(struct xlp_rsa_command *cmd, unsigned int bits)
+{
+ if (bits == 0)
+ return (-1);
+ /* XLP hardware expects always a fixed size with unused bytes
+ * zeroed out in the input data */
+ if (bits <= 512) {
+ cmd->rsatype = 0x40;
+ cmd->rsaopsize = (512/8);
+ return (0);
+ } else if ((bits > 512) && (bits <= 1024)) {
+ cmd->rsatype = 0x41;
+ cmd->rsaopsize = (1024/8);
+ return (0);
+ } else if ((bits > 1024) && (bits <= 2048)) {
+ cmd->rsatype = 0x42;
+ cmd->rsaopsize = (2048/8);
+ return (0);
+ } else if ((bits > 2048) && (bits <= 4096)) {
+ cmd->rsatype = 0x43;
+ cmd->rsaopsize = (4096/8);
+ return (0);
+ } else if ((bits > 4096) && (bits <= 8192)) {
+ cmd->rsatype = 0x44;
+ cmd->rsaopsize = (8192/8);
+ return (0);
+ } else {
+ return (-1);
+ }
+}
+
+static int
+xlp_rsa_inp2hwformat(uint8_t *src, uint8_t *dst, uint32_t paramsize,
+ uint8_t result)
+{
+ uint32_t pdwords, pbytes;
+ int i=0, j=0, k=0;
+
+ pdwords = (paramsize / 8);
+ pbytes = (paramsize % 8);
+
+ for (i = 0, k = 0; i < pdwords; i++) {
+ /* copy dwords of inp/hw to hw/out format */
+ for (j = 7; j >= 0; j--, k++)
+ dst[(i*8)+j] = src[k];
+ }
+ if (pbytes) {
+ if (!result) {
+ /* copy rem bytes of input data to hw format */
+ for (j = 7; k < paramsize; j--, k++)
+ dst[(i*8)+j] = src[k];
+ } else {
+ /* copy rem bytes of hw data to exp output format */
+ for (j = 7; k < paramsize; j--, k++)
+ dst[k] = src[(i*8)+j];
+ }
+ }
+
+ return (0);
+}
+
+static int
+nlm_crypto_complete_rsa_request(struct xlp_rsa_softc *sc,
+ struct xlp_rsa_command *cmd)
+{
+ unsigned int fbvc;
+ struct nlm_fmn_msg m;
+ int ret;
+
+ fbvc = nlm_cpuid() / CMS_MAX_VCPU_VC;
+ m.msg[0] = m.msg[1] = m.msg[2] = m.msg[3] = 0;
+
+ m.msg[0] = nlm_crypto_form_rsa_ecc_fmn_entry0(1, cmd->rsatype,
+ cmd->rsafn, vtophys(cmd->rsasrc));
+ m.msg[1] = nlm_crypto_form_rsa_ecc_fmn_entry1(0, 1, fbvc,
+ vtophys(cmd->rsasrc + (cmd->rsaopsize * cmd->krp->krp_iparams)));
+ /* Software scratch pad */
+ m.msg[2] = (uintptr_t)cmd;
+
+ /* Send the message to rsa engine vc */
+ ret = nlm_fmn_msgsend(sc->rsaecc_vc_start, 3, FMN_SWCODE_RSA, &m);
+ if (ret != 0) {
+#ifdef NLM_SEC_DEBUG
+ printf("%s: msgsnd failed (%x)\n", __func__, ret);
+#endif
+ return (ERESTART);
+ }
+ return (0);
+}
+
+static int
+xlp_rsa_kprocess(device_t dev, struct cryptkop *krp, int hint)
+{
+ struct xlp_rsa_softc *sc = device_get_softc(dev);
+ struct xlp_rsa_command *cmd = NULL;
+ int err = -1, i;
+
+ if (krp == NULL || krp->krp_callback == NULL)
+ return (EINVAL);
+
+ if ((cmd = malloc(sizeof(struct xlp_rsa_command), M_DEVBUF,
+ M_NOWAIT | M_ZERO)) == NULL) {
+ err = ENOMEM;
+ goto errout;
+ }
+ cmd->krp = krp;
+
+#ifdef NLM_RSA_DEBUG
+ print_krp_params(krp);
+#endif
+ switch (krp->krp_op) {
+ case CRK_MOD_EXP:
+ if (krp->krp_iparams == 3 && krp->krp_oparams == 1)
+ break;
+ goto errout;
+ default:
+ printf("Op:%d not yet supported\n", krp->krp_op);
+ goto errout;
+ }
+
+ if ((xlp_get_rsa_opsize(cmd,
+ krp->krp_param[krp->krp_iparams-1].crp_nbits)) != 0) {
+ err = EINVAL;
+ goto errout;
+ }
+ cmd->rsafn = 0; /* Mod Exp */
+ if ((cmd->rsasrc = malloc((cmd->rsaopsize *
+ (krp->krp_iparams+krp->krp_oparams)), M_DEVBUF,
+ M_NOWAIT | M_ZERO)) == NULL) {
+ err = ENOMEM;
+ goto errout;
+ }
+ if (((uintptr_t)cmd->rsasrc & (XLP_L2L3_CACHELINE_SIZE - 1))) {
+ err = EINVAL;
+ goto errout;
+ }
+
+ for (i=0;i<krp->krp_iparams;i++) {
+ KASSERT(krp->krp_param[i].crp_nbits != 0,
+ ("%s: parameter[%d]'s length is zero\n", __FUNCTION__, i));
+ xlp_rsa_inp2hwformat(krp->krp_param[i].crp_p,
+ ((uint8_t *)cmd->rsasrc+(i*cmd->rsaopsize)),
+ ((krp->krp_param[i].crp_nbits+7)/8), 0);
+ }
+ if (nlm_crypto_complete_rsa_request(sc, cmd) != 0)
+ goto errout;
+
+ return (0);
+errout:
+ xlp_free_cmd_params(cmd);
+ krp->krp_status = err;
+ crypto_kdone(krp);
+ return (err);
+}
diff --git a/sys/mips/nlm/dev/sec/nlmrsalib.h b/sys/mips/nlm/dev/sec/nlmrsalib.h
new file mode 100644
index 0000000..24c42e1
--- /dev/null
+++ b/sys/mips/nlm/dev/sec/nlmrsalib.h
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _NLMRSALIB_H_
+#define _NLMRSALIB_H_
+
+#define XLP_RSA_SESSION(sid) ((sid) & 0x000007ff)
+#define XLP_RSA_SID(crd,ses) (((crd) << 28) | ((ses) & 0x7ff))
+
+#define NUM_RSAECC_VC 9
+
+#define RSA_ERROR(__msg0) ((__msg0 >> 53) & 0x1f)
+
+struct xlp_rsa_session {
+ uint32_t sessionid;
+ int hs_used;
+};
+
+struct xlp_rsa_command {
+ uint16_t session_num;
+ struct xlp_rsa_session *ses;
+ struct cryptkop *krp;
+ uint8_t *rsasrc;
+ uint32_t rsaopsize;
+ uint32_t rsatype;
+ uint32_t rsafn;
+};
+
+/*
+ * Holds data specific to nlm security accelerators
+ */
+struct xlp_rsa_softc {
+ device_t sc_dev; /* device backpointer */
+ uint64_t rsa_base;
+ int sc_cid;
+ struct xlp_rsa_session *sc_sessions;
+ int sc_nsessions;
+ int rsaecc_vc_start;
+ int rsaecc_vc_end;
+};
+
+#endif /* _NLMRSALIB_H_ */
diff --git a/sys/mips/nlm/dev/sec/nlmsec.c b/sys/mips/nlm/dev/sec/nlmsec.c
new file mode 100644
index 0000000..4c95661
--- /dev/null
+++ b/sys/mips/nlm/dev/sec/nlmsec.c
@@ -0,0 +1,850 @@
+/*-
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/errno.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/mbuf.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sysctl.h>
+#include <sys/bus.h>
+#include <sys/random.h>
+#include <sys/rman.h>
+#include <sys/uio.h>
+#include <sys/kobj.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <opencrypto/cryptodev.h>
+
+#include "cryptodev_if.h"
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <mips/nlm/hal/haldefs.h>
+#include <mips/nlm/hal/iomap.h>
+#include <mips/nlm/xlp.h>
+#include <mips/nlm/hal/sys.h>
+#include <mips/nlm/hal/fmn.h>
+#include <mips/nlm/hal/nlmsaelib.h>
+#include <mips/nlm/dev/sec/nlmseclib.h>
+#include <mips/nlm/hal/cop2.h>
+#include <mips/nlm/hal/mips-extns.h>
+#include <mips/nlm/msgring.h>
+
+unsigned int creditleft;
+
+void xlp_sec_print_data(struct cryptop *crp);
+
+static int xlp_sec_init(struct xlp_sec_softc *sc);
+static int xlp_sec_newsession(device_t , uint32_t *, struct cryptoini *);
+static int xlp_sec_freesession(device_t , uint64_t);
+static int xlp_sec_process(device_t , struct cryptop *, int);
+static int xlp_copyiv(struct xlp_sec_softc *, struct xlp_sec_command *,
+ struct cryptodesc *enccrd);
+static int xlp_get_nsegs(struct cryptop *, unsigned int *);
+static int xlp_alloc_cmd_params(struct xlp_sec_command *, unsigned int);
+static void xlp_free_cmd_params(struct xlp_sec_command *);
+
+static int xlp_sec_probe(device_t);
+static int xlp_sec_attach(device_t);
+static int xlp_sec_detach(device_t);
+
+static device_method_t xlp_sec_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, xlp_sec_probe),
+ DEVMETHOD(device_attach, xlp_sec_attach),
+ DEVMETHOD(device_detach, xlp_sec_detach),
+
+ /* bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+
+ /* crypto device methods */
+ DEVMETHOD(cryptodev_newsession, xlp_sec_newsession),
+ DEVMETHOD(cryptodev_freesession,xlp_sec_freesession),
+ DEVMETHOD(cryptodev_process, xlp_sec_process),
+
+ DEVMETHOD_END
+};
+
+static driver_t xlp_sec_driver = {
+ "nlmsec",
+ xlp_sec_methods,
+ sizeof(struct xlp_sec_softc)
+};
+static devclass_t xlp_sec_devclass;
+
+DRIVER_MODULE(nlmsec, pci, xlp_sec_driver, xlp_sec_devclass, 0, 0);
+MODULE_DEPEND(nlmsec, crypto, 1, 1, 1);
+
+void
+nlm_xlpsec_msgring_handler(int vc, int size, int code, int src_id,
+ struct nlm_fmn_msg *msg, void *data);
+
+#ifdef NLM_SEC_DEBUG
+
+#define extract_bits(x, bitshift, bitcnt) \
+ (((unsigned long long)x >> bitshift) & ((1ULL << bitcnt) - 1))
+
+void
+print_crypto_params(struct xlp_sec_command *cmd, struct nlm_fmn_msg m)
+{
+ unsigned long long msg0,msg1,msg2,msg3,msg4,msg5,msg6,msg7,msg8;
+
+ msg0 = cmd->ctrlp->desc0;
+ msg1 = cmd->paramp->desc0;
+ msg2 = cmd->paramp->desc1;
+ msg3 = cmd->paramp->desc2;
+ msg4 = cmd->paramp->desc3;
+ msg5 = cmd->paramp->segment[0][0];
+ msg6 = cmd->paramp->segment[0][1];
+ msg7 = m.msg[0];
+ msg8 = m.msg[1];
+
+ printf("msg0 %llx msg1 %llx msg2 %llx msg3 %llx msg4 %llx msg5 %llx"
+ "msg6 %llx msg7 %llx msg8 %llx\n", msg0, msg1, msg2, msg3, msg4,
+ msg5, msg6, msg7, msg8);
+
+ printf("c0: hmac %d htype %d hmode %d ctype %d cmode %d arc4 %x\n",
+ (unsigned int)extract_bits(msg0, 61, 1),
+ (unsigned int)extract_bits(msg0, 52, 8),
+ (unsigned int)extract_bits(msg0, 43, 8),
+ (unsigned int)extract_bits(msg0, 34, 8),
+ (unsigned int)extract_bits(msg0, 25, 8),
+ (unsigned int)extract_bits(msg0, 0, 23));
+
+ printf("p0: tls %d hsrc %d hl3 %d enc %d ivl %d hd %llx\n",
+ (unsigned int)extract_bits(msg1, 63, 1),
+ (unsigned int)extract_bits(msg1,62,1),
+ (unsigned int)extract_bits(msg1,60,1),
+ (unsigned int)extract_bits(msg1,59,1),
+ (unsigned int)extract_bits(msg1,41,16), extract_bits(msg1,0,40));
+
+ printf("p1: clen %u hl %u\n", (unsigned int)extract_bits(msg2, 32, 32),
+ (unsigned int)extract_bits(msg2,0,32));
+
+ printf("p2: ivoff %d cbit %d coff %d hbit %d hclb %d hoff %d\n",
+ (unsigned int)extract_bits(msg3, 45, 17),
+ (unsigned int)extract_bits(msg3, 42,3),
+ (unsigned int)extract_bits(msg3, 22,16),
+ (unsigned int)extract_bits(msg3, 19,3),
+ (unsigned int)extract_bits(msg3, 18,1),
+ (unsigned int)extract_bits(msg3, 0, 16));
+
+ printf("p3: desfbid %d tlen %d arc4 %x hmacpad %d\n",
+ (unsigned int)extract_bits(msg4, 48,16),
+ (unsigned int)extract_bits(msg4,11,16),
+ (unsigned int)extract_bits(msg4,6,3),
+ (unsigned int)extract_bits(msg4,5,1));
+
+ printf("p4: sflen %d sddr %llx \n",
+ (unsigned int)extract_bits(msg5, 48, 16),extract_bits(msg5, 0, 40));
+
+ printf("p5: dflen %d cl3 %d cclob %d cdest %llx \n",
+ (unsigned int)extract_bits(msg6, 48, 16),
+ (unsigned int)extract_bits(msg6, 46, 1),
+ (unsigned int)extract_bits(msg6, 41, 1), extract_bits(msg6, 0, 40));
+
+ printf("fmn0: fbid %d dfrlen %d dfrv %d cklen %d cdescaddr %llx\n",
+ (unsigned int)extract_bits(msg7, 48, 16),
+ (unsigned int)extract_bits(msg7,46,2),
+ (unsigned int)extract_bits(msg7,45,1),
+ (unsigned int)extract_bits(msg7,40,5),
+ (extract_bits(msg7,0,34)<< 6));
+
+ printf("fmn1: arc4 %d hklen %d pdesclen %d pktdescad %llx\n",
+ (unsigned int)extract_bits(msg8, 63, 1),
+ (unsigned int)extract_bits(msg8,56,5),
+ (unsigned int)extract_bits(msg8,43,12),
+ (extract_bits(msg8,0,34) << 6));
+
+ return;
+}
+
+void
+xlp_sec_print_data(struct cryptop *crp)
+{
+ int i, key_len;
+ struct cryptodesc *crp_desc;
+
+ printf("session id = 0x%llx, crp_ilen = %d, crp_olen=%d \n",
+ crp->crp_sid, crp->crp_ilen, crp->crp_olen);
+
+ printf("crp_flags = 0x%x\n", crp->crp_flags);
+
+ printf("crp buf:\n");
+ for (i = 0; i < crp->crp_ilen; i++) {
+ printf("%c ", crp->crp_buf[i]);
+ if (i % 10 == 0)
+ printf("\n");
+ }
+
+ printf("\n");
+ printf("****************** desc ****************\n");
+ crp_desc = crp->crp_desc;
+ printf("crd_skip=%d, crd_len=%d, crd_flags=0x%x, crd_alg=%d\n",
+ crp_desc->crd_skip, crp_desc->crd_len, crp_desc->crd_flags,
+ crp_desc->crd_alg);
+
+ key_len = crp_desc->crd_klen / 8;
+ printf("key(%d) :\n", key_len);
+ for (i = 0; i < key_len; i++)
+ printf("%d", crp_desc->crd_key[i]);
+ printf("\n");
+
+ printf(" IV : \n");
+ for (i = 0; i < EALG_MAX_BLOCK_LEN; i++)
+ printf("%d", crp_desc->crd_iv[i]);
+ printf("\n");
+
+ printf("crd_next=%p\n", crp_desc->crd_next);
+ return;
+}
+
+void
+print_cmd(struct xlp_sec_command *cmd)
+{
+ printf("session_num :%d\n",cmd->session_num);
+ printf("crp :0x%x\n",(uint32_t)cmd->crp);
+ printf("enccrd :0x%x\n",(uint32_t)cmd->enccrd);
+ printf("maccrd :0x%x\n",(uint32_t)cmd->maccrd);
+ printf("ses :%d\n",(uint32_t)cmd->ses);
+ printf("ctrlp :0x%x\n",(uint32_t)cmd->ctrlp);
+ printf("paramp :0x%x\n",(uint32_t)cmd->paramp);
+ printf("hashdest :0x%x\n",(uint32_t)cmd->hashdest);
+ printf("hashsrc :%d\n",cmd->hashsrc);
+ printf("hmacpad :%d\n",cmd->hmacpad);
+ printf("hashoff :%d\n",cmd->hashoff);
+ printf("hashlen :%d\n",cmd->hashlen);
+ printf("cipheroff :%d\n",cmd->cipheroff);
+ printf("cipherlen :%d\n",cmd->cipherlen);
+ printf("ivoff :%d\n",cmd->ivoff);
+ printf("ivlen :%d\n",cmd->ivlen);
+ printf("hashalg :%d\n",cmd->hashalg);
+ printf("hashmode :%d\n",cmd->hashmode);
+ printf("cipheralg :%d\n",cmd->cipheralg);
+ printf("ciphermode :%d\n",cmd->ciphermode);
+ printf("nsegs :%d\n",cmd->nsegs);
+ printf("hash_dst_len :%d\n",cmd->hash_dst_len);
+}
+#endif /* NLM_SEC_DEBUG */
+
+static int
+xlp_sec_init(struct xlp_sec_softc *sc)
+{
+
+ /* Register interrupt handler for the SEC CMS messages */
+ if (register_msgring_handler(sc->sec_vc_start,
+ sc->sec_vc_end, nlm_xlpsec_msgring_handler, sc) != 0) {
+ printf("Couldn't register sec msgring handler\n");
+ return (-1);
+ }
+
+ /* Do the CMS credit initialization */
+ /* Currently it is configured by default to 50 when kernel comes up */
+
+ return (0);
+}
+
+/* This function is called from an interrupt handler */
+void
+nlm_xlpsec_msgring_handler(int vc, int size, int code, int src_id,
+ struct nlm_fmn_msg *msg, void *data)
+{
+ struct xlp_sec_command *cmd = NULL;
+ struct xlp_sec_softc *sc = NULL;
+ struct cryptodesc *crd = NULL;
+ unsigned int ivlen = 0;
+
+ KASSERT(code == FMN_SWCODE_CRYPTO,
+ ("%s: bad code = %d, expected code = %d\n", __FUNCTION__,
+ code, FMN_SWCODE_CRYPTO));
+
+ sc = (struct xlp_sec_softc *)data;
+ KASSERT(src_id >= sc->sec_vc_start && src_id <= sc->sec_vc_end,
+ ("%s: bad src_id = %d, expect %d - %d\n", __FUNCTION__,
+ src_id, sc->sec_vc_start, sc->sec_vc_end));
+
+ cmd = (struct xlp_sec_command *)(uintptr_t)msg->msg[0];
+ KASSERT(cmd != NULL && cmd->crp != NULL,
+ ("%s :cmd not received properly\n",__FUNCTION__));
+
+ KASSERT(CRYPTO_ERROR(msg->msg[1]) == 0,
+ ("%s: Message rcv msg0 %llx msg1 %llx err %x \n", __FUNCTION__,
+ (unsigned long long)msg->msg[0], (unsigned long long)msg->msg[1],
+ (int)CRYPTO_ERROR(msg->msg[1])));
+
+ crd = cmd->enccrd;
+ /* Copy the last 8 or 16 bytes to the session iv, so that in few
+ * cases this will be used as IV for the next request
+ */
+ if (crd != NULL) {
+ if ((crd->crd_alg == CRYPTO_DES_CBC ||
+ crd->crd_alg == CRYPTO_3DES_CBC ||
+ crd->crd_alg == CRYPTO_AES_CBC) &&
+ (crd->crd_flags & CRD_F_ENCRYPT)) {
+ ivlen = ((crd->crd_alg == CRYPTO_AES_CBC) ?
+ XLP_SEC_AES_IV_LENGTH : XLP_SEC_DES_IV_LENGTH);
+ crypto_copydata(cmd->crp->crp_flags, cmd->crp->crp_buf,
+ crd->crd_skip + crd->crd_len - ivlen, ivlen,
+ sc->sc_sessions[cmd->session_num].ses_iv);
+ }
+ }
+
+ /* If there are not enough credits to send, then send request
+ * will fail with ERESTART and the driver will be blocked until it is
+ * unblocked here after knowing that there are sufficient credits to
+ * send the request again.
+ */
+ if (sc->sc_needwakeup) {
+ atomic_add_int(&creditleft, sc->sec_msgsz);
+ if (creditleft >= (NLM_CRYPTO_LEFT_REQS)) {
+ crypto_unblock(sc->sc_cid, sc->sc_needwakeup);
+ sc->sc_needwakeup &= (~(CRYPTO_SYMQ | CRYPTO_ASYMQ));
+ }
+ }
+ if(cmd->maccrd) {
+ crypto_copyback(cmd->crp->crp_flags,
+ cmd->crp->crp_buf, cmd->maccrd->crd_inject,
+ cmd->hash_dst_len, cmd->hashdest);
+ }
+
+ /* This indicates completion of the crypto operation */
+ crypto_done(cmd->crp);
+
+ xlp_free_cmd_params(cmd);
+
+ return;
+}
+
+static int
+xlp_sec_probe(device_t dev)
+{
+ struct xlp_sec_softc *sc;
+
+ if (pci_get_vendor(dev) == PCI_VENDOR_NETLOGIC &&
+ pci_get_device(dev) == PCI_DEVICE_ID_NLM_SAE) {
+ sc = device_get_softc(dev);
+ return (BUS_PROBE_DEFAULT);
+ }
+ return (ENXIO);
+}
+
+/*
+ * Attach an interface that successfully probed.
+ */
+static int
+xlp_sec_attach(device_t dev)
+{
+ struct xlp_sec_softc *sc = device_get_softc(dev);
+ uint64_t base;
+ int qstart, qnum;
+ int freq, node;
+
+ sc->sc_dev = dev;
+
+ node = nlm_get_device_node(pci_get_slot(dev));
+ freq = nlm_set_device_frequency(node, DFS_DEVICE_SAE, 250);
+ if (bootverbose)
+ device_printf(dev, "SAE Freq: %dMHz\n", freq);
+ if(pci_get_device(dev) == PCI_DEVICE_ID_NLM_SAE) {
+ device_set_desc(dev, "XLP Security Accelerator");
+ sc->sc_cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE);
+ if (sc->sc_cid < 0) {
+ printf("xlp_sec - error : could not get the driver"
+ " id\n");
+ goto error_exit;
+ }
+ if (crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0) != 0)
+ printf("register failed for CRYPTO_DES_CBC\n");
+
+ if (crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0) != 0)
+ printf("register failed for CRYPTO_3DES_CBC\n");
+
+ if (crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0) != 0)
+ printf("register failed for CRYPTO_AES_CBC\n");
+
+ if (crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0) != 0)
+ printf("register failed for CRYPTO_ARC4\n");
+
+ if (crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0) != 0)
+ printf("register failed for CRYPTO_MD5\n");
+
+ if (crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0) != 0)
+ printf("register failed for CRYPTO_SHA1\n");
+
+ if (crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0) != 0)
+ printf("register failed for CRYPTO_MD5_HMAC\n");
+
+ if (crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0) != 0)
+ printf("register failed for CRYPTO_SHA1_HMAC\n");
+
+ base = nlm_get_sec_pcibase(node);
+ qstart = nlm_qidstart(base);
+ qnum = nlm_qnum(base);
+ sc->sec_vc_start = qstart;
+ sc->sec_vc_end = qstart + qnum - 1;
+ }
+
+ if (xlp_sec_init(sc) != 0)
+ goto error_exit;
+ if (bootverbose)
+ device_printf(dev, "SEC Initialization complete!\n");
+ return (0);
+
+error_exit:
+ return (ENXIO);
+
+}
+
+/*
+ * Detach an interface that successfully probed.
+ */
+static int
+xlp_sec_detach(device_t dev)
+{
+ return (0);
+}
+
+/*
+ * Allocate a new 'session' and return an encoded session id. 'sidp'
+ * contains our registration id, and should contain an encoded session
+ * id on successful allocation.
+ */
+static int
+xlp_sec_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
+{
+ struct cryptoini *c;
+ struct xlp_sec_softc *sc = device_get_softc(dev);
+ int mac = 0, cry = 0, sesn;
+ struct xlp_sec_session *ses = NULL;
+ struct xlp_sec_command *cmd = NULL;
+
+ if (sidp == NULL || cri == NULL || sc == NULL)
+ return (EINVAL);
+
+ if (sc->sc_sessions == NULL) {
+ ses = sc->sc_sessions = malloc(sizeof(struct xlp_sec_session),
+ M_DEVBUF, M_NOWAIT);
+ if (ses == NULL)
+ return (ENOMEM);
+ sesn = 0;
+ sc->sc_nsessions = 1;
+ } else {
+ for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
+ if (!sc->sc_sessions[sesn].hs_used) {
+ ses = &sc->sc_sessions[sesn];
+ break;
+ }
+ }
+
+ if (ses == NULL) {
+ sesn = sc->sc_nsessions;
+ ses = malloc((sesn + 1)*sizeof(struct xlp_sec_session),
+ M_DEVBUF, M_NOWAIT);
+ if (ses == NULL)
+ return (ENOMEM);
+ bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
+ bzero(sc->sc_sessions, sesn * sizeof(*ses));
+ free(sc->sc_sessions, M_DEVBUF);
+ sc->sc_sessions = ses;
+ ses = &sc->sc_sessions[sesn];
+ sc->sc_nsessions++;
+ }
+ }
+ bzero(ses, sizeof(*ses));
+ ses->sessionid = sesn;
+ cmd = &ses->cmd;
+ ses->hs_used = 1;
+
+ for (c = cri; c != NULL; c = c->cri_next) {
+ switch (c->cri_alg) {
+ case CRYPTO_MD5:
+ case CRYPTO_SHA1:
+ case CRYPTO_MD5_HMAC:
+ case CRYPTO_SHA1_HMAC:
+ if (mac)
+ return (EINVAL);
+ mac = 1;
+ ses->hs_mlen = c->cri_mlen;
+ if (ses->hs_mlen == 0) {
+ switch (c->cri_alg) {
+ case CRYPTO_MD5:
+ case CRYPTO_MD5_HMAC:
+ ses->hs_mlen = 16;
+ break;
+ case CRYPTO_SHA1:
+ case CRYPTO_SHA1_HMAC:
+ ses->hs_mlen = 20;
+ break;
+ }
+ }
+ break;
+ case CRYPTO_DES_CBC:
+ case CRYPTO_3DES_CBC:
+ case CRYPTO_AES_CBC:
+ /* XXX this may read fewer, does it matter? */
+ read_random(ses->ses_iv, c->cri_alg ==
+ CRYPTO_AES_CBC ? XLP_SEC_AES_IV_LENGTH :
+ XLP_SEC_DES_IV_LENGTH);
+ /* FALLTHROUGH */
+ case CRYPTO_ARC4:
+ if (cry)
+ return (EINVAL);
+ cry = 1;
+ break;
+ default:
+ return (EINVAL);
+ }
+ }
+ if (mac == 0 && cry == 0)
+ return (EINVAL);
+
+ cmd->hash_dst_len = ses->hs_mlen;
+ *sidp = XLP_SEC_SID(device_get_unit(sc->sc_dev), sesn);
+ return (0);
+}
+
+/*
+ * Deallocate a session.
+ * XXX this routine should run a zero'd mac/encrypt key into context ram.
+ * XXX to blow away any keys already stored there.
+ */
+static int
+xlp_sec_freesession(device_t dev, u_int64_t tid)
+{
+ struct xlp_sec_softc *sc = device_get_softc(dev);
+ int session;
+ u_int32_t sid = CRYPTO_SESID2LID(tid);
+
+ if (sc == NULL)
+ return (EINVAL);
+
+ session = XLP_SEC_SESSION(sid);
+ if (session >= sc->sc_nsessions)
+ return (EINVAL);
+
+ sc->sc_sessions[session].hs_used = 0;
+ return (0);
+}
+
+static int
+xlp_copyiv(struct xlp_sec_softc *sc, struct xlp_sec_command *cmd,
+ struct cryptodesc *enccrd)
+{
+ unsigned int ivlen = 0;
+ int session;
+ struct cryptop *crp = NULL;
+
+ crp = cmd->crp;
+ session = cmd->session_num;
+
+ if (enccrd->crd_alg != CRYPTO_ARC4) {
+ ivlen = ((enccrd->crd_alg == CRYPTO_AES_CBC) ?
+ XLP_SEC_AES_IV_LENGTH : XLP_SEC_DES_IV_LENGTH);
+ if (enccrd->crd_flags & CRD_F_ENCRYPT) {
+ if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) {
+ bcopy(enccrd->crd_iv, cmd->iv, ivlen);
+ } else {
+ bcopy(sc->sc_sessions[session].ses_iv, cmd->iv,
+ ivlen);
+ }
+ if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
+ crypto_copyback(crp->crp_flags,
+ crp->crp_buf, enccrd->crd_inject,
+ ivlen, cmd->iv);
+ }
+ } else {
+ if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) {
+ bcopy(enccrd->crd_iv, cmd->iv, ivlen);
+ } else {
+ crypto_copydata(crp->crp_flags, crp->crp_buf,
+ enccrd->crd_inject, ivlen, cmd->iv);
+ }
+ }
+ }
+ return (0);
+}
+
+static int
+xlp_get_nsegs(struct cryptop *crp, unsigned int *nsegs)
+{
+
+ if (crp->crp_flags & CRYPTO_F_IMBUF) {
+ struct mbuf *m = NULL;
+
+ m = (struct mbuf *)crp->crp_buf;
+ while (m != NULL) {
+ *nsegs += NLM_CRYPTO_NUM_SEGS_REQD(m->m_len);
+ m = m->m_next;
+ }
+ } else if (crp->crp_flags & CRYPTO_F_IOV) {
+ struct uio *uio = NULL;
+ struct iovec *iov = NULL;
+ int iol = 0;
+
+ uio = (struct uio *)crp->crp_buf;
+ iov = (struct iovec *)uio->uio_iov;
+ iol = uio->uio_iovcnt;
+ while (iol > 0) {
+ *nsegs += NLM_CRYPTO_NUM_SEGS_REQD(iov->iov_len);
+ iol--;
+ iov++;
+ }
+ } else {
+ *nsegs = NLM_CRYPTO_NUM_SEGS_REQD(crp->crp_ilen);
+ }
+ return (0);
+}
+
+static int
+xlp_alloc_cmd_params(struct xlp_sec_command *cmd, unsigned int nsegs)
+{
+ int err = 0;
+
+ if(cmd == NULL) {
+ err = EINVAL;
+ goto error;
+ }
+ if ((cmd->ctrlp = malloc(sizeof(struct nlm_crypto_pkt_ctrl), M_DEVBUF,
+ M_NOWAIT | M_ZERO)) == NULL) {
+ err = ENOMEM;
+ goto error;
+ }
+ if (((uintptr_t)cmd->ctrlp & (XLP_L2L3_CACHELINE_SIZE - 1))) {
+ err = EINVAL;
+ goto error;
+ }
+ /* (nsegs - 1) because one seg is part of the structure already */
+ if ((cmd->paramp = malloc(sizeof(struct nlm_crypto_pkt_param) +
+ (16 * (nsegs - 1)), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
+ err = ENOMEM;
+ goto error;
+ }
+ if (((uintptr_t)cmd->paramp & (XLP_L2L3_CACHELINE_SIZE - 1))) {
+ err = EINVAL;
+ goto error;
+ }
+ if ((cmd->iv = malloc(EALG_MAX_BLOCK_LEN, M_DEVBUF,
+ M_NOWAIT | M_ZERO)) == NULL) {
+ err = ENOMEM;
+ goto error;
+ }
+ if ((cmd->hashdest = malloc(HASH_MAX_LEN, M_DEVBUF,
+ M_NOWAIT | M_ZERO)) == NULL) {
+ err = ENOMEM;
+ goto error;
+ }
+error:
+ return (err);
+}
+
+static void
+xlp_free_cmd_params(struct xlp_sec_command *cmd)
+{
+ if (cmd->ctrlp != NULL)
+ free(cmd->ctrlp, M_DEVBUF);
+ if (cmd->paramp != NULL)
+ free(cmd->paramp, M_DEVBUF);
+ if (cmd->iv != NULL)
+ free(cmd->iv, M_DEVBUF);
+ if (cmd->hashdest != NULL)
+ free(cmd->hashdest, M_DEVBUF);
+ if (cmd != NULL)
+ free(cmd, M_DEVBUF);
+ return;
+}
+
+static int
+xlp_sec_process(device_t dev, struct cryptop *crp, int hint)
+{
+ struct xlp_sec_softc *sc = device_get_softc(dev);
+ struct xlp_sec_command *cmd = NULL;
+ int session, err = -1, ret = 0;
+ struct cryptodesc *crd1, *crd2;
+ struct xlp_sec_session *ses;
+ unsigned int nsegs = 0;
+
+ if (crp == NULL || crp->crp_callback == NULL) {
+ return (EINVAL);
+ }
+ session = XLP_SEC_SESSION(crp->crp_sid);
+ if (sc == NULL || session >= sc->sc_nsessions) {
+ err = EINVAL;
+ goto errout;
+ }
+ ses = &sc->sc_sessions[session];
+
+ if ((cmd = malloc(sizeof(struct xlp_sec_command), M_DEVBUF,
+ M_NOWAIT | M_ZERO)) == NULL) {
+ err = ENOMEM;
+ goto errout;
+ }
+
+ cmd->crp = crp;
+ cmd->session_num = session;
+ cmd->hash_dst_len = ses->hs_mlen;
+
+ if ((crd1 = crp->crp_desc) == NULL) {
+ err = EINVAL;
+ goto errout;
+ }
+ crd2 = crd1->crd_next;
+
+ if ((ret = xlp_get_nsegs(crp, &nsegs)) != 0) {
+ err = EINVAL;
+ goto errout;
+ }
+ if (((crd1 != NULL) && (crd1->crd_flags & CRD_F_IV_EXPLICIT)) ||
+ ((crd2 != NULL) && (crd2->crd_flags & CRD_F_IV_EXPLICIT))) {
+ /* Since IV is given as separate segment to avoid copy */
+ nsegs += 1;
+ }
+ cmd->nsegs = nsegs;
+
+ if ((err = xlp_alloc_cmd_params(cmd, nsegs)) != 0)
+ goto errout;
+
+ if ((crd1 != NULL) && (crd2 == NULL)) {
+ if (crd1->crd_alg == CRYPTO_DES_CBC ||
+ crd1->crd_alg == CRYPTO_3DES_CBC ||
+ crd1->crd_alg == CRYPTO_AES_CBC ||
+ crd1->crd_alg == CRYPTO_ARC4) {
+ cmd->enccrd = crd1;
+ cmd->maccrd = NULL;
+ if ((ret = nlm_get_cipher_param(cmd)) != 0) {
+ err = EINVAL;
+ goto errout;
+ }
+ if (crd1->crd_flags & CRD_F_IV_EXPLICIT)
+ cmd->cipheroff = cmd->ivlen;
+ else
+ cmd->cipheroff = cmd->enccrd->crd_skip;
+ cmd->cipherlen = cmd->enccrd->crd_len;
+ if (crd1->crd_flags & CRD_F_IV_PRESENT)
+ cmd->ivoff = 0;
+ else
+ cmd->ivoff = cmd->enccrd->crd_inject;
+ if ((err = xlp_copyiv(sc, cmd, cmd->enccrd)) != 0)
+ goto errout;
+ if ((err = nlm_crypto_do_cipher(sc, cmd)) != 0)
+ goto errout;
+ } else if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
+ crd1->crd_alg == CRYPTO_SHA1_HMAC ||
+ crd1->crd_alg == CRYPTO_SHA1 ||
+ crd1->crd_alg == CRYPTO_MD5) {
+ cmd->enccrd = NULL;
+ cmd->maccrd = crd1;
+ if ((ret = nlm_get_digest_param(cmd)) != 0) {
+ err = EINVAL;
+ goto errout;
+ }
+ cmd->hashoff = cmd->maccrd->crd_skip;
+ cmd->hashlen = cmd->maccrd->crd_len;
+ cmd->hmacpad = 0;
+ cmd->hashsrc = 0;
+ if ((err = nlm_crypto_do_digest(sc, cmd)) != 0)
+ goto errout;
+ } else {
+ err = EINVAL;
+ goto errout;
+ }
+ } else if( (crd1 != NULL) && (crd2 != NULL) ) {
+ if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
+ crd1->crd_alg == CRYPTO_SHA1_HMAC ||
+ crd1->crd_alg == CRYPTO_MD5 ||
+ crd1->crd_alg == CRYPTO_SHA1) &&
+ (crd2->crd_alg == CRYPTO_DES_CBC ||
+ crd2->crd_alg == CRYPTO_3DES_CBC ||
+ crd2->crd_alg == CRYPTO_AES_CBC ||
+ crd2->crd_alg == CRYPTO_ARC4)) {
+ cmd->maccrd = crd1;
+ cmd->enccrd = crd2;
+ } else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
+ crd1->crd_alg == CRYPTO_ARC4 ||
+ crd1->crd_alg == CRYPTO_3DES_CBC ||
+ crd1->crd_alg == CRYPTO_AES_CBC) &&
+ (crd2->crd_alg == CRYPTO_MD5_HMAC ||
+ crd2->crd_alg == CRYPTO_SHA1_HMAC ||
+ crd2->crd_alg == CRYPTO_MD5 ||
+ crd2->crd_alg == CRYPTO_SHA1)) {
+ cmd->enccrd = crd1;
+ cmd->maccrd = crd2;
+ } else {
+ err = EINVAL;
+ goto errout;
+ }
+ if ((ret = nlm_get_cipher_param(cmd)) != 0) {
+ err = EINVAL;
+ goto errout;
+ }
+ if ((ret = nlm_get_digest_param(cmd)) != 0) {
+ err = EINVAL;
+ goto errout;
+ }
+ cmd->ivoff = cmd->enccrd->crd_inject;
+ cmd->hashoff = cmd->maccrd->crd_skip;
+ cmd->hashlen = cmd->maccrd->crd_len;
+ cmd->hmacpad = 0;
+ if (cmd->enccrd->crd_flags & CRD_F_ENCRYPT)
+ cmd->hashsrc = 1;
+ else
+ cmd->hashsrc = 0;
+ cmd->cipheroff = cmd->enccrd->crd_skip;
+ cmd->cipherlen = cmd->enccrd->crd_len;
+ if ((err = xlp_copyiv(sc, cmd, cmd->enccrd)) != 0)
+ goto errout;
+ if ((err = nlm_crypto_do_cipher_digest(sc, cmd)) != 0)
+ goto errout;
+ } else {
+ err = EINVAL;
+ goto errout;
+ }
+ return (0);
+errout:
+ xlp_free_cmd_params(cmd);
+ if (err == ERESTART) {
+ sc->sc_needwakeup |= CRYPTO_SYMQ;
+ creditleft = 0;
+ return (err);
+ }
+ crp->crp_etype = err;
+ crypto_done(crp);
+ return (err);
+}
diff --git a/sys/mips/nlm/dev/sec/nlmseclib.c b/sys/mips/nlm/dev/sec/nlmseclib.c
new file mode 100644
index 0000000..8439260
--- /dev/null
+++ b/sys/mips/nlm/dev/sec/nlmseclib.c
@@ -0,0 +1,307 @@
+/*-
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/bus.h>
+#include <sys/uio.h>
+#include <machine/bus.h>
+#include <machine/md_var.h>
+#include <machine/cpuregs.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <opencrypto/cryptodev.h>
+
+#include <mips/nlm/hal/haldefs.h>
+#include <mips/nlm/hal/cop2.h>
+#include <mips/nlm/hal/fmn.h>
+#include <mips/nlm/hal/mips-extns.h>
+#include <mips/nlm/hal/nlmsaelib.h>
+#include <mips/nlm/dev/sec/nlmseclib.h>
+
+static int
+nlm_crypto_complete_sec_request(struct xlp_sec_softc *sc,
+ struct xlp_sec_command *cmd)
+{
+ unsigned int fbvc;
+ struct nlm_fmn_msg m;
+ int ret;
+
+ fbvc = nlm_cpuid() / CMS_MAX_VCPU_VC;
+ m.msg[0] = m.msg[1] = m.msg[2] = m.msg[3] = 0;
+
+ m.msg[0] = nlm_crypto_form_pkt_fmn_entry0(fbvc, 0, 0,
+ cmd->ctrlp->cipherkeylen, vtophys(cmd->ctrlp));
+
+ m.msg[1] = nlm_crypto_form_pkt_fmn_entry1(0, cmd->ctrlp->hashkeylen,
+ NLM_CRYPTO_PKT_DESC_SIZE(cmd->nsegs), vtophys(cmd->paramp));
+
+ /* Software scratch pad */
+ m.msg[2] = (uintptr_t)cmd;
+ sc->sec_msgsz = 3;
+
+ /* Send the message to sec/rsa engine vc */
+ ret = nlm_fmn_msgsend(sc->sec_vc_start, sc->sec_msgsz,
+ FMN_SWCODE_CRYPTO, &m);
+ if (ret != 0) {
+#ifdef NLM_SEC_DEBUG
+ printf("%s: msgsnd failed (%x)\n", __func__, ret);
+#endif
+ return (ERESTART);
+ }
+ return (0);
+}
+
+int
+nlm_crypto_form_srcdst_segs(struct xlp_sec_command *cmd)
+{
+ unsigned int srcseg = 0, dstseg = 0;
+ struct cryptodesc *cipdesc = NULL;
+ struct cryptop *crp = NULL;
+
+ crp = cmd->crp;
+ cipdesc = cmd->enccrd;
+
+ if (cipdesc != NULL) {
+ /* IV is given as ONE segment to avoid copy */
+ if (cipdesc->crd_flags & CRD_F_IV_EXPLICIT) {
+ srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
+ cmd->iv, cmd->ivlen);
+ dstseg = nlm_crypto_fill_dst_seg(cmd->paramp, dstseg,
+ cmd->iv, cmd->ivlen);
+ }
+ }
+
+ if (crp->crp_flags & CRYPTO_F_IMBUF) {
+ struct mbuf *m = NULL;
+
+ m = (struct mbuf *)crp->crp_buf;
+ while (m != NULL) {
+ srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
+ mtod(m,caddr_t), m->m_len);
+ if (cipdesc != NULL) {
+ dstseg = nlm_crypto_fill_dst_seg(cmd->paramp,
+ dstseg, mtod(m,caddr_t), m->m_len);
+ }
+ m = m->m_next;
+ }
+ } else if (crp->crp_flags & CRYPTO_F_IOV) {
+ struct uio *uio = NULL;
+ struct iovec *iov = NULL;
+ int iol = 0;
+
+ uio = (struct uio *)crp->crp_buf;
+ iov = (struct iovec *)uio->uio_iov;
+ iol = uio->uio_iovcnt;
+
+ while (iol > 0) {
+ srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
+ (caddr_t)iov->iov_base, iov->iov_len);
+ if (cipdesc != NULL) {
+ dstseg = nlm_crypto_fill_dst_seg(cmd->paramp,
+ dstseg, (caddr_t)iov->iov_base,
+ iov->iov_len);
+ }
+ iov++;
+ iol--;
+ }
+ } else {
+ srcseg = nlm_crypto_fill_src_seg(cmd->paramp, srcseg,
+ ((caddr_t)crp->crp_buf), crp->crp_ilen);
+ if (cipdesc != NULL) {
+ dstseg = nlm_crypto_fill_dst_seg(cmd->paramp, dstseg,
+ ((caddr_t)crp->crp_buf), crp->crp_ilen);
+ }
+ }
+ return (0);
+}
+
+int
+nlm_crypto_do_cipher(struct xlp_sec_softc *sc, struct xlp_sec_command *cmd)
+{
+ struct cryptodesc *cipdesc = NULL;
+ unsigned char *cipkey = NULL;
+ int ret = 0;
+
+ cipdesc = cmd->enccrd;
+ cipkey = (unsigned char *)cipdesc->crd_key;
+ if (cmd->cipheralg == NLM_CIPHER_3DES) {
+ if (!(cipdesc->crd_flags & CRD_F_ENCRYPT)) {
+ uint64_t *k, *tkey;
+ k = (uint64_t *)cipdesc->crd_key;
+ tkey = (uint64_t *)cmd->des3key;
+ tkey[2] = k[0];
+ tkey[1] = k[1];
+ tkey[0] = k[2];
+ cipkey = (unsigned char *)tkey;
+ }
+ }
+ nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, 0, NLM_HASH_BYPASS, 0,
+ cmd->cipheralg, cmd->ciphermode, cipkey,
+ (cipdesc->crd_klen >> 3), NULL, 0);
+
+ nlm_crypto_fill_cipher_pkt_param(cmd->ctrlp, cmd->paramp,
+ (cipdesc->crd_flags & CRD_F_ENCRYPT) ? 1 : 0, cmd->ivoff,
+ cmd->ivlen, cmd->cipheroff, cmd->cipherlen);
+ nlm_crypto_form_srcdst_segs(cmd);
+
+ ret = nlm_crypto_complete_sec_request(sc, cmd);
+ return (ret);
+}
+
+int
+nlm_crypto_do_digest(struct xlp_sec_softc *sc, struct xlp_sec_command *cmd)
+{
+ struct cryptodesc *digdesc = NULL;
+ int ret=0;
+
+ digdesc = cmd->maccrd;
+
+ nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, (digdesc->crd_klen) ? 1 : 0,
+ cmd->hashalg, cmd->hashmode, NLM_CIPHER_BYPASS, 0,
+ NULL, 0, digdesc->crd_key, digdesc->crd_klen >> 3);
+
+ nlm_crypto_fill_auth_pkt_param(cmd->ctrlp, cmd->paramp,
+ cmd->hashoff, cmd->hashlen, cmd->hmacpad,
+ (unsigned char *)cmd->hashdest);
+
+ nlm_crypto_form_srcdst_segs(cmd);
+
+ ret = nlm_crypto_complete_sec_request(sc, cmd);
+
+ return (ret);
+}
+
+int
+nlm_crypto_do_cipher_digest(struct xlp_sec_softc *sc,
+ struct xlp_sec_command *cmd)
+{
+ struct cryptodesc *cipdesc=NULL, *digdesc=NULL;
+ unsigned char *cipkey = NULL;
+ int ret=0;
+
+ cipdesc = cmd->enccrd;
+ digdesc = cmd->maccrd;
+
+ cipkey = (unsigned char *)cipdesc->crd_key;
+ if (cmd->cipheralg == NLM_CIPHER_3DES) {
+ if (!(cipdesc->crd_flags & CRD_F_ENCRYPT)) {
+ uint64_t *k, *tkey;
+ k = (uint64_t *)cipdesc->crd_key;
+ tkey = (uint64_t *)cmd->des3key;
+ tkey[2] = k[0];
+ tkey[1] = k[1];
+ tkey[0] = k[2];
+ cipkey = (unsigned char *)tkey;
+ }
+ }
+ nlm_crypto_fill_pkt_ctrl(cmd->ctrlp, (digdesc->crd_klen) ? 1 : 0,
+ cmd->hashalg, cmd->hashmode, cmd->cipheralg, cmd->ciphermode,
+ cipkey, (cipdesc->crd_klen >> 3),
+ digdesc->crd_key, (digdesc->crd_klen >> 3));
+
+ nlm_crypto_fill_cipher_auth_pkt_param(cmd->ctrlp, cmd->paramp,
+ (cipdesc->crd_flags & CRD_F_ENCRYPT) ? 1 : 0, cmd->hashsrc,
+ cmd->ivoff, cmd->ivlen, cmd->hashoff, cmd->hashlen,
+ cmd->hmacpad, cmd->cipheroff, cmd->cipherlen,
+ (unsigned char *)cmd->hashdest);
+
+ nlm_crypto_form_srcdst_segs(cmd);
+
+ ret = nlm_crypto_complete_sec_request(sc, cmd);
+ return (ret);
+}
+
+int
+nlm_get_digest_param(struct xlp_sec_command *cmd)
+{
+ switch(cmd->maccrd->crd_alg) {
+ case CRYPTO_MD5:
+ cmd->hashalg = NLM_HASH_MD5;
+ cmd->hashmode = NLM_HASH_MODE_SHA1;
+ break;
+ case CRYPTO_SHA1:
+ cmd->hashalg = NLM_HASH_SHA;
+ cmd->hashmode = NLM_HASH_MODE_SHA1;
+ break;
+ case CRYPTO_MD5_HMAC:
+ cmd->hashalg = NLM_HASH_MD5;
+ cmd->hashmode = NLM_HASH_MODE_SHA1;
+ break;
+ case CRYPTO_SHA1_HMAC:
+ cmd->hashalg = NLM_HASH_SHA;
+ cmd->hashmode = NLM_HASH_MODE_SHA1;
+ break;
+ default:
+ /* Not supported */
+ return (-1);
+ }
+ return (0);
+}
+int
+nlm_get_cipher_param(struct xlp_sec_command *cmd)
+{
+ switch(cmd->enccrd->crd_alg) {
+ case CRYPTO_DES_CBC:
+ cmd->cipheralg = NLM_CIPHER_DES;
+ cmd->ciphermode = NLM_CIPHER_MODE_CBC;
+ cmd->ivlen = XLP_SEC_DES_IV_LENGTH;
+ break;
+ case CRYPTO_3DES_CBC:
+ cmd->cipheralg = NLM_CIPHER_3DES;
+ cmd->ciphermode = NLM_CIPHER_MODE_CBC;
+ cmd->ivlen = XLP_SEC_DES_IV_LENGTH;
+ break;
+ case CRYPTO_AES_CBC:
+ cmd->cipheralg = NLM_CIPHER_AES128;
+ cmd->ciphermode = NLM_CIPHER_MODE_CBC;
+ cmd->ivlen = XLP_SEC_AES_IV_LENGTH;
+ break;
+ case CRYPTO_ARC4:
+ cmd->cipheralg = NLM_CIPHER_ARC4;
+ cmd->ciphermode = NLM_CIPHER_MODE_ECB;
+ cmd->ivlen = XLP_SEC_ARC4_IV_LENGTH;
+ break;
+ default:
+ /* Not supported */
+ return (-1);
+ }
+ return (0);
+}
diff --git a/sys/mips/nlm/dev/sec/nlmseclib.h b/sys/mips/nlm/dev/sec/nlmseclib.h
new file mode 100644
index 0000000..be20905
--- /dev/null
+++ b/sys/mips/nlm/dev/sec/nlmseclib.h
@@ -0,0 +1,157 @@
+/*-
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NLMSECLIB_H_
+#define _NLMSECLIB_H_
+
+/*
+ * Cryptographic parameter definitions
+ */
+#define XLP_SEC_DES_KEY_LENGTH 8 /* Bytes */
+#define XLP_SEC_3DES_KEY_LENGTH 24 /* Bytes */
+#define XLP_SEC_AES128_KEY_LENGTH 16 /* Bytes */
+#define XLP_SEC_AES192_KEY_LENGTH 24 /* Bytes */
+#define XLP_SEC_AES256_KEY_LENGTH 32 /* Bytes */
+#define XLP_SEC_AES128F8_KEY_LENGTH 32 /* Bytes */
+#define XLP_SEC_AES192F8_KEY_LENGTH 48 /* Bytes */
+#define XLP_SEC_AES256F8_KEY_LENGTH 64 /* Bytes */
+#define XLP_SEC_KASUMI_F8_KEY_LENGTH 16 /* Bytes */
+#define XLP_SEC_MAX_CRYPT_KEY_LENGTH XLP_SEC_AES256F8_KEY_LENGTH
+
+
+#define XLP_SEC_DES_IV_LENGTH 8 /* Bytes */
+#define XLP_SEC_AES_IV_LENGTH 16 /* Bytes */
+#define XLP_SEC_ARC4_IV_LENGTH 0 /* Bytes */
+#define XLP_SEC_KASUMI_F8_IV_LENGTH 16 /* Bytes */
+#define XLP_SEC_MAX_IV_LENGTH 16 /* Bytes */
+#define XLP_SEC_IV_LENGTH_BYTES 8 /* Bytes */
+
+#define XLP_SEC_AES_BLOCK_SIZE 16 /* Bytes */
+#define XLP_SEC_DES_BLOCK_SIZE 8 /* Bytes */
+#define XLP_SEC_3DES_BLOCK_SIZE 8 /* Bytes */
+
+#define XLP_SEC_MD5_BLOCK_SIZE 64 /* Bytes */
+#define XLP_SEC_SHA1_BLOCK_SIZE 64 /* Bytes */
+#define XLP_SEC_SHA256_BLOCK_SIZE 64 /* Bytes */
+#define XLP_SEC_SHA384_BLOCK_SIZE 128 /* Bytes */
+#define XLP_SEC_SHA512_BLOCK_SIZE 128 /* Bytes */
+#define XLP_SEC_GCM_BLOCK_SIZE 16 /* XXX: Bytes */
+#define XLP_SEC_KASUMI_F9_BLOCK_SIZE 16 /* XXX: Bytes */
+#define XLP_SEC_MAX_BLOCK_SIZE 64 /* Max of MD5/SHA */
+#define XLP_SEC_MD5_LENGTH 16 /* Bytes */
+#define XLP_SEC_SHA1_LENGTH 20 /* Bytes */
+#define XLP_SEC_SHA256_LENGTH 32 /* Bytes */
+#define XLP_SEC_SHA384_LENGTH 64 /* Bytes */
+#define XLP_SEC_SHA512_LENGTH 64 /* Bytes */
+#define XLP_SEC_GCM_LENGTH 16 /* Bytes */
+#define XLP_SEC_KASUMI_F9_LENGTH 16 /* Bytes */
+#define XLP_SEC_KASUMI_F9_RESULT_LENGTH 4 /* Bytes */
+#define XLP_SEC_HMAC_LENGTH 64 /* Max of MD5/SHA/SHA256 */
+#define XLP_SEC_MAX_AUTH_KEY_LENGTH XLP_SEC_SHA512_BLOCK_SIZE
+#define XLP_SEC_MAX_RC4_STATE_SIZE 264 /* char s[256], int i, int j */
+
+#define XLP_SEC_SESSION(sid) ((sid) & 0x000007ff)
+#define XLP_SEC_SID(crd,ses) (((crd) << 28) | ((ses) & 0x7ff))
+
+#define CRYPTO_ERROR(msg1) ((unsigned int)msg1)
+
+#define NLM_CRYPTO_LEFT_REQS (CMS_DEFAULT_CREDIT/2)
+#define NLM_CRYPTO_NUM_SEGS_REQD(__bufsize) \
+ ((__bufsize + NLM_CRYPTO_MAX_SEG_LEN - 1) / NLM_CRYPTO_MAX_SEG_LEN)
+
+#define NLM_CRYPTO_PKT_DESC_SIZE(nsegs) (32 + (nsegs * 16))
+
+extern unsigned int creditleft;
+
+struct xlp_sec_command {
+ uint16_t session_num;
+ struct cryptop *crp;
+ struct cryptodesc *enccrd, *maccrd;
+ struct xlp_sec_session *ses;
+ struct nlm_crypto_pkt_ctrl *ctrlp;
+ struct nlm_crypto_pkt_param *paramp;
+ void *iv;
+ uint8_t des3key[24];
+ uint8_t *hashdest;
+ uint8_t hashsrc;
+ uint8_t hmacpad;
+ uint32_t hashoff;
+ uint32_t hashlen;
+ uint32_t cipheroff;
+ uint32_t cipherlen;
+ uint32_t ivoff;
+ uint32_t ivlen;
+ uint32_t hashalg;
+ uint32_t hashmode;
+ uint32_t cipheralg;
+ uint32_t ciphermode;
+ uint32_t nsegs;
+ uint32_t hash_dst_len; /* used to store hash alg dst size */
+};
+
+struct xlp_sec_session {
+ uint32_t sessionid;
+ int hs_used;
+ int hs_mlen;
+ uint8_t ses_iv[EALG_MAX_BLOCK_LEN];
+ struct xlp_sec_command cmd;
+};
+
+/*
+ * Holds data specific to nlm security accelerators
+ */
+struct xlp_sec_softc {
+ device_t sc_dev; /* device backpointer */
+ uint64_t sec_base;
+ int32_t sc_cid;
+ struct xlp_sec_session *sc_sessions;
+ int sc_nsessions;
+ int sc_needwakeup;
+ uint32_t sec_vc_start;
+ uint32_t sec_vc_end;
+ uint32_t sec_msgsz;
+};
+
+#ifdef NLM_SEC_DEBUG
+void print_crypto_params(struct xlp_sec_command *cmd, struct nlm_fmn_msg m);
+void xlp_sec_print_data(struct cryptop *crp);
+void print_cmd(struct xlp_sec_command *cmd);
+#endif
+int nlm_crypto_form_srcdst_segs(struct xlp_sec_command *cmd);
+int nlm_crypto_do_cipher(struct xlp_sec_softc *sc,
+ struct xlp_sec_command *cmd);
+int nlm_crypto_do_digest(struct xlp_sec_softc *sc,
+ struct xlp_sec_command *cmd);
+int nlm_crypto_do_cipher_digest(struct xlp_sec_softc *sc,
+ struct xlp_sec_command *cmd);
+int nlm_get_digest_param(struct xlp_sec_command *cmd);
+int nlm_get_cipher_param(struct xlp_sec_command *cmd);
+
+#endif /* _NLMSECLIB_H_ */
diff --git a/sys/mips/nlm/dev/sec/rsa_ucode.h b/sys/mips/nlm/dev/sec/rsa_ucode.h
new file mode 100644
index 0000000..a0f7cb3
--- /dev/null
+++ b/sys/mips/nlm/dev/sec/rsa_ucode.h
@@ -0,0 +1,956 @@
+/*-
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NLM_HAL_RSA_UCODE_H
+#define _NLM_HAL_RSA_UCODE_H
+static uint64_t nlm_rsa_ucode_data [] = {
+ 0x0000000000000000ULL,
+ 0x00000000503840ecULL,
+ 0x00000001903800ecULL,
+ 0x00000002c03820ecULL,
+ 0x0000003760000044ULL,
+ 0x0000000000000014ULL,
+ 0x000000071000000cULL,
+ 0x00000007d000010cULL,
+ 0x0000001b80000c0cULL,
+ 0x00000000e03fc0ecULL,
+ 0x00000001103fc1ecULL,
+ 0x00000001403f42ecULL,
+ 0x00000001403fc4ecULL,
+ 0x0000003760000044ULL,
+ 0x000000001800003cULL,
+ 0x0000000d8000030cULL,
+ 0x0000000630000044ULL,
+ 0x000000002800003cULL,
+ 0x0000000ef000030cULL,
+ 0x0000000630000044ULL,
+ 0x00000000503fc23cULL,
+ 0x00000000a03fc33cULL,
+ 0x00000001403fc43cULL,
+ 0x00000010c000030cULL,
+ 0x0000000630000044ULL,
+ 0x0000000000000014ULL,
+ 0x000000071000000cULL,
+ 0x0000001c1000070cULL,
+ 0x0000002500000d0cULL,
+ 0x00000027c0000e0cULL,
+ 0x0000002d60000f0cULL,
+ 0x00000002603f00ecULL,
+ 0x00000002603f82ecULL,
+ 0x00000002803f83ecULL,
+ 0x00000002803f04ecULL,
+ 0x00000002a03f06ecULL,
+ 0x00000002a03f88ecULL,
+ 0x0000003760000044ULL,
+ 0x000000086000010cULL,
+ 0x00000003f0000044ULL,
+ 0x00000008d000010cULL,
+ 0x00000004b0000044ULL,
+ 0x00000008d000010cULL,
+ 0x0000000570000044ULL,
+ 0x000000000000001cULL,
+ 0x000000076000000cULL,
+ 0x0000001c1000070cULL,
+ 0x0000002690000d0cULL,
+ 0x0000002990000e0cULL,
+ 0x0000002e10000f0cULL,
+ 0x00000003903f20ecULL,
+ 0x00000003903fa2ecULL,
+ 0x00000003b03fa3ecULL,
+ 0x00000003b03f24ecULL,
+ 0x00000003d03f26ecULL,
+ 0x00000003d03fa8ecULL,
+ 0x0000003760000044ULL,
+ 0x000000096000010cULL,
+ 0x00000003f0000044ULL,
+ 0x0000000a0000010cULL,
+ 0x00000004b0000044ULL,
+ 0x0000000a0000010cULL,
+ 0x0000000570000044ULL,
+ 0x000000000800003cULL,
+ 0x0000000af000020cULL,
+ 0x0000000bc000030cULL,
+ 0x000000129000040cULL,
+ 0x000000178000050cULL,
+ 0x000000191000060cULL,
+ 0x0000001ff000080cULL,
+ 0x000000205000090cULL,
+ 0x00000022c0000a0cULL,
+ 0x00000020b0000b0cULL,
+ 0x0000001ac0000c0cULL,
+ 0x0000000680000044ULL,
+ 0x000000001000003cULL,
+ 0x0000000b5000020cULL,
+ 0x0000000c5000030cULL,
+ 0x000000137000040cULL,
+ 0x00000017e000050cULL,
+ 0x000000197000060cULL,
+ 0x000000200000080cULL,
+ 0x000000206000090cULL,
+ 0x0000002340000a0cULL,
+ 0x0000002110000b0cULL,
+ 0x0000001b10000c0cULL,
+ 0x0000000680000044ULL,
+ 0x000000001800003cULL,
+ 0x0000000b5000020cULL,
+ 0x0000000d8000030cULL,
+ 0x000000154000040cULL,
+ 0x000000187000050cULL,
+ 0x0000001a0000060cULL,
+ 0x000000202000080cULL,
+ 0x000000208000090cULL,
+ 0x0000002410000a0cULL,
+ 0x00000021c0000b0cULL,
+ 0x0000001b80000c0cULL,
+ 0x0000000680000044ULL,
+ 0x000000000000000aULL,
+ 0x0000000000000024ULL,
+ 0x0000002ed01f80e4ULL,
+ 0x00000030101f81e4ULL,
+ 0x0000003760000044ULL,
+ 0x000000000000000aULL,
+ 0x0000000000000024ULL,
+ 0x00000030d01f00e4ULL,
+ 0x00000030d01f82e4ULL,
+ 0x00000034801f83e4ULL,
+ 0x00000035401e04e4ULL,
+ 0x00000037101f88e4ULL,
+ 0x00000035401f89e4ULL,
+ 0x0000003760000044ULL,
+ 0x0000000000000074ULL,
+ 0x0000000f0000008cULL,
+ 0x00000008000000a4ULL,
+ 0x000000080400007bULL,
+ 0x00000000000000c4ULL,
+ 0x0000000000000074ULL,
+ 0x0000000c000000a4ULL,
+ 0x0000000004004071ULL,
+ 0x0000000b0000008cULL,
+ 0x00000008000000a4ULL,
+ 0x000000080400007bULL,
+ 0x00000000000000c4ULL,
+ 0x000000034c0b4091ULL,
+ 0x0000000b040b0093ULL,
+ 0x0000000000000000ULL,
+ 0x0000000004000802ULL,
+ 0x00000002c88b0021ULL,
+ 0x0000000a828b0423ULL,
+ 0x00000010000000a4ULL,
+ 0x000000081000006cULL,
+ 0x00000000000000c4ULL,
+ 0x000000004c0b4091ULL,
+ 0x00000008000000a4ULL,
+ 0x0000000002000402ULL,
+ 0x000000004a8b0021ULL,
+ 0x00000010000000a4ULL,
+ 0x000000089000006cULL,
+ 0x00000000000000c4ULL,
+ 0x000000034c0b4091ULL,
+ 0x0000000b040b0093ULL,
+ 0x00000008000000a4ULL,
+ 0x0000000002000402ULL,
+ 0x00000002c88b0021ULL,
+ 0x0000000a828b0423ULL,
+ 0x00000010000000a4ULL,
+ 0x000000091000006cULL,
+ 0x00000000000000c4ULL,
+ 0x000000004c0b4091ULL,
+ 0x00000008000000a4ULL,
+ 0x0000000002000402ULL,
+ 0x000000004a8b0021ULL,
+ 0x00000010000000a4ULL,
+ 0x0000000990000064ULL,
+ 0x000000004a8b0021ULL,
+ 0x0000000000898611ULL,
+ 0x0000000c000000a4ULL,
+ 0x00000000000000c4ULL,
+ 0x000000034c0b4091ULL,
+ 0x0000000b040b0093ULL,
+ 0x00000008000000a4ULL,
+ 0x0000000002000402ULL,
+ 0x00000002c88b0021ULL,
+ 0x0000000a828b0423ULL,
+ 0x00000010000000a4ULL,
+ 0x0000000a40000064ULL,
+ 0x0000000088800021ULL,
+ 0x0000000880800423ULL,
+ 0x00000000001004a1ULL,
+ 0x0000000c000000a4ULL,
+ 0x00000002c88b0061ULL,
+ 0x0000000a808b0463ULL,
+ 0x00000000000000c4ULL,
+ 0x00000000058f0011ULL,
+ 0x0000000001860002ULL,
+ 0x00000010000000a4ULL,
+ 0x00000000000000ccULL,
+ 0x000000004d8f0021ULL,
+ 0x0000000b10000044ULL,
+ 0x00000007058f0013ULL,
+ 0x0000000001860002ULL,
+ 0x00000010000000a4ULL,
+ 0x00000000000000ccULL,
+ 0x000000034c0f0021ULL,
+ 0x0000000b058f0423ULL,
+ 0x0000000b70000044ULL,
+ 0x0000000000180001ULL,
+ 0x000000000b600031ULL,
+ 0x00000008000000a4ULL,
+ 0x0000000004800041ULL,
+ 0x00000008000000a4ULL,
+ 0x0000000007c03f41ULL,
+ 0x00000000440ac491ULL,
+ 0x00000004000000a4ULL,
+ 0x00000000000000c4ULL,
+ 0x0000000010180001ULL,
+ 0x0000000088a00031ULL,
+ 0x00000002c3430431ULL,
+ 0x00000004000000a4ULL,
+ 0x0000000204938041ULL,
+ 0x00000008000000a4ULL,
+ 0x000000012c002b41ULL,
+ 0x0000000117982861ULL,
+ 0x0000000088a03631ULL,
+ 0x00000002c3430c31ULL,
+ 0x00000004000000a4ULL,
+ 0x0000000204938041ULL,
+ 0x00000008000000a4ULL,
+ 0x000000012c002b41ULL,
+ 0x0000000347cb2861ULL,
+ 0x000000034c09f691ULL,
+ 0x00000003040a8491ULL,
+ 0x0000000000000000ULL,
+ 0x00000000000000c4ULL,
+ 0x0000000010180001ULL,
+ 0x0000000088a00031ULL,
+ 0x00000002c0830431ULL,
+ 0x0000000283430431ULL,
+ 0x000000080000009cULL,
+ 0x0000000204938041ULL,
+ 0x00000008000000a4ULL,
+ 0x000000012c002b41ULL,
+ 0x0000000104202861ULL,
+ 0x0000000117d82861ULL,
+ 0x0000000088a02f31ULL,
+ 0x00000002c0833c31ULL,
+ 0x0000002283430c3bULL,
+ 0x0000000000000000ULL,
+ 0x0000000204938041ULL,
+ 0x00000008000000a4ULL,
+ 0x000000012c002b41ULL,
+ 0x00000003442b2861ULL,
+ 0x0000000307cb2861ULL,
+ 0x000000034c09ef91ULL,
+ 0x000000030409bc91ULL,
+ 0x00000003040a8491ULL,
+ 0x00000000000000c4ULL,
+ 0x0000000010180001ULL,
+ 0x0000000088a00031ULL,
+ 0x00000002c0830431ULL,
+ 0x0000000280830431ULL,
+ 0x0000000280c30431ULL,
+ 0x0000000004900041ULL,
+ 0x0000000283430531ULL,
+ 0x0000000a00038007ULL,
+ 0x0000000000000000ULL,
+ 0x000000012c002b41ULL,
+ 0x0000000344202861ULL,
+ 0x0000001304032863ULL,
+ 0x0000000317db2861ULL,
+ 0x00000000b8a02b31ULL,
+ 0x00000002c0832831ULL,
+ 0x0000000280832831ULL,
+ 0x0000000280c33c31ULL,
+ 0x0000000004900041ULL,
+ 0x0000002e83430d3bULL,
+ 0x0000000200038000ULL,
+ 0x0000000000000000ULL,
+ 0x000000012c002b41ULL,
+ 0x00000003442b2861ULL,
+ 0x00000013040b2863ULL,
+ 0x0000000307cb2861ULL,
+ 0x000000037c09eb91ULL,
+ 0x000000130409a893ULL,
+ 0x000000030409bc91ULL,
+ 0x00000003040a849dULL,
+ 0x0000000010180001ULL,
+ 0x0000000088a00031ULL,
+ 0x00000002c0830431ULL,
+ 0x0000000280830431ULL,
+ 0x0000000280c30431ULL,
+ 0x0000000004900041ULL,
+ 0x0000000280830531ULL,
+ 0x0000001e80830433ULL,
+ 0x0000000283430431ULL,
+ 0x0000000b2c03ab67ULL,
+ 0x0000000344202861ULL,
+ 0x0000001304032863ULL,
+ 0x0000000317db2861ULL,
+ 0x00000002b8a3ab31ULL,
+ 0x00000002c0832831ULL,
+ 0x0000000280832831ULL,
+ 0x0000000280c32831ULL,
+ 0x0000000004900041ULL,
+ 0x0000000280832931ULL,
+ 0x0000001e80832833ULL,
+ 0x0000002e83430c3bULL,
+ 0x000000032c03ab61ULL,
+ 0x00000003442b2861ULL,
+ 0x00000013040b2863ULL,
+ 0x0000000307cb2861ULL,
+ 0x000000037c09eb91ULL,
+ 0x000000130409a893ULL,
+ 0x000000030409bc91ULL,
+ 0x00000003040a849dULL,
+ 0x0000000000140001ULL,
+ 0x0000004000140001ULL,
+ 0x000000000b600061ULL,
+ 0x000000400b600061ULL,
+ 0x00000004000000a4ULL,
+ 0x0000000004800041ULL,
+ 0x0000004004800041ULL,
+ 0x00000004000000a4ULL,
+ 0x0000000007c03f41ULL,
+ 0x0000004007c03f41ULL,
+ 0x00000000440ac591ULL,
+ 0x00000040440ac591ULL,
+ 0x0000000000000000ULL,
+ 0x00000000000000c4ULL,
+ 0x0000000010140001ULL,
+ 0x0000004010140001ULL,
+ 0x0000000088e00061ULL,
+ 0x0000004088e00061ULL,
+ 0x00000002c3430561ULL,
+ 0x00000042c3430561ULL,
+ 0x0000000204938041ULL,
+ 0x0000004204938041ULL,
+ 0x00000004000000a4ULL,
+ 0x000000012c402b41ULL,
+ 0x000000412c402b41ULL,
+ 0x0000000117f42961ULL,
+ 0x0000004117f42961ULL,
+ 0x0000000088e03f61ULL,
+ 0x0000004088e03f61ULL,
+ 0x00000002c3430d61ULL,
+ 0x00000042c3430d61ULL,
+ 0x0000000204938041ULL,
+ 0x0000004204938041ULL,
+ 0x00000004000000a4ULL,
+ 0x000000012c402b41ULL,
+ 0x000000412c402b41ULL,
+ 0x0000000347eb2961ULL,
+ 0x0000004347eb2961ULL,
+ 0x000000034c7dff91ULL,
+ 0x000000434c7dff91ULL,
+ 0x00000003040a0591ULL,
+ 0x00000043040a0591ULL,
+ 0x00000000000000c4ULL,
+ 0x0000000010140001ULL,
+ 0x0000004010140001ULL,
+ 0x0000000088e00061ULL,
+ 0x0000004088e00061ULL,
+ 0x00000002c0c30561ULL,
+ 0x00000042c0c30561ULL,
+ 0x0000000004900041ULL,
+ 0x0000004004900041ULL,
+ 0x0000000283430561ULL,
+ 0x0000004283430561ULL,
+ 0x0000000b2c43ab47ULL,
+ 0x000000432c43ab41ULL,
+ 0x0000000344602961ULL,
+ 0x0000004344602961ULL,
+ 0x0000000317d72961ULL,
+ 0x0000004317d72961ULL,
+ 0x00000002b8e3ab61ULL,
+ 0x00000042b8e3ab61ULL,
+ 0x00000002c0c32961ULL,
+ 0x00000042c0c32961ULL,
+ 0x0000000004900041ULL,
+ 0x0000004004900041ULL,
+ 0x0000000283430d61ULL,
+ 0x0000007683430d6bULL,
+ 0x000000032c43ab41ULL,
+ 0x000000432c43ab41ULL,
+ 0x00000003446b2961ULL,
+ 0x00000043446b2961ULL,
+ 0x0000000307cb2961ULL,
+ 0x0000004307cb2961ULL,
+ 0x000000037c7de791ULL,
+ 0x000000437c7de791ULL,
+ 0x0000000304499d91ULL,
+ 0x0000004304499d91ULL,
+ 0x00000003040a0591ULL,
+ 0x00000043040a059dULL,
+ 0x0000000048840011ULL,
+ 0x00000000028b3691ULL,
+ 0x000000000e09c691ULL,
+ 0x000000000c09c691ULL,
+ 0x0000000000000000ULL,
+ 0x00000000000000c4ULL,
+ 0x00000000c8840011ULL,
+ 0x0000000212ab3691ULL,
+ 0x0000000080800411ULL,
+ 0x0000000002cb3691ULL,
+ 0x000000034c29ef91ULL,
+ 0x0000000006098491ULL,
+ 0x000000034c09ef91ULL,
+ 0x0000000004098491ULL,
+ 0x00000000000000c4ULL,
+ 0x00000000e8840011ULL,
+ 0x0000000210ab3a91ULL,
+ 0x0000000880800415ULL,
+ 0x00000006128b3699ULL,
+ 0x000000034c29eb91ULL,
+ 0x0000000f0409a893ULL,
+ 0x0000000026098891ULL,
+ 0x000000034c09eb91ULL,
+ 0x0000000f0409a893ULL,
+ 0x000000000409849dULL,
+ 0x0000000048841011ULL,
+ 0x00000000068b7691ULL,
+ 0x000000000e099611ULL,
+ 0x000000000c098611ULL,
+ 0x0000000000000000ULL,
+ 0x00000000000000c4ULL,
+ 0x00000000c8840011ULL,
+ 0x0000000216ab7691ULL,
+ 0x0000000080801411ULL,
+ 0x0000000006cb3691ULL,
+ 0x000000034c29af11ULL,
+ 0x0000000006099411ULL,
+ 0x000000034c09af11ULL,
+ 0x0000000004098411ULL,
+ 0x00000000000000c4ULL,
+ 0x00000000e8840011ULL,
+ 0x0000000214ab7a91ULL,
+ 0x0000000c80800415ULL,
+ 0x00000006168b3699ULL,
+ 0x0000000080801411ULL,
+ 0x00000002168b3691ULL,
+ 0x000000034c29ab11ULL,
+ 0x0000000f0409a813ULL,
+ 0x0000000026099811ULL,
+ 0x000000034c09ab11ULL,
+ 0x0000000f0409a813ULL,
+ 0x000000000409841dULL,
+ 0x0000000c000000d4ULL,
+ 0x0000000000000000ULL,
+ 0x000000004a801011ULL,
+ 0x000000000e004691ULL,
+ 0x000000000009800dULL,
+ 0x0000000c000000d4ULL,
+ 0x000000004a801011ULL,
+ 0x000000018c004691ULL,
+ 0x0000000000800411ULL,
+ 0x0000000006003691ULL,
+ 0x0000000200098001ULL,
+ 0x000000000009800dULL,
+ 0x0000000c000000d4ULL,
+ 0x000000004a801011ULL,
+ 0x000000018c004691ULL,
+ 0x0000000c00800415ULL,
+ 0x0000000584003699ULL,
+ 0x0000000000800411ULL,
+ 0x0000000006003691ULL,
+ 0x0000000a00098003ULL,
+ 0x000000000009800dULL,
+ 0x000000200000302aULL,
+ 0x00000000000e0012ULL,
+ 0x0000000000100211ULL,
+ 0x0000000002000002ULL,
+ 0x00000006000b0003ULL,
+ 0x0000000000000000ULL,
+ 0x00000000000000ccULL,
+ 0x0000000006000302ULL,
+ 0x00000002810b0011ULL,
+ 0x0000000a808b0013ULL,
+ 0x0000000002010002ULL,
+ 0x00000006108b0093ULL,
+ 0x0000000002800002ULL,
+ 0x00000007040b0013ULL,
+ 0x0000000006800002ULL,
+ 0x00000007040b0013ULL,
+ 0x0000000003000002ULL,
+ 0x0000000000090101ULL,
+ 0x0000000200098001ULL,
+ 0x0000000a000b0003ULL,
+ 0x0000000007000302ULL,
+ 0x0000000400890015ULL,
+ 0x0000000784098019ULL,
+ 0x0000000007800002ULL,
+ 0x0000000000090001ULL,
+ 0x0000000000098101ULL,
+ 0x0000001dd000006cULL,
+ 0x000000280300060aULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000e02ULL,
+ 0x0000000001000011ULL,
+ 0x00000010000000a4ULL,
+ 0x0000001dc0000064ULL,
+ 0x0000000000000f02ULL,
+ 0x0000000001000011ULL,
+ 0x0000000002000602ULL,
+ 0x0000000680890013ULL,
+ 0x0000000002806002ULL,
+ 0x0000000004000011ULL,
+ 0x000000031489f691ULL,
+ 0x0000000804000415ULL,
+ 0x000000071489b699ULL,
+ 0x0000000006000e02ULL,
+ 0x0000000680890013ULL,
+ 0x0000000006800e02ULL,
+ 0x0000000680898013ULL,
+ 0x0000002c0300540aULL,
+ 0x0000000007800012ULL,
+ 0x00000000000b8000ULL,
+ 0x000000000700cd42ULL,
+ 0x0000000000800011ULL,
+ 0x000000029489f691ULL,
+ 0x0000000800800415ULL,
+ 0x000000069489b699ULL,
+ 0x000000200000e02aULL,
+ 0x00000000000000fcULL,
+ 0x0000000c000000a4ULL,
+ 0x0000001dc0000064ULL,
+ 0x000000240000c02aULL,
+ 0x0000000002000012ULL,
+ 0x0000000600090003ULL,
+ 0x00000000000000c4ULL,
+ 0x000000001680409dULL,
+ 0x0000000014804091ULL,
+ 0x000000001680049dULL,
+ 0x0000000014804091ULL,
+ 0x0000000014800491ULL,
+ 0x000000001680049dULL,
+ 0x000000001680419dULL,
+ 0x0000000014804191ULL,
+ 0x000000001680049dULL,
+ 0x0000000014804191ULL,
+ 0x0000000014800491ULL,
+ 0x000000001680049dULL,
+ 0x0000000000800011ULL,
+ 0x00000000068b5691ULL,
+ 0x0000000004098611ULL,
+ 0x000000000700dc22ULL,
+ 0x0000000000800011ULL,
+ 0x0000000296cb569dULL,
+ 0x0000000000800011ULL,
+ 0x0000000294ab7691ULL,
+ 0x0000000000801411ULL,
+ 0x00000000068b3691ULL,
+ 0x000000034409af11ULL,
+ 0x0000000004098411ULL,
+ 0x000000000700dc22ULL,
+ 0x0000000000800011ULL,
+ 0x00000002948b7691ULL,
+ 0x0000000000801411ULL,
+ 0x0000000296cb369dULL,
+ 0x0000000000800011ULL,
+ 0x0000000294ab7691ULL,
+ 0x0000000000800411ULL,
+ 0x00000002948b3691ULL,
+ 0x0000000000801411ULL,
+ 0x00000000068b3a91ULL,
+ 0x000000034409ab11ULL,
+ 0x000000030409a411ULL,
+ 0x0000000004098411ULL,
+ 0x000000000700dc22ULL,
+ 0x0000000000800011ULL,
+ 0x00000002948b7691ULL,
+ 0x0000000000800411ULL,
+ 0x00000002948b3691ULL,
+ 0x0000000000801411ULL,
+ 0x0000000296cb369dULL,
+ 0x0000000001000011ULL,
+ 0x0000000006098611ULL,
+ 0x0000000000000000ULL,
+ 0x0000000007000e02ULL,
+ 0x0000000000888061ULL,
+ 0x0000000003000602ULL,
+ 0x0000000000888061ULL,
+ 0x00000000000984edULL,
+ 0x0000000001000011ULL,
+ 0x0000000b8409b615ULL,
+ 0x0000000400800419ULL,
+ 0x000000000609b611ULL,
+ 0x0000000007000e02ULL,
+ 0x0000000080800061ULL,
+ 0x0000000200cb0461ULL,
+ 0x00000000000b8000ULL,
+ 0x0000000003000602ULL,
+ 0x0000000080800061ULL,
+ 0x0000000200cb0461ULL,
+ 0x00000000000b8001ULL,
+ 0x00000000000985edULL,
+ 0x0000000001000011ULL,
+ 0x0000000b8409b615ULL,
+ 0x0000000400800419ULL,
+ 0x000000000609b611ULL,
+ 0x0000000007000e02ULL,
+ 0x0000000080800061ULL,
+ 0x00000002808b0461ULL,
+ 0x0000000200cb0461ULL,
+ 0x00000000000b8000ULL,
+ 0x0000000003000602ULL,
+ 0x0000000080800061ULL,
+ 0x00000002808b0461ULL,
+ 0x0000000200cb0461ULL,
+ 0x00000000000b8001ULL,
+ 0x00000000000985edULL,
+ 0x0000000002800002ULL,
+ 0x000000500220220aULL,
+ 0x000000140606550aULL,
+ 0x000000140606c50aULL,
+ 0x0000000002a01202ULL,
+ 0x000000500680100aULL,
+ 0x000000140286550aULL,
+ 0x000000000300d502ULL,
+ 0x000000500220340aULL,
+ 0x000000140306660aULL,
+ 0x000000140686c40aULL,
+ 0x000000140206660aULL,
+ 0x000000000600dd02ULL,
+ 0x000000500720550aULL,
+ 0x0000001806064c0aULL,
+ 0x000000180306c60aULL,
+ 0x0000000002001102ULL,
+ 0x000000500020c50aULL,
+ 0x000000000600e402ULL,
+ 0x000000500220440aULL,
+ 0x000000140606cc0aULL,
+ 0x000000000320d602ULL,
+ 0x000000500100e50aULL,
+ 0x000000180086c60aULL,
+ 0x00000000000000c4ULL,
+ 0x0000000002000002ULL,
+ 0x0000005002a0210aULL,
+ 0x000000140280540aULL,
+ 0x0000000003005502ULL,
+ 0x000000500620200aULL,
+ 0x000000140680c50aULL,
+ 0x0000000002004402ULL,
+ 0x0000005003a0cc0aULL,
+ 0x0000000002a03702ULL,
+ 0x000000500700c50aULL,
+ 0x000000140280650aULL,
+ 0x000000140280e50aULL,
+ 0x000000000000c502ULL,
+ 0x000000500120c70aULL,
+ 0x000000000200c402ULL,
+ 0x0000005000a0d50aULL,
+ 0x0000000000000000ULL,
+ 0x000000140080410aULL,
+ 0x00000000000000c4ULL,
+ 0x0000000006009202ULL,
+ 0x000000500220a10aULL,
+ 0x0000001806064c0aULL,
+ 0x0000000002808202ULL,
+ 0x0000005006a0a00aULL,
+ 0x000000180706d50aULL,
+ 0x000000000320cc02ULL,
+ 0x000000500280ee0aULL,
+ 0x0000000006a0d502ULL,
+ 0x000000500780a20aULL,
+ 0x000000140386dd0aULL,
+ 0x000000000300f602ULL,
+ 0x0000005002a0e50aULL,
+ 0x000000180306560aULL,
+ 0x0000000000000000ULL,
+ 0x000000180306760aULL,
+ 0x0000001806866d0aULL,
+ 0x000000000380f502ULL,
+ 0x0000005007a0450aULL,
+ 0x000000300281070aULL,
+ 0x000000200000502aULL,
+ 0x00000000000000fcULL,
+ 0x0000000c000000a4ULL,
+ 0x0000002bc000006cULL,
+ 0x000000000600dc02ULL,
+ 0x000000500020e60aULL,
+ 0x000000180086fc0aULL,
+ 0x000000140107170aULL,
+ 0x00000000000000c4ULL,
+ 0x000000000200a102ULL,
+ 0x000000500620920aULL,
+ 0x000000140600c40aULL,
+ 0x000000000200a002ULL,
+ 0x0000005006a0820aULL,
+ 0x000000140680d40aULL,
+ 0x000000140200dc0aULL,
+ 0x000000000700a202ULL,
+ 0x0000005002a0dd0aULL,
+ 0x000000000300c402ULL,
+ 0x0000005003a0350aULL,
+ 0x0000000000000000ULL,
+ 0x000000140300670aULL,
+ 0x000000000380d502ULL,
+ 0x0000005007a0e60aULL,
+ 0x0000000000000000ULL,
+ 0x0000001407807f0aULL,
+ 0x000000000380d102ULL,
+ 0x000000500320c00aULL,
+ 0x0000000000000000ULL,
+ 0x000000140380760aULL,
+ 0x0000000003007502ULL,
+ 0x0000005002a0d50aULL,
+ 0x000000000200f402ULL,
+ 0x0000005003a0e50aULL,
+ 0x000000300281070aULL,
+ 0x000000200000502aULL,
+ 0x00000000000000fcULL,
+ 0x0000000c000000a4ULL,
+ 0x0000002bc000006cULL,
+ 0x000000000000df02ULL,
+ 0x0000005000a0a60aULL,
+ 0x000000140101170aULL,
+ 0x000000140080410aULL,
+ 0x00000000000000c4ULL,
+ 0x000000300281020aULL,
+ 0x0000003006810a0aULL,
+ 0x0000003006010c0aULL,
+ 0x000000200000202aULL,
+ 0x00000000000000fcULL,
+ 0x0000000c000000a4ULL,
+ 0x0000002d1000006cULL,
+ 0x000000200000a02aULL,
+ 0x00000000000000fcULL,
+ 0x0000000c000000a4ULL,
+ 0x0000002d5000006cULL,
+ 0x000000200000c02aULL,
+ 0x00000000000000fcULL,
+ 0x0000000c000000a4ULL,
+ 0x0000002cd0000064ULL,
+ 0x00000034000000d4ULL,
+ 0x00000000000000c4ULL,
+ 0x0000000001000002ULL,
+ 0x00000006000b0003ULL,
+ 0x0000000000000000ULL,
+ 0x00000000000000c4ULL,
+ 0x000000140001180aULL,
+ 0x000000140081190aULL,
+ 0x0000001401011a0aULL,
+ 0x00000000000000c4ULL,
+ 0x00000000000000c4ULL,
+ 0x0000000001810302ULL,
+ 0x0000005005a10b0aULL,
+ 0x0000000002000002ULL,
+ 0x000000500620110aULL,
+ 0x000000140206340aULL,
+ 0x000000180606cb0aULL,
+ 0x0000000002000402ULL,
+ 0x0000005006210c0aULL,
+ 0x000000140206c40aULL,
+ 0x000000300201040aULL,
+ 0x00000000000000c4ULL,
+ 0x0000000002801002ULL,
+ 0x0000005005a10b0aULL,
+ 0x000000140286b50aULL,
+ 0x000000140186300aULL,
+ 0x0000000002000002ULL,
+ 0x000000500620110aULL,
+ 0x000000140606c50aULL,
+ 0x0000000002003402ULL,
+ 0x0000005006210c0aULL,
+ 0x000000140206c40aULL,
+ 0x000000300201040aULL,
+ 0x00000000000000c4ULL,
+ 0x000000040400000aULL,
+ 0x000000000000002cULL,
+ 0x0000000c0000800eULL,
+ 0x0000000c0400880aULL,
+ 0x000000080000007cULL,
+ 0x0000000004000002ULL,
+ 0x00000006808b0013ULL,
+ 0x0000000000000034ULL,
+ 0x0000000000000002ULL,
+ 0x0000002ff000005cULL,
+ 0x0000002f4000004cULL,
+ 0x00000002000b0101ULL,
+ 0x0000000a000b0003ULL,
+ 0x0000003760000044ULL,
+ 0x0000000000000034ULL,
+ 0x0000000c0000000aULL,
+ 0x0000002ff0000054ULL,
+ 0x0000000c0000800aULL,
+ 0x0000002fb000004cULL,
+ 0x0000003640000044ULL,
+ 0x0000000c0000800aULL,
+ 0x000000040400000aULL,
+ 0x000000000000002cULL,
+ 0x0000000c0000800eULL,
+ 0x0000000c0400880aULL,
+ 0x000000080000007cULL,
+ 0x000000040400000aULL,
+ 0x000000000000002cULL,
+ 0x0000000c0000800eULL,
+ 0x0000000c0400880aULL,
+ 0x000000080000007cULL,
+ 0x0000003640000044ULL,
+ 0x000000080180000aULL,
+ 0x0000000001820002ULL,
+ 0x00000007040b0013ULL,
+ 0x000000040200000aULL,
+ 0x000000000000002cULL,
+ 0x0000000c0180430eULL,
+ 0x0000000c0200440aULL,
+ 0x000000080000007cULL,
+ 0x0000000001010002ULL,
+ 0x00000006108b0093ULL,
+ 0x0000000005010002ULL,
+ 0x00000006108b0093ULL,
+ 0x0000000000000000ULL,
+ 0x00000032e01f80e4ULL,
+ 0x00000034401f81e4ULL,
+ 0x00000034601f82e4ULL,
+ 0x0000000c0181020aULL,
+ 0x0000000c0181030aULL,
+ 0x0000001c000000d4ULL,
+ 0x0000000000004002ULL,
+ 0x0000005000a0410aULL,
+ 0x0000000001004202ULL,
+ 0x000000500021000aULL,
+ 0x0000000000810102ULL,
+ 0x000000500121020aULL,
+ 0x000000200000202aULL,
+ 0x00000000000000fcULL,
+ 0x0000000c000000a4ULL,
+ 0x0000000000000002ULL,
+ 0x0000000600098003ULL,
+ 0x0000000000810002ULL,
+ 0x0000000610898093ULL,
+ 0x0000003760000044ULL,
+ 0x0000000004000002ULL,
+ 0x00000006808b0013ULL,
+ 0x0000000004800102ULL,
+ 0x00000006808b0013ULL,
+ 0x0000000005000202ULL,
+ 0x00000006808b0013ULL,
+ 0x0000000000000034ULL,
+ 0x0000000000000002ULL,
+ 0x000000342000005cULL,
+ 0x000000334000004cULL,
+ 0x0000001000000084ULL,
+ 0x00000006000b0009ULL,
+ 0x00000002000b0101ULL,
+ 0x0000002000000084ULL,
+ 0x00000006000b0009ULL,
+ 0x0000003760000044ULL,
+ 0x0000000000000034ULL,
+ 0x00000034000000d4ULL,
+ 0x0000003420000054ULL,
+ 0x00000038000000d4ULL,
+ 0x00000033e000004cULL,
+ 0x00000031d0000044ULL,
+ 0x00000038000000d4ULL,
+ 0x00000031d0000044ULL,
+ 0x00000034000000d4ULL,
+ 0x00000031d0000044ULL,
+ 0x000000080180000aULL,
+ 0x0000000001820002ULL,
+ 0x00000007040b0013ULL,
+ 0x0000000005840002ULL,
+ 0x00000007040b0013ULL,
+ 0x0000003c000000d4ULL,
+ 0x00000004000000a4ULL,
+ 0x000000200000402aULL,
+ 0x0000000000000012ULL,
+ 0x00000000000b0001ULL,
+ 0x0000000000098101ULL,
+ 0x0000003760000044ULL,
+ 0x000000040200000aULL,
+ 0x000000000000002cULL,
+ 0x0000000c0000400eULL,
+ 0x0000000c0200440aULL,
+ 0x000000080000007cULL,
+ 0x00000036c01f87e4ULL,
+ 0x00000036401f89e4ULL,
+ 0x000000040200000aULL,
+ 0x000000000000002cULL,
+ 0x0000000c0400480eULL,
+ 0x0000000c0200440aULL,
+ 0x000000080000007cULL,
+ 0x00000036a01f86e4ULL,
+ 0x000000080180000aULL,
+ 0x00000036601f84e4ULL,
+ 0x00000036801f85e4ULL,
+ 0x000000300001000aULL,
+ 0x0000003760000044ULL,
+ 0x000000140006800aULL,
+ 0x0000003640000044ULL,
+ 0x000000180006800aULL,
+ 0x0000003640000044ULL,
+ 0x0000000c0000800aULL,
+ 0x0000003640000044ULL,
+ 0x0000000c0181080aULL,
+ 0x0000001c000000d4ULL,
+ 0x00000004000000a4ULL,
+ 0x0000000c0000400aULL,
+ 0x0000003640000044ULL,
+ 0x0000000c0181000aULL,
+ 0x0000001c000000d4ULL,
+ 0x00000004000000a4ULL,
+ 0x000000140001140aULL,
+ 0x0000003640000044ULL,
+ 0x0000000c000000a4ULL,
+ 0x0000000000000044ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+ 0x0000000000000000ULL,
+};
+
+#endif /* _NLM_HAL_RSA_UCODE_H_ */
diff --git a/sys/mips/nlm/files.xlp b/sys/mips/nlm/files.xlp
index 682bbbf..69b1d5e 100644
--- a/sys/mips/nlm/files.xlp
+++ b/sys/mips/nlm/files.xlp
@@ -14,3 +14,9 @@ mips/nlm/intern_dev.c optional pci
mips/nlm/uart_pci_xlp.c optional uart
mips/nlm/uart_cpu_xlp.c optional uart
mips/nlm/usb_init.c optional usb
+#
+# Security Driver
+#
+mips/nlm/dev/sec/nlmsec.c optional nlmsec
+mips/nlm/dev/sec/nlmseclib.c optional nlmsec
+mips/nlm/dev/sec/nlmrsa.c optional nlmrsa
diff --git a/sys/mips/nlm/hal/iomap.h b/sys/mips/nlm/hal/iomap.h
index 17d42bd..f2d1dd5 100644
--- a/sys/mips/nlm/hal/iomap.h
+++ b/sys/mips/nlm/hal/iomap.h
@@ -36,6 +36,7 @@
#define NMI_BASE 0xbfc00000
#define XLP_IO_CLK 133333333
+#define XLP_L2L3_CACHELINE_SIZE 64
#define XLP_PCIE_CFG_SIZE 0x1000 /* 4K */
#define XLP_PCIE_DEV_BLK_SIZE (8 * XLP_PCIE_CFG_SIZE)
#define XLP_PCIE_BUS_BLK_SIZE (256 * XLP_PCIE_DEV_BLK_SIZE)
diff --git a/sys/mips/nlm/hal/nlmsaelib.h b/sys/mips/nlm/hal/nlmsaelib.h
new file mode 100644
index 0000000..3d12729
--- /dev/null
+++ b/sys/mips/nlm/hal/nlmsaelib.h
@@ -0,0 +1,607 @@
+/*-
+ * Copyright (c) 2003-2012 Broadcom Corporation
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NLM_HAL_CRYPTO_H_
+#define _NLM_HAL_CRYPTO_H_
+
+#define SAE_CFG_REG 0x00
+#define SAE_ENG_SEL_0 0x01
+#define SAE_ENG_SEL_1 0x02
+#define SAE_ENG_SEL_2 0x03
+#define SAE_ENG_SEL_3 0x04
+#define SAE_ENG_SEL_4 0x05
+#define SAE_ENG_SEL_5 0x06
+#define SAE_ENG_SEL_6 0x07
+#define SAE_ENG_SEL_7 0x08
+
+#define RSA_CFG_REG 0x00
+#define RSA_ENG_SEL_0 0x01
+#define RSA_ENG_SEL_1 0x02
+#define RSA_ENG_SEL_2 0x03
+
+#define nlm_read_sec_reg(b, r) nlm_read_reg(b, r)
+#define nlm_write_sec_reg(b, r, v) nlm_write_reg(b, r, v)
+#define nlm_get_sec_pcibase(node) nlm_pcicfg_base(XLP_IO_SEC_OFFSET(node))
+#define nlm_get_sec_regbase(node) \
+ (nlm_get_sec_pcibase(node) + XLP_IO_PCI_HDRSZ)
+
+#define nlm_read_rsa_reg(b, r) nlm_read_reg(b, r)
+#define nlm_write_rsa_reg(b, r, v) nlm_write_reg(b, r, v)
+#define nlm_get_rsa_pcibase(node) nlm_pcicfg_base(XLP_IO_RSA_OFFSET(node))
+#define nlm_get_rsa_regbase(node) \
+ (nlm_get_rsa_pcibase(node) + XLP_IO_PCI_HDRSZ)
+
+#define nlm_pcibase_sec(node) nlm_pcicfg_base(XLP_IO_SEC_OFFSET(node))
+#define nlm_qidstart_sec(node) nlm_qidstart_kseg(nlm_pcibase_sec(node))
+#define nlm_qnum_sec(node) nlm_qnum_kseg(nlm_pcibase_sec(node))
+
+/*
+ * Since buffer allocation for crypto at kernel is done as malloc, each
+ * segment size is given as page size which is 4K by default
+ */
+#define NLM_CRYPTO_MAX_SEG_LEN PAGE_SIZE
+
+#define MAX_KEY_LEN_IN_DW 20
+
+#define left_shift64(x, bitshift, numofbits) \
+ ((uint64_t)(x) << (bitshift))
+
+#define left_shift64_mask(x, bitshift, numofbits) \
+ (((uint64_t)(x) & ((1ULL << (numofbits)) - 1)) << (bitshift))
+
+/**
+* @brief cipher algorithms
+* @ingroup crypto
+*/
+enum nlm_cipher_algo {
+ NLM_CIPHER_BYPASS = 0,
+ NLM_CIPHER_DES = 1,
+ NLM_CIPHER_3DES = 2,
+ NLM_CIPHER_AES128 = 3,
+ NLM_CIPHER_AES192 = 4,
+ NLM_CIPHER_AES256 = 5,
+ NLM_CIPHER_ARC4 = 6,
+ NLM_CIPHER_KASUMI_F8 = 7,
+ NLM_CIPHER_SNOW3G_F8 = 8,
+ NLM_CIPHER_CAMELLIA128 = 9,
+ NLM_CIPHER_CAMELLIA192 = 0xA,
+ NLM_CIPHER_CAMELLIA256 = 0xB,
+ NLM_CIPHER_MAX = 0xC,
+};
+
+/**
+* @brief cipher modes
+* @ingroup crypto
+*/
+enum nlm_cipher_mode {
+ NLM_CIPHER_MODE_ECB = 0,
+ NLM_CIPHER_MODE_CBC = 1,
+ NLM_CIPHER_MODE_CFB = 2,
+ NLM_CIPHER_MODE_OFB = 3,
+ NLM_CIPHER_MODE_CTR = 4,
+ NLM_CIPHER_MODE_AES_F8 = 5,
+ NLM_CIPHER_MODE_GCM = 6,
+ NLM_CIPHER_MODE_CCM = 7,
+ NLM_CIPHER_MODE_UNDEFINED1 = 8,
+ NLM_CIPHER_MODE_UNDEFINED2 = 9,
+ NLM_CIPHER_MODE_LRW = 0xA,
+ NLM_CIPHER_MODE_XTS = 0xB,
+ NLM_CIPHER_MODE_MAX = 0xC,
+};
+
+/**
+* @brief hash algorithms
+* @ingroup crypto
+*/
+enum nlm_hash_algo {
+ NLM_HASH_BYPASS = 0,
+ NLM_HASH_MD5 = 1,
+ NLM_HASH_SHA = 2,
+ NLM_HASH_UNDEFINED = 3,
+ NLM_HASH_AES128 = 4,
+ NLM_HASH_AES192 = 5,
+ NLM_HASH_AES256 = 6,
+ NLM_HASH_KASUMI_F9 = 7,
+ NLM_HASH_SNOW3G_F9 = 8,
+ NLM_HASH_CAMELLIA128 = 9,
+ NLM_HASH_CAMELLIA192 = 0xA,
+ NLM_HASH_CAMELLIA256 = 0xB,
+ NLM_HASH_GHASH = 0xC,
+ NLM_HASH_MAX = 0xD
+};
+
+/**
+* @brief hash modes
+* @ingroup crypto
+*/
+enum nlm_hash_mode {
+ NLM_HASH_MODE_SHA1 = 0, /* Only SHA */
+ NLM_HASH_MODE_SHA224 = 1, /* Only SHA */
+ NLM_HASH_MODE_SHA256 = 2, /* Only SHA */
+ NLM_HASH_MODE_SHA384 = 3, /* Only SHA */
+ NLM_HASH_MODE_SHA512 = 4, /* Only SHA */
+ NLM_HASH_MODE_CMAC = 5, /* AES and Camellia */
+ NLM_HASH_MODE_XCBC = 6, /* AES and Camellia */
+ NLM_HASH_MODE_CBC_MAC = 7, /* AES and Camellia */
+ NLM_HASH_MODE_CCM = 8, /* AES */
+ NLM_HASH_MODE_GCM = 9, /* AES */
+ NLM_HASH_MODE_MAX = 0xA,
+};
+
+/**
+* @brief crypto control descriptor, should be cache aligned
+* @ingroup crypto
+*/
+struct nlm_crypto_pkt_ctrl {
+ uint64_t desc0;
+ /* combination of cipher and hash keys */
+ uint64_t key[MAX_KEY_LEN_IN_DW];
+ uint32_t cipherkeylen;
+ uint32_t hashkeylen;
+ uint32_t taglen;
+};
+
+/**
+* @brief crypto packet descriptor, should be cache aligned
+* @ingroup crypto
+*/
+struct nlm_crypto_pkt_param {
+ uint64_t desc0;
+ uint64_t desc1;
+ uint64_t desc2;
+ uint64_t desc3;
+ uint64_t segment[1][2];
+};
+
+static __inline__ uint64_t
+nlm_crypto_form_rsa_ecc_fmn_entry0(unsigned int l3alloc, unsigned int type,
+ unsigned int func, uint64_t srcaddr)
+{
+ return (left_shift64(l3alloc, 61, 1) |
+ left_shift64(type, 46, 7) |
+ left_shift64(func, 40, 6) |
+ left_shift64(srcaddr, 0, 40));
+}
+
+static __inline__ uint64_t
+nlm_crypto_form_rsa_ecc_fmn_entry1(unsigned int dstclobber,
+ unsigned int l3alloc, unsigned int fbvc, uint64_t dstaddr)
+{
+ return (left_shift64(dstclobber, 62, 1) |
+ left_shift64(l3alloc, 61, 1) |
+ left_shift64(fbvc, 40, 12) |
+ left_shift64(dstaddr, 0, 40));
+}
+
+/**
+* @brief Generate cypto control descriptor
+* @ingroup crypto
+* hmac : 1 for hash with hmac
+* hashalg, see hash_alg enums
+* hashmode, see hash_mode enums
+* cipherhalg, see cipher_alg enums
+* ciphermode, see cipher_mode enums
+* arc4_cipherkeylen : length of arc4 cipher key, 0 is interpreted as 32
+* arc4_keyinit :
+* cfbmask : cipher text for feedback,
+* 0(1 bit), 1(2 bits), 2(4 bits), 3(8 bits), 4(16bits), 5(32 bits),
+* 6(64 bits), 7(128 bits)
+*/
+static __inline__ uint64_t
+nlm_crypto_form_pkt_ctrl_desc(unsigned int hmac, unsigned int hashalg,
+ unsigned int hashmode, unsigned int cipheralg, unsigned int ciphermode,
+ unsigned int arc4_cipherkeylen, unsigned int arc4_keyinit,
+ unsigned int cfbmask)
+{
+ return (left_shift64(hmac, 61, 1) |
+ left_shift64(hashalg, 52, 8) |
+ left_shift64(hashmode, 43, 8) |
+ left_shift64(cipheralg, 34, 8) |
+ left_shift64(ciphermode, 25, 8) |
+ left_shift64(arc4_cipherkeylen, 18, 5) |
+ left_shift64(arc4_keyinit, 17, 1) |
+ left_shift64(cfbmask, 0, 3));
+}
+/**
+* @brief Generate cypto packet descriptor 0
+* @ingroup crypto
+* tls : 1 (tls enabled) 0(tls disabled)
+* hash_source : 1 (encrypted data is sent to the auth engine)
+* 0 (plain data is sent to the auth engine)
+* hashout_l3alloc : 1 (auth output is transited through l3 cache)
+* encrypt : 1 (for encrypt) 0 (for decrypt)
+* ivlen : iv length in bytes
+* hashdst_addr : hash out physical address, byte aligned
+*/
+static __inline__ uint64_t
+nlm_crypto_form_pkt_desc0(unsigned int tls, unsigned int hash_source,
+ unsigned int hashout_l3alloc, unsigned int encrypt, unsigned int ivlen,
+ uint64_t hashdst_addr)
+{
+ return (left_shift64(tls, 63, 1) |
+ left_shift64(hash_source, 62, 1) |
+ left_shift64(hashout_l3alloc, 60, 1) |
+ left_shift64(encrypt, 59, 1) |
+ left_shift64_mask((ivlen - 1), 41, 16) |
+ left_shift64(hashdst_addr, 0, 40));
+}
+
+/**
+* @brief Generate cypto packet descriptor 1
+* @ingroup crypto
+* cipherlen : cipher length in bytes
+* hashlen : hash length in bytes
+*/
+static __inline__ uint64_t
+nlm_crypto_form_pkt_desc1(unsigned int cipherlen, unsigned int hashlen)
+{
+ return (left_shift64_mask((cipherlen - 1), 32, 32) |
+ left_shift64_mask((hashlen - 1), 0, 32));
+}
+
+/**
+* @brief Generate cypto packet descriptor 2
+* @ingroup crypto
+* ivoff : iv offset, offset from start of src data addr
+* ciperbit_cnt : number of valid bits in the last input byte to the cipher,
+* 0 (8 bits), 1 (1 bit)..7 (7 bits)
+* cipheroff : cipher offset, offset from start of src data addr
+* hashbit_cnt : number of valid bits in the last input byte to the auth
+* 0 (8 bits), 1 (1 bit)..7 (7 bits)
+* hashclobber : 1 (hash output will be written as multiples of cachelines, no
+* read modify write)
+* hashoff : hash offset, offset from start of src data addr
+*/
+
+static __inline__ uint64_t
+nlm_crypto_form_pkt_desc2(unsigned int ivoff, unsigned int cipherbit_cnt,
+ unsigned int cipheroff, unsigned int hashbit_cnt, unsigned int hashclobber,
+ unsigned int hashoff)
+{
+ return (left_shift64(ivoff , 45, 16) |
+ left_shift64(cipherbit_cnt, 42, 3) |
+ left_shift64(cipheroff, 22, 16) |
+ left_shift64(hashbit_cnt, 19, 3) |
+ left_shift64(hashclobber, 18, 1) |
+ left_shift64(hashoff, 0, 16));
+}
+
+/**
+* @brief Generate cypto packet descriptor 3
+* @ingroup crypto
+* designer_vc : designer freeback fmn destination id
+* taglen : length in bits of the tag generated by the auth engine
+* md5 (128 bits), sha1 (160), sha224 (224), sha384 (384),
+* sha512 (512), Kasumi (32), snow3g (32), gcm (128)
+* hmacpad : 1 if hmac padding is already done
+*/
+static __inline__ uint64_t
+nlm_crypto_form_pkt_desc3(unsigned int designer_vc, unsigned int taglen,
+ unsigned int arc4_state_save_l3, unsigned int arc4_save_state,
+ unsigned int hmacpad)
+{
+ return (left_shift64(designer_vc, 48, 16) |
+ left_shift64(taglen, 11, 16) |
+ left_shift64(arc4_state_save_l3, 8, 1) |
+ left_shift64(arc4_save_state, 6, 1) |
+ left_shift64(hmacpad, 5, 1));
+}
+
+/**
+* @brief Generate cypto packet descriptor 4
+* @ingroup crypto
+* srcfraglen : length of the source fragment(header + data + tail) in bytes
+* srcfragaddr : physical address of the srouce fragment
+*/
+static __inline__ uint64_t
+nlm_crypto_form_pkt_desc4(uint64_t srcfraglen,
+ unsigned int srcfragaddr )
+{
+ return (left_shift64_mask((srcfraglen - 1), 48, 16) |
+ left_shift64(srcfragaddr, 0, 40));
+}
+
+/**
+* @brief Generate cypto packet descriptor 5
+* @ingroup crypto
+* dstfraglen : length of the dst fragment(header + data + tail) in bytes
+* chipherout_l3alloc : 1(cipher output is transited through l3 cache)
+* cipherclobber : 1 (cipher output will be written as multiples of cachelines,
+* no read modify write)
+* chiperdst_addr : physical address of the cipher destination address
+*/
+static __inline__ uint64_t
+nlm_crypto_form_pkt_desc5(unsigned int dstfraglen,
+ unsigned int cipherout_l3alloc, unsigned int cipherclobber,
+ uint64_t cipherdst_addr)
+
+{
+ return (left_shift64_mask((dstfraglen - 1), 48, 16) |
+ left_shift64(cipherout_l3alloc, 46, 1) |
+ left_shift64(cipherclobber, 41, 1) |
+ left_shift64(cipherdst_addr, 0, 40));
+}
+
+/**
+ * @brief Generate crypto packet fmn message entry 0
+ * @ingroup crypto
+ * freeback_vc: freeback response destination address
+ * designer_fblen : Designer freeback length, 1 - 4
+ * designerdesc_valid : designer desc valid or not
+ * cipher_keylen : cipher key length in bytes
+ * ctrldesc_addr : physicall address of the control descriptor
+ */
+static __inline__ uint64_t
+nlm_crypto_form_pkt_fmn_entry0(unsigned int freeback_vc,
+ unsigned int designer_fblen, unsigned int designerdesc_valid,
+ unsigned int cipher_keylen, uint64_t cntldesc_addr)
+{
+ return (left_shift64(freeback_vc, 48, 16) |
+ left_shift64_mask(designer_fblen - 1, 46, 2) |
+ left_shift64(designerdesc_valid, 45, 1) |
+ left_shift64_mask(((cipher_keylen + 7) >> 3), 40, 5) |
+ left_shift64(cntldesc_addr >> 6, 0, 34));
+}
+
+/**
+ * @brief Generate crypto packet fmn message entry 1
+ * @ingroup crypto
+ * arc4load_state : 1 if load state required 0 otherwise
+ * hash_keylen : hash key length in bytes
+ * pktdesc_size : packet descriptor size in bytes
+ * pktdesc_addr : physicall address of the packet descriptor
+ */
+static __inline__ uint64_t
+nlm_crypto_form_pkt_fmn_entry1(unsigned int arc4load_state,
+ unsigned int hash_keylen, unsigned int pktdesc_size,
+ uint64_t pktdesc_addr)
+{
+ return (left_shift64(arc4load_state, 63, 1) |
+ left_shift64_mask(((hash_keylen + 7) >> 3), 56, 5) |
+ left_shift64_mask(((pktdesc_size >> 4) - 1), 43, 12) |
+ left_shift64(pktdesc_addr >> 6, 0, 34));
+}
+
+static __inline__ int
+nlm_crypto_get_hklen_taglen(enum nlm_hash_algo hashalg,
+ enum nlm_hash_mode hashmode, unsigned int *taglen, unsigned int *hklen)
+{
+ if (hashalg == NLM_HASH_MD5) {
+ *taglen = 128;
+ *hklen = 64;
+ } else if (hashalg == NLM_HASH_SHA) {
+ switch (hashmode) {
+ case NLM_HASH_MODE_SHA1:
+ *taglen = 160;
+ *hklen = 64;
+ break;
+ case NLM_HASH_MODE_SHA224:
+ *taglen = 224;
+ *hklen = 64;
+ break;
+ case NLM_HASH_MODE_SHA256:
+ *taglen = 256;
+ *hklen = 64;
+ break;
+ case NLM_HASH_MODE_SHA384:
+ *taglen = 384;
+ *hklen = 128;
+ break;
+ case NLM_HASH_MODE_SHA512:
+ *taglen = 512;
+ *hklen = 128;
+ break;
+ default:
+ printf("Error : invalid shaid (%s)\n", __func__);
+ return (-1);
+ }
+ } else if (hashalg == NLM_HASH_KASUMI_F9) {
+ *taglen = 32;
+ *hklen = 0;
+ } else if (hashalg == NLM_HASH_SNOW3G_F9) {
+ *taglen = 32;
+ *hklen = 0;
+ } else if (hashmode == NLM_HASH_MODE_XCBC) {
+ *taglen = 128;
+ *hklen = 0;
+ } else if (hashmode == NLM_HASH_MODE_GCM) {
+ *taglen = 128;
+ *hklen = 0;
+ } else if (hashalg == NLM_HASH_BYPASS) {
+ *taglen = 0;
+ *hklen = 0;
+ } else {
+ printf("Error:Hash alg/mode not found\n");
+ return (-1);
+ }
+
+ /* TODO : Add remaining cases */
+ return (0);
+}
+
+/**
+* @brief Generate fill cryto control info structure
+* @ingroup crypto
+* hmac : 1 for hash with hmac
+* hashalg: see above, hash_alg enums
+* hashmode: see above, hash_mode enums
+* cipherhalg: see above, cipher_alg enums
+* ciphermode: see above, cipher_mode enums
+*
+*/
+static __inline__ int
+nlm_crypto_fill_pkt_ctrl(struct nlm_crypto_pkt_ctrl *ctrl, unsigned int hmac,
+ enum nlm_hash_algo hashalg, enum nlm_hash_mode hashmode,
+ enum nlm_cipher_algo cipheralg, enum nlm_cipher_mode ciphermode,
+ unsigned char *cipherkey, unsigned int cipherkeylen,
+ unsigned char *hashkey, unsigned int hashkeylen)
+{
+ unsigned int taglen = 0, hklen = 0;
+
+ ctrl->desc0 = nlm_crypto_form_pkt_ctrl_desc(hmac, hashalg, hashmode,
+ cipheralg, ciphermode, 0, 0, 0);
+ memset(ctrl->key, 0, sizeof(ctrl->key));
+ if (cipherkey)
+ memcpy(ctrl->key, cipherkey, cipherkeylen);
+ if (hashkey)
+ memcpy((unsigned char *)&ctrl->key[(cipherkeylen + 7) / 8],
+ hashkey, hashkeylen);
+ if (nlm_crypto_get_hklen_taglen(hashalg, hashmode, &taglen, &hklen)
+ < 0)
+ return (-1);
+
+ ctrl->cipherkeylen = cipherkeylen;
+ ctrl->hashkeylen = hklen;
+ ctrl->taglen = taglen;
+
+ /* TODO : add the invalid checks and return error */
+ return (0);
+}
+
+/**
+* @brief Top level function for generation pkt desc 0 to 3 for cipher auth
+* @ingroup crypto
+* ctrl : pointer to control structure
+* param : pointer to the param structure
+* encrypt : 1(for encrypt) 0(for decrypt)
+* hash_source : 1(encrypted data is sent to the auth engine) 0(plain data is
+* sent to the auth engine)
+* ivoff : iv offset from start of data
+* ivlen : iv length in bytes
+* hashoff : hash offset from start of data
+* hashlen : hash length in bytes
+* hmacpad : hmac padding required or not, 1 if already padded
+* cipheroff : cipher offset from start of data
+* cipherlen : cipher length in bytes
+* hashdst_addr : hash destination physical address
+*/
+static __inline__ void
+nlm_crypto_fill_cipher_auth_pkt_param(struct nlm_crypto_pkt_ctrl *ctrl,
+ struct nlm_crypto_pkt_param *param, unsigned int encrypt,
+ unsigned int hash_source, unsigned int ivoff, unsigned int ivlen,
+ unsigned int hashoff, unsigned int hashlen, unsigned int hmacpad,
+ unsigned int cipheroff, unsigned int cipherlen, unsigned char *hashdst_addr)
+{
+ param->desc0 = nlm_crypto_form_pkt_desc0(0, hash_source, 1, encrypt,
+ ivlen, vtophys(hashdst_addr));
+ param->desc1 = nlm_crypto_form_pkt_desc1(cipherlen, hashlen);
+ param->desc2 = nlm_crypto_form_pkt_desc2(ivoff, 0, cipheroff, 0, 0,
+ hashoff);
+ param->desc3 = nlm_crypto_form_pkt_desc3(0, ctrl->taglen, 0, 0,
+ hmacpad);
+}
+
+/**
+* @brief Top level function for generation pkt desc 0 to 3 for cipher operation
+* @ingroup crypto
+* ctrl : pointer to control structure
+* param : pointer to the param structure
+* encrypt : 1(for encrypt) 0(for decrypt)
+* ivoff : iv offset from start of data
+* ivlen : iv length in bytes
+* cipheroff : cipher offset from start of data
+* cipherlen : cipher length in bytes
+*/
+
+
+static __inline__ void
+nlm_crypto_fill_cipher_pkt_param(struct nlm_crypto_pkt_ctrl *ctrl,
+ struct nlm_crypto_pkt_param *param, unsigned int encrypt,
+ unsigned int ivoff, unsigned int ivlen, unsigned int cipheroff,
+ unsigned int cipherlen)
+{
+ param->desc0 = nlm_crypto_form_pkt_desc0(0, 0, 0, encrypt, ivlen, 0ULL);
+ param->desc1 = nlm_crypto_form_pkt_desc1(cipherlen, 1);
+ param->desc2 = nlm_crypto_form_pkt_desc2(ivoff, 0, cipheroff, 0, 0, 0);
+ param->desc3 = nlm_crypto_form_pkt_desc3(0, ctrl->taglen, 0, 0, 0);
+}
+
+/**
+* @brief Top level function for generation pkt desc 0 to 3 for auth operation
+* @ingroup crypto
+* ctrl : pointer to control structure
+* param : pointer to the param structure
+* hashoff : hash offset from start of data
+* hashlen : hash length in bytes
+* hmacpad : hmac padding required or not, 1 if already padded
+* hashdst_addr : hash destination physical address
+*/
+static __inline__ void
+nlm_crypto_fill_auth_pkt_param(struct nlm_crypto_pkt_ctrl *ctrl,
+ struct nlm_crypto_pkt_param *param, unsigned int hashoff,
+ unsigned int hashlen, unsigned int hmacpad, unsigned char *hashdst_addr)
+{
+ param->desc0 = nlm_crypto_form_pkt_desc0(0, 0, 1, 0, 1,
+ vtophys(hashdst_addr));
+ param->desc1 = nlm_crypto_form_pkt_desc1(1, hashlen);
+ param->desc2 = nlm_crypto_form_pkt_desc2(0, 0, 0, 0, 0, hashoff);
+ param->desc3 = nlm_crypto_form_pkt_desc3(0, ctrl->taglen, 0, 0,
+ hmacpad);
+}
+
+static __inline__ unsigned int
+nlm_crypto_fill_src_seg(struct nlm_crypto_pkt_param *param, int seg,
+ unsigned char *input, unsigned int inlen)
+{
+ unsigned off = 0, len = 0;
+ unsigned int remlen = inlen;
+
+ for (; remlen > 0;) {
+ len = remlen > NLM_CRYPTO_MAX_SEG_LEN ?
+ NLM_CRYPTO_MAX_SEG_LEN : remlen;
+ param->segment[seg][0] = nlm_crypto_form_pkt_desc4(len,
+ vtophys(input + off));
+ remlen -= len;
+ off += len;
+ seg++;
+ }
+ return (seg);
+}
+
+static __inline__ unsigned int
+nlm_crypto_fill_dst_seg(struct nlm_crypto_pkt_param *param,
+ int seg, unsigned char *output, unsigned int outlen)
+{
+ unsigned off = 0, len = 0;
+ unsigned int remlen = outlen;
+
+ for (; remlen > 0;) {
+ len = remlen > NLM_CRYPTO_MAX_SEG_LEN ?
+ NLM_CRYPTO_MAX_SEG_LEN : remlen;
+ param->segment[seg][1] = nlm_crypto_form_pkt_desc5(len, 1, 0,
+ vtophys(output + off));
+ remlen -= len;
+ off += len;
+ seg++;
+ }
+ return (seg);
+}
+
+#endif
OpenPOWER on IntegriCloud