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