cryptosoft.c revision 143406
1104476Ssam/*	$OpenBSD: cryptosoft.c,v 1.35 2002/04/26 08:43:50 deraadt Exp $	*/
2104476Ssam
3139825Simp/*-
4104476Ssam * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
5104476Ssam *
6104476Ssam * This code was written by Angelos D. Keromytis in Athens, Greece, in
7104476Ssam * February 2000. Network Security Technologies Inc. (NSTI) kindly
8104476Ssam * supported the development of this code.
9104476Ssam *
10104476Ssam * Copyright (c) 2000, 2001 Angelos D. Keromytis
11104476Ssam *
12104476Ssam * Permission to use, copy, and modify this software with or without fee
13104476Ssam * is hereby granted, provided that this entire notice is included in
14104476Ssam * all source code copies of any software which is or includes a copy or
15104476Ssam * modification of this software.
16104476Ssam *
17104476Ssam * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
18104476Ssam * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
19104476Ssam * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
20104476Ssam * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
21104476Ssam * PURPOSE.
22104476Ssam */
23104476Ssam
24116191Sobrien#include <sys/cdefs.h>
25116191Sobrien__FBSDID("$FreeBSD: head/sys/opencrypto/cryptosoft.c 143406 2005-03-11 12:37:07Z ume $");
26116191Sobrien
27104476Ssam#include <sys/param.h>
28104476Ssam#include <sys/systm.h>
29104476Ssam#include <sys/malloc.h>
30104476Ssam#include <sys/mbuf.h>
31104476Ssam#include <sys/sysctl.h>
32104476Ssam#include <sys/errno.h>
33104476Ssam#include <sys/random.h>
34104476Ssam#include <sys/kernel.h>
35104476Ssam#include <sys/uio.h>
36104476Ssam
37104476Ssam#include <crypto/blowfish/blowfish.h>
38104476Ssam#include <crypto/sha1.h>
39104476Ssam#include <opencrypto/rmd160.h>
40143406Sume#include <opencrypto/cast.h>
41104476Ssam#include <opencrypto/skipjack.h>
42104476Ssam#include <sys/md5.h>
43104476Ssam
44104476Ssam#include <opencrypto/cryptodev.h>
45104476Ssam#include <opencrypto/cryptosoft.h>
46104476Ssam#include <opencrypto/xform.h>
47104476Ssam
48104476Ssamu_int8_t hmac_ipad_buffer[64] = {
49104476Ssam	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
50104476Ssam	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
51104476Ssam	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
52104476Ssam	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
53104476Ssam	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
54104476Ssam	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
55104476Ssam	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
56104476Ssam	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
57104476Ssam};
58104476Ssam
59104476Ssamu_int8_t hmac_opad_buffer[64] = {
60104476Ssam	0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
61104476Ssam	0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
62104476Ssam	0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
63104476Ssam	0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
64104476Ssam	0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
65104476Ssam	0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
66104476Ssam	0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
67104476Ssam	0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C
68104476Ssam};
69104476Ssam
70104476Ssam
71104476Ssamstruct swcr_data **swcr_sessions = NULL;
72104476Ssamu_int32_t swcr_sesnum = 0;
73104476Ssamint32_t swcr_id = -1;
74104476Ssam
75104476Ssam#define COPYBACK(x, a, b, c, d) \
76104476Ssam	(x) == CRYPTO_BUF_MBUF ? m_copyback((struct mbuf *)a,b,c,d) \
77104476Ssam	: cuio_copyback((struct uio *)a,b,c,d)
78104476Ssam#define COPYDATA(x, a, b, c, d) \
79104476Ssam	(x) == CRYPTO_BUF_MBUF ? m_copydata((struct mbuf *)a,b,c,d) \
80104476Ssam	: cuio_copydata((struct uio *)a,b,c,d)
81104476Ssam
82104476Ssamstatic	int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
83104476Ssamstatic	int swcr_authcompute(struct cryptop *crp, struct cryptodesc *crd,
84104476Ssam			     struct swcr_data *sw, caddr_t buf, int outtype);
85104476Ssamstatic	int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int);
86104476Ssamstatic	int swcr_process(void *, struct cryptop *, int);
87104476Ssamstatic	int swcr_newsession(void *, u_int32_t *, struct cryptoini *);
88104476Ssamstatic	int swcr_freesession(void *, u_int64_t);
89104476Ssam
90104476Ssam/*
91104476Ssam * Apply a symmetric encryption/decryption algorithm.
92104476Ssam */
93104476Ssamstatic int
94104476Ssamswcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
95104476Ssam    int outtype)
96104476Ssam{
97104476Ssam	unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN], *idat;
98104476Ssam	unsigned char *ivp, piv[EALG_MAX_BLOCK_LEN];
99104476Ssam	struct enc_xform *exf;
100104476Ssam	int i, k, j, blks;
101104476Ssam
102104476Ssam	exf = sw->sw_exf;
103104476Ssam	blks = exf->blocksize;
104104476Ssam
105104476Ssam	/* Check for non-padded data */
106104476Ssam	if (crd->crd_len % blks)
107104476Ssam		return EINVAL;
108104476Ssam
109104476Ssam	/* Initialize the IV */
110104476Ssam	if (crd->crd_flags & CRD_F_ENCRYPT) {
111104476Ssam		/* IV explicitly provided ? */
112104476Ssam		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
113104476Ssam			bcopy(crd->crd_iv, iv, blks);
114104476Ssam		else {
115104476Ssam			/* Get random IV */
116104476Ssam			for (i = 0;
117104476Ssam			    i + sizeof (u_int32_t) < EALG_MAX_BLOCK_LEN;
118104476Ssam			    i += sizeof (u_int32_t)) {
119104476Ssam				u_int32_t temp = arc4random();
120104476Ssam
121104476Ssam				bcopy(&temp, iv + i, sizeof(u_int32_t));
122104476Ssam			}
123104476Ssam			/*
124104476Ssam			 * What if the block size is not a multiple
125104476Ssam			 * of sizeof (u_int32_t), which is the size of
126104476Ssam			 * what arc4random() returns ?
127104476Ssam			 */
128104476Ssam			if (EALG_MAX_BLOCK_LEN % sizeof (u_int32_t) != 0) {
129104476Ssam				u_int32_t temp = arc4random();
130104476Ssam
131104476Ssam				bcopy (&temp, iv + i,
132104476Ssam				    EALG_MAX_BLOCK_LEN - i);
133104476Ssam			}
134104476Ssam		}
135104476Ssam
136104476Ssam		/* Do we need to write the IV */
137104476Ssam		if (!(crd->crd_flags & CRD_F_IV_PRESENT)) {
138104476Ssam			COPYBACK(outtype, buf, crd->crd_inject, blks, iv);
139104476Ssam		}
140104476Ssam
141104476Ssam	} else {	/* Decryption */
142104476Ssam			/* IV explicitly provided ? */
143104476Ssam		if (crd->crd_flags & CRD_F_IV_EXPLICIT)
144104476Ssam			bcopy(crd->crd_iv, iv, blks);
145104476Ssam		else {
146104476Ssam			/* Get IV off buf */
147104476Ssam			COPYDATA(outtype, buf, crd->crd_inject, blks, iv);
148104476Ssam		}
149104476Ssam	}
150104476Ssam
151125330Sphk	if (crd->crd_flags & CRD_F_KEY_EXPLICIT) {
152125330Sphk		int error;
153125330Sphk
154125330Sphk		if (sw->sw_kschedule)
155125330Sphk			exf->zerokey(&(sw->sw_kschedule));
156125330Sphk		error = exf->setkey(&sw->sw_kschedule,
157125330Sphk				crd->crd_key, crd->crd_klen / 8);
158125330Sphk		if (error)
159125330Sphk			return (error);
160125330Sphk	}
161104476Ssam	ivp = iv;
162104476Ssam
163104476Ssam	if (outtype == CRYPTO_BUF_CONTIG) {
164104476Ssam		if (crd->crd_flags & CRD_F_ENCRYPT) {
165104476Ssam			for (i = crd->crd_skip;
166104476Ssam			    i < crd->crd_skip + crd->crd_len; i += blks) {
167104476Ssam				/* XOR with the IV/previous block, as appropriate. */
168104476Ssam				if (i == crd->crd_skip)
169104476Ssam					for (k = 0; k < blks; k++)
170104476Ssam						buf[i + k] ^= ivp[k];
171104476Ssam				else
172104476Ssam					for (k = 0; k < blks; k++)
173104476Ssam						buf[i + k] ^= buf[i + k - blks];
174104476Ssam				exf->encrypt(sw->sw_kschedule, buf + i);
175104476Ssam			}
176104476Ssam		} else {		/* Decrypt */
177104476Ssam			/*
178104476Ssam			 * Start at the end, so we don't need to keep the encrypted
179104476Ssam			 * block as the IV for the next block.
180104476Ssam			 */
181104476Ssam			for (i = crd->crd_skip + crd->crd_len - blks;
182104476Ssam			    i >= crd->crd_skip; i -= blks) {
183104476Ssam				exf->decrypt(sw->sw_kschedule, buf + i);
184104476Ssam
185104476Ssam				/* XOR with the IV/previous block, as appropriate */
186104476Ssam				if (i == crd->crd_skip)
187104476Ssam					for (k = 0; k < blks; k++)
188104476Ssam						buf[i + k] ^= ivp[k];
189104476Ssam				else
190104476Ssam					for (k = 0; k < blks; k++)
191104476Ssam						buf[i + k] ^= buf[i + k - blks];
192104476Ssam			}
193104476Ssam		}
194104476Ssam
195104476Ssam		return 0;
196104476Ssam	} else if (outtype == CRYPTO_BUF_MBUF) {
197104476Ssam		struct mbuf *m = (struct mbuf *) buf;
198104476Ssam
199104476Ssam		/* Find beginning of data */
200104476Ssam		m = m_getptr(m, crd->crd_skip, &k);
201104476Ssam		if (m == NULL)
202104476Ssam			return EINVAL;
203104476Ssam
204104476Ssam		i = crd->crd_len;
205104476Ssam
206104476Ssam		while (i > 0) {
207104476Ssam			/*
208104476Ssam			 * If there's insufficient data at the end of
209104476Ssam			 * an mbuf, we have to do some copying.
210104476Ssam			 */
211104476Ssam			if (m->m_len < k + blks && m->m_len != k) {
212104476Ssam				m_copydata(m, k, blks, blk);
213104476Ssam
214104476Ssam				/* Actual encryption/decryption */
215104476Ssam				if (crd->crd_flags & CRD_F_ENCRYPT) {
216104476Ssam					/* XOR with previous block */
217104476Ssam					for (j = 0; j < blks; j++)
218104476Ssam						blk[j] ^= ivp[j];
219104476Ssam
220104476Ssam					exf->encrypt(sw->sw_kschedule, blk);
221104476Ssam
222104476Ssam					/*
223104476Ssam					 * Keep encrypted block for XOR'ing
224104476Ssam					 * with next block
225104476Ssam					 */
226104476Ssam					bcopy(blk, iv, blks);
227104476Ssam					ivp = iv;
228104476Ssam				} else {	/* decrypt */
229104476Ssam					/*
230104476Ssam					 * Keep encrypted block for XOR'ing
231104476Ssam					 * with next block
232104476Ssam					 */
233104476Ssam					if (ivp == iv)
234104476Ssam						bcopy(blk, piv, blks);
235104476Ssam					else
236104476Ssam						bcopy(blk, iv, blks);
237104476Ssam
238104476Ssam					exf->decrypt(sw->sw_kschedule, blk);
239104476Ssam
240104476Ssam					/* XOR with previous block */
241104476Ssam					for (j = 0; j < blks; j++)
242104476Ssam						blk[j] ^= ivp[j];
243104476Ssam
244104476Ssam					if (ivp == iv)
245104476Ssam						bcopy(piv, iv, blks);
246104476Ssam					else
247104476Ssam						ivp = iv;
248104476Ssam				}
249104476Ssam
250104476Ssam				/* Copy back decrypted block */
251104476Ssam				m_copyback(m, k, blks, blk);
252104476Ssam
253104476Ssam				/* Advance pointer */
254104476Ssam				m = m_getptr(m, k + blks, &k);
255104476Ssam				if (m == NULL)
256104476Ssam					return EINVAL;
257104476Ssam
258104476Ssam				i -= blks;
259104476Ssam
260104476Ssam				/* Could be done... */
261104476Ssam				if (i == 0)
262104476Ssam					break;
263104476Ssam			}
264104476Ssam
265104476Ssam			/* Skip possibly empty mbufs */
266104476Ssam			if (k == m->m_len) {
267104476Ssam				for (m = m->m_next; m && m->m_len == 0;
268104476Ssam				    m = m->m_next)
269104476Ssam					;
270104476Ssam				k = 0;
271104476Ssam			}
272104476Ssam
273104476Ssam			/* Sanity check */
274104476Ssam			if (m == NULL)
275104476Ssam				return EINVAL;
276104476Ssam
277104476Ssam			/*
278104476Ssam			 * Warning: idat may point to garbage here, but
279104476Ssam			 * we only use it in the while() loop, only if
280104476Ssam			 * there are indeed enough data.
281104476Ssam			 */
282104476Ssam			idat = mtod(m, unsigned char *) + k;
283104476Ssam
284104476Ssam	   		while (m->m_len >= k + blks && i > 0) {
285104476Ssam				if (crd->crd_flags & CRD_F_ENCRYPT) {
286104476Ssam					/* XOR with previous block/IV */
287104476Ssam					for (j = 0; j < blks; j++)
288104476Ssam						idat[j] ^= ivp[j];
289104476Ssam
290104476Ssam					exf->encrypt(sw->sw_kschedule, idat);
291104476Ssam					ivp = idat;
292104476Ssam				} else {	/* decrypt */
293104476Ssam					/*
294104476Ssam					 * Keep encrypted block to be used
295104476Ssam					 * in next block's processing.
296104476Ssam					 */
297104476Ssam					if (ivp == iv)
298104476Ssam						bcopy(idat, piv, blks);
299104476Ssam					else
300104476Ssam						bcopy(idat, iv, blks);
301104476Ssam
302104476Ssam					exf->decrypt(sw->sw_kschedule, idat);
303104476Ssam
304104476Ssam					/* XOR with previous block/IV */
305104476Ssam					for (j = 0; j < blks; j++)
306104476Ssam						idat[j] ^= ivp[j];
307104476Ssam
308104476Ssam					if (ivp == iv)
309104476Ssam						bcopy(piv, iv, blks);
310104476Ssam					else
311104476Ssam						ivp = iv;
312104476Ssam				}
313104476Ssam
314104476Ssam				idat += blks;
315104476Ssam				k += blks;
316104476Ssam				i -= blks;
317104476Ssam			}
318104476Ssam		}
319104476Ssam
320104476Ssam		return 0; /* Done with mbuf encryption/decryption */
321104476Ssam	} else if (outtype == CRYPTO_BUF_IOV) {
322104476Ssam		struct uio *uio = (struct uio *) buf;
323104476Ssam		struct iovec *iov;
324104476Ssam
325104476Ssam		/* Find beginning of data */
326104476Ssam		iov = cuio_getptr(uio, crd->crd_skip, &k);
327104476Ssam		if (iov == NULL)
328104476Ssam			return EINVAL;
329104476Ssam
330104476Ssam		i = crd->crd_len;
331104476Ssam
332104476Ssam		while (i > 0) {
333104476Ssam			/*
334104476Ssam			 * If there's insufficient data at the end of
335104476Ssam			 * an iovec, we have to do some copying.
336104476Ssam			 */
337104476Ssam			if (iov->iov_len < k + blks && iov->iov_len != k) {
338104476Ssam				cuio_copydata(uio, k, blks, blk);
339104476Ssam
340104476Ssam				/* Actual encryption/decryption */
341104476Ssam				if (crd->crd_flags & CRD_F_ENCRYPT) {
342104476Ssam					/* XOR with previous block */
343104476Ssam					for (j = 0; j < blks; j++)
344104476Ssam						blk[j] ^= ivp[j];
345104476Ssam
346104476Ssam					exf->encrypt(sw->sw_kschedule, blk);
347104476Ssam
348104476Ssam					/*
349104476Ssam					 * Keep encrypted block for XOR'ing
350104476Ssam					 * with next block
351104476Ssam					 */
352104476Ssam					bcopy(blk, iv, blks);
353104476Ssam					ivp = iv;
354104476Ssam				} else {	/* decrypt */
355104476Ssam					/*
356104476Ssam					 * Keep encrypted block for XOR'ing
357104476Ssam					 * with next block
358104476Ssam					 */
359104476Ssam					if (ivp == iv)
360104476Ssam						bcopy(blk, piv, blks);
361104476Ssam					else
362104476Ssam						bcopy(blk, iv, blks);
363104476Ssam
364104476Ssam					exf->decrypt(sw->sw_kschedule, blk);
365104476Ssam
366104476Ssam					/* XOR with previous block */
367104476Ssam					for (j = 0; j < blks; j++)
368104476Ssam						blk[j] ^= ivp[j];
369104476Ssam
370104476Ssam					if (ivp == iv)
371104476Ssam						bcopy(piv, iv, blks);
372104476Ssam					else
373104476Ssam						ivp = iv;
374104476Ssam				}
375104476Ssam
376104476Ssam				/* Copy back decrypted block */
377104476Ssam				cuio_copyback(uio, k, blks, blk);
378104476Ssam
379104476Ssam				/* Advance pointer */
380104476Ssam				iov = cuio_getptr(uio, k + blks, &k);
381104476Ssam				if (iov == NULL)
382104476Ssam					return EINVAL;
383104476Ssam
384104476Ssam				i -= blks;
385104476Ssam
386104476Ssam				/* Could be done... */
387104476Ssam				if (i == 0)
388104476Ssam					break;
389104476Ssam			}
390104476Ssam
391104476Ssam			/*
392104476Ssam			 * Warning: idat may point to garbage here, but
393104476Ssam			 * we only use it in the while() loop, only if
394104476Ssam			 * there are indeed enough data.
395104476Ssam			 */
396104908Smike			idat = (char *)iov->iov_base + k;
397104476Ssam
398104476Ssam	   		while (iov->iov_len >= k + blks && i > 0) {
399104476Ssam				if (crd->crd_flags & CRD_F_ENCRYPT) {
400104476Ssam					/* XOR with previous block/IV */
401104476Ssam					for (j = 0; j < blks; j++)
402104476Ssam						idat[j] ^= ivp[j];
403104476Ssam
404104476Ssam					exf->encrypt(sw->sw_kschedule, idat);
405104476Ssam					ivp = idat;
406104476Ssam				} else {	/* decrypt */
407104476Ssam					/*
408104476Ssam					 * Keep encrypted block to be used
409104476Ssam					 * in next block's processing.
410104476Ssam					 */
411104476Ssam					if (ivp == iv)
412104476Ssam						bcopy(idat, piv, blks);
413104476Ssam					else
414104476Ssam						bcopy(idat, iv, blks);
415104476Ssam
416104476Ssam					exf->decrypt(sw->sw_kschedule, idat);
417104476Ssam
418104476Ssam					/* XOR with previous block/IV */
419104476Ssam					for (j = 0; j < blks; j++)
420104476Ssam						idat[j] ^= ivp[j];
421104476Ssam
422104476Ssam					if (ivp == iv)
423104476Ssam						bcopy(piv, iv, blks);
424104476Ssam					else
425104476Ssam						ivp = iv;
426104476Ssam				}
427104476Ssam
428104476Ssam				idat += blks;
429104476Ssam				k += blks;
430104476Ssam				i -= blks;
431104476Ssam			}
432104476Ssam		}
433104476Ssam
434104476Ssam		return 0; /* Done with mbuf encryption/decryption */
435104476Ssam	}
436104476Ssam
437104476Ssam	/* Unreachable */
438104476Ssam	return EINVAL;
439104476Ssam}
440104476Ssam
441104476Ssam/*
442104476Ssam * Compute keyed-hash authenticator.
443104476Ssam */
444104476Ssamstatic int
445104476Ssamswcr_authcompute(struct cryptop *crp, struct cryptodesc *crd,
446104476Ssam    struct swcr_data *sw, caddr_t buf, int outtype)
447104476Ssam{
448104476Ssam	unsigned char aalg[AALG_MAX_RESULT_LEN];
449104476Ssam	struct auth_hash *axf;
450104476Ssam	union authctx ctx;
451104476Ssam	int err;
452104476Ssam
453104476Ssam	if (sw->sw_ictx == 0)
454104476Ssam		return EINVAL;
455104476Ssam
456104476Ssam	axf = sw->sw_axf;
457104476Ssam
458104476Ssam	bcopy(sw->sw_ictx, &ctx, axf->ctxsize);
459104476Ssam
460104476Ssam	switch (outtype) {
461104476Ssam	case CRYPTO_BUF_CONTIG:
462104476Ssam		axf->Update(&ctx, buf + crd->crd_skip, crd->crd_len);
463104476Ssam		break;
464104476Ssam	case CRYPTO_BUF_MBUF:
465104476Ssam		err = m_apply((struct mbuf *) buf, crd->crd_skip, crd->crd_len,
466123564Sbms		    (int (*)(void *, void *, unsigned int)) axf->Update,
467104476Ssam		    (caddr_t) &ctx);
468104476Ssam		if (err)
469104476Ssam			return err;
470104476Ssam		break;
471104476Ssam	case CRYPTO_BUF_IOV:
472104476Ssam	default:
473104476Ssam		return EINVAL;
474104476Ssam	}
475104476Ssam
476104476Ssam	switch (sw->sw_alg) {
477104476Ssam	case CRYPTO_MD5_HMAC:
478104476Ssam	case CRYPTO_SHA1_HMAC:
479104476Ssam	case CRYPTO_SHA2_HMAC:
480104476Ssam	case CRYPTO_RIPEMD160_HMAC:
481104476Ssam		if (sw->sw_octx == NULL)
482104476Ssam			return EINVAL;
483104476Ssam
484104476Ssam		axf->Final(aalg, &ctx);
485104476Ssam		bcopy(sw->sw_octx, &ctx, axf->ctxsize);
486104476Ssam		axf->Update(&ctx, aalg, axf->hashsize);
487104476Ssam		axf->Final(aalg, &ctx);
488104476Ssam		break;
489104476Ssam
490104476Ssam	case CRYPTO_MD5_KPDK:
491104476Ssam	case CRYPTO_SHA1_KPDK:
492104476Ssam		if (sw->sw_octx == NULL)
493104476Ssam			return EINVAL;
494104476Ssam
495104476Ssam		axf->Update(&ctx, sw->sw_octx, sw->sw_klen);
496104476Ssam		axf->Final(aalg, &ctx);
497104476Ssam		break;
498104476Ssam
499104476Ssam	case CRYPTO_NULL_HMAC:
500104476Ssam		axf->Final(aalg, &ctx);
501104476Ssam		break;
502104476Ssam	}
503104476Ssam
504104476Ssam	/* Inject the authentication data */
505104476Ssam	if (outtype == CRYPTO_BUF_CONTIG)
506104476Ssam		bcopy(aalg, buf + crd->crd_inject, axf->authsize);
507104476Ssam	else
508104476Ssam		m_copyback((struct mbuf *) buf, crd->crd_inject,
509104476Ssam		    axf->authsize, aalg);
510104476Ssam	return 0;
511104476Ssam}
512104476Ssam
513104476Ssam/*
514104476Ssam * Apply a compression/decompression algorithm
515104476Ssam */
516104476Ssamstatic int
517104476Ssamswcr_compdec(struct cryptodesc *crd, struct swcr_data *sw,
518104476Ssam    caddr_t buf, int outtype)
519104476Ssam{
520104476Ssam	u_int8_t *data, *out;
521104476Ssam	struct comp_algo *cxf;
522104476Ssam	int adj;
523104476Ssam	u_int32_t result;
524104476Ssam
525104476Ssam	cxf = sw->sw_cxf;
526104476Ssam
527104476Ssam	/* We must handle the whole buffer of data in one time
528104476Ssam	 * then if there is not all the data in the mbuf, we must
529104476Ssam	 * copy in a buffer.
530104476Ssam	 */
531104476Ssam
532104476Ssam	MALLOC(data, u_int8_t *, crd->crd_len, M_CRYPTO_DATA,  M_NOWAIT);
533104476Ssam	if (data == NULL)
534104476Ssam		return (EINVAL);
535104476Ssam	COPYDATA(outtype, buf, crd->crd_skip, crd->crd_len, data);
536104476Ssam
537104476Ssam	if (crd->crd_flags & CRD_F_COMP)
538104476Ssam		result = cxf->compress(data, crd->crd_len, &out);
539104476Ssam	else
540104476Ssam		result = cxf->decompress(data, crd->crd_len, &out);
541104476Ssam
542104476Ssam	FREE(data, M_CRYPTO_DATA);
543104476Ssam	if (result == 0)
544104476Ssam		return EINVAL;
545104476Ssam
546104476Ssam	/* Copy back the (de)compressed data. m_copyback is
547104476Ssam	 * extending the mbuf as necessary.
548104476Ssam	 */
549104476Ssam	sw->sw_size = result;
550104476Ssam	/* Check the compressed size when doing compression */
551104476Ssam	if (crd->crd_flags & CRD_F_COMP) {
552104476Ssam		if (result > crd->crd_len) {
553104476Ssam			/* Compression was useless, we lost time */
554104476Ssam			FREE(out, M_CRYPTO_DATA);
555104476Ssam			return 0;
556104476Ssam		}
557104476Ssam	}
558104476Ssam
559104476Ssam	COPYBACK(outtype, buf, crd->crd_skip, result, out);
560104476Ssam	if (result < crd->crd_len) {
561104476Ssam		adj = result - crd->crd_len;
562104476Ssam		if (outtype == CRYPTO_BUF_MBUF) {
563104476Ssam			adj = result - crd->crd_len;
564104476Ssam			m_adj((struct mbuf *)buf, adj);
565104476Ssam		} else {
566104476Ssam			struct uio *uio = (struct uio *)buf;
567104476Ssam			int ind;
568104476Ssam
569104476Ssam			adj = crd->crd_len - result;
570104476Ssam			ind = uio->uio_iovcnt - 1;
571104476Ssam
572104476Ssam			while (adj > 0 && ind >= 0) {
573104476Ssam				if (adj < uio->uio_iov[ind].iov_len) {
574104476Ssam					uio->uio_iov[ind].iov_len -= adj;
575104476Ssam					break;
576104476Ssam				}
577104476Ssam
578104476Ssam				adj -= uio->uio_iov[ind].iov_len;
579104476Ssam				uio->uio_iov[ind].iov_len = 0;
580104476Ssam				ind--;
581104476Ssam				uio->uio_iovcnt--;
582104476Ssam			}
583104476Ssam		}
584104476Ssam	}
585104476Ssam	FREE(out, M_CRYPTO_DATA);
586104476Ssam	return 0;
587104476Ssam}
588104476Ssam
589104476Ssam/*
590104476Ssam * Generate a new software session.
591104476Ssam */
592104476Ssamstatic int
593104476Ssamswcr_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
594104476Ssam{
595104476Ssam	struct swcr_data **swd;
596104476Ssam	struct auth_hash *axf;
597104476Ssam	struct enc_xform *txf;
598104476Ssam	struct comp_algo *cxf;
599104476Ssam	u_int32_t i;
600104476Ssam	int k, error;
601104476Ssam
602104476Ssam	if (sid == NULL || cri == NULL)
603104476Ssam		return EINVAL;
604104476Ssam
605104476Ssam	if (swcr_sessions) {
606104476Ssam		for (i = 1; i < swcr_sesnum; i++)
607104476Ssam			if (swcr_sessions[i] == NULL)
608104476Ssam				break;
609104476Ssam	} else
610104476Ssam		i = 1;		/* NB: to silence compiler warning */
611104476Ssam
612104476Ssam	if (swcr_sessions == NULL || i == swcr_sesnum) {
613104476Ssam		if (swcr_sessions == NULL) {
614104476Ssam			i = 1; /* We leave swcr_sessions[0] empty */
615104476Ssam			swcr_sesnum = CRYPTO_SW_SESSIONS;
616104476Ssam		} else
617104476Ssam			swcr_sesnum *= 2;
618104476Ssam
619104476Ssam		swd = malloc(swcr_sesnum * sizeof(struct swcr_data *),
620104476Ssam		    M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
621104476Ssam		if (swd == NULL) {
622104476Ssam			/* Reset session number */
623104476Ssam			if (swcr_sesnum == CRYPTO_SW_SESSIONS)
624104476Ssam				swcr_sesnum = 0;
625104476Ssam			else
626104476Ssam				swcr_sesnum /= 2;
627104476Ssam			return ENOBUFS;
628104476Ssam		}
629104476Ssam
630104476Ssam		/* Copy existing sessions */
631104476Ssam		if (swcr_sessions) {
632104476Ssam			bcopy(swcr_sessions, swd,
633104476Ssam			    (swcr_sesnum / 2) * sizeof(struct swcr_data *));
634104476Ssam			free(swcr_sessions, M_CRYPTO_DATA);
635104476Ssam		}
636104476Ssam
637104476Ssam		swcr_sessions = swd;
638104476Ssam	}
639104476Ssam
640104476Ssam	swd = &swcr_sessions[i];
641104476Ssam	*sid = i;
642104476Ssam
643104476Ssam	while (cri) {
644104476Ssam		MALLOC(*swd, struct swcr_data *, sizeof(struct swcr_data),
645104476Ssam		    M_CRYPTO_DATA, M_NOWAIT|M_ZERO);
646104476Ssam		if (*swd == NULL) {
647104476Ssam			swcr_freesession(NULL, i);
648104476Ssam			return ENOBUFS;
649104476Ssam		}
650104476Ssam
651104476Ssam		switch (cri->cri_alg) {
652104476Ssam		case CRYPTO_DES_CBC:
653104476Ssam			txf = &enc_xform_des;
654104476Ssam			goto enccommon;
655104476Ssam		case CRYPTO_3DES_CBC:
656104476Ssam			txf = &enc_xform_3des;
657104476Ssam			goto enccommon;
658104476Ssam		case CRYPTO_BLF_CBC:
659104476Ssam			txf = &enc_xform_blf;
660104476Ssam			goto enccommon;
661104476Ssam		case CRYPTO_CAST_CBC:
662104476Ssam			txf = &enc_xform_cast5;
663104476Ssam			goto enccommon;
664104476Ssam		case CRYPTO_SKIPJACK_CBC:
665104476Ssam			txf = &enc_xform_skipjack;
666104476Ssam			goto enccommon;
667104476Ssam		case CRYPTO_RIJNDAEL128_CBC:
668104476Ssam			txf = &enc_xform_rijndael128;
669104476Ssam			goto enccommon;
670104476Ssam		case CRYPTO_NULL_CBC:
671104476Ssam			txf = &enc_xform_null;
672104476Ssam			goto enccommon;
673104476Ssam		enccommon:
674104476Ssam			error = txf->setkey(&((*swd)->sw_kschedule),
675104476Ssam					cri->cri_key, cri->cri_klen / 8);
676104476Ssam			if (error) {
677104476Ssam				swcr_freesession(NULL, i);
678104476Ssam				return error;
679104476Ssam			}
680104476Ssam			(*swd)->sw_exf = txf;
681104476Ssam			break;
682104476Ssam
683104476Ssam		case CRYPTO_MD5_HMAC:
684104476Ssam			axf = &auth_hash_hmac_md5_96;
685104476Ssam			goto authcommon;
686104476Ssam		case CRYPTO_SHA1_HMAC:
687104476Ssam			axf = &auth_hash_hmac_sha1_96;
688104476Ssam			goto authcommon;
689104476Ssam		case CRYPTO_SHA2_HMAC:
690104476Ssam			if (cri->cri_klen == 256)
691104476Ssam				axf = &auth_hash_hmac_sha2_256;
692104476Ssam			else if (cri->cri_klen == 384)
693104476Ssam				axf = &auth_hash_hmac_sha2_384;
694104476Ssam			else if (cri->cri_klen == 512)
695104476Ssam				axf = &auth_hash_hmac_sha2_512;
696104476Ssam			else {
697104476Ssam				swcr_freesession(NULL, i);
698104476Ssam				return EINVAL;
699104476Ssam			}
700104476Ssam			goto authcommon;
701104476Ssam		case CRYPTO_NULL_HMAC:
702104476Ssam			axf = &auth_hash_null;
703104476Ssam			goto authcommon;
704104476Ssam		case CRYPTO_RIPEMD160_HMAC:
705104476Ssam			axf = &auth_hash_hmac_ripemd_160_96;
706104476Ssam		authcommon:
707104476Ssam			(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
708104476Ssam			    M_NOWAIT);
709104476Ssam			if ((*swd)->sw_ictx == NULL) {
710104476Ssam				swcr_freesession(NULL, i);
711104476Ssam				return ENOBUFS;
712104476Ssam			}
713104476Ssam
714104476Ssam			(*swd)->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA,
715104476Ssam			    M_NOWAIT);
716104476Ssam			if ((*swd)->sw_octx == NULL) {
717104476Ssam				swcr_freesession(NULL, i);
718104476Ssam				return ENOBUFS;
719104476Ssam			}
720104476Ssam
721104476Ssam			for (k = 0; k < cri->cri_klen / 8; k++)
722104476Ssam				cri->cri_key[k] ^= HMAC_IPAD_VAL;
723104476Ssam
724104476Ssam			axf->Init((*swd)->sw_ictx);
725104476Ssam			axf->Update((*swd)->sw_ictx, cri->cri_key,
726104476Ssam			    cri->cri_klen / 8);
727104476Ssam			axf->Update((*swd)->sw_ictx, hmac_ipad_buffer,
728104476Ssam			    HMAC_BLOCK_LEN - (cri->cri_klen / 8));
729104476Ssam
730104476Ssam			for (k = 0; k < cri->cri_klen / 8; k++)
731104476Ssam				cri->cri_key[k] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
732104476Ssam
733104476Ssam			axf->Init((*swd)->sw_octx);
734104476Ssam			axf->Update((*swd)->sw_octx, cri->cri_key,
735104476Ssam			    cri->cri_klen / 8);
736104476Ssam			axf->Update((*swd)->sw_octx, hmac_opad_buffer,
737104476Ssam			    HMAC_BLOCK_LEN - (cri->cri_klen / 8));
738104476Ssam
739104476Ssam			for (k = 0; k < cri->cri_klen / 8; k++)
740104476Ssam				cri->cri_key[k] ^= HMAC_OPAD_VAL;
741104476Ssam			(*swd)->sw_axf = axf;
742104476Ssam			break;
743104476Ssam
744104476Ssam		case CRYPTO_MD5_KPDK:
745104476Ssam			axf = &auth_hash_key_md5;
746104476Ssam			goto auth2common;
747104476Ssam
748104476Ssam		case CRYPTO_SHA1_KPDK:
749104476Ssam			axf = &auth_hash_key_sha1;
750104476Ssam		auth2common:
751104476Ssam			(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
752104476Ssam			    M_NOWAIT);
753104476Ssam			if ((*swd)->sw_ictx == NULL) {
754104476Ssam				swcr_freesession(NULL, i);
755104476Ssam				return ENOBUFS;
756104476Ssam			}
757104476Ssam
758104476Ssam			/* Store the key so we can "append" it to the payload */
759104476Ssam			(*swd)->sw_octx = malloc(cri->cri_klen / 8, M_CRYPTO_DATA,
760104476Ssam			    M_NOWAIT);
761104476Ssam			if ((*swd)->sw_octx == NULL) {
762104476Ssam				swcr_freesession(NULL, i);
763104476Ssam				return ENOBUFS;
764104476Ssam			}
765104476Ssam
766104476Ssam			(*swd)->sw_klen = cri->cri_klen / 8;
767104476Ssam			bcopy(cri->cri_key, (*swd)->sw_octx, cri->cri_klen / 8);
768104476Ssam			axf->Init((*swd)->sw_ictx);
769104476Ssam			axf->Update((*swd)->sw_ictx, cri->cri_key,
770104476Ssam			    cri->cri_klen / 8);
771104476Ssam			axf->Final(NULL, (*swd)->sw_ictx);
772104476Ssam			(*swd)->sw_axf = axf;
773104476Ssam			break;
774104476Ssam#ifdef notdef
775104476Ssam		case CRYPTO_MD5:
776104476Ssam			axf = &auth_hash_md5;
777104476Ssam			goto auth3common;
778104476Ssam
779104476Ssam		case CRYPTO_SHA1:
780104476Ssam			axf = &auth_hash_sha1;
781104476Ssam		auth3common:
782104476Ssam			(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
783104476Ssam			    M_NOWAIT);
784104476Ssam			if ((*swd)->sw_ictx == NULL) {
785104476Ssam				swcr_freesession(NULL, i);
786104476Ssam				return ENOBUFS;
787104476Ssam			}
788104476Ssam
789104476Ssam			axf->Init((*swd)->sw_ictx);
790104476Ssam			(*swd)->sw_axf = axf;
791104476Ssam			break;
792104476Ssam#endif
793104476Ssam		case CRYPTO_DEFLATE_COMP:
794104476Ssam			cxf = &comp_algo_deflate;
795104476Ssam			(*swd)->sw_cxf = cxf;
796104476Ssam			break;
797104476Ssam		default:
798104476Ssam			swcr_freesession(NULL, i);
799104476Ssam			return EINVAL;
800104476Ssam		}
801104476Ssam
802104476Ssam		(*swd)->sw_alg = cri->cri_alg;
803104476Ssam		cri = cri->cri_next;
804104476Ssam		swd = &((*swd)->sw_next);
805104476Ssam	}
806104476Ssam	return 0;
807104476Ssam}
808104476Ssam
809104476Ssam/*
810104476Ssam * Free a session.
811104476Ssam */
812104476Ssamstatic int
813104476Ssamswcr_freesession(void *arg, u_int64_t tid)
814104476Ssam{
815104476Ssam	struct swcr_data *swd;
816104476Ssam	struct enc_xform *txf;
817104476Ssam	struct auth_hash *axf;
818104476Ssam	struct comp_algo *cxf;
819116924Ssam	u_int32_t sid = CRYPTO_SESID2LID(tid);
820104476Ssam
821104476Ssam	if (sid > swcr_sesnum || swcr_sessions == NULL ||
822104476Ssam	    swcr_sessions[sid] == NULL)
823104476Ssam		return EINVAL;
824104476Ssam
825104476Ssam	/* Silently accept and return */
826104476Ssam	if (sid == 0)
827104476Ssam		return 0;
828104476Ssam
829104476Ssam	while ((swd = swcr_sessions[sid]) != NULL) {
830104476Ssam		swcr_sessions[sid] = swd->sw_next;
831104476Ssam
832104476Ssam		switch (swd->sw_alg) {
833104476Ssam		case CRYPTO_DES_CBC:
834104476Ssam		case CRYPTO_3DES_CBC:
835104476Ssam		case CRYPTO_BLF_CBC:
836104476Ssam		case CRYPTO_CAST_CBC:
837104476Ssam		case CRYPTO_SKIPJACK_CBC:
838104476Ssam		case CRYPTO_RIJNDAEL128_CBC:
839104476Ssam		case CRYPTO_NULL_CBC:
840104476Ssam			txf = swd->sw_exf;
841104476Ssam
842104476Ssam			if (swd->sw_kschedule)
843104476Ssam				txf->zerokey(&(swd->sw_kschedule));
844104476Ssam			break;
845104476Ssam
846104476Ssam		case CRYPTO_MD5_HMAC:
847104476Ssam		case CRYPTO_SHA1_HMAC:
848104476Ssam		case CRYPTO_SHA2_HMAC:
849104476Ssam		case CRYPTO_RIPEMD160_HMAC:
850104476Ssam		case CRYPTO_NULL_HMAC:
851104476Ssam			axf = swd->sw_axf;
852104476Ssam
853104476Ssam			if (swd->sw_ictx) {
854104476Ssam				bzero(swd->sw_ictx, axf->ctxsize);
855104476Ssam				free(swd->sw_ictx, M_CRYPTO_DATA);
856104476Ssam			}
857104476Ssam			if (swd->sw_octx) {
858104476Ssam				bzero(swd->sw_octx, axf->ctxsize);
859104476Ssam				free(swd->sw_octx, M_CRYPTO_DATA);
860104476Ssam			}
861104476Ssam			break;
862104476Ssam
863104476Ssam		case CRYPTO_MD5_KPDK:
864104476Ssam		case CRYPTO_SHA1_KPDK:
865104476Ssam			axf = swd->sw_axf;
866104476Ssam
867104476Ssam			if (swd->sw_ictx) {
868104476Ssam				bzero(swd->sw_ictx, axf->ctxsize);
869104476Ssam				free(swd->sw_ictx, M_CRYPTO_DATA);
870104476Ssam			}
871104476Ssam			if (swd->sw_octx) {
872104476Ssam				bzero(swd->sw_octx, swd->sw_klen);
873104476Ssam				free(swd->sw_octx, M_CRYPTO_DATA);
874104476Ssam			}
875104476Ssam			break;
876104476Ssam
877104476Ssam		case CRYPTO_MD5:
878104476Ssam		case CRYPTO_SHA1:
879104476Ssam			axf = swd->sw_axf;
880104476Ssam
881104476Ssam			if (swd->sw_ictx)
882104476Ssam				free(swd->sw_ictx, M_CRYPTO_DATA);
883104476Ssam			break;
884104476Ssam
885104476Ssam		case CRYPTO_DEFLATE_COMP:
886104476Ssam			cxf = swd->sw_cxf;
887104476Ssam			break;
888104476Ssam		}
889104476Ssam
890104476Ssam		FREE(swd, M_CRYPTO_DATA);
891104476Ssam	}
892104476Ssam	return 0;
893104476Ssam}
894104476Ssam
895104476Ssam/*
896104476Ssam * Process a software request.
897104476Ssam */
898104476Ssamstatic int
899104476Ssamswcr_process(void *arg, struct cryptop *crp, int hint)
900104476Ssam{
901104476Ssam	struct cryptodesc *crd;
902104476Ssam	struct swcr_data *sw;
903104476Ssam	u_int32_t lid;
904104476Ssam	int type;
905104476Ssam
906104476Ssam	/* Sanity check */
907104476Ssam	if (crp == NULL)
908104476Ssam		return EINVAL;
909104476Ssam
910104476Ssam	if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
911104476Ssam		crp->crp_etype = EINVAL;
912104476Ssam		goto done;
913104476Ssam	}
914104476Ssam
915104476Ssam	lid = crp->crp_sid & 0xffffffff;
916104476Ssam	if (lid >= swcr_sesnum || lid == 0 || swcr_sessions[lid] == NULL) {
917104476Ssam		crp->crp_etype = ENOENT;
918104476Ssam		goto done;
919104476Ssam	}
920104476Ssam
921104476Ssam	if (crp->crp_flags & CRYPTO_F_IMBUF) {
922104476Ssam		type = CRYPTO_BUF_MBUF;
923104476Ssam	} else if (crp->crp_flags & CRYPTO_F_IOV) {
924104476Ssam		type = CRYPTO_BUF_IOV;
925104476Ssam	} else {
926104476Ssam		type = CRYPTO_BUF_CONTIG;
927104476Ssam	}
928104476Ssam
929104476Ssam	/* Go through crypto descriptors, processing as we go */
930104476Ssam	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
931104476Ssam		/*
932104476Ssam		 * Find the crypto context.
933104476Ssam		 *
934104476Ssam		 * XXX Note that the logic here prevents us from having
935104476Ssam		 * XXX the same algorithm multiple times in a session
936104476Ssam		 * XXX (or rather, we can but it won't give us the right
937104476Ssam		 * XXX results). To do that, we'd need some way of differentiating
938104476Ssam		 * XXX between the various instances of an algorithm (so we can
939104476Ssam		 * XXX locate the correct crypto context).
940104476Ssam		 */
941104476Ssam		for (sw = swcr_sessions[lid];
942104476Ssam		    sw && sw->sw_alg != crd->crd_alg;
943104476Ssam		    sw = sw->sw_next)
944104476Ssam			;
945104476Ssam
946104476Ssam		/* No such context ? */
947104476Ssam		if (sw == NULL) {
948104476Ssam			crp->crp_etype = EINVAL;
949104476Ssam			goto done;
950104476Ssam		}
951104476Ssam		switch (sw->sw_alg) {
952104476Ssam		case CRYPTO_DES_CBC:
953104476Ssam		case CRYPTO_3DES_CBC:
954104476Ssam		case CRYPTO_BLF_CBC:
955104476Ssam		case CRYPTO_CAST_CBC:
956104476Ssam		case CRYPTO_SKIPJACK_CBC:
957104476Ssam		case CRYPTO_RIJNDAEL128_CBC:
958104476Ssam			if ((crp->crp_etype = swcr_encdec(crd, sw,
959104476Ssam			    crp->crp_buf, type)) != 0)
960104476Ssam				goto done;
961104476Ssam			break;
962104476Ssam		case CRYPTO_NULL_CBC:
963104476Ssam			crp->crp_etype = 0;
964104476Ssam			break;
965104476Ssam		case CRYPTO_MD5_HMAC:
966104476Ssam		case CRYPTO_SHA1_HMAC:
967104476Ssam		case CRYPTO_SHA2_HMAC:
968104476Ssam		case CRYPTO_RIPEMD160_HMAC:
969104476Ssam		case CRYPTO_NULL_HMAC:
970104476Ssam		case CRYPTO_MD5_KPDK:
971104476Ssam		case CRYPTO_SHA1_KPDK:
972104476Ssam		case CRYPTO_MD5:
973104476Ssam		case CRYPTO_SHA1:
974104476Ssam			if ((crp->crp_etype = swcr_authcompute(crp, crd, sw,
975104476Ssam			    crp->crp_buf, type)) != 0)
976104476Ssam				goto done;
977104476Ssam			break;
978104476Ssam
979104476Ssam		case CRYPTO_DEFLATE_COMP:
980104476Ssam			if ((crp->crp_etype = swcr_compdec(crd, sw,
981104476Ssam			    crp->crp_buf, type)) != 0)
982104476Ssam				goto done;
983104476Ssam			else
984104476Ssam				crp->crp_olen = (int)sw->sw_size;
985104476Ssam			break;
986104476Ssam
987104476Ssam		default:
988104476Ssam			/* Unknown/unsupported algorithm */
989104476Ssam			crp->crp_etype = EINVAL;
990104476Ssam			goto done;
991104476Ssam		}
992104476Ssam	}
993104476Ssam
994104476Ssamdone:
995104476Ssam	crypto_done(crp);
996104476Ssam	return 0;
997104476Ssam}
998104476Ssam
999104476Ssam/*
1000104476Ssam * Initialize the driver, called from the kernel main().
1001104476Ssam */
1002104476Ssamstatic void
1003104476Ssamswcr_init(void)
1004104476Ssam{
1005116924Ssam	swcr_id = crypto_get_driverid(CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC);
1006104476Ssam	if (swcr_id < 0)
1007104476Ssam		panic("Software crypto device cannot initialize!");
1008104476Ssam	crypto_register(swcr_id, CRYPTO_DES_CBC,
1009104476Ssam	    0, 0, swcr_newsession, swcr_freesession, swcr_process, NULL);
1010104476Ssam#define	REGISTER(alg) \
1011104476Ssam	crypto_register(swcr_id, alg, 0,0,NULL,NULL,NULL,NULL)
1012104476Ssam	REGISTER(CRYPTO_3DES_CBC);
1013104476Ssam	REGISTER(CRYPTO_BLF_CBC);
1014104476Ssam	REGISTER(CRYPTO_CAST_CBC);
1015104476Ssam	REGISTER(CRYPTO_SKIPJACK_CBC);
1016104476Ssam	REGISTER(CRYPTO_NULL_CBC);
1017104476Ssam	REGISTER(CRYPTO_MD5_HMAC);
1018104476Ssam	REGISTER(CRYPTO_SHA1_HMAC);
1019104476Ssam	REGISTER(CRYPTO_SHA2_HMAC);
1020104476Ssam	REGISTER(CRYPTO_RIPEMD160_HMAC);
1021104476Ssam	REGISTER(CRYPTO_NULL_HMAC);
1022104476Ssam	REGISTER(CRYPTO_MD5_KPDK);
1023104476Ssam	REGISTER(CRYPTO_SHA1_KPDK);
1024104476Ssam	REGISTER(CRYPTO_MD5);
1025104476Ssam	REGISTER(CRYPTO_SHA1);
1026104476Ssam	REGISTER(CRYPTO_RIJNDAEL128_CBC);
1027104476Ssam	REGISTER(CRYPTO_DEFLATE_COMP);
1028104476Ssam#undef REGISTER
1029104476Ssam}
1030104476SsamSYSINIT(cryptosoft_init, SI_SUB_PSEUDO, SI_ORDER_ANY, swcr_init, NULL)
1031