Author: jchandra Date: Tue Mar 27 11:43:46 2012 New Revision: 233541 URL: http://svn.freebsd.org/changeset/base/233541
Log: Opencrypto driver for XLP Security and RSA/ECC blocks Support for the Security and RSA blocks on XLP SoC. Even though the XLP supports many more algorithms, only the ones supported in OCF have been added. Submitted by: Venkatesh J. V. (venkatesh at netlogicmicro com) Added: head/sys/mips/nlm/dev/ head/sys/mips/nlm/dev/sec/ head/sys/mips/nlm/dev/sec/nlmrsa.c (contents, props changed) head/sys/mips/nlm/dev/sec/nlmrsalib.h (contents, props changed) head/sys/mips/nlm/dev/sec/nlmsec.c (contents, props changed) head/sys/mips/nlm/dev/sec/nlmseclib.c (contents, props changed) head/sys/mips/nlm/dev/sec/nlmseclib.h (contents, props changed) head/sys/mips/nlm/dev/sec/rsa_ucode.h (contents, props changed) head/sys/mips/nlm/hal/nlmsaelib.h (contents, props changed) Modified: head/sys/mips/conf/std.XLP head/sys/mips/nlm/files.xlp head/sys/mips/nlm/hal/iomap.h Modified: head/sys/mips/conf/std.XLP ============================================================================== --- head/sys/mips/conf/std.XLP Tue Mar 27 11:17:04 2012 (r233540) +++ head/sys/mips/conf/std.XLP Tue Mar 27 11:43:46 2012 (r233541) @@ -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 Added: head/sys/mips/nlm/dev/sec/nlmrsa.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/mips/nlm/dev/sec/nlmrsa.c Tue Mar 27 11:43:46 2012 (r233541) @@ -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); +} Added: head/sys/mips/nlm/dev/sec/nlmrsalib.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/mips/nlm/dev/sec/nlmrsalib.h Tue Mar 27 11:43:46 2012 (r233541) @@ -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_ */ Added: head/sys/mips/nlm/dev/sec/nlmsec.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/mips/nlm/dev/sec/nlmsec.c Tue Mar 27 11:43:46 2012 (r233541) @@ -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); *** DIFF OUTPUT TRUNCATED AT 1000 LINES *** _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"