padlock.c revision 159279
1/*-
2 * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3 * Copyright (c) 2004 Mark R V Murray
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28/*	$OpenBSD: via.c,v 1.3 2004/06/15 23:36:55 deraadt Exp $	*/
29/*-
30 * Copyright (c) 2003 Jason Wright
31 * Copyright (c) 2003, 2004 Theo de Raadt
32 * All rights reserved.
33 *
34 * Permission to use, copy, modify, and distribute this software for any
35 * purpose with or without fee is hereby granted, provided that the above
36 * copyright notice and this permission notice appear in all copies.
37 *
38 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
39 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
40 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
41 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
42 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
43 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
44 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
45 */
46
47#include <sys/cdefs.h>
48__FBSDID("$FreeBSD: head/sys/crypto/via/padlock.c 159279 2006-06-05 16:22:04Z pjd $");
49
50#include <sys/param.h>
51#include <sys/systm.h>
52#include <sys/kernel.h>
53#include <sys/module.h>
54#include <sys/lock.h>
55#include <sys/mutex.h>
56#include <sys/malloc.h>
57#include <sys/libkern.h>
58#if defined(__i386__) && !defined(PC98)
59#include <machine/cpufunc.h>
60#include <machine/cputypes.h>
61#endif
62
63#include <opencrypto/cryptodev.h>
64#include <opencrypto/cryptosoft.h> /* for hmac_ipad_buffer and hmac_opad_buffer */
65#include <opencrypto/xform.h>
66#include <crypto/rijndael/rijndael.h>
67
68
69#define	PADLOCK_ROUND_COUNT_AES128	10
70#define	PADLOCK_ROUND_COUNT_AES192	12
71#define	PADLOCK_ROUND_COUNT_AES256	14
72
73#define	PADLOCK_ALGORITHM_TYPE_AES	0
74
75#define	PADLOCK_KEY_GENERATION_HW	0
76#define	PADLOCK_KEY_GENERATION_SW	1
77
78#define	PADLOCK_DIRECTION_ENCRYPT	0
79#define	PADLOCK_DIRECTION_DECRYPT	1
80
81#define	PADLOCK_KEY_SIZE_128	0
82#define	PADLOCK_KEY_SIZE_192	1
83#define	PADLOCK_KEY_SIZE_256	2
84
85union padlock_cw {
86	uint64_t raw;
87	struct {
88		u_int round_count : 4;
89		u_int algorithm_type : 3;
90		u_int key_generation : 1;
91		u_int intermediate : 1;
92		u_int direction : 1;
93		u_int key_size : 2;
94		u_int filler0 : 20;
95		u_int filler1 : 32;
96		u_int filler2 : 32;
97		u_int filler3 : 32;
98	} __field;
99};
100#define	cw_round_count		__field.round_count
101#define	cw_algorithm_type	__field.algorithm_type
102#define	cw_key_generation	__field.key_generation
103#define	cw_intermediate		__field.intermediate
104#define	cw_direction		__field.direction
105#define	cw_key_size		__field.key_size
106#define	cw_filler0		__field.filler0
107#define	cw_filler1		__field.filler1
108#define	cw_filler2		__field.filler2
109#define	cw_filler3		__field.filler3
110
111struct padlock_session {
112	union padlock_cw ses_cw __aligned(16);
113	uint32_t	ses_ekey[4 * (RIJNDAEL_MAXNR + 1) + 4] __aligned(16);	/* 128 bit aligned */
114	uint32_t	ses_dkey[4 * (RIJNDAEL_MAXNR + 1) + 4] __aligned(16);	/* 128 bit aligned */
115	uint8_t		ses_iv[16] __aligned(16);			/* 128 bit aligned */
116	struct auth_hash *ses_axf;
117	uint8_t		*ses_ictx;
118	uint8_t		*ses_octx;
119	int		ses_mlen;
120	int		ses_used;
121	uint32_t	ses_id;
122	TAILQ_ENTRY(padlock_session) ses_next;
123};
124
125struct padlock_softc {
126	int32_t		sc_cid;
127	uint32_t	sc_sid;
128	TAILQ_HEAD(, padlock_session) sc_sessions;
129	struct mtx	sc_sessions_mtx;
130};
131
132static struct padlock_softc *padlock_sc;
133
134static int padlock_newsession(void *arg __unused, uint32_t *sidp,
135    struct cryptoini *cri);
136static int padlock_freesession(void *arg __unused, uint64_t tid);
137static int padlock_process(void *arg __unused, struct cryptop *crp,
138    int hint __unused);
139
140static __inline void
141padlock_cbc(void *in, void *out, size_t count, void *key, union padlock_cw *cw,
142    void *iv)
143{
144#ifdef __GNUCLIKE_ASM
145	/* The .byte line is really VIA C3 "xcrypt-cbc" instruction */
146	__asm __volatile(
147		"pushf				\n\t"
148		"popf				\n\t"
149		"rep				\n\t"
150		".byte	0x0f, 0xa7, 0xd0"
151			: "+a" (iv), "+c" (count), "+D" (out), "+S" (in)
152			: "b" (key), "d" (cw)
153			: "cc", "memory"
154		);
155#endif
156}
157
158static int
159padlock_init(void)
160{
161	struct padlock_softc *sc;
162#if defined(__i386__) && !defined(PC98)
163	u_int regs[4];
164	int has_ace = 0;
165
166	if (cpu_class < CPUCLASS_586)
167		return (EINVAL);
168	do_cpuid(1, regs);
169	if ((regs[0] & 0xf) >= 3) {
170		do_cpuid(0xc0000000, regs);
171		if (regs[0] == 0xc0000001) {
172			do_cpuid(0xc0000001, regs);
173			if ((regs[3] & 0xc0) == 0xc0)
174				has_ace = 1;
175		}
176	}
177	if (!has_ace) {
178		printf("PADLOCK: No ACE support.\n");
179		return (EINVAL);
180	}
181#else
182	return (EINVAL);
183#endif
184
185	padlock_sc = sc = malloc(sizeof(*padlock_sc), M_DEVBUF,
186	    M_WAITOK | M_ZERO);
187	TAILQ_INIT(&sc->sc_sessions);
188	sc->sc_sid = 1;
189
190	sc->sc_cid = crypto_get_driverid(0);
191	if (sc->sc_cid < 0) {
192		printf("PADLOCK: Could not get crypto driver id.\n");
193		free(padlock_sc, M_DEVBUF);
194		padlock_sc = NULL;
195		return (ENOMEM);
196	}
197
198	mtx_init(&sc->sc_sessions_mtx, "padlock_mtx", NULL, MTX_DEF);
199	crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0, padlock_newsession,
200	    padlock_freesession, padlock_process, NULL);
201	crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0, padlock_newsession,
202	    padlock_freesession, padlock_process, NULL);
203	crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0, padlock_newsession,
204	    padlock_freesession, padlock_process, NULL);
205	crypto_register(sc->sc_cid, CRYPTO_RIPEMD160_HMAC, 0, 0,
206	    padlock_newsession, padlock_freesession, padlock_process, NULL);
207	crypto_register(sc->sc_cid, CRYPTO_SHA2_256_HMAC, 0, 0,
208	    padlock_newsession, padlock_freesession, padlock_process, NULL);
209	crypto_register(sc->sc_cid, CRYPTO_SHA2_384_HMAC, 0, 0,
210	    padlock_newsession, padlock_freesession, padlock_process, NULL);
211	crypto_register(sc->sc_cid, CRYPTO_SHA2_512_HMAC, 0, 0,
212	    padlock_newsession, padlock_freesession, padlock_process, NULL);
213	return (0);
214}
215
216static int
217padlock_destroy(void)
218{
219	struct padlock_softc *sc = padlock_sc;
220	struct padlock_session *ses;
221	u_int active = 0;
222
223	if (sc == NULL)
224		return (0);
225	mtx_lock(&sc->sc_sessions_mtx);
226	TAILQ_FOREACH(ses, &sc->sc_sessions, ses_next) {
227		if (ses->ses_used)
228			active++;
229	}
230	if (active > 0) {
231		mtx_unlock(&sc->sc_sessions_mtx);
232		printf("PADLOCK: Cannot destroy, %u sessions active.\n",
233		    active);
234		return (EBUSY);
235	}
236	padlock_sc = NULL;
237	for (ses = TAILQ_FIRST(&sc->sc_sessions); ses != NULL;
238	    ses = TAILQ_FIRST(&sc->sc_sessions)) {
239		TAILQ_REMOVE(&sc->sc_sessions, ses, ses_next);
240		free(ses, M_DEVBUF);
241	}
242	mtx_destroy(&sc->sc_sessions_mtx);
243	crypto_unregister_all(sc->sc_cid);
244	free(sc, M_DEVBUF);
245	return (0);
246}
247
248static void
249padlock_setup_enckey(struct padlock_session *ses, caddr_t key, int klen)
250{
251	union padlock_cw *cw;
252	int i;
253
254	cw = &ses->ses_cw;
255	if (cw->cw_key_generation == PADLOCK_KEY_GENERATION_SW) {
256		/* Build expanded keys for both directions */
257		rijndaelKeySetupEnc(ses->ses_ekey, key, klen);
258		rijndaelKeySetupDec(ses->ses_dkey, key, klen);
259		for (i = 0; i < 4 * (RIJNDAEL_MAXNR + 1); i++) {
260			ses->ses_ekey[i] = ntohl(ses->ses_ekey[i]);
261			ses->ses_dkey[i] = ntohl(ses->ses_dkey[i]);
262		}
263	} else {
264		bcopy(key, ses->ses_ekey, klen);
265		bcopy(key, ses->ses_dkey, klen);
266	}
267}
268
269static void
270padlock_setup_mackey(struct padlock_session *ses, caddr_t key, int klen)
271{
272	struct auth_hash *axf;
273	int i;
274
275	klen /= 8;
276	axf = ses->ses_axf;
277
278	for (i = 0; i < klen; i++)
279		key[i] ^= HMAC_IPAD_VAL;
280
281	axf->Init(ses->ses_ictx);
282	axf->Update(ses->ses_ictx, key, klen);
283	axf->Update(ses->ses_ictx, hmac_ipad_buffer, axf->blocksize - klen);
284
285	for (i = 0; i < klen; i++)
286		key[i] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
287
288	axf->Init(ses->ses_octx);
289	axf->Update(ses->ses_octx, key, klen);
290	axf->Update(ses->ses_octx, hmac_opad_buffer, axf->blocksize - klen);
291
292	for (i = 0; i < klen; i++)
293		key[i] ^= HMAC_OPAD_VAL;
294}
295
296/*
297 * Compute keyed-hash authenticator.
298 */
299static int
300padlock_authcompute(struct padlock_session *ses, struct cryptodesc *crd,
301    caddr_t buf, int flags)
302{
303	u_char hash[HASH_MAX_LEN];
304	struct auth_hash *axf;
305	union authctx ctx;
306	int error;
307
308	axf = ses->ses_axf;
309
310	bcopy(ses->ses_ictx, &ctx, axf->ctxsize);
311
312	error = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len,
313	    (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx);
314	if (error != 0)
315		return (error);
316
317	axf->Final(hash, &ctx);
318	bcopy(ses->ses_octx, &ctx, axf->ctxsize);
319	axf->Update(&ctx, hash, axf->hashsize);
320	axf->Final(hash, &ctx);
321
322	/* Inject the authentication data */
323	crypto_copyback(flags, buf, crd->crd_inject,
324	    ses->ses_mlen == 0 ? axf->hashsize : ses->ses_mlen, hash);
325	return (0);
326}
327
328
329static int
330padlock_newsession(void *arg __unused, uint32_t *sidp, struct cryptoini *cri)
331{
332	struct padlock_softc *sc = padlock_sc;
333	struct padlock_session *ses = NULL;
334	struct cryptoini *encini, *macini;
335	union padlock_cw *cw;
336
337	if (sc == NULL || sidp == NULL || cri == NULL)
338		return (EINVAL);
339
340	encini = macini = NULL;
341	for (; cri != NULL; cri = cri->cri_next) {
342		switch (cri->cri_alg) {
343		case CRYPTO_NULL_HMAC:
344		case CRYPTO_MD5_HMAC:
345		case CRYPTO_SHA1_HMAC:
346		case CRYPTO_RIPEMD160_HMAC:
347		case CRYPTO_SHA2_256_HMAC:
348		case CRYPTO_SHA2_384_HMAC:
349		case CRYPTO_SHA2_512_HMAC:
350			if (macini != NULL)
351				return (EINVAL);
352			macini = cri;
353			break;
354		case CRYPTO_AES_CBC:
355			if (encini != NULL)
356				return (EINVAL);
357			encini = cri;
358			break;
359		default:
360			return (EINVAL);
361		}
362	}
363
364	/*
365	 * We only support HMAC algorithms to be able to work with
366	 * fast_ipsec(4), so if we are asked only for authentication without
367	 * encryption, don't pretend we can accellerate it.
368	 */
369	if (encini == NULL)
370		return (EINVAL);
371	if (encini->cri_klen != 128 && encini->cri_klen != 192 &&
372	    encini->cri_klen != 256) {
373		return (EINVAL);
374	}
375
376	/*
377	 * Let's look for a free session structure.
378	 */
379	mtx_lock(&sc->sc_sessions_mtx);
380	/*
381	 * Free sessions goes first, so if first session is used, we need to
382	 * allocate one.
383	 */
384	ses = TAILQ_FIRST(&sc->sc_sessions);
385	if (ses == NULL || ses->ses_used)
386		ses = NULL;
387	else {
388		TAILQ_REMOVE(&sc->sc_sessions, ses, ses_next);
389		ses->ses_used = 1;
390		TAILQ_INSERT_TAIL(&sc->sc_sessions, ses, ses_next);
391	}
392	mtx_unlock(&sc->sc_sessions_mtx);
393	if (ses == NULL) {
394		ses = malloc(sizeof(*ses), M_DEVBUF, M_NOWAIT | M_ZERO);
395		if (ses == NULL)
396			return (ENOMEM);
397		ses->ses_used = 1;
398		mtx_lock(&sc->sc_sessions_mtx);
399		ses->ses_id = sc->sc_sid++;
400		TAILQ_INSERT_TAIL(&sc->sc_sessions, ses, ses_next);
401		mtx_unlock(&sc->sc_sessions_mtx);
402	}
403
404	cw = &ses->ses_cw;
405	bzero(cw, sizeof(*cw));
406	cw->cw_algorithm_type = PADLOCK_ALGORITHM_TYPE_AES;
407	cw->cw_key_generation = PADLOCK_KEY_GENERATION_SW;
408	cw->cw_intermediate = 0;
409	switch (encini->cri_klen) {
410	case 128:
411		cw->cw_round_count = PADLOCK_ROUND_COUNT_AES128;
412		cw->cw_key_size = PADLOCK_KEY_SIZE_128;
413#ifdef HW_KEY_GENERATION
414		/* This doesn't buy us much, that's why it is commented out. */
415		cw->cw_key_generation = PADLOCK_KEY_GENERATION_HW;
416#endif
417		break;
418	case 192:
419		cw->cw_round_count = PADLOCK_ROUND_COUNT_AES192;
420		cw->cw_key_size = PADLOCK_KEY_SIZE_192;
421		break;
422	case 256:
423		cw->cw_round_count = PADLOCK_ROUND_COUNT_AES256;
424		cw->cw_key_size = PADLOCK_KEY_SIZE_256;
425		break;
426	}
427	if (encini->cri_key != NULL)
428		padlock_setup_enckey(ses, encini->cri_key, encini->cri_klen);
429
430	arc4rand(ses->ses_iv, sizeof(ses->ses_iv), 0);
431
432	if (macini != NULL) {
433		ses->ses_mlen = macini->cri_mlen;
434
435		/* Find software structure which describes HMAC algorithm. */
436		switch (macini->cri_alg) {
437		case CRYPTO_NULL_HMAC:
438			ses->ses_axf = &auth_hash_null;
439			break;
440		case CRYPTO_MD5_HMAC:
441			ses->ses_axf = &auth_hash_hmac_md5;
442			break;
443		case CRYPTO_SHA1_HMAC:
444			ses->ses_axf = &auth_hash_hmac_sha1;
445			break;
446		case CRYPTO_RIPEMD160_HMAC:
447			ses->ses_axf = &auth_hash_hmac_ripemd_160;
448			break;
449		case CRYPTO_SHA2_256_HMAC:
450			ses->ses_axf = &auth_hash_hmac_sha2_256;
451			break;
452		case CRYPTO_SHA2_384_HMAC:
453			ses->ses_axf = &auth_hash_hmac_sha2_384;
454			break;
455		case CRYPTO_SHA2_512_HMAC:
456			ses->ses_axf = &auth_hash_hmac_sha2_512;
457			break;
458		}
459
460		/* Allocate memory for HMAC inner and outer contexts. */
461		ses->ses_ictx = malloc(ses->ses_axf->ctxsize, M_CRYPTO_DATA,
462		    M_NOWAIT);
463		ses->ses_octx = malloc(ses->ses_axf->ctxsize, M_CRYPTO_DATA,
464		    M_NOWAIT);
465		if (ses->ses_ictx == NULL || ses->ses_octx == NULL) {
466			padlock_freesession(NULL, ses->ses_id);
467			return (ENOMEM);
468		}
469
470		/* Setup key if given. */
471		if (macini->cri_key != NULL) {
472			padlock_setup_mackey(ses, macini->cri_key,
473			    macini->cri_klen);
474		}
475	}
476
477	*sidp = ses->ses_id;
478	return (0);
479}
480
481static int
482padlock_freesession(void *arg __unused, uint64_t tid)
483{
484	struct padlock_softc *sc = padlock_sc;
485	struct padlock_session *ses;
486	uint32_t sid = ((uint32_t)tid) & 0xffffffff;
487
488	if (sc == NULL)
489		return (EINVAL);
490	mtx_lock(&sc->sc_sessions_mtx);
491	TAILQ_FOREACH(ses, &sc->sc_sessions, ses_next) {
492		if (ses->ses_id == sid)
493			break;
494	}
495	if (ses == NULL) {
496		mtx_unlock(&sc->sc_sessions_mtx);
497		return (EINVAL);
498	}
499	TAILQ_REMOVE(&sc->sc_sessions, ses, ses_next);
500	if (ses->ses_ictx != NULL) {
501		bzero(ses->ses_ictx, sizeof(ses->ses_ictx));
502		free(ses->ses_ictx, M_CRYPTO_DATA);
503	}
504	if (ses->ses_octx != NULL) {
505		bzero(ses->ses_octx, sizeof(ses->ses_octx));
506		free(ses->ses_octx, M_CRYPTO_DATA);
507	}
508	bzero(ses, sizeof(ses));
509	ses->ses_used = 0;
510	TAILQ_INSERT_TAIL(&sc->sc_sessions, ses, ses_next);
511	mtx_unlock(&sc->sc_sessions_mtx);
512	return (0);
513}
514
515static int
516padlock_process(void *arg __unused, struct cryptop *crp, int hint __unused)
517{
518	struct padlock_softc *sc = padlock_sc;
519	struct padlock_session *ses;
520	union padlock_cw *cw;
521	struct cryptodesc *crd, *enccrd, *maccrd;
522	uint32_t *key;
523	u_char *buf, *abuf;
524	int error = 0;
525
526	buf = NULL;
527	if (crp == NULL || crp->crp_callback == NULL || crp->crp_desc == NULL) {
528		error = EINVAL;
529		goto out;
530	}
531
532	enccrd = maccrd = NULL;
533	for (crd = crp->crp_desc; crd != NULL; crd = crd->crd_next) {
534		switch (crd->crd_alg) {
535		case CRYPTO_NULL_HMAC:
536		case CRYPTO_MD5_HMAC:
537		case CRYPTO_SHA1_HMAC:
538		case CRYPTO_RIPEMD160_HMAC:
539		case CRYPTO_SHA2_256_HMAC:
540		case CRYPTO_SHA2_384_HMAC:
541		case CRYPTO_SHA2_512_HMAC:
542			if (maccrd != NULL) {
543				error = EINVAL;
544				goto out;
545			}
546			maccrd = crd;
547			break;
548		case CRYPTO_AES_CBC:
549			if (enccrd != NULL) {
550				error = EINVAL;
551				goto out;
552			}
553			enccrd = crd;
554			break;
555		default:
556			return (EINVAL);
557		}
558	}
559	if (enccrd == NULL || (enccrd->crd_len % AES_BLOCK_LEN) != 0) {
560		error = EINVAL;
561		goto out;
562	}
563
564	mtx_lock(&sc->sc_sessions_mtx);
565	TAILQ_FOREACH(ses, &sc->sc_sessions, ses_next) {
566		if (ses->ses_id == (crp->crp_sid & 0xffffffff))
567			break;
568	}
569	mtx_unlock(&sc->sc_sessions_mtx);
570	if (ses == NULL) {
571		error = EINVAL;
572		goto out;
573	}
574
575	buf = malloc(enccrd->crd_len + 16, M_DEVBUF, M_NOWAIT);
576	if (buf == NULL) {
577		error = ENOMEM;
578		goto out;
579	}
580	/* Buffer has to be 16 bytes aligned. */
581	abuf = buf + 16 - ((uintptr_t)buf % 16);
582
583	if ((enccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0)
584		padlock_setup_enckey(ses, enccrd->crd_key, enccrd->crd_klen);
585	if (maccrd != NULL && (maccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0)
586		padlock_setup_mackey(ses, maccrd->crd_key, maccrd->crd_klen);
587
588	cw = &ses->ses_cw;
589	cw->cw_filler0 = 0;
590	cw->cw_filler1 = 0;
591	cw->cw_filler2 = 0;
592	cw->cw_filler3 = 0;
593	if ((enccrd->crd_flags & CRD_F_ENCRYPT) != 0) {
594		cw->cw_direction = PADLOCK_DIRECTION_ENCRYPT;
595		key = ses->ses_ekey;
596		if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0)
597			bcopy(enccrd->crd_iv, ses->ses_iv, 16);
598
599		if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0) {
600			crypto_copyback(crp->crp_flags, crp->crp_buf,
601			    enccrd->crd_inject, AES_BLOCK_LEN, ses->ses_iv);
602		}
603	} else {
604		cw->cw_direction = PADLOCK_DIRECTION_DECRYPT;
605		key = ses->ses_dkey;
606		if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0)
607			bcopy(enccrd->crd_iv, ses->ses_iv, AES_BLOCK_LEN);
608		else {
609			crypto_copydata(crp->crp_flags, crp->crp_buf,
610			    enccrd->crd_inject, AES_BLOCK_LEN, ses->ses_iv);
611		}
612	}
613
614	/* Perform data authentication if requested before encryption. */
615	if (maccrd != NULL && maccrd->crd_next == enccrd) {
616		error = padlock_authcompute(ses, maccrd, crp->crp_buf,
617		    crp->crp_flags);
618		if (error != 0)
619			goto out;
620	}
621
622	crypto_copydata(crp->crp_flags, crp->crp_buf, enccrd->crd_skip,
623	    enccrd->crd_len, abuf);
624
625	padlock_cbc(abuf, abuf, enccrd->crd_len / 16, key, cw, ses->ses_iv);
626
627	crypto_copyback(crp->crp_flags, crp->crp_buf, enccrd->crd_skip,
628	    enccrd->crd_len, abuf);
629
630	/* Perform data authentication if requested after encryption. */
631	if (maccrd != NULL && enccrd->crd_next == maccrd) {
632		error = padlock_authcompute(ses, maccrd, crp->crp_buf,
633		    crp->crp_flags);
634		if (error != 0)
635			goto out;
636	}
637
638	/* copy out last block for use as next session IV */
639	if ((enccrd->crd_flags & CRD_F_ENCRYPT) != 0) {
640		crypto_copydata(crp->crp_flags, crp->crp_buf,
641		    enccrd->crd_skip + enccrd->crd_len - AES_BLOCK_LEN,
642		    AES_BLOCK_LEN, ses->ses_iv);
643	}
644
645out:
646	if (buf != NULL) {
647		bzero(buf, enccrd->crd_len + 16);
648		free(buf, M_DEVBUF);
649	}
650	crp->crp_etype = error;
651	crypto_done(crp);
652	return (error);
653}
654
655static int
656padlock_modevent(module_t mod, int type, void *unused __unused)
657{
658	int error;
659
660	error = EOPNOTSUPP;
661	switch (type) {
662	case MOD_LOAD:
663		error = padlock_init();
664		break;
665	case MOD_UNLOAD:
666		error = padlock_destroy();
667		break;
668	}
669	return (error);
670}
671
672static moduledata_t padlock_mod = {
673	"padlock",
674	padlock_modevent,
675	0
676};
677DECLARE_MODULE(padlock, padlock_mod, SI_SUB_DRIVERS, SI_ORDER_ANY);
678MODULE_VERSION(padlock, 1);
679MODULE_DEPEND(padlock, crypto, 1, 1, 1);
680