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