Add an opencrypto provider for the AES xcrypt instructions found on VIA
C5P and later cores (also known as 'ACE', which is part of the VIA PadLock security engine). Ported from OpenBSD. Reviewed on tech-crypto and port-i386, no objections to commiting this.
This commit is contained in:
parent
ede64e5874
commit
c339e55881
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: options.4,v 1.341 2006/12/23 07:35:28 wiz Exp $
|
||||
.\" $NetBSD: options.4,v 1.342 2007/02/17 00:28:23 daniel Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1996
|
||||
.\" Perry E. Metzger. All rights reserved.
|
||||
@ -30,7 +30,7 @@
|
||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.Dd November 22, 2006
|
||||
.Dd February 17, 2007
|
||||
.Os
|
||||
.Dt OPTIONS 4
|
||||
.Sh NAME
|
||||
@ -2405,6 +2405,12 @@ capable
|
||||
Include support for the AMD
|
||||
.Tn PowerNow! Technology
|
||||
present in AMD Athlon Mobile processors.
|
||||
.It Cd options VIA_PADLOCK
|
||||
Include support for the
|
||||
.Tn AES
|
||||
encryption instructions of the
|
||||
.Tn VIA PadLock Security engine ,
|
||||
which is attached as a provider to the opencrypto framework.
|
||||
.It Cd options CPURESET_DELAY=value
|
||||
Specifies the time (in millisecond) to wait before doing a hardware reset
|
||||
in the last phase of a reboot.
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: GENERIC,v 1.807 2007/02/09 21:55:04 ad Exp $
|
||||
# $NetBSD: GENERIC,v 1.808 2007/02/17 00:28:23 daniel Exp $
|
||||
#
|
||||
# GENERIC machine description file
|
||||
#
|
||||
@ -22,7 +22,7 @@ include "arch/i386/conf/std.i386"
|
||||
|
||||
options INCLUDE_CONFIG_FILE # embed config file in kernel binary
|
||||
|
||||
#ident "GENERIC-$Revision: 1.807 $"
|
||||
#ident "GENERIC-$Revision: 1.808 $"
|
||||
|
||||
maxusers 32 # estimated number of users
|
||||
|
||||
@ -52,6 +52,9 @@ options POWERNOW_K7
|
||||
# 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
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: autoconf.c,v 1.84 2006/06/07 22:37:58 kardel Exp $ */
|
||||
/* $NetBSD: autoconf.c,v 1.85 2007/02/17 00:28:24 daniel Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
@ -46,7 +46,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.84 2006/06/07 22:37:58 kardel Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.85 2007/02/17 00:28:24 daniel Exp $");
|
||||
|
||||
#include "opt_compat_oldboot.h"
|
||||
#include "opt_multiprocessor.h"
|
||||
@ -91,6 +91,8 @@ __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.84 2006/06/07 22:37:58 kardel Exp $")
|
||||
#include <machine/kvm86.h>
|
||||
#endif
|
||||
|
||||
#include "opt_viapadlock.h"
|
||||
|
||||
/*
|
||||
* Determine i/o configuration for a machine.
|
||||
*/
|
||||
@ -139,4 +141,8 @@ cpu_configure(void)
|
||||
#if NLAPIC > 0
|
||||
lapic_tpr = 0;
|
||||
#endif
|
||||
|
||||
#if defined(I686_CPU) && defined(VIA_PADLOCK)
|
||||
via_padlock_attach();
|
||||
#endif /* defined(I686_CPU) && defined(VIA_PADLOCK) */
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: identcpu.c,v 1.56 2007/02/09 21:55:04 ad Exp $ */
|
||||
/* $NetBSD: identcpu.c,v 1.57 2007/02/17 00:28:24 daniel Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.56 2007/02/09 21:55:04 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: identcpu.c,v 1.57 2007/02/17 00:28:24 daniel Exp $");
|
||||
|
||||
#include "opt_cputype.h"
|
||||
#include "opt_enhanced_speedstep.h"
|
||||
@ -653,8 +653,10 @@ winchip_cpu_setup(struct cpu_info *ci)
|
||||
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.
|
||||
@ -669,6 +671,24 @@ via_cpu_probe(struct cpu_info *ci)
|
||||
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 *
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: machdep.c,v 1.595 2007/02/09 21:55:04 ad Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.596 2007/02/17 00:28:24 daniel Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998, 2000, 2004, 2006 The NetBSD Foundation, Inc.
|
||||
@ -72,7 +72,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.595 2007/02/09 21:55:04 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.596 2007/02/17 00:28:24 daniel Exp $");
|
||||
|
||||
#include "opt_beep.h"
|
||||
#include "opt_compat_ibcs2.h"
|
||||
@ -242,6 +242,7 @@ int dumpmem_low;
|
||||
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;
|
||||
@ -1499,6 +1500,7 @@ init386(paddr_t first_avail)
|
||||
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;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cpu.h,v 1.132 2007/02/16 02:53:46 ad Exp $ */
|
||||
/* $NetBSD: cpu.h,v 1.133 2007/02/17 00:28:25 daniel Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
@ -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 */
|
||||
@ -133,6 +134,7 @@ struct cpu_info {
|
||||
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 */
|
||||
@ -160,6 +162,8 @@ struct cpu_info {
|
||||
char *ci_ddbipi_stack;
|
||||
|
||||
struct evcnt ci_ipi_events[X86_NIPI];
|
||||
|
||||
struct via_padlock ci_vp; /* VIA PadLock private storage */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -328,6 +332,7 @@ extern int biosbasemem;
|
||||
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[];
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files.x86,v 1.22 2007/02/09 21:55:13 ad Exp $
|
||||
# $NetBSD: files.x86,v 1.23 2007/02/17 00:28:25 daniel Exp $
|
||||
|
||||
# options for MP configuration through the MP spec
|
||||
defflag opt_mpbios.h MPBIOS MPVERBOSE MPDEBUG MPBIOS_SCANPCI
|
||||
@ -13,6 +13,10 @@ defflag opt_pcifixup.h PCI_ADDR_FIXUP PCI_BUS_FIXUP
|
||||
# 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 {}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: specialreg.h,v 1.14 2007/01/16 15:43:44 christos Exp $ */
|
||||
/* $NetBSD: specialreg.h,v 1.15 2007/02/17 00:28:25 daniel Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991 The Regents of the University of California.
|
||||
@ -154,6 +154,13 @@
|
||||
#define CPUID_EXT_FLAGS3 "\20\31FXSR\32SSE\33SSE2\34B27\35HTT\36LONG" \
|
||||
"\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
|
||||
*/
|
||||
@ -281,6 +288,18 @@
|
||||
#define MSR_MC3_ADDR 0x412
|
||||
#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.
|
||||
*/
|
||||
|
77
sys/arch/x86/include/via_padlock.h
Normal file
77
sys/arch/x86/include/via_padlock.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* $NetBSD: via_padlock.h,v 1.1 2007/02/17 00:28:25 daniel Exp $ */
|
||||
|
||||
/*-
|
||||
* 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_ */
|
481
sys/arch/x86/x86/via_padlock.c
Normal file
481
sys/arch/x86/x86/via_padlock.c
Normal file
@ -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: via_padlock.c,v 1.1 2007/02/17 00:28:25 daniel Exp $");
|
||||
|
||||
#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 */
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cryptosoft.c,v 1.15 2006/11/16 01:33:51 christos Exp $ */
|
||||
/* $NetBSD: cryptosoft.c,v 1.16 2007/02/17 00:28:25 daniel Exp $ */
|
||||
/* $FreeBSD: src/sys/opencrypto/cryptosoft.c,v 1.2.2.1 2002/11/21 23:34:23 sam Exp $ */
|
||||
/* $OpenBSD: cryptosoft.c,v 1.35 2002/04/26 08:43:50 deraadt Exp $ */
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: cryptosoft.c,v 1.15 2006/11/16 01:33:51 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: cryptosoft.c,v 1.16 2007/02/17 00:28:25 daniel Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -60,8 +60,6 @@ int32_t swcr_id = -1;
|
||||
: 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 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
|
||||
/*
|
||||
* Compute keyed-hash authenticator.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
swcr_authcompute(struct cryptop *crp, struct cryptodesc *crd,
|
||||
struct swcr_data *sw, caddr_t buf, int outtype)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: cryptosoft.h,v 1.3 2005/11/25 16:16:46 thorpej Exp $ */
|
||||
/* $NetBSD: cryptosoft.h,v 1.4 2007/02/17 00:28:25 daniel Exp $ */
|
||||
/* $OpenBSD: cryptosoft.h,v 1.10 2002/04/22 23:10:09 deraadt Exp $ */
|
||||
|
||||
/*
|
||||
@ -57,4 +57,9 @@ struct swcr_data {
|
||||
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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user