VIA ACE patch

Daniel de Kok <[email protected]>
Newsgroups gmane.os.netbsd.devel.crypto,gmane.os.netbsd.ports.i386
Message-ID <[email protected]>
Hi,

I have mostly completed my port of the OpenBSD VIA ACE code, and I have 
attached a patch. This area is pretty new to me, so please be gentle.

-- Daniel
via_ace.diff (text/plain, 24.6 KB)
Index: sys/arch/i386/conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/conf/GENERIC,v
retrieving revision 1.803
diff -u -r1.803 GENERIC
--- sys/arch/i386/conf/GENERIC	17 Dec 2006 23:02:06 -0000	1.803
+++ sys/arch/i386/conf/GENERIC	12 Jan 2007 16:26:28 -0000
@@ -52,6 +52,9 @@
 # AMD PowerNow! and Cool`n'Quiet technology
 options 	POWERNOW_K8
 
+# VIA PadLock
+#options	VIA_PADLOCK
+
 options 	MTRR		# memory-type range register syscall support
 # doesn't work with MP just yet..
 #options 	PERFCTRS	# performance-monitoring counters support
Index: sys/arch/i386/i386/autoconf.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/autoconf.c,v
retrieving revision 1.84
diff -u -r1.84 autoconf.c
--- sys/arch/i386/i386/autoconf.c	7 Jun 2006 22:37:58 -0000	1.84
+++ sys/arch/i386/i386/autoconf.c	12 Jan 2007 16:26:28 -0000
@@ -91,6 +91,8 @@
 #include <machine/kvm86.h>
 #endif
 
+#include "opt_viapadlock.h"
+
 /*
  * Determine i/o configuration for a machine.
  */
@@ -139,4 +141,10 @@
 #if NLAPIC > 0
 	lapic_tpr = 0;
 #endif
+
+#if defined(I686_CPU)
+#ifdef VIA_PADLOCK
+	via_padlock_attach();
+#endif /* VIA_PADLOCK */
+#endif /* defined(I686_CPU) */
 }
Index: sys/arch/i386/i386/identcpu.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/identcpu.c,v
retrieving revision 1.52
diff -u -r1.52 identcpu.c
--- sys/arch/i386/i386/identcpu.c	1 Jan 2007 20:56:58 -0000	1.52
+++ sys/arch/i386/i386/identcpu.c	12 Jan 2007 16:26:28 -0000
@@ -652,8 +652,10 @@
 void
 via_cpu_probe(struct cpu_info *ci)
 {
+	u_int model = CPUID2MODEL(ci->ci_signature);
+	u_int stepping = CPUID2STEPPING(ci->ci_signature);
 	u_int descs[4];
-	u_int lfunc;
+	u_int lfunc, msr;
 
 	/*
 	 * Determine the largest extended function value.
@@ -668,6 +670,24 @@
 		CPUID(0x80000001, descs[0], descs[1], descs[2], descs[3]);
 		ci->ci_feature_flags |= descs[3];
 	}
+
+	if (model >= 0x9) {
+		/* Nehemiah or Esther */
+		CPUID(0xc0000000, descs[0], descs[1], descs[2], descs[3]);
+		lfunc = descs[0];
+		if (lfunc == 0xc0000001) {
+			CPUID(lfunc, descs[0], descs[1], descs[2], descs[3]);
+			lfunc = descs[3];
+			if (model > 0x9 || stepping >= 8) {	/* ACE */
+				if ((lfunc & 0xc0) == 0xc0) {
+					ci->ci_padlock_flags |= CPUID_FEAT_VACE;
+					msr = rdmsr(MSR_VIA_ACE);
+					wrmsr(MSR_VIA_ACE,
+					    msr | MSR_VIA_ACE_ENABLE);
+				}
+			}
+		}
+	}
 }
 
 const char *
Index: sys/arch/i386/i386/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/i386/machdep.c,v
retrieving revision 1.592
diff -u -r1.592 machdep.c
--- sys/arch/i386/i386/machdep.c	7 Jan 2007 01:04:26 -0000	1.592
+++ sys/arch/i386/i386/machdep.c	12 Jan 2007 16:26:28 -0000
@@ -236,6 +236,7 @@
 int	dumpmem_high;
 unsigned int cpu_feature;
 unsigned int cpu_feature2;
+unsigned int cpu_feature_padlock;
 int	cpu_class;
 int	i386_fpu_present;
 int	i386_fpu_exception;
@@ -1516,6 +1517,7 @@
 	cpu_probe_features(&cpu_info_primary);
 	cpu_feature = cpu_info_primary.ci_feature_flags;
 	cpu_feature2 = cpu_info_primary.ci_feature2_flags;
+	cpu_feature_padlock = cpu_info_primary.ci_padlock_flags;
 
 	proc0paddr = UAREA_TO_USER(proc0uarea);
 	lwp0.l_addr = proc0paddr;
Index: sys/arch/i386/include/cpu.h
===================================================================
RCS file: /cvsroot/src/sys/arch/i386/include/cpu.h,v
retrieving revision 1.130
diff -u -r1.130 cpu.h
--- sys/arch/i386/include/cpu.h	8 Dec 2006 15:05:18 -0000	1.130
+++ sys/arch/i386/include/cpu.h	12 Jan 2007 16:26:28 -0000
@@ -54,6 +54,7 @@
 #include <machine/tss.h>
 #include <machine/intrdefs.h>
 #include <x86/cacheinfo.h>
+#include <x86/via_padlock.h>
 
 #include <sys/device.h>
 #include <sys/lock.h>			/* will also get LOCKDEBUG */
@@ -123,6 +124,7 @@
 	uint32_t	ci_feature_flags;/* X86 %edx CPUID feature bits */
 	uint32_t	ci_feature2_flags;/* X86 %ecx CPUID feature bits */
 	uint32_t	ci_feature3_flags;/* X86 extended feature bits */
+	uint32_t	ci_padlock_flags;/* VIA PadLock feature bits */
 	uint32_t	ci_cpu_class;	 /* CPU class */
 	uint32_t	ci_brand_id;	 /* Intel brand id */
 	uint32_t	ci_vendor[4];	 /* vendor string */
@@ -150,6 +152,8 @@
 	char *ci_ddbipi_stack;
 
 	struct evcnt ci_ipi_events[X86_NIPI];
+
+	struct via_padlock	ci_vp;	/* VIA PadLock private storage */
 };
 
 /*
@@ -335,6 +339,7 @@
 extern int biosextmem;
 extern unsigned int cpu_feature;
 extern unsigned int cpu_feature2;
+extern unsigned int cpu_feature_padlock;
 extern int cpu;
 extern int cpu_class;
 extern char cpu_brand_string[];
Index: sys/arch/x86/conf/files.x86
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/conf/files.x86,v
retrieving revision 1.21
diff -u -r1.21 files.x86
--- sys/arch/x86/conf/files.x86	1 Jan 2007 20:56:59 -0000	1.21
+++ sys/arch/x86/conf/files.x86	12 Jan 2007 16:26:28 -0000
@@ -13,6 +13,10 @@
 # AMD Powernow/Cool`n'Quiet Technology
 defflag opt_powernow_k8.h	POWERNOW_K8
 
+# VIA PadLock support
+defflag	opt_viapadlock.h	VIA_PADLOCK:	opencrypto
+file	arch/x86/x86/via_padlock.c	via_padlock
+
 define  cpubus { [apid = -1] }
 define  ipmibus {}
 
Index: sys/arch/x86/include/specialreg.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/specialreg.h,v
retrieving revision 1.12
diff -u -r1.12 specialreg.h
--- sys/arch/x86/include/specialreg.h	1 Jan 2007 20:56:59 -0000	1.12
+++ sys/arch/x86/include/specialreg.h	12 Jan 2007 16:26:28 -0000
@@ -155,6 +155,13 @@
 				    "\0373DNOW2\0403DNOW"
 
 /*
+ * "Features" that are copied from elsewhere -- not necessarily tied to
+ * a specific CPUID response
+ */
+
+#define CPUID_FEAT_VACE	0x00000002	/* VIA C3 AES Crypto Extension */
+
+/*
  * CPUID "features" bits in %ecx
  */
 
@@ -278,6 +285,18 @@
 #define MSR_MC3_MISC		0x413
 
 /*
+ * VIA "Nehemiah" MSRs
+ */
+#define MSR_VIA_RNG		0x110b
+#define MSR_VIA_RNG_ENABLE	0x00000040
+#define MSR_VIA_RNG_NOISE_MASK	0x00000300
+#define MSR_VIA_RNG_NOISE_A	0x00000000
+#define MSR_VIA_RNG_NOISE_B	0x00000100
+#define MSR_VIA_RNG_2NOISE	0x00000300
+#define MSR_VIA_ACE		0x1107
+#define MSR_VIA_ACE_ENABLE	0x10000000
+
+/*
  * AMD K6/K7 MSRs.
  */
 #define	MSR_K6_UWCCR		0xc0000085
Index: sys/arch/x86/include/via_padlock.h
===================================================================
RCS file: sys/arch/x86/include/via_padlock.h
diff -N sys/arch/x86/include/via_padlock.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/arch/x86/include/via_padlock.h	12 Jan 2007 16:26:28 -0000
@@ -0,0 +1,77 @@
+/*	$NetBSD$	*/
+
+/*-
+ * Copyright (c) 2003 Jason Wright
+ * Copyright (c) 2003, 2004 Theo de Raadt
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _X86_VIA_PADLOCK_H_
+#define _X86_VIA_PADLOCK_H_
+
+#ifdef _KERNEL
+
+#include <crypto/rijndael/rijndael.h>
+
+/* VIA C3 xcrypt-* instruction context control options */
+#define C3_CRYPT_CWLO_ROUND_M		0x0000000f
+#define C3_CRYPT_CWLO_ALG_M		0x00000070
+#define C3_CRYPT_CWLO_ALG_AES		0x00000000
+#define C3_CRYPT_CWLO_KEYGEN_M		0x00000080
+#define C3_CRYPT_CWLO_KEYGEN_HW		0x00000000
+#define C3_CRYPT_CWLO_KEYGEN_SW		0x00000080
+#define C3_CRYPT_CWLO_NORMAL		0x00000000
+#define C3_CRYPT_CWLO_INTERMEDIATE	0x00000100
+#define C3_CRYPT_CWLO_ENCRYPT		0x00000000
+#define C3_CRYPT_CWLO_DECRYPT		0x00000200
+#define C3_CRYPT_CWLO_KEY128		0x0000000a      /* 128bit, 10 rds */
+#define C3_CRYPT_CWLO_KEY192		0x0000040c      /* 192bit, 12 rds */
+#define C3_CRYPT_CWLO_KEY256		0x0000080e      /* 256bit, 15 rds */
+
+struct via_padlock_session {
+        u_int32_t	ses_ekey[4 * (RIJNDAEL_MAXNR + 1) + 4];	/* 128 bit aligned */
+        u_int32_t	ses_dkey[4 * (RIJNDAEL_MAXNR + 1) + 4];	/* 128 bit aligned */
+        u_int8_t	ses_iv[16];				/* 128 bit aligned */
+        u_int32_t	ses_cw0;
+        struct swcr_data	*swd;
+        int	ses_klen;
+        int	ses_used;
+};
+
+struct via_padlock_softc {
+	u_int32_t	op_cw[4];	/* 128 bit aligned */
+	u_int8_t	op_iv[16];	/* 128 bit aligned */
+	void		*op_buf;
+
+	/* normal softc stuff */
+	int32_t		sc_cid;
+	int		sc_nsessions;
+	struct via_padlock_session *sc_sessions;
+};
+
+#define VIAC3_SESSION(sid)	((sid) & 0x0fffffff)
+#define VIAC3_SID(crd,ses)	(((crd) << 28) | ((ses) & 0x0fffffff))
+
+struct cpu_info;
+
+struct via_padlock {
+	struct cpu_info		*vp_ci;
+	int			vp_freq;
+};
+
+void	via_padlock_attach(void);
+
+#endif /* _KERNEL */
+#endif /* _X86_VIA_PADLOCK_H_ */
Index: sys/arch/x86/x86/via_padlock.c
===================================================================
RCS file: sys/arch/x86/x86/via_padlock.c
diff -N sys/arch/x86/x86/via_padlock.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ sys/arch/x86/x86/via_padlock.c	12 Jan 2007 16:26:36 -0000
@@ -0,0 +1,480 @@
+/*	$OpenBSD: via.c,v 1.8 2006/11/17 07:47:56 tom Exp $	*/
+/*	$NetBSD	*/
+
+/*-
+ * Copyright (c) 2003 Jason Wright
+ * Copyright (c) 2003, 2004 Theo de Raadt
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include "opt_viapadlock.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/signalvar.h>
+#include <sys/kernel.h>
+#include <sys/rnd.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+
+#include <machine/cpu.h>
+#include <x86/specialreg.h>
+
+#include <opencrypto/cryptodev.h>
+#include <opencrypto/cryptosoft.h>
+#include <opencrypto/xform.h>
+#include <crypto/rijndael/rijndael.h>
+
+#include <opencrypto/cryptosoft_xform.c>
+
+#ifdef VIA_PADLOCK
+
+int	via_padlock_crypto_newsession(void *, u_int32_t *, struct cryptoini *);
+int	via_padlock_crypto_process(void *, struct cryptop *, int);
+int	via_padlock_crypto_swauth(struct cryptop *, struct cryptodesc *,
+	    struct swcr_data *, caddr_t);
+int	via_padlock_crypto_encdec(struct cryptop *, struct cryptodesc *,
+	    struct via_padlock_session *, struct via_padlock_softc *, caddr_t);
+int	via_padlock_crypto_freesession(void *, u_int64_t);
+static	__inline void via_padlock_cbc(void *, void *, void *, void *, int,
+	    void *);
+
+void
+via_padlock_attach(void)
+{
+	if (!(cpu_feature_padlock & CPUID_FEAT_VACE))
+		return;
+
+	struct via_padlock_softc *vp_sc;
+	if ((vp_sc = malloc(sizeof(*vp_sc), M_DEVBUF, M_NOWAIT)) == NULL)
+		return;
+	bzero(vp_sc, sizeof(*vp_sc));
+
+	vp_sc->sc_cid = crypto_get_driverid(0);
+	if (vp_sc->sc_cid < 0) {
+		printf("PadLock: Could not get a crypto driver ID\n");
+		return;
+	}
+
+	/*
+	 * Ask the opencrypto subsystem to register ourselves. Although
+	 * we don't support hardware offloading for various HMAC algorithms,
+	 * we will handle them, because opencrypto prefers drivers that
+	 * support all requested algorithms.
+	 */
+#define REGISTER(alg) \
+	crypto_register(vp_sc->sc_cid, alg, 0, 0, \
+	    via_padlock_crypto_newsession, via_padlock_crypto_freesession, \
+	    via_padlock_crypto_process, vp_sc);
+
+	REGISTER(CRYPTO_AES_CBC);
+	REGISTER(CRYPTO_MD5_HMAC);
+	REGISTER(CRYPTO_SHA1_HMAC);
+	REGISTER(CRYPTO_RIPEMD160_HMAC);
+	REGISTER(CRYPTO_SHA2_HMAC);
+
+	printf("PadLock: registered support for AES_CBC\n");
+}
+
+int
+via_padlock_crypto_newsession(void *arg, u_int32_t *sidp, struct cryptoini *cri)
+{
+	struct cryptoini *c;
+	struct via_padlock_softc *sc = arg;
+	struct via_padlock_session *ses = NULL;
+	const struct swcr_auth_hash *axf;
+	struct swcr_data *swd;
+	int sesn, i, cw0;
+
+	KASSERT(sc != NULL /*, ("via_padlock_crypto_freesession: null softc")*/);
+	if (sc == NULL || sidp == NULL || cri == NULL)
+		return (EINVAL);
+
+	if (sc->sc_sessions == NULL) {
+		ses = sc->sc_sessions = malloc(sizeof(*ses), 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].ses_used == 0) {
+				ses = &sc->sc_sessions[sesn];
+				break;
+			}
+		}
+
+		if (ses == NULL) {
+			sesn = sc->sc_nsessions;
+			ses = malloc((sesn + 1) * sizeof(*ses), 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->ses_used = 1;
+
+	for (c = cri; c != NULL; c = c->cri_next) {
+		switch (c->cri_alg) {
+		case CRYPTO_AES_CBC:
+			switch (c->cri_klen) {
+			case 128:
+				cw0 = C3_CRYPT_CWLO_KEY128;
+				break;
+			case 192:
+				cw0 = C3_CRYPT_CWLO_KEY192;
+				break;
+			case 256:
+				cw0 = C3_CRYPT_CWLO_KEY256;
+				break;
+			default:
+				return (EINVAL);
+			}
+			cw0 |= C3_CRYPT_CWLO_ALG_AES |
+				C3_CRYPT_CWLO_KEYGEN_SW |
+				C3_CRYPT_CWLO_NORMAL;
+
+#ifdef __NetBSD__
+			rnd_extract_data(ses->ses_iv, sizeof(ses->ses_iv),
+			    RND_EXTRACT_ANY);
+#else
+			get_random_bytes(ses->ses_iv, sizeof(ses->ses_iv));
+#endif
+			ses->ses_klen = c->cri_klen;
+			ses->ses_cw0 = cw0;
+
+			/* Build expanded keys for both directions */
+			rijndaelKeySetupEnc(ses->ses_ekey, c->cri_key,
+			    c->cri_klen);
+			rijndaelKeySetupDec(ses->ses_dkey, c->cri_key,
+			    c->cri_klen);
+			for (i = 0; i < 4 * (RIJNDAEL_MAXNR + 1); i++) {
+				ses->ses_ekey[i] = ntohl(ses->ses_ekey[i]);
+				ses->ses_dkey[i] = ntohl(ses->ses_dkey[i]);
+			}
+
+			break;
+
+		/* Use hashing implementations from the cryptosoft code. */
+		case CRYPTO_MD5_HMAC:
+			axf = &swcr_auth_hash_hmac_md5_96;
+			goto authcommon;
+		case CRYPTO_SHA1_HMAC:
+			axf = &swcr_auth_hash_hmac_sha1_96;
+			goto authcommon;
+		case CRYPTO_RIPEMD160_HMAC:
+			axf = &swcr_auth_hash_hmac_ripemd_160_96;
+			goto authcommon;
+		case CRYPTO_SHA2_HMAC:
+			if (cri->cri_klen == 256)
+				axf = &swcr_auth_hash_hmac_sha2_256;
+			else if (cri->cri_klen == 384)
+				axf = &swcr_auth_hash_hmac_sha2_384;
+			else if (cri->cri_klen == 512)
+				axf = &swcr_auth_hash_hmac_sha2_512;
+			else {
+				return EINVAL;
+			}
+		authcommon:
+			MALLOC(swd, struct swcr_data *,
+			    sizeof(struct swcr_data), M_CRYPTO_DATA,
+			    M_NOWAIT);
+			if (swd == NULL) {
+				via_padlock_crypto_freesession(sc, sesn);
+				return (ENOMEM);
+			}
+			bzero(swd, sizeof(struct swcr_data));
+			ses->swd = swd;
+
+			swd->sw_ictx = malloc(axf->auth_hash->ctxsize,
+			    M_CRYPTO_DATA, M_NOWAIT);
+			if (swd->sw_ictx == NULL) {
+				via_padlock_crypto_freesession(sc, sesn);
+				return (ENOMEM);
+			}
+
+			swd->sw_octx = malloc(axf->auth_hash->ctxsize,
+			    M_CRYPTO_DATA, M_NOWAIT);
+			if (swd->sw_octx == NULL) {
+				via_padlock_crypto_freesession(sc, sesn);
+				return (ENOMEM);
+			}
+
+			for (i = 0; i < c->cri_klen / 8; i++)
+				c->cri_key[i] ^= HMAC_IPAD_VAL;
+
+			axf->Init(swd->sw_ictx);
+			axf->Update(swd->sw_ictx, c->cri_key, c->cri_klen / 8);
+			axf->Update(swd->sw_ictx, hmac_ipad_buffer,
+			    HMAC_BLOCK_LEN - (c->cri_klen / 8));
+
+			for (i = 0; i < c->cri_klen / 8; i++)
+				c->cri_key[i] ^= (HMAC_IPAD_VAL ^
+				    HMAC_OPAD_VAL);
+
+			axf->Init(swd->sw_octx);
+			axf->Update(swd->sw_octx, c->cri_key, c->cri_klen / 8);
+			axf->Update(swd->sw_octx, hmac_opad_buffer,
+			    HMAC_BLOCK_LEN - (c->cri_klen / 8));
+
+			for (i = 0; i < c->cri_klen / 8; i++)
+				c->cri_key[i] ^= HMAC_OPAD_VAL;
+
+			swd->sw_axf = axf;
+			swd->sw_alg = c->cri_alg;
+
+			break;
+		default:
+			return (EINVAL);
+		}
+	}
+
+	*sidp = VIAC3_SID(0, sesn);
+	return (0);
+}
+
+int
+via_padlock_crypto_freesession(void *arg, u_int64_t tid)
+{
+	struct via_padlock_softc *sc = arg;
+	struct swcr_data *swd;
+	struct auth_hash *axf;
+	int sesn;
+	u_int32_t sid = ((u_int32_t)tid) & 0xffffffff;
+
+	KASSERT(sc != NULL /*, ("via_padlock_crypto_freesession: null softc")*/);
+	if (sc == NULL)
+		return (EINVAL);
+
+	sesn = VIAC3_SESSION(sid);
+	if (sesn >= sc->sc_nsessions)
+		return (EINVAL);
+
+	if (sc->sc_sessions[sesn].swd) {
+		swd = sc->sc_sessions[sesn].swd;
+		axf = swd->sw_axf->auth_hash;
+
+		if (swd->sw_ictx) {
+			bzero(swd->sw_ictx, axf->ctxsize);
+			free(swd->sw_ictx, M_CRYPTO_DATA);
+		}
+		if (swd->sw_octx) {
+			bzero(swd->sw_octx, axf->ctxsize);
+			free(swd->sw_octx, M_CRYPTO_DATA);
+		}
+		FREE(swd, M_CRYPTO_DATA);
+	}
+
+	bzero(&sc->sc_sessions[sesn], sizeof(sc->sc_sessions[sesn]));
+	return (0);
+}
+
+static __inline void
+via_padlock_cbc(void *cw, void *src, void *dst, void *key, int rep,
+    void *iv)
+{
+	unsigned int creg0;
+
+	creg0 = rcr0();		/* Permit access to SIMD/FPU path */
+	lcr0(creg0 & ~(CR0_EM|CR0_TS));
+
+	/* Do the deed */
+	__asm __volatile("pushfl; popfl");	/* force key reload */
+	__asm __volatile(".byte 0xf3, 0x0f, 0xa7, 0xd0" : /* rep xcrypt-dbd */
+			: "a" (iv), "b" (key), "c" (rep), "d" (cw), "S" (src), "D" (dst)
+			: "memory", "cc");
+
+	lcr0(creg0);
+}
+
+int
+via_padlock_crypto_swauth(struct cryptop *crp, struct cryptodesc *crd,
+    struct swcr_data *sw, caddr_t buf)
+{
+	int	type;
+
+	if (crp->crp_flags & CRYPTO_F_IMBUF)
+		type = CRYPTO_BUF_MBUF;
+	else
+		type= CRYPTO_BUF_IOV;
+
+	return (swcr_authcompute(crp, crd, sw, buf, type));
+}
+
+int
+via_padlock_crypto_encdec(struct cryptop *crp, struct cryptodesc *crd,
+    struct via_padlock_session *ses, struct via_padlock_softc *sc, caddr_t buf)
+{
+	u_int32_t *key;
+	int err = 0;
+
+	if ((crd->crd_len % 16) != 0) {
+		err = EINVAL;
+		return (err);
+	}
+
+	sc->op_buf = malloc(crd->crd_len, M_DEVBUF, M_NOWAIT);
+	if (sc->op_buf == NULL) {
+		err = ENOMEM;
+		return (err);
+	}
+
+	if (crd->crd_flags & CRD_F_ENCRYPT) {
+		sc->op_cw[0] = ses->ses_cw0 | C3_CRYPT_CWLO_ENCRYPT;
+		key = ses->ses_ekey;
+		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
+			bcopy(crd->crd_iv, sc->op_iv, 16);
+		else
+			bcopy(ses->ses_iv, sc->op_iv, 16);
+
+		if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
+			if (crp->crp_flags & CRYPTO_F_IMBUF)
+				m_copyback((struct mbuf *)crp->crp_buf,
+				    crd->crd_inject, 16, sc->op_iv);
+			else if (crp->crp_flags & CRYPTO_F_IOV)
+				cuio_copyback((struct uio *)crp->crp_buf,
+				    crd->crd_inject, 16, sc->op_iv);
+			else
+				bcopy(sc->op_iv,
+				    crp->crp_buf + crd->crd_inject, 16);
+		}
+	} else {
+		sc->op_cw[0] = ses->ses_cw0 | C3_CRYPT_CWLO_DECRYPT;
+		key = ses->ses_dkey;
+		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
+			bcopy(crd->crd_iv, sc->op_iv, 16);
+		else {
+			if (crp->crp_flags & CRYPTO_F_IMBUF)
+				m_copydata((struct mbuf *)crp->crp_buf,
+				    crd->crd_inject, 16, sc->op_iv);
+			else if (crp->crp_flags & CRYPTO_F_IOV)
+				cuio_copydata((struct uio *)crp->crp_buf,
+				    crd->crd_inject, 16, sc->op_iv);
+			else
+				bcopy(crp->crp_buf + crd->crd_inject,
+				    sc->op_iv, 16);
+		}
+	}
+
+	if (crp->crp_flags & CRYPTO_F_IMBUF)
+		m_copydata((struct mbuf *)crp->crp_buf,
+		    crd->crd_skip, crd->crd_len, sc->op_buf);
+	else if (crp->crp_flags & CRYPTO_F_IOV)
+		cuio_copydata((struct uio *)crp->crp_buf,
+		    crd->crd_skip, crd->crd_len, sc->op_buf);
+	else
+		bcopy(crp->crp_buf + crd->crd_skip, sc->op_buf,
+crd->crd_len);
+
+	sc->op_cw[1] = sc->op_cw[2] = sc->op_cw[3] = 0;
+	via_padlock_cbc(&sc->op_cw, sc->op_buf, sc->op_buf, key,
+	    crd->crd_len / 16, sc->op_iv);
+
+	if (crp->crp_flags & CRYPTO_F_IMBUF)
+		m_copyback((struct mbuf *)crp->crp_buf,
+		    crd->crd_skip, crd->crd_len, sc->op_buf);
+	else if (crp->crp_flags & CRYPTO_F_IOV)
+		cuio_copyback((struct uio *)crp->crp_buf,
+		    crd->crd_skip, crd->crd_len, sc->op_buf);
+	else
+		bcopy(sc->op_buf, crp->crp_buf + crd->crd_skip,
+		    crd->crd_len);
+
+	/* copy out last block for use as next session IV */
+	if (crd->crd_flags & CRD_F_ENCRYPT) {
+		if (crp->crp_flags & CRYPTO_F_IMBUF)
+			m_copydata((struct mbuf *)crp->crp_buf,
+			    crd->crd_skip + crd->crd_len - 16, 16,
+			    ses->ses_iv);
+		else if (crp->crp_flags & CRYPTO_F_IOV)
+			cuio_copydata((struct uio *)crp->crp_buf,
+			    crd->crd_skip + crd->crd_len - 16, 16,
+			    ses->ses_iv);
+		else
+			bcopy(crp->crp_buf + crd->crd_skip +
+			    crd->crd_len - 16, ses->ses_iv, 16);
+	}
+
+	if (sc->op_buf != NULL) {
+		bzero(sc->op_buf, crd->crd_len);
+		free(sc->op_buf, M_DEVBUF);
+		sc->op_buf = NULL;
+	}
+
+	return (err);
+}
+
+int
+via_padlock_crypto_process(void *arg, struct cryptop *crp, int hint)
+{
+	struct via_padlock_softc *sc = arg;
+	struct via_padlock_session *ses;
+	struct cryptodesc *crd;
+	int sesn, err = 0;
+
+	KASSERT(sc != NULL /*, ("via_padlock_crypto_process: null softc")*/);
+	if (crp == NULL || crp->crp_callback == NULL) {
+		err = EINVAL;
+		goto out;
+	}
+
+	sesn = VIAC3_SESSION(crp->crp_sid);
+	if (sesn >= sc->sc_nsessions) {
+		err = EINVAL;
+		goto out;
+	}
+	ses = &sc->sc_sessions[sesn];
+
+	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
+		switch (crd->crd_alg) {
+		case CRYPTO_AES_CBC:
+			if ((err = via_padlock_crypto_encdec(crp, crd, ses,
+			    sc, crp->crp_buf)) != 0)
+				goto out;
+			break;
+
+		case CRYPTO_MD5_HMAC:
+		case CRYPTO_SHA1_HMAC:
+		case CRYPTO_RIPEMD160_HMAC:
+		case CRYPTO_SHA2_HMAC:
+			if ((err = via_padlock_crypto_swauth(crp, crd,
+			    ses->swd, crp->crp_buf)) != 0)
+				goto out;
+			break;
+
+		default:
+			err = EINVAL;
+			goto out;
+		}
+	}
+out:
+	crp->crp_etype = err;
+	crypto_done(crp);
+	return (err);
+}
+
+#endif /* VIA_PADLOCK */
Index: sys/opencrypto/cryptosoft.c
===================================================================
RCS file: /cvsroot/src/sys/opencrypto/cryptosoft.c,v
retrieving revision 1.15
diff -u -r1.15 cryptosoft.c
--- sys/opencrypto/cryptosoft.c	16 Nov 2006 01:33:51 -0000	1.15
+++ sys/opencrypto/cryptosoft.c	12 Jan 2007 16:26:36 -0000
@@ -60,8 +60,6 @@
 	: cuio_copydata((struct uio *)a,b,c,d)
 
 static	int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
-static	int swcr_authcompute(struct cryptop *crp, struct cryptodesc *crd,
-			     struct swcr_data *sw, caddr_t buf, int outtype);
 static	int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
 static	int swcr_process(void *, struct cryptop *, int);
 static	int swcr_newsession(void *, u_int32_t *, struct cryptoini *);
@@ -530,7 +528,7 @@
 /*
  * Compute keyed-hash authenticator.
  */
-static int
+int
 swcr_authcompute(struct cryptop *crp, struct cryptodesc *crd,
     struct swcr_data *sw, caddr_t buf, int outtype)
 {
Index: sys/opencrypto/cryptosoft.h
===================================================================
RCS file: /cvsroot/src/sys/opencrypto/cryptosoft.h,v
retrieving revision 1.3
diff -u -r1.3 cryptosoft.h
--- sys/opencrypto/cryptosoft.h	25 Nov 2005 16:16:46 -0000	1.3
+++ sys/opencrypto/cryptosoft.h	12 Jan 2007 16:26:36 -0000
@@ -57,4 +57,9 @@
 	struct swcr_data *sw_next;
 };
 
+#ifdef _KERNEL
+int swcr_authcompute(struct cryptop *crp, struct cryptodesc *crd,
+    struct swcr_data *sw, caddr_t buf, int outtype);
+#endif /* _KERNEL */
+
 #endif /* _CRYPTO_CRYPTO_H_ */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.