tech-crypto archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: VIA ACE patch



On Fri, 12 Jan 2007, Daniel de Kok wrote:
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.

Here's the updated patch, primarily integrating Rui's suggestions.

-- Daniel
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  14 Jan 2007 23:22:49 -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       14 Jan 2007 23:22:53 -0000
@@ -91,6 +91,8 @@
 #include <machine/kvm86.h>
 #endif
 
+#include "opt_viapadlock.h"
+
 /*
  * Determine i/o configuration for a machine.
  */
@@ -139,4 +141,8 @@
 #if NLAPIC > 0
        lapic_tpr = 0;
 #endif
+
+#if defined(I686_CPU) && defined(VIA_PADLOCK)
+       via_padlock_attach();
+#endif /* defined(I686_CPU) && defined(VIA_PADLOCK) */
 }
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       14 Jan 2007 23:22:56 -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        14 Jan 2007 23:22:57 -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 14 Jan 2007 23:23:01 -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 14 Jan 2007 23:23:16 -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   14 Jan 2007 23:23:18 -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            0x0000110b
+#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            0x00001107
+#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  14 Jan 2007 23:23:18 -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      14 Jan 2007 23:23:22 -0000
@@ -0,0 +1,481 @@
+/*     $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;
+       memset(vp_sc, 0, 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");
+               free(vp_sc, M_DEVBUF);
+               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);
+                       memcpy(ses, sc->sc_sessions, sesn * sizeof(*ses));
+                       memset(sc->sc_sessions, 0, sesn * sizeof(*ses));
+                       free(sc->sc_sessions, M_DEVBUF);
+                       sc->sc_sessions = ses;
+                       ses = &sc->sc_sessions[sesn];
+                       sc->sc_nsessions++;
+               }
+       }
+
+       memset(ses, 0, 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);
+                       }
+                       memset(swd, 0, 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) {
+                       memset(swd->sw_ictx, 0, axf->ctxsize);
+                       free(swd->sw_ictx, M_CRYPTO_DATA);
+               }
+               if (swd->sw_octx) {
+                       memset(swd->sw_octx, 0, axf->ctxsize);
+                       free(swd->sw_octx, M_CRYPTO_DATA);
+               }
+               FREE(swd, M_CRYPTO_DATA);
+       }
+
+       memset(&sc->sc_sessions[sesn], 0, 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-cbc */
+                       : "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)
+                       memcpy(sc->op_iv, crd->crd_iv, 16);
+               else
+                       memcpy(sc->op_iv, ses->ses_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
+                               memcpy(crp->crp_buf + crd->crd_inject,
+                                   sc->op_iv, 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)
+                       memcpy(sc->op_iv, crd->crd_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
+                               memcpy(sc->op_iv, crp->crp_buf +
+                                   crd->crd_inject, 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
+               memcpy(sc->op_buf, crp->crp_buf + crd->crd_skip,
+                   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
+               memcpy(crp->crp_buf + crd->crd_skip, sc->op_buf,
+                   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
+                       memcpy(ses->ses_iv, crp->crp_buf + crd->crd_skip +
+                           crd->crd_len - 16, 16);
+       }
+
+       if (sc->op_buf != NULL) {
+               memset(sc->op_buf, 0, 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 14 Jan 2007 23:23:23 -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 14 Jan 2007 23:23:23 -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_ */


Home | Main Index | Thread Index | Old Index