Page MenuHomeFreeBSD

D8297.diff
No OneTemporary

D8297.diff

Index: head/share/man/man4/Makefile
===================================================================
--- head/share/man/man4/Makefile
+++ head/share/man/man4/Makefile
@@ -53,6 +53,7 @@
${_aout.4} \
${_apic.4} \
arcmsr.4 \
+ ${_armv8crypto.4} \
${_asmc.4} \
ata.4 \
ath.4 \
@@ -746,6 +747,10 @@
MLINKS+=xl.4 if_xl.4
MLINKS+=zyd.4 if_zyd.4
+.if ${MACHINE_CPUARCH} == "aarch64"
+_armv8crypto.4= armv8crypto.4
+.endif
+
.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386"
_acpi_asus.4= acpi_asus.4
_acpi_asus_wmi.4= acpi_asus_wmi.4
Index: head/share/man/man4/armv8crypto.4
===================================================================
--- head/share/man/man4/armv8crypto.4
+++ head/share/man/man4/armv8crypto.4
@@ -0,0 +1,83 @@
+.\" Copyright (c) 2016 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This software was developed by Andrew Turner under
+.\" sponsorship from the FreeBSD Foundation.
+.\"
+.\" 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 THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR 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$
+.\"
+.Dd October 20, 2016
+.Dt ARMV8CRYPTO 4
+.Os
+.Sh NAME
+.Nm armv8crypto
+.Nd "driver for the AES accelerator on ARM CPUs"
+.Sh SYNOPSIS
+To compile this driver into the kernel,
+place the following lines in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device crypto"
+.Cd "device armv8crypto"
+.Ed
+.Pp
+Alternatively, to load the driver as a
+module at boot time, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+armv8crypto_load="YES"
+.Ed
+.Sh DESCRIPTION
+Starting with the ARMv8 architecture ARM Limited has added optional
+cryptography instructions to accelerate AES, SHA-1, SHA-2, and
+finite field arithmetic.
+.Pp
+The processor capability is reported as AES in the Instruction Set
+Attributes 0 line at boot.
+The
+.Nm
+driver does not attach on systems that lack the required CPU capability.
+.Pp
+The
+.Nm
+driver registers itself to accelerate AES operations for
+.Xr crypto 4 .
+.Sh SEE ALSO
+.Xr crypt 3 ,
+.Xr crypto 4 ,
+.Xr intro 4 ,
+.Xr ipsec 4 ,
+.Xr random 4 ,
+.Xr crypto 9
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Fx 11.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Andrew Turner Aq Mt andrew@FreeBSD.org .
Index: head/sys/conf/files.arm64
===================================================================
--- head/sys/conf/files.arm64
+++ head/sys/conf/files.arm64
@@ -136,6 +136,12 @@
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
contrib/vchiq/interface/vchiq_arm/vchiq_util.c optional vchiq soc_brcm_bcm2837 \
compile-with "${NORMAL_C} -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -I$S/contrib/vchiq"
+crypto/armv8/armv8_crypto.c optional armv8crypto
+armv8_crypto_wrap.o optional armv8crypto \
+ dependency "$S/crypto/armv8/armv8_crypto_wrap.c" \
+ compile-with "${CC} -c ${CFLAGS:C/^-O2$/-O3/:N-nostdinc:N-mgeneral-regs-only} ${WERROR} ${NO_WCAST_QUAL} ${PROF} -march=armv8a+crypto ${.IMPSRC}" \
+ no-implicit-rule \
+ clean "armv8_crypto_wrap.o"
crypto/blowfish/bf_enc.c optional crypto | ipsec
crypto/des/des_enc.c optional crypto | ipsec | netsmb
dev/acpica/acpi_if.m optional acpi
Index: head/sys/crypto/armv8/armv8_crypto.h
===================================================================
--- head/sys/crypto/armv8/armv8_crypto.h
+++ head/sys/crypto/armv8/armv8_crypto.h
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2016 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Andrew Turner under
+ * sponsorship from the FreeBSD Foundation.
+ *
+ * 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 THE AUTHORS AND CONTRIBUTORS ``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 THE AUTHORS 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 _ARMV8_CRYPTO_H_
+#define _ARMV8_CRYPTO_H_
+
+#define AES128_ROUNDS 10
+#define AES192_ROUNDS 12
+#define AES256_ROUNDS 14
+#define AES_SCHED_LEN ((AES256_ROUNDS + 1) * AES_BLOCK_LEN)
+
+struct armv8_crypto_session {
+ uint32_t enc_schedule[AES_SCHED_LEN/4];
+ uint32_t dec_schedule[AES_SCHED_LEN/4];
+ int algo;
+ int rounds;
+ int used;
+ uint32_t id;
+ TAILQ_ENTRY(armv8_crypto_session) next;
+};
+
+void armv8_aes_encrypt_cbc(int, const void *, size_t, const uint8_t *,
+ uint8_t *, const uint8_t[static AES_BLOCK_LEN]);
+void armv8_aes_decrypt_cbc(int, const void *, size_t, uint8_t *,
+ const uint8_t[static AES_BLOCK_LEN]);
+
+#endif /* _ARMV8_CRYPTO_H_ */
Index: head/sys/crypto/armv8/armv8_crypto.c
===================================================================
--- head/sys/crypto/armv8/armv8_crypto.c
+++ head/sys/crypto/armv8/armv8_crypto.c
@@ -0,0 +1,565 @@
+/*-
+ * Copyright (c) 2005-2008 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * Copyright (c) 2010 Konstantin Belousov <kib@FreeBSD.org>
+ * Copyright (c) 2014,2016 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by John-Mark Gurney
+ * under sponsorship of the FreeBSD Foundation and
+ * Rubicon Communications, LLC (Netgate).
+ *
+ * This software was developed by Andrew Turner under
+ * sponsorship from the FreeBSD Foundation.
+ *
+ * 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 THE AUTHORS AND CONTRIBUTORS ``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 THE AUTHORS 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.
+ */
+
+/*
+ * This is based on the aesni code.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <sys/queue.h>
+#include <sys/rwlock.h>
+#include <sys/smp.h>
+#include <sys/uio.h>
+
+#include <machine/vfp.h>
+
+#include <opencrypto/cryptodev.h>
+#include <cryptodev_if.h>
+#include <crypto/armv8/armv8_crypto.h>
+#include <crypto/rijndael/rijndael.h>
+
+struct armv8_crypto_softc {
+ int dieing;
+ int32_t cid;
+ uint32_t sid;
+ TAILQ_HEAD(armv8_crypto_sessions_head, armv8_crypto_session) sessions;
+ struct rwlock lock;
+};
+
+static struct mtx *ctx_mtx;
+static struct fpu_kern_ctx **ctx_vfp;
+
+#define AQUIRE_CTX(i, ctx) \
+ do { \
+ (i) = PCPU_GET(cpuid); \
+ mtx_lock(&ctx_mtx[(i)]); \
+ (ctx) = ctx_vfp[(i)]; \
+ } while (0)
+#define RELEASE_CTX(i, ctx) \
+ do { \
+ mtx_unlock(&ctx_mtx[(i)]); \
+ (i) = -1; \
+ (ctx) = NULL; \
+ } while (0)
+
+static void armv8_crypto_freesession_locked(struct armv8_crypto_softc *,
+ struct armv8_crypto_session *);
+static int armv8_crypto_cipher_process(struct armv8_crypto_session *,
+ struct cryptodesc *, struct cryptop *);
+
+MALLOC_DEFINE(M_ARMV8_CRYPTO, "armv8_crypto", "ARMv8 Crypto Data");
+
+static void
+armv8_crypto_identify(driver_t *drv, device_t parent)
+{
+
+ /* NB: order 10 is so we get attached after h/w devices */
+ if (device_find_child(parent, "armv8crypto", -1) == NULL &&
+ BUS_ADD_CHILD(parent, 10, "armv8crypto", -1) == 0)
+ panic("ARMv8 crypto: could not attach");
+}
+
+static int
+armv8_crypto_probe(device_t dev)
+{
+ uint64_t reg;
+ int ret = ENXIO;
+
+ reg = READ_SPECIALREG(id_aa64isar0_el1);
+
+ switch (ID_AA64ISAR0_AES(reg)) {
+ case ID_AA64ISAR0_AES_BASE:
+ case ID_AA64ISAR0_AES_PMULL:
+ ret = 0;
+ break;
+ }
+
+ device_set_desc_copy(dev, "AES-CBC");
+
+ /* TODO: Check more fields as we support more features */
+
+ return (ret);
+}
+
+static int
+armv8_crypto_attach(device_t dev)
+{
+ struct armv8_crypto_softc *sc;
+ int i;
+
+ sc = device_get_softc(dev);
+ TAILQ_INIT(&sc->sessions);
+ sc->dieing = 0;
+ sc->sid = 1;
+
+ sc->cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE |
+ CRYPTOCAP_F_SYNC);
+ if (sc->cid < 0) {
+ device_printf(dev, "Could not get crypto driver id.\n");
+ return (ENOMEM);
+ }
+
+ rw_init(&sc->lock, "armv8crypto");
+
+ ctx_mtx = malloc(sizeof(*ctx_mtx) * (mp_maxid + 1), M_ARMV8_CRYPTO,
+ M_WAITOK|M_ZERO);
+ ctx_vfp = malloc(sizeof(*ctx_vfp) * (mp_maxid + 1), M_ARMV8_CRYPTO,
+ M_WAITOK|M_ZERO);
+
+ CPU_FOREACH(i) {
+ ctx_vfp[i] = fpu_kern_alloc_ctx(0);
+ mtx_init(&ctx_mtx[i], "armv8cryptoctx", NULL, MTX_DEF|MTX_NEW);
+ }
+
+ crypto_register(sc->cid, CRYPTO_AES_CBC, 0, 0);
+
+ return (0);
+}
+
+static int
+armv8_crypto_detach(device_t dev)
+{
+ struct armv8_crypto_softc *sc;
+ struct armv8_crypto_session *ses;
+ int i;
+
+ sc = device_get_softc(dev);
+
+ rw_wlock(&sc->lock);
+ TAILQ_FOREACH(ses, &sc->sessions, next) {
+ if (ses->used) {
+ rw_wunlock(&sc->lock);
+ device_printf(dev,
+ "Cannot detach, sessions still active.\n");
+ return (EBUSY);
+ }
+ }
+ sc->dieing = 1;
+ while ((ses = TAILQ_FIRST(&sc->sessions)) != NULL) {
+ TAILQ_REMOVE(&sc->sessions, ses, next);
+ free(ses, M_ARMV8_CRYPTO);
+ }
+ rw_wunlock(&sc->lock);
+ crypto_unregister_all(sc->cid);
+
+ rw_destroy(&sc->lock);
+
+ CPU_FOREACH(i) {
+ if (ctx_vfp[i] != NULL) {
+ mtx_destroy(&ctx_mtx[i]);
+ fpu_kern_free_ctx(ctx_vfp[i]);
+ }
+ ctx_vfp[i] = NULL;
+ }
+ free(ctx_mtx, M_ARMV8_CRYPTO);
+ ctx_mtx = NULL;
+ free(ctx_vfp, M_ARMV8_CRYPTO);
+ ctx_vfp = NULL;
+
+ return (0);
+}
+
+static int
+armv8_crypto_cipher_setup(struct armv8_crypto_session *ses,
+ struct cryptoini *encini)
+{
+ int i;
+
+ switch (ses->algo) {
+ case CRYPTO_AES_CBC:
+ switch (encini->cri_klen) {
+ case 128:
+ ses->rounds = AES128_ROUNDS;
+ break;
+ case 192:
+ ses->rounds = AES192_ROUNDS;
+ break;
+ case 256:
+ ses->rounds = AES256_ROUNDS;
+ break;
+ default:
+ CRYPTDEB("invalid CBC/ICM/GCM key length");
+ return (EINVAL);
+ }
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ rijndaelKeySetupEnc(ses->enc_schedule, encini->cri_key,
+ encini->cri_klen);
+ rijndaelKeySetupDec(ses->dec_schedule, encini->cri_key,
+ encini->cri_klen);
+ for (i = 0; i < nitems(ses->enc_schedule); i++) {
+ ses->enc_schedule[i] = bswap32(ses->enc_schedule[i]);
+ ses->dec_schedule[i] = bswap32(ses->dec_schedule[i]);
+ }
+
+ return (0);
+}
+
+static int
+armv8_crypto_newsession(device_t dev, uint32_t *sidp, struct cryptoini *cri)
+{
+ struct armv8_crypto_softc *sc;
+ struct armv8_crypto_session *ses;
+ struct cryptoini *encini;
+ int error;
+
+ if (sidp == NULL || cri == NULL) {
+ CRYPTDEB("no sidp or cri");
+ return (EINVAL);
+ }
+
+ sc = device_get_softc(dev);
+ if (sc->dieing)
+ return (EINVAL);
+
+ ses = NULL;
+ encini = NULL;
+ for (; cri != NULL; cri = cri->cri_next) {
+ switch (cri->cri_alg) {
+ case CRYPTO_AES_CBC:
+ if (encini != NULL) {
+ CRYPTDEB("encini already set");
+ return (EINVAL);
+ }
+ encini = cri;
+ break;
+ default:
+ CRYPTDEB("unhandled algorithm");
+ return (EINVAL);
+ }
+ }
+ if (encini == NULL) {
+ CRYPTDEB("no cipher");
+ return (EINVAL);
+ }
+
+ rw_wlock(&sc->lock);
+ if (sc->dieing) {
+ rw_wunlock(&sc->lock);
+ return (EINVAL);
+ }
+
+ /*
+ * Free sessions goes first, so if first session is used, we need to
+ * allocate one.
+ */
+ ses = TAILQ_FIRST(&sc->sessions);
+ if (ses == NULL || ses->used) {
+ ses = malloc(sizeof(*ses), M_ARMV8_CRYPTO, M_NOWAIT | M_ZERO);
+ if (ses == NULL) {
+ rw_wunlock(&sc->lock);
+ return (ENOMEM);
+ }
+ ses->id = sc->sid++;
+ } else {
+ TAILQ_REMOVE(&sc->sessions, ses, next);
+ }
+ ses->used = 1;
+ TAILQ_INSERT_TAIL(&sc->sessions, ses, next);
+ rw_wunlock(&sc->lock);
+ ses->algo = encini->cri_alg;
+
+ error = armv8_crypto_cipher_setup(ses, encini);
+ if (error != 0) {
+ CRYPTDEB("setup failed");
+ rw_wlock(&sc->lock);
+ armv8_crypto_freesession_locked(sc, ses);
+ rw_wunlock(&sc->lock);
+ return (error);
+ }
+
+ *sidp = ses->id;
+ return (0);
+}
+
+static void
+armv8_crypto_freesession_locked(struct armv8_crypto_softc *sc,
+ struct armv8_crypto_session *ses)
+{
+ uint32_t sid;
+
+ rw_assert(&sc->lock, RA_WLOCKED);
+
+ sid = ses->id;
+ TAILQ_REMOVE(&sc->sessions, ses, next);
+ *ses = (struct armv8_crypto_session){};
+ ses->id = sid;
+ TAILQ_INSERT_HEAD(&sc->sessions, ses, next);
+}
+
+static int
+armv8_crypto_freesession(device_t dev, uint64_t tid)
+{
+ struct armv8_crypto_softc *sc;
+ struct armv8_crypto_session *ses;
+ uint32_t sid;
+
+ sc = device_get_softc(dev);
+ sid = ((uint32_t)tid) & 0xffffffff;
+ rw_wlock(&sc->lock);
+ TAILQ_FOREACH_REVERSE(ses, &sc->sessions, armv8_crypto_sessions_head,
+ next) {
+ if (ses->id == sid)
+ break;
+ }
+ if (ses == NULL) {
+ rw_wunlock(&sc->lock);
+ return (EINVAL);
+ }
+ armv8_crypto_freesession_locked(sc, ses);
+ rw_wunlock(&sc->lock);
+
+ return (0);
+}
+
+static int
+armv8_crypto_process(device_t dev, struct cryptop *crp, int hint __unused)
+{
+ struct armv8_crypto_softc *sc = device_get_softc(dev);
+ struct cryptodesc *crd, *enccrd;
+ struct armv8_crypto_session *ses;
+ int error;
+
+ error = 0;
+ enccrd = NULL;
+
+ /* Sanity check. */
+ if (crp == NULL)
+ return (EINVAL);
+
+ if (crp->crp_callback == NULL || crp->crp_desc == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+
+ for (crd = crp->crp_desc; crd != NULL; crd = crd->crd_next) {
+ switch (crd->crd_alg) {
+ case CRYPTO_AES_CBC:
+ if (enccrd != NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ enccrd = crd;
+ break;
+ default:
+ error = EINVAL;
+ goto out;
+ }
+ }
+
+ if (enccrd == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+
+ /* We can only handle full blocks for now */
+ if ((enccrd->crd_len % AES_BLOCK_LEN) != 0) {
+ error = EINVAL;
+ goto out;
+ }
+
+ rw_rlock(&sc->lock);
+ TAILQ_FOREACH_REVERSE(ses, &sc->sessions, armv8_crypto_sessions_head,
+ next) {
+ if (ses->id == (crp->crp_sid & 0xffffffff))
+ break;
+ }
+ rw_runlock(&sc->lock);
+ if (ses == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+
+ error = armv8_crypto_cipher_process(ses, enccrd, crp);
+
+out:
+ crp->crp_etype = error;
+ crypto_done(crp);
+ return (error);
+}
+
+static uint8_t *
+armv8_crypto_cipher_alloc(struct cryptodesc *enccrd, struct cryptop *crp,
+ int *allocated)
+{
+ struct mbuf *m;
+ struct uio *uio;
+ struct iovec *iov;
+ uint8_t *addr;
+
+ if (crp->crp_flags & CRYPTO_F_IMBUF) {
+ m = (struct mbuf *)crp->crp_buf;
+ if (m->m_next != NULL)
+ goto alloc;
+ addr = mtod(m, uint8_t *);
+ } else if (crp->crp_flags & CRYPTO_F_IOV) {
+ uio = (struct uio *)crp->crp_buf;
+ if (uio->uio_iovcnt != 1)
+ goto alloc;
+ iov = uio->uio_iov;
+ addr = (uint8_t *)iov->iov_base;
+ } else
+ addr = (uint8_t *)crp->crp_buf;
+ *allocated = 0;
+ addr += enccrd->crd_skip;
+ return (addr);
+
+alloc:
+ addr = malloc(enccrd->crd_len, M_ARMV8_CRYPTO, M_NOWAIT);
+ if (addr != NULL) {
+ *allocated = 1;
+ crypto_copydata(crp->crp_flags, crp->crp_buf, enccrd->crd_skip,
+ enccrd->crd_len, addr);
+ } else
+ *allocated = 0;
+ return (addr);
+}
+
+static int
+armv8_crypto_cipher_process(struct armv8_crypto_session *ses,
+ struct cryptodesc *enccrd, struct cryptop *crp)
+{
+ struct fpu_kern_ctx *ctx;
+ uint8_t *buf;
+ uint8_t iv[AES_BLOCK_LEN];
+ int allocated, error, i;
+ int encflag, ivlen;
+ int kt;
+
+ encflag = (enccrd->crd_flags & CRD_F_ENCRYPT) == CRD_F_ENCRYPT;
+
+ buf = armv8_crypto_cipher_alloc(enccrd, crp, &allocated);
+ if (buf == NULL)
+ return (ENOMEM);
+
+ error = 0;
+
+ kt = is_fpu_kern_thread(0);
+ if (!kt) {
+ AQUIRE_CTX(i, ctx);
+ error = fpu_kern_enter(curthread, ctx,
+ FPU_KERN_NORMAL | FPU_KERN_KTHR);
+ if (error != 0)
+ goto out;
+ }
+
+ if ((enccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0) {
+ panic("CRD_F_KEY_EXPLICIT");
+ }
+
+ switch (enccrd->crd_alg) {
+ case CRYPTO_AES_CBC:
+ ivlen = AES_BLOCK_LEN;
+ break;
+ }
+
+ /* Setup iv */
+ if (encflag) {
+ if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0)
+ bcopy(enccrd->crd_iv, iv, ivlen);
+ else
+ arc4rand(iv, ivlen, 0);
+
+ if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0)
+ crypto_copyback(crp->crp_flags, crp->crp_buf,
+ enccrd->crd_inject, ivlen, iv);
+ } else {
+ if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0)
+ bcopy(enccrd->crd_iv, iv, ivlen);
+ else
+ crypto_copydata(crp->crp_flags, crp->crp_buf,
+ enccrd->crd_inject, ivlen, iv);
+ }
+
+ /* Do work */
+ switch (ses->algo) {
+ case CRYPTO_AES_CBC:
+ if (encflag)
+ armv8_aes_encrypt_cbc(ses->rounds, ses->enc_schedule,
+ enccrd->crd_len, buf, buf, iv);
+ else
+ armv8_aes_decrypt_cbc(ses->rounds, ses->dec_schedule,
+ enccrd->crd_len, buf, iv);
+ break;
+ }
+
+ if (allocated)
+ crypto_copyback(crp->crp_flags, crp->crp_buf, enccrd->crd_skip,
+ enccrd->crd_len, buf);
+
+ if (!kt) {
+ fpu_kern_leave(curthread, ctx);
+out:
+ RELEASE_CTX(i, ctx);
+ }
+ if (allocated) {
+ bzero(buf, enccrd->crd_len);
+ free(buf, M_ARMV8_CRYPTO);
+ }
+ return (error);
+}
+
+static device_method_t armv8_crypto_methods[] = {
+ DEVMETHOD(device_identify, armv8_crypto_identify),
+ DEVMETHOD(device_probe, armv8_crypto_probe),
+ DEVMETHOD(device_attach, armv8_crypto_attach),
+ DEVMETHOD(device_detach, armv8_crypto_detach),
+
+ DEVMETHOD(cryptodev_newsession, armv8_crypto_newsession),
+ DEVMETHOD(cryptodev_freesession, armv8_crypto_freesession),
+ DEVMETHOD(cryptodev_process, armv8_crypto_process),
+
+ DEVMETHOD_END,
+};
+
+static DEFINE_CLASS_0(armv8crypto, armv8_crypto_driver, armv8_crypto_methods,
+ sizeof(struct armv8_crypto_softc));
+static devclass_t armv8_crypto_devclass;
+
+DRIVER_MODULE(armv8crypto, nexus, armv8_crypto_driver, armv8_crypto_devclass,
+ 0, 0);
Index: head/sys/crypto/armv8/armv8_crypto_wrap.c
===================================================================
--- head/sys/crypto/armv8/armv8_crypto_wrap.c
+++ head/sys/crypto/armv8/armv8_crypto_wrap.c
@@ -0,0 +1,128 @@
+/*-
+ * Copyright (c) 2016 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Andrew Turner under
+ * sponsorship from the FreeBSD Foundation.
+ *
+ * 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 THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR 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.
+ */
+
+/*
+ * This code is built with floating-point enabled. Make sure to have entered
+ * into floating-point context before calling any of these functions.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/queue.h>
+
+#include <opencrypto/cryptodev.h>
+#include <crypto/armv8/armv8_crypto.h>
+
+#include <arm_neon.h>
+
+static uint8x16_t
+armv8_aes_enc(int rounds, const uint8x16_t *keysched, const uint8x16_t from)
+{
+ uint8x16_t tmp;
+ int i;
+
+ tmp = from;
+ for (i = 0; i < rounds - 1; i += 2) {
+ tmp = vaeseq_u8(tmp, keysched[i]);
+ tmp = vaesmcq_u8(tmp);
+ tmp = vaeseq_u8(tmp, keysched[i + 1]);
+ tmp = vaesmcq_u8(tmp);
+ }
+
+ tmp = vaeseq_u8(tmp, keysched[rounds - 1]);
+ tmp = vaesmcq_u8(tmp);
+ tmp = vaeseq_u8(tmp, keysched[rounds]);
+ tmp = veorq_u8(tmp, keysched[rounds + 1]);
+
+ return (tmp);
+}
+
+static uint8x16_t
+armv8_aes_dec(int rounds, const uint8x16_t *keysched, const uint8x16_t from)
+{
+ uint8x16_t tmp;
+ int i;
+
+ tmp = from;
+ for (i = 0; i < rounds - 1; i += 2) {
+ tmp = vaesdq_u8(tmp, keysched[i]);
+ tmp = vaesimcq_u8(tmp);
+ tmp = vaesdq_u8(tmp, keysched[i+1]);
+ tmp = vaesimcq_u8(tmp);
+ }
+
+ tmp = vaesdq_u8(tmp, keysched[rounds - 1]);
+ tmp = vaesimcq_u8(tmp);
+ tmp = vaesdq_u8(tmp, keysched[rounds]);
+ tmp = veorq_u8(tmp, keysched[rounds + 1]);
+
+ return (tmp);
+}
+
+void
+armv8_aes_encrypt_cbc(int rounds, const void *key_schedule, size_t len,
+ const uint8_t *from, uint8_t *to, const uint8_t iv[static AES_BLOCK_LEN])
+{
+ uint8x16_t tot, ivreg, tmp;
+ size_t i;
+
+ len /= AES_BLOCK_LEN;
+ ivreg = vld1q_u8(iv);
+ for (i = 0; i < len; i++) {
+ tmp = vld1q_u8(from);
+ tot = armv8_aes_enc(rounds - 1, key_schedule,
+ veorq_u8(tmp, ivreg));
+ ivreg = tot;
+ vst1q_u8(to, tot);
+ from += AES_BLOCK_LEN;
+ to += AES_BLOCK_LEN;
+ }
+}
+
+void
+armv8_aes_decrypt_cbc(int rounds, const void *key_schedule, size_t len,
+ uint8_t *buf, const uint8_t iv[static AES_BLOCK_LEN])
+{
+ uint8x16_t ivreg, nextiv, tmp;
+ size_t i;
+
+ len /= AES_BLOCK_LEN;
+ ivreg = vld1q_u8(iv);
+ for (i = 0; i < len; i++) {
+ nextiv = vld1q_u8(buf);
+ tmp = armv8_aes_dec(rounds - 1, key_schedule, nextiv);
+ vst1q_u8(buf, veorq_u8(tmp, ivreg));
+ ivreg = nextiv;
+ buf += AES_BLOCK_LEN;
+ }
+}
Index: head/sys/modules/Makefile
===================================================================
--- head/sys/modules/Makefile
+++ head/sys/modules/Makefile
@@ -42,6 +42,7 @@
${_apm} \
${_arcmsr} \
${_arcnet} \
+ ${_armv8crypto} \
${_asmc} \
ata \
ath \
@@ -539,6 +540,7 @@
.endif
.if ${MACHINE_CPUARCH} == "aarch64"
+_armv8crypto= armv8crypto
_em= em
_igb= igb
.endif
Index: head/sys/modules/armv8crypto/Makefile
===================================================================
--- head/sys/modules/armv8crypto/Makefile
+++ head/sys/modules/armv8crypto/Makefile
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../crypto/armv8
+
+KMOD= armv8crypto
+SRCS= armv8_crypto.c
+SRCS+= device_if.h bus_if.h opt_bus.h cryptodev_if.h
+
+OBJS+= armv8_crypto_wrap.o
+
+# Remove -nostdinc so we can get the intrinsics.
+armv8_crypto_wrap.o: armv8_crypto_wrap.c
+ ${CC} -c ${CFLAGS:C/^-O2$/-O3/:N-nostdinc:N-mgeneral-regs-only} \
+ ${WERROR} ${PROF} \
+ -march=armv8a+crypto ${.IMPSRC}
+ ${CTFCONVERT_CMD}
+
+armv8_crypto_wrap.o: armv8_crypto.h
+
+.include <bsd.kmod.mk>

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 12, 9:43 PM (12 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17126540
Default Alt Text
D8297.diff (25 KB)

Event Timeline