cryptosoft.c revision 1.16.2.2 1 1.16.2.2 rmind /* $NetBSD: cryptosoft.c,v 1.16.2.2 2007/03/12 06:00:50 rmind Exp $ */
2 1.16.2.2 rmind /* $FreeBSD: src/sys/opencrypto/cryptosoft.c,v 1.2.2.1 2002/11/21 23:34:23 sam Exp $ */
3 1.16.2.2 rmind /* $OpenBSD: cryptosoft.c,v 1.35 2002/04/26 08:43:50 deraadt Exp $ */
4 1.16.2.2 rmind
5 1.16.2.2 rmind /*
6 1.16.2.2 rmind * The author of this code is Angelos D. Keromytis (angelos (at) cis.upenn.edu)
7 1.16.2.2 rmind *
8 1.16.2.2 rmind * This code was written by Angelos D. Keromytis in Athens, Greece, in
9 1.16.2.2 rmind * February 2000. Network Security Technologies Inc. (NSTI) kindly
10 1.16.2.2 rmind * supported the development of this code.
11 1.16.2.2 rmind *
12 1.16.2.2 rmind * Copyright (c) 2000, 2001 Angelos D. Keromytis
13 1.16.2.2 rmind *
14 1.16.2.2 rmind * Permission to use, copy, and modify this software with or without fee
15 1.16.2.2 rmind * is hereby granted, provided that this entire notice is included in
16 1.16.2.2 rmind * all source code copies of any software which is or includes a copy or
17 1.16.2.2 rmind * modification of this software.
18 1.16.2.2 rmind *
19 1.16.2.2 rmind * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
20 1.16.2.2 rmind * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
21 1.16.2.2 rmind * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
22 1.16.2.2 rmind * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
23 1.16.2.2 rmind * PURPOSE.
24 1.16.2.2 rmind */
25 1.16.2.2 rmind
26 1.16.2.2 rmind #include <sys/cdefs.h>
27 1.16.2.2 rmind __KERNEL_RCSID(0, "$NetBSD: cryptosoft.c,v 1.16.2.2 2007/03/12 06:00:50 rmind Exp $");
28 1.16.2.2 rmind
29 1.16.2.2 rmind #include <sys/param.h>
30 1.16.2.2 rmind #include <sys/systm.h>
31 1.16.2.2 rmind #include <sys/malloc.h>
32 1.16.2.2 rmind #include <sys/mbuf.h>
33 1.16.2.2 rmind #include <sys/sysctl.h>
34 1.16.2.2 rmind #include <sys/errno.h>
35 1.16.2.2 rmind
36 1.16.2.2 rmind #include <opencrypto/cryptodev.h>
37 1.16.2.2 rmind #include <opencrypto/cryptosoft.h>
38 1.16.2.2 rmind #include <opencrypto/xform.h>
39 1.16.2.2 rmind
40 1.16.2.2 rmind #include <opencrypto/cryptosoft_xform.c>
41 1.16.2.2 rmind
42 1.16.2.2 rmind union authctx {
43 1.16.2.2 rmind MD5_CTX md5ctx;
44 1.16.2.2 rmind SHA1_CTX sha1ctx;
45 1.16.2.2 rmind RMD160_CTX rmd160ctx;
46 1.16.2.2 rmind SHA256_CTX sha256ctx;
47 1.16.2.2 rmind SHA384_CTX sha384ctx;
48 1.16.2.2 rmind SHA512_CTX sha512ctx;
49 1.16.2.2 rmind };
50 1.16.2.2 rmind
51 1.16.2.2 rmind struct swcr_data **swcr_sessions = NULL;
52 1.16.2.2 rmind u_int32_t swcr_sesnum = 0;
53 1.16.2.2 rmind int32_t swcr_id = -1;
54 1.16.2.2 rmind
55 1.16.2.2 rmind #define COPYBACK(x, a, b, c, d) \
56 1.16.2.2 rmind (x) == CRYPTO_BUF_MBUF ? m_copyback((struct mbuf *)a,b,c,d) \
57 1.16.2.2 rmind : cuio_copyback((struct uio *)a,b,c,d)
58 1.16.2.2 rmind #define COPYDATA(x, a, b, c, d) \
59 1.16.2.2 rmind (x) == CRYPTO_BUF_MBUF ? m_copydata((struct mbuf *)a,b,c,d) \
60 1.16.2.2 rmind : cuio_copydata((struct uio *)a,b,c,d)
61 1.16.2.2 rmind
62 1.16.2.2 rmind static int swcr_encdec(struct cryptodesc *, struct swcr_data *, void *, int);
63 1.16.2.2 rmind static int swcr_compdec(struct cryptodesc *, struct swcr_data *, void *, int);
64 1.16.2.2 rmind static int swcr_process(void *, struct cryptop *, int);
65 1.16.2.2 rmind static int swcr_newsession(void *, u_int32_t *, struct cryptoini *);
66 1.16.2.2 rmind static int swcr_freesession(void *, u_int64_t);
67 1.16.2.2 rmind
68 1.16.2.2 rmind /*
69 1.16.2.2 rmind * Apply a symmetric encryption/decryption algorithm.
70 1.16.2.2 rmind */
71 1.16.2.2 rmind static int
72 1.16.2.2 rmind swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, void *bufv,
73 1.16.2.2 rmind int outtype)
74 1.16.2.2 rmind {
75 1.16.2.2 rmind char *buf = bufv;
76 1.16.2.2 rmind unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN], *idat;
77 1.16.2.2 rmind unsigned char *ivp, piv[EALG_MAX_BLOCK_LEN];
78 1.16.2.2 rmind const struct swcr_enc_xform *exf;
79 1.16.2.2 rmind int i, k, j, blks;
80 1.16.2.2 rmind int count, ind;
81 1.16.2.2 rmind
82 1.16.2.2 rmind exf = sw->sw_exf;
83 1.16.2.2 rmind blks = exf->enc_xform->blocksize;
84 1.16.2.2 rmind
85 1.16.2.2 rmind /* Check for non-padded data */
86 1.16.2.2 rmind if (crd->crd_len % blks)
87 1.16.2.2 rmind return EINVAL;
88 1.16.2.2 rmind
89 1.16.2.2 rmind /* Initialize the IV */
90 1.16.2.2 rmind if (crd->crd_flags & CRD_F_ENCRYPT) {
91 1.16.2.2 rmind /* IV explicitly provided ? */
92 1.16.2.2 rmind if (crd->crd_flags & CRD_F_IV_EXPLICIT)
93 1.16.2.2 rmind bcopy(crd->crd_iv, iv, blks);
94 1.16.2.2 rmind else {
95 1.16.2.2 rmind /* Get random IV */
96 1.16.2.2 rmind for (i = 0;
97 1.16.2.2 rmind i + sizeof (u_int32_t) < EALG_MAX_BLOCK_LEN;
98 1.16.2.2 rmind i += sizeof (u_int32_t)) {
99 1.16.2.2 rmind u_int32_t temp = arc4random();
100 1.16.2.2 rmind
101 1.16.2.2 rmind bcopy(&temp, iv + i, sizeof(u_int32_t));
102 1.16.2.2 rmind }
103 1.16.2.2 rmind /*
104 1.16.2.2 rmind * What if the block size is not a multiple
105 1.16.2.2 rmind * of sizeof (u_int32_t), which is the size of
106 1.16.2.2 rmind * what arc4random() returns ?
107 1.16.2.2 rmind */
108 1.16.2.2 rmind if (EALG_MAX_BLOCK_LEN % sizeof (u_int32_t) != 0) {
109 1.16.2.2 rmind u_int32_t temp = arc4random();
110 1.16.2.2 rmind
111 1.16.2.2 rmind bcopy (&temp, iv + i,
112 1.16.2.2 rmind EALG_MAX_BLOCK_LEN - i);
113 1.16.2.2 rmind }
114 1.16.2.2 rmind }
115 1.16.2.2 rmind
116 1.16.2.2 rmind /* Do we need to write the IV */
117 1.16.2.2 rmind if (!(crd->crd_flags & CRD_F_IV_PRESENT)) {
118 1.16.2.2 rmind COPYBACK(outtype, buf, crd->crd_inject, blks, iv);
119 1.16.2.2 rmind }
120 1.16.2.2 rmind
121 1.16.2.2 rmind } else { /* Decryption */
122 1.16.2.2 rmind /* IV explicitly provided ? */
123 1.16.2.2 rmind if (crd->crd_flags & CRD_F_IV_EXPLICIT)
124 1.16.2.2 rmind bcopy(crd->crd_iv, iv, blks);
125 1.16.2.2 rmind else {
126 1.16.2.2 rmind /* Get IV off buf */
127 1.16.2.2 rmind COPYDATA(outtype, buf, crd->crd_inject, blks, iv);
128 1.16.2.2 rmind }
129 1.16.2.2 rmind }
130 1.16.2.2 rmind
131 1.16.2.2 rmind ivp = iv;
132 1.16.2.2 rmind
133 1.16.2.2 rmind if (outtype == CRYPTO_BUF_CONTIG) {
134 1.16.2.2 rmind if (crd->crd_flags & CRD_F_ENCRYPT) {
135 1.16.2.2 rmind for (i = crd->crd_skip;
136 1.16.2.2 rmind i < crd->crd_skip + crd->crd_len; i += blks) {
137 1.16.2.2 rmind /* XOR with the IV/previous block, as appropriate. */
138 1.16.2.2 rmind if (i == crd->crd_skip)
139 1.16.2.2 rmind for (k = 0; k < blks; k++)
140 1.16.2.2 rmind buf[i + k] ^= ivp[k];
141 1.16.2.2 rmind else
142 1.16.2.2 rmind for (k = 0; k < blks; k++)
143 1.16.2.2 rmind buf[i + k] ^= buf[i + k - blks];
144 1.16.2.2 rmind exf->encrypt(sw->sw_kschedule, buf + i);
145 1.16.2.2 rmind }
146 1.16.2.2 rmind } else { /* Decrypt */
147 1.16.2.2 rmind /*
148 1.16.2.2 rmind * Start at the end, so we don't need to keep the encrypted
149 1.16.2.2 rmind * block as the IV for the next block.
150 1.16.2.2 rmind */
151 1.16.2.2 rmind for (i = crd->crd_skip + crd->crd_len - blks;
152 1.16.2.2 rmind i >= crd->crd_skip; i -= blks) {
153 1.16.2.2 rmind exf->decrypt(sw->sw_kschedule, buf + i);
154 1.16.2.2 rmind
155 1.16.2.2 rmind /* XOR with the IV/previous block, as appropriate */
156 1.16.2.2 rmind if (i == crd->crd_skip)
157 1.16.2.2 rmind for (k = 0; k < blks; k++)
158 1.16.2.2 rmind buf[i + k] ^= ivp[k];
159 1.16.2.2 rmind else
160 1.16.2.2 rmind for (k = 0; k < blks; k++)
161 1.16.2.2 rmind buf[i + k] ^= buf[i + k - blks];
162 1.16.2.2 rmind }
163 1.16.2.2 rmind }
164 1.16.2.2 rmind
165 1.16.2.2 rmind return 0;
166 1.16.2.2 rmind } else if (outtype == CRYPTO_BUF_MBUF) {
167 1.16.2.2 rmind struct mbuf *m = (struct mbuf *) buf;
168 1.16.2.2 rmind
169 1.16.2.2 rmind /* Find beginning of data */
170 1.16.2.2 rmind m = m_getptr(m, crd->crd_skip, &k);
171 1.16.2.2 rmind if (m == NULL)
172 1.16.2.2 rmind return EINVAL;
173 1.16.2.2 rmind
174 1.16.2.2 rmind i = crd->crd_len;
175 1.16.2.2 rmind
176 1.16.2.2 rmind while (i > 0) {
177 1.16.2.2 rmind /*
178 1.16.2.2 rmind * If there's insufficient data at the end of
179 1.16.2.2 rmind * an mbuf, we have to do some copying.
180 1.16.2.2 rmind */
181 1.16.2.2 rmind if (m->m_len < k + blks && m->m_len != k) {
182 1.16.2.2 rmind m_copydata(m, k, blks, blk);
183 1.16.2.2 rmind
184 1.16.2.2 rmind /* Actual encryption/decryption */
185 1.16.2.2 rmind if (crd->crd_flags & CRD_F_ENCRYPT) {
186 1.16.2.2 rmind /* XOR with previous block */
187 1.16.2.2 rmind for (j = 0; j < blks; j++)
188 1.16.2.2 rmind blk[j] ^= ivp[j];
189 1.16.2.2 rmind
190 1.16.2.2 rmind exf->encrypt(sw->sw_kschedule, blk);
191 1.16.2.2 rmind
192 1.16.2.2 rmind /*
193 1.16.2.2 rmind * Keep encrypted block for XOR'ing
194 1.16.2.2 rmind * with next block
195 1.16.2.2 rmind */
196 1.16.2.2 rmind bcopy(blk, iv, blks);
197 1.16.2.2 rmind ivp = iv;
198 1.16.2.2 rmind } else { /* decrypt */
199 1.16.2.2 rmind /*
200 1.16.2.2 rmind * Keep encrypted block for XOR'ing
201 1.16.2.2 rmind * with next block
202 1.16.2.2 rmind */
203 1.16.2.2 rmind if (ivp == iv)
204 1.16.2.2 rmind bcopy(blk, piv, blks);
205 1.16.2.2 rmind else
206 1.16.2.2 rmind bcopy(blk, iv, blks);
207 1.16.2.2 rmind
208 1.16.2.2 rmind exf->decrypt(sw->sw_kschedule, blk);
209 1.16.2.2 rmind
210 1.16.2.2 rmind /* XOR with previous block */
211 1.16.2.2 rmind for (j = 0; j < blks; j++)
212 1.16.2.2 rmind blk[j] ^= ivp[j];
213 1.16.2.2 rmind
214 1.16.2.2 rmind if (ivp == iv)
215 1.16.2.2 rmind bcopy(piv, iv, blks);
216 1.16.2.2 rmind else
217 1.16.2.2 rmind ivp = iv;
218 1.16.2.2 rmind }
219 1.16.2.2 rmind
220 1.16.2.2 rmind /* Copy back decrypted block */
221 1.16.2.2 rmind m_copyback(m, k, blks, blk);
222 1.16.2.2 rmind
223 1.16.2.2 rmind /* Advance pointer */
224 1.16.2.2 rmind m = m_getptr(m, k + blks, &k);
225 1.16.2.2 rmind if (m == NULL)
226 1.16.2.2 rmind return EINVAL;
227 1.16.2.2 rmind
228 1.16.2.2 rmind i -= blks;
229 1.16.2.2 rmind
230 1.16.2.2 rmind /* Could be done... */
231 1.16.2.2 rmind if (i == 0)
232 1.16.2.2 rmind break;
233 1.16.2.2 rmind }
234 1.16.2.2 rmind
235 1.16.2.2 rmind /* Skip possibly empty mbufs */
236 1.16.2.2 rmind if (k == m->m_len) {
237 1.16.2.2 rmind for (m = m->m_next; m && m->m_len == 0;
238 1.16.2.2 rmind m = m->m_next)
239 1.16.2.2 rmind ;
240 1.16.2.2 rmind k = 0;
241 1.16.2.2 rmind }
242 1.16.2.2 rmind
243 1.16.2.2 rmind /* Sanity check */
244 1.16.2.2 rmind if (m == NULL)
245 1.16.2.2 rmind return EINVAL;
246 1.16.2.2 rmind
247 1.16.2.2 rmind /*
248 1.16.2.2 rmind * Warning: idat may point to garbage here, but
249 1.16.2.2 rmind * we only use it in the while() loop, only if
250 1.16.2.2 rmind * there are indeed enough data.
251 1.16.2.2 rmind */
252 1.16.2.2 rmind idat = mtod(m, unsigned char *) + k;
253 1.16.2.2 rmind
254 1.16.2.2 rmind while (m->m_len >= k + blks && i > 0) {
255 1.16.2.2 rmind if (crd->crd_flags & CRD_F_ENCRYPT) {
256 1.16.2.2 rmind /* XOR with previous block/IV */
257 1.16.2.2 rmind for (j = 0; j < blks; j++)
258 1.16.2.2 rmind idat[j] ^= ivp[j];
259 1.16.2.2 rmind
260 1.16.2.2 rmind exf->encrypt(sw->sw_kschedule, idat);
261 1.16.2.2 rmind ivp = idat;
262 1.16.2.2 rmind } else { /* decrypt */
263 1.16.2.2 rmind /*
264 1.16.2.2 rmind * Keep encrypted block to be used
265 1.16.2.2 rmind * in next block's processing.
266 1.16.2.2 rmind */
267 1.16.2.2 rmind if (ivp == iv)
268 1.16.2.2 rmind bcopy(idat, piv, blks);
269 1.16.2.2 rmind else
270 1.16.2.2 rmind bcopy(idat, iv, blks);
271 1.16.2.2 rmind
272 1.16.2.2 rmind exf->decrypt(sw->sw_kschedule, idat);
273 1.16.2.2 rmind
274 1.16.2.2 rmind /* XOR with previous block/IV */
275 1.16.2.2 rmind for (j = 0; j < blks; j++)
276 1.16.2.2 rmind idat[j] ^= ivp[j];
277 1.16.2.2 rmind
278 1.16.2.2 rmind if (ivp == iv)
279 1.16.2.2 rmind bcopy(piv, iv, blks);
280 1.16.2.2 rmind else
281 1.16.2.2 rmind ivp = iv;
282 1.16.2.2 rmind }
283 1.16.2.2 rmind
284 1.16.2.2 rmind idat += blks;
285 1.16.2.2 rmind k += blks;
286 1.16.2.2 rmind i -= blks;
287 1.16.2.2 rmind }
288 1.16.2.2 rmind }
289 1.16.2.2 rmind
290 1.16.2.2 rmind return 0; /* Done with mbuf encryption/decryption */
291 1.16.2.2 rmind } else if (outtype == CRYPTO_BUF_IOV) {
292 1.16.2.2 rmind struct uio *uio = (struct uio *) buf;
293 1.16.2.2 rmind
294 1.16.2.2 rmind #ifdef __FreeBSD__
295 1.16.2.2 rmind struct iovec *iov;
296 1.16.2.2 rmind /* Find beginning of data */
297 1.16.2.2 rmind iov = cuio_getptr(uio, crd->crd_skip, &k);
298 1.16.2.2 rmind if (iov == NULL)
299 1.16.2.2 rmind return EINVAL;
300 1.16.2.2 rmind
301 1.16.2.2 rmind i = crd->crd_len;
302 1.16.2.2 rmind
303 1.16.2.2 rmind while (i > 0) {
304 1.16.2.2 rmind /*
305 1.16.2.2 rmind * If there's insufficient data at the end of
306 1.16.2.2 rmind * an iovec, we have to do some copying.
307 1.16.2.2 rmind */
308 1.16.2.2 rmind if (iov->iov_len < k + blks && iov->iov_len != k) {
309 1.16.2.2 rmind cuio_copydata(uio, k, blks, blk);
310 1.16.2.2 rmind
311 1.16.2.2 rmind /* Actual encryption/decryption */
312 1.16.2.2 rmind if (crd->crd_flags & CRD_F_ENCRYPT) {
313 1.16.2.2 rmind /* XOR with previous block */
314 1.16.2.2 rmind for (j = 0; j < blks; j++)
315 1.16.2.2 rmind blk[j] ^= ivp[j];
316 1.16.2.2 rmind
317 1.16.2.2 rmind exf->encrypt(sw->sw_kschedule, blk);
318 1.16.2.2 rmind
319 1.16.2.2 rmind /*
320 1.16.2.2 rmind * Keep encrypted block for XOR'ing
321 1.16.2.2 rmind * with next block
322 1.16.2.2 rmind */
323 1.16.2.2 rmind bcopy(blk, iv, blks);
324 1.16.2.2 rmind ivp = iv;
325 1.16.2.2 rmind } else { /* decrypt */
326 1.16.2.2 rmind /*
327 1.16.2.2 rmind * Keep encrypted block for XOR'ing
328 1.16.2.2 rmind * with next block
329 1.16.2.2 rmind */
330 1.16.2.2 rmind if (ivp == iv)
331 1.16.2.2 rmind bcopy(blk, piv, blks);
332 1.16.2.2 rmind else
333 1.16.2.2 rmind bcopy(blk, iv, blks);
334 1.16.2.2 rmind
335 1.16.2.2 rmind exf->decrypt(sw->sw_kschedule, blk);
336 1.16.2.2 rmind
337 1.16.2.2 rmind /* XOR with previous block */
338 1.16.2.2 rmind for (j = 0; j < blks; j++)
339 1.16.2.2 rmind blk[j] ^= ivp[j];
340 1.16.2.2 rmind
341 1.16.2.2 rmind if (ivp == iv)
342 1.16.2.2 rmind bcopy(piv, iv, blks);
343 1.16.2.2 rmind else
344 1.16.2.2 rmind ivp = iv;
345 1.16.2.2 rmind }
346 1.16.2.2 rmind
347 1.16.2.2 rmind /* Copy back decrypted block */
348 1.16.2.2 rmind cuio_copyback(uio, k, blks, blk);
349 1.16.2.2 rmind
350 1.16.2.2 rmind /* Advance pointer */
351 1.16.2.2 rmind iov = cuio_getptr(uio, k + blks, &k);
352 1.16.2.2 rmind if (iov == NULL)
353 1.16.2.2 rmind return EINVAL;
354 1.16.2.2 rmind
355 1.16.2.2 rmind i -= blks;
356 1.16.2.2 rmind
357 1.16.2.2 rmind /* Could be done... */
358 1.16.2.2 rmind if (i == 0)
359 1.16.2.2 rmind break;
360 1.16.2.2 rmind }
361 1.16.2.2 rmind
362 1.16.2.2 rmind /*
363 1.16.2.2 rmind * Warning: idat may point to garbage here, but
364 1.16.2.2 rmind * we only use it in the while() loop, only if
365 1.16.2.2 rmind * there are indeed enough data.
366 1.16.2.2 rmind */
367 1.16.2.2 rmind idat = (char *)iov->iov_base + k;
368 1.16.2.2 rmind
369 1.16.2.2 rmind while (iov->iov_len >= k + blks && i > 0) {
370 1.16.2.2 rmind if (crd->crd_flags & CRD_F_ENCRYPT) {
371 1.16.2.2 rmind /* XOR with previous block/IV */
372 1.16.2.2 rmind for (j = 0; j < blks; j++)
373 1.16.2.2 rmind idat[j] ^= ivp[j];
374 1.16.2.2 rmind
375 1.16.2.2 rmind exf->encrypt(sw->sw_kschedule, idat);
376 1.16.2.2 rmind ivp = idat;
377 1.16.2.2 rmind } else { /* decrypt */
378 1.16.2.2 rmind /*
379 1.16.2.2 rmind * Keep encrypted block to be used
380 1.16.2.2 rmind * in next block's processing.
381 1.16.2.2 rmind */
382 1.16.2.2 rmind if (ivp == iv)
383 1.16.2.2 rmind bcopy(idat, piv, blks);
384 1.16.2.2 rmind else
385 1.16.2.2 rmind bcopy(idat, iv, blks);
386 1.16.2.2 rmind
387 1.16.2.2 rmind exf->decrypt(sw->sw_kschedule, idat);
388 1.16.2.2 rmind
389 1.16.2.2 rmind /* XOR with previous block/IV */
390 1.16.2.2 rmind for (j = 0; j < blks; j++)
391 1.16.2.2 rmind idat[j] ^= ivp[j];
392 1.16.2.2 rmind
393 1.16.2.2 rmind if (ivp == iv)
394 1.16.2.2 rmind bcopy(piv, iv, blks);
395 1.16.2.2 rmind else
396 1.16.2.2 rmind ivp = iv;
397 1.16.2.2 rmind }
398 1.16.2.2 rmind
399 1.16.2.2 rmind idat += blks;
400 1.16.2.2 rmind k += blks;
401 1.16.2.2 rmind i -= blks;
402 1.16.2.2 rmind }
403 1.16.2.2 rmind }
404 1.16.2.2 rmind
405 1.16.2.2 rmind return 0; /* Done with mbuf encryption/decryption */
406 1.16.2.2 rmind #else /* !freebsd iov */
407 1.16.2.2 rmind /* Find beginning of data */
408 1.16.2.2 rmind count = crd->crd_skip;
409 1.16.2.2 rmind ind = cuio_getptr(uio, count, &k);
410 1.16.2.2 rmind if (ind == -1)
411 1.16.2.2 rmind return EINVAL;
412 1.16.2.2 rmind
413 1.16.2.2 rmind i = crd->crd_len;
414 1.16.2.2 rmind
415 1.16.2.2 rmind while (i > 0) {
416 1.16.2.2 rmind /*
417 1.16.2.2 rmind * If there's insufficient data at the end,
418 1.16.2.2 rmind * we have to do some copying.
419 1.16.2.2 rmind */
420 1.16.2.2 rmind if (uio->uio_iov[ind].iov_len < k + blks &&
421 1.16.2.2 rmind uio->uio_iov[ind].iov_len != k) {
422 1.16.2.2 rmind cuio_copydata(uio, k, blks, blk);
423 1.16.2.2 rmind
424 1.16.2.2 rmind /* Actual encryption/decryption */
425 1.16.2.2 rmind if (crd->crd_flags & CRD_F_ENCRYPT) {
426 1.16.2.2 rmind /* XOR with previous block */
427 1.16.2.2 rmind for (j = 0; j < blks; j++)
428 1.16.2.2 rmind blk[j] ^= ivp[j];
429 1.16.2.2 rmind
430 1.16.2.2 rmind exf->encrypt(sw->sw_kschedule, blk);
431 1.16.2.2 rmind
432 1.16.2.2 rmind /*
433 1.16.2.2 rmind * Keep encrypted block for XOR'ing
434 1.16.2.2 rmind * with next block
435 1.16.2.2 rmind */
436 1.16.2.2 rmind bcopy(blk, iv, blks);
437 1.16.2.2 rmind ivp = iv;
438 1.16.2.2 rmind } else { /* decrypt */
439 1.16.2.2 rmind /*
440 1.16.2.2 rmind * Keep encrypted block for XOR'ing
441 1.16.2.2 rmind * with next block
442 1.16.2.2 rmind */
443 1.16.2.2 rmind if (ivp == iv)
444 1.16.2.2 rmind bcopy(blk, piv, blks);
445 1.16.2.2 rmind else
446 1.16.2.2 rmind bcopy(blk, iv, blks);
447 1.16.2.2 rmind
448 1.16.2.2 rmind exf->decrypt(sw->sw_kschedule, blk);
449 1.16.2.2 rmind
450 1.16.2.2 rmind /* XOR with previous block */
451 1.16.2.2 rmind for (j = 0; j < blks; j++)
452 1.16.2.2 rmind blk[j] ^= ivp[j];
453 1.16.2.2 rmind
454 1.16.2.2 rmind if (ivp == iv)
455 1.16.2.2 rmind bcopy(piv, iv, blks);
456 1.16.2.2 rmind else
457 1.16.2.2 rmind ivp = iv;
458 1.16.2.2 rmind }
459 1.16.2.2 rmind
460 1.16.2.2 rmind /* Copy back decrypted block */
461 1.16.2.2 rmind cuio_copyback(uio, k, blks, blk);
462 1.16.2.2 rmind
463 1.16.2.2 rmind count += blks;
464 1.16.2.2 rmind
465 1.16.2.2 rmind /* Advance pointer */
466 1.16.2.2 rmind ind = cuio_getptr(uio, count, &k);
467 1.16.2.2 rmind if (ind == -1)
468 1.16.2.2 rmind return (EINVAL);
469 1.16.2.2 rmind
470 1.16.2.2 rmind i -= blks;
471 1.16.2.2 rmind
472 1.16.2.2 rmind /* Could be done... */
473 1.16.2.2 rmind if (i == 0)
474 1.16.2.2 rmind break;
475 1.16.2.2 rmind }
476 1.16.2.2 rmind
477 1.16.2.2 rmind /*
478 1.16.2.2 rmind * Warning: idat may point to garbage here, but
479 1.16.2.2 rmind * we only use it in the while() loop, only if
480 1.16.2.2 rmind * there are indeed enough data.
481 1.16.2.2 rmind */
482 1.16.2.2 rmind idat = ((char *)uio->uio_iov[ind].iov_base) + k;
483 1.16.2.2 rmind
484 1.16.2.2 rmind while (uio->uio_iov[ind].iov_len >= k + blks &&
485 1.16.2.2 rmind i > 0) {
486 1.16.2.2 rmind if (crd->crd_flags & CRD_F_ENCRYPT) {
487 1.16.2.2 rmind /* XOR with previous block/IV */
488 1.16.2.2 rmind for (j = 0; j < blks; j++)
489 1.16.2.2 rmind idat[j] ^= ivp[j];
490 1.16.2.2 rmind
491 1.16.2.2 rmind exf->encrypt(sw->sw_kschedule, idat);
492 1.16.2.2 rmind ivp = idat;
493 1.16.2.2 rmind } else { /* decrypt */
494 1.16.2.2 rmind /*
495 1.16.2.2 rmind * Keep encrypted block to be used
496 1.16.2.2 rmind * in next block's processing.
497 1.16.2.2 rmind */
498 1.16.2.2 rmind if (ivp == iv)
499 1.16.2.2 rmind bcopy(idat, piv, blks);
500 1.16.2.2 rmind else
501 1.16.2.2 rmind bcopy(idat, iv, blks);
502 1.16.2.2 rmind
503 1.16.2.2 rmind exf->decrypt(sw->sw_kschedule, idat);
504 1.16.2.2 rmind
505 1.16.2.2 rmind /* XOR with previous block/IV */
506 1.16.2.2 rmind for (j = 0; j < blks; j++)
507 1.16.2.2 rmind idat[j] ^= ivp[j];
508 1.16.2.2 rmind
509 1.16.2.2 rmind if (ivp == iv)
510 1.16.2.2 rmind bcopy(piv, iv, blks);
511 1.16.2.2 rmind else
512 1.16.2.2 rmind ivp = iv;
513 1.16.2.2 rmind }
514 1.16.2.2 rmind
515 1.16.2.2 rmind idat += blks;
516 1.16.2.2 rmind count += blks;
517 1.16.2.2 rmind k += blks;
518 1.16.2.2 rmind i -= blks;
519 1.16.2.2 rmind }
520 1.16.2.2 rmind }
521 1.16.2.2 rmind #endif
522 1.16.2.2 rmind return 0; /* Done with mbuf encryption/decryption */
523 1.16.2.2 rmind }
524 1.16.2.2 rmind
525 1.16.2.2 rmind /* Unreachable */
526 1.16.2.2 rmind return EINVAL;
527 1.16.2.2 rmind }
528 1.16.2.2 rmind
529 1.16.2.2 rmind /*
530 1.16.2.2 rmind * Compute keyed-hash authenticator.
531 1.16.2.2 rmind */
532 1.16.2.2 rmind int
533 1.16.2.2 rmind swcr_authcompute(struct cryptop *crp, struct cryptodesc *crd,
534 1.16.2.2 rmind struct swcr_data *sw, void *buf, int outtype)
535 1.16.2.2 rmind {
536 1.16.2.2 rmind unsigned char aalg[AALG_MAX_RESULT_LEN];
537 1.16.2.2 rmind const struct swcr_auth_hash *axf;
538 1.16.2.2 rmind union authctx ctx;
539 1.16.2.2 rmind int err;
540 1.16.2.2 rmind
541 1.16.2.2 rmind if (sw->sw_ictx == 0)
542 1.16.2.2 rmind return EINVAL;
543 1.16.2.2 rmind
544 1.16.2.2 rmind axf = sw->sw_axf;
545 1.16.2.2 rmind
546 1.16.2.2 rmind bcopy(sw->sw_ictx, &ctx, axf->auth_hash->ctxsize);
547 1.16.2.2 rmind
548 1.16.2.2 rmind switch (outtype) {
549 1.16.2.2 rmind case CRYPTO_BUF_CONTIG:
550 1.16.2.2 rmind axf->Update(&ctx, (char *)buf + crd->crd_skip, crd->crd_len);
551 1.16.2.2 rmind break;
552 1.16.2.2 rmind case CRYPTO_BUF_MBUF:
553 1.16.2.2 rmind err = m_apply((struct mbuf *) buf, crd->crd_skip, crd->crd_len,
554 1.16.2.2 rmind (int (*)(void*, void *, unsigned int)) axf->Update,
555 1.16.2.2 rmind (void *) &ctx);
556 1.16.2.2 rmind if (err)
557 1.16.2.2 rmind return err;
558 1.16.2.2 rmind break;
559 1.16.2.2 rmind case CRYPTO_BUF_IOV:
560 1.16.2.2 rmind #ifdef __FreeBSD__
561 1.16.2.2 rmind /*XXX FIXME: handle iov case*/
562 1.16.2.2 rmind return EINVAL;
563 1.16.2.2 rmind #else
564 1.16.2.2 rmind err = cuio_apply((struct uio *) buf, crd->crd_skip,
565 1.16.2.2 rmind crd->crd_len,
566 1.16.2.2 rmind (int (*)(void *, void *, unsigned int)) axf->Update,
567 1.16.2.2 rmind (void *) &ctx);
568 1.16.2.2 rmind if (err) {
569 1.16.2.2 rmind return err;
570 1.16.2.2 rmind }
571 1.16.2.2 rmind #endif
572 1.16.2.2 rmind break;
573 1.16.2.2 rmind default:
574 1.16.2.2 rmind return EINVAL;
575 1.16.2.2 rmind }
576 1.16.2.2 rmind
577 1.16.2.2 rmind switch (sw->sw_alg) {
578 1.16.2.2 rmind case CRYPTO_MD5_HMAC:
579 1.16.2.2 rmind case CRYPTO_SHA1_HMAC:
580 1.16.2.2 rmind case CRYPTO_SHA2_HMAC:
581 1.16.2.2 rmind case CRYPTO_RIPEMD160_HMAC:
582 1.16.2.2 rmind if (sw->sw_octx == NULL)
583 1.16.2.2 rmind return EINVAL;
584 1.16.2.2 rmind
585 1.16.2.2 rmind axf->Final(aalg, &ctx);
586 1.16.2.2 rmind bcopy(sw->sw_octx, &ctx, axf->auth_hash->ctxsize);
587 1.16.2.2 rmind axf->Update(&ctx, aalg, axf->auth_hash->hashsize);
588 1.16.2.2 rmind axf->Final(aalg, &ctx);
589 1.16.2.2 rmind break;
590 1.16.2.2 rmind
591 1.16.2.2 rmind case CRYPTO_MD5_KPDK:
592 1.16.2.2 rmind case CRYPTO_SHA1_KPDK:
593 1.16.2.2 rmind if (sw->sw_octx == NULL)
594 1.16.2.2 rmind return EINVAL;
595 1.16.2.2 rmind
596 1.16.2.2 rmind axf->Update(&ctx, sw->sw_octx, sw->sw_klen);
597 1.16.2.2 rmind axf->Final(aalg, &ctx);
598 1.16.2.2 rmind break;
599 1.16.2.2 rmind
600 1.16.2.2 rmind case CRYPTO_NULL_HMAC:
601 1.16.2.2 rmind case CRYPTO_MD5:
602 1.16.2.2 rmind case CRYPTO_SHA1:
603 1.16.2.2 rmind axf->Final(aalg, &ctx);
604 1.16.2.2 rmind break;
605 1.16.2.2 rmind }
606 1.16.2.2 rmind
607 1.16.2.2 rmind /* Inject the authentication data */
608 1.16.2.2 rmind switch (outtype) {
609 1.16.2.2 rmind case CRYPTO_BUF_CONTIG:
610 1.16.2.2 rmind (void)memcpy((char *)buf + crd->crd_inject, aalg,
611 1.16.2.2 rmind axf->auth_hash->authsize);
612 1.16.2.2 rmind break;
613 1.16.2.2 rmind case CRYPTO_BUF_MBUF:
614 1.16.2.2 rmind m_copyback((struct mbuf *) buf, crd->crd_inject,
615 1.16.2.2 rmind axf->auth_hash->authsize, aalg);
616 1.16.2.2 rmind break;
617 1.16.2.2 rmind case CRYPTO_BUF_IOV:
618 1.16.2.2 rmind bcopy(aalg, crp->crp_mac, axf->auth_hash->authsize);
619 1.16.2.2 rmind break;
620 1.16.2.2 rmind default:
621 1.16.2.2 rmind return EINVAL;
622 1.16.2.2 rmind }
623 1.16.2.2 rmind return 0;
624 1.16.2.2 rmind }
625 1.16.2.2 rmind
626 1.16.2.2 rmind /*
627 1.16.2.2 rmind * Apply a compression/decompression algorithm
628 1.16.2.2 rmind */
629 1.16.2.2 rmind static int
630 1.16.2.2 rmind swcr_compdec(struct cryptodesc *crd, struct swcr_data *sw,
631 1.16.2.2 rmind void *buf, int outtype)
632 1.16.2.2 rmind {
633 1.16.2.2 rmind u_int8_t *data, *out;
634 1.16.2.2 rmind const struct swcr_comp_algo *cxf;
635 1.16.2.2 rmind int adj;
636 1.16.2.2 rmind u_int32_t result;
637 1.16.2.2 rmind
638 1.16.2.2 rmind cxf = sw->sw_cxf;
639 1.16.2.2 rmind
640 1.16.2.2 rmind /* We must handle the whole buffer of data in one time
641 1.16.2.2 rmind * then if there is not all the data in the mbuf, we must
642 1.16.2.2 rmind * copy in a buffer.
643 1.16.2.2 rmind */
644 1.16.2.2 rmind
645 1.16.2.2 rmind data = malloc(crd->crd_len, M_CRYPTO_DATA, M_NOWAIT);
646 1.16.2.2 rmind if (data == NULL)
647 1.16.2.2 rmind return (EINVAL);
648 1.16.2.2 rmind COPYDATA(outtype, buf, crd->crd_skip, crd->crd_len, data);
649 1.16.2.2 rmind
650 1.16.2.2 rmind if (crd->crd_flags & CRD_F_COMP)
651 1.16.2.2 rmind result = cxf->compress(data, crd->crd_len, &out);
652 1.16.2.2 rmind else
653 1.16.2.2 rmind result = cxf->decompress(data, crd->crd_len, &out);
654 1.16.2.2 rmind
655 1.16.2.2 rmind FREE(data, M_CRYPTO_DATA);
656 1.16.2.2 rmind if (result == 0)
657 1.16.2.2 rmind return EINVAL;
658 1.16.2.2 rmind
659 1.16.2.2 rmind /* Copy back the (de)compressed data. m_copyback is
660 1.16.2.2 rmind * extending the mbuf as necessary.
661 1.16.2.2 rmind */
662 1.16.2.2 rmind sw->sw_size = result;
663 1.16.2.2 rmind /* Check the compressed size when doing compression */
664 1.16.2.2 rmind if (crd->crd_flags & CRD_F_COMP) {
665 1.16.2.2 rmind if (result > crd->crd_len) {
666 1.16.2.2 rmind /* Compression was useless, we lost time */
667 1.16.2.2 rmind FREE(out, M_CRYPTO_DATA);
668 1.16.2.2 rmind return 0;
669 1.16.2.2 rmind }
670 1.16.2.2 rmind }
671 1.16.2.2 rmind
672 1.16.2.2 rmind COPYBACK(outtype, buf, crd->crd_skip, result, out);
673 1.16.2.2 rmind if (result < crd->crd_len) {
674 1.16.2.2 rmind adj = result - crd->crd_len;
675 1.16.2.2 rmind if (outtype == CRYPTO_BUF_MBUF) {
676 1.16.2.2 rmind adj = result - crd->crd_len;
677 1.16.2.2 rmind m_adj((struct mbuf *)buf, adj);
678 1.16.2.2 rmind } else {
679 1.16.2.2 rmind struct uio *uio = (struct uio *)buf;
680 1.16.2.2 rmind int ind;
681 1.16.2.2 rmind
682 1.16.2.2 rmind adj = crd->crd_len - result;
683 1.16.2.2 rmind ind = uio->uio_iovcnt - 1;
684 1.16.2.2 rmind
685 1.16.2.2 rmind while (adj > 0 && ind >= 0) {
686 1.16.2.2 rmind if (adj < uio->uio_iov[ind].iov_len) {
687 1.16.2.2 rmind uio->uio_iov[ind].iov_len -= adj;
688 1.16.2.2 rmind break;
689 1.16.2.2 rmind }
690 1.16.2.2 rmind
691 1.16.2.2 rmind adj -= uio->uio_iov[ind].iov_len;
692 1.16.2.2 rmind uio->uio_iov[ind].iov_len = 0;
693 1.16.2.2 rmind ind--;
694 1.16.2.2 rmind uio->uio_iovcnt--;
695 1.16.2.2 rmind }
696 1.16.2.2 rmind }
697 1.16.2.2 rmind }
698 1.16.2.2 rmind FREE(out, M_CRYPTO_DATA);
699 1.16.2.2 rmind return 0;
700 1.16.2.2 rmind }
701 1.16.2.2 rmind
702 1.16.2.2 rmind /*
703 1.16.2.2 rmind * Generate a new software session.
704 1.16.2.2 rmind */
705 1.16.2.2 rmind static int
706 1.16.2.2 rmind swcr_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
707 1.16.2.2 rmind {
708 1.16.2.2 rmind struct swcr_data **swd;
709 1.16.2.2 rmind const struct swcr_auth_hash *axf;
710 1.16.2.2 rmind const struct swcr_enc_xform *txf;
711 1.16.2.2 rmind const struct swcr_comp_algo *cxf;
712 1.16.2.2 rmind u_int32_t i;
713 1.16.2.2 rmind int k, error;
714 1.16.2.2 rmind
715 1.16.2.2 rmind if (sid == NULL || cri == NULL)
716 1.16.2.2 rmind return EINVAL;
717 1.16.2.2 rmind
718 1.16.2.2 rmind if (swcr_sessions) {
719 1.16.2.2 rmind for (i = 1; i < swcr_sesnum; i++)
720 1.16.2.2 rmind if (swcr_sessions[i] == NULL)
721 1.16.2.2 rmind break;
722 1.16.2.2 rmind } else
723 1.16.2.2 rmind i = 1; /* NB: to silence compiler warning */
724 1.16.2.2 rmind
725 1.16.2.2 rmind if (swcr_sessions == NULL || i == swcr_sesnum) {
726 1.16.2.2 rmind if (swcr_sessions == NULL) {
727 1.16.2.2 rmind i = 1; /* We leave swcr_sessions[0] empty */
728 1.16.2.2 rmind swcr_sesnum = CRYPTO_SW_SESSIONS;
729 1.16.2.2 rmind } else
730 1.16.2.2 rmind swcr_sesnum *= 2;
731 1.16.2.2 rmind
732 1.16.2.2 rmind swd = malloc(swcr_sesnum * sizeof(struct swcr_data *),
733 1.16.2.2 rmind M_CRYPTO_DATA, M_NOWAIT);
734 1.16.2.2 rmind if (swd == NULL) {
735 1.16.2.2 rmind /* Reset session number */
736 1.16.2.2 rmind if (swcr_sesnum == CRYPTO_SW_SESSIONS)
737 1.16.2.2 rmind swcr_sesnum = 0;
738 1.16.2.2 rmind else
739 1.16.2.2 rmind swcr_sesnum /= 2;
740 1.16.2.2 rmind return ENOBUFS;
741 1.16.2.2 rmind }
742 1.16.2.2 rmind
743 1.16.2.2 rmind bzero(swd, swcr_sesnum * sizeof(struct swcr_data *));
744 1.16.2.2 rmind
745 1.16.2.2 rmind /* Copy existing sessions */
746 1.16.2.2 rmind if (swcr_sessions) {
747 1.16.2.2 rmind bcopy(swcr_sessions, swd,
748 1.16.2.2 rmind (swcr_sesnum / 2) * sizeof(struct swcr_data *));
749 1.16.2.2 rmind free(swcr_sessions, M_CRYPTO_DATA);
750 1.16.2.2 rmind }
751 1.16.2.2 rmind
752 1.16.2.2 rmind swcr_sessions = swd;
753 1.16.2.2 rmind }
754 1.16.2.2 rmind
755 1.16.2.2 rmind swd = &swcr_sessions[i];
756 1.16.2.2 rmind *sid = i;
757 1.16.2.2 rmind
758 1.16.2.2 rmind while (cri) {
759 1.16.2.2 rmind *swd = malloc(sizeof **swd, M_CRYPTO_DATA, M_NOWAIT);
760 1.16.2.2 rmind if (*swd == NULL) {
761 1.16.2.2 rmind swcr_freesession(NULL, i);
762 1.16.2.2 rmind return ENOBUFS;
763 1.16.2.2 rmind }
764 1.16.2.2 rmind bzero(*swd, sizeof(struct swcr_data));
765 1.16.2.2 rmind
766 1.16.2.2 rmind switch (cri->cri_alg) {
767 1.16.2.2 rmind case CRYPTO_DES_CBC:
768 1.16.2.2 rmind txf = &swcr_enc_xform_des;
769 1.16.2.2 rmind goto enccommon;
770 1.16.2.2 rmind case CRYPTO_3DES_CBC:
771 1.16.2.2 rmind txf = &swcr_enc_xform_3des;
772 1.16.2.2 rmind goto enccommon;
773 1.16.2.2 rmind case CRYPTO_BLF_CBC:
774 1.16.2.2 rmind txf = &swcr_enc_xform_blf;
775 1.16.2.2 rmind goto enccommon;
776 1.16.2.2 rmind case CRYPTO_CAST_CBC:
777 1.16.2.2 rmind txf = &swcr_enc_xform_cast5;
778 1.16.2.2 rmind goto enccommon;
779 1.16.2.2 rmind case CRYPTO_SKIPJACK_CBC:
780 1.16.2.2 rmind txf = &swcr_enc_xform_skipjack;
781 1.16.2.2 rmind goto enccommon;
782 1.16.2.2 rmind case CRYPTO_RIJNDAEL128_CBC:
783 1.16.2.2 rmind txf = &swcr_enc_xform_rijndael128;
784 1.16.2.2 rmind goto enccommon;
785 1.16.2.2 rmind case CRYPTO_NULL_CBC:
786 1.16.2.2 rmind txf = &swcr_enc_xform_null;
787 1.16.2.2 rmind goto enccommon;
788 1.16.2.2 rmind enccommon:
789 1.16.2.2 rmind error = txf->setkey(&((*swd)->sw_kschedule),
790 1.16.2.2 rmind cri->cri_key, cri->cri_klen / 8);
791 1.16.2.2 rmind if (error) {
792 1.16.2.2 rmind swcr_freesession(NULL, i);
793 1.16.2.2 rmind return error;
794 1.16.2.2 rmind }
795 1.16.2.2 rmind (*swd)->sw_exf = txf;
796 1.16.2.2 rmind break;
797 1.16.2.2 rmind
798 1.16.2.2 rmind case CRYPTO_MD5_HMAC:
799 1.16.2.2 rmind axf = &swcr_auth_hash_hmac_md5_96;
800 1.16.2.2 rmind goto authcommon;
801 1.16.2.2 rmind case CRYPTO_SHA1_HMAC:
802 1.16.2.2 rmind axf = &swcr_auth_hash_hmac_sha1_96;
803 1.16.2.2 rmind goto authcommon;
804 1.16.2.2 rmind case CRYPTO_SHA2_HMAC:
805 1.16.2.2 rmind if (cri->cri_klen == 256)
806 1.16.2.2 rmind axf = &swcr_auth_hash_hmac_sha2_256;
807 1.16.2.2 rmind else if (cri->cri_klen == 384)
808 1.16.2.2 rmind axf = &swcr_auth_hash_hmac_sha2_384;
809 1.16.2.2 rmind else if (cri->cri_klen == 512)
810 1.16.2.2 rmind axf = &swcr_auth_hash_hmac_sha2_512;
811 1.16.2.2 rmind else {
812 1.16.2.2 rmind swcr_freesession(NULL, i);
813 1.16.2.2 rmind return EINVAL;
814 1.16.2.2 rmind }
815 1.16.2.2 rmind goto authcommon;
816 1.16.2.2 rmind case CRYPTO_NULL_HMAC:
817 1.16.2.2 rmind axf = &swcr_auth_hash_null;
818 1.16.2.2 rmind goto authcommon;
819 1.16.2.2 rmind case CRYPTO_RIPEMD160_HMAC:
820 1.16.2.2 rmind axf = &swcr_auth_hash_hmac_ripemd_160_96;
821 1.16.2.2 rmind authcommon:
822 1.16.2.2 rmind (*swd)->sw_ictx = malloc(axf->auth_hash->ctxsize,
823 1.16.2.2 rmind M_CRYPTO_DATA, M_NOWAIT);
824 1.16.2.2 rmind if ((*swd)->sw_ictx == NULL) {
825 1.16.2.2 rmind swcr_freesession(NULL, i);
826 1.16.2.2 rmind return ENOBUFS;
827 1.16.2.2 rmind }
828 1.16.2.2 rmind
829 1.16.2.2 rmind (*swd)->sw_octx = malloc(axf->auth_hash->ctxsize,
830 1.16.2.2 rmind M_CRYPTO_DATA, M_NOWAIT);
831 1.16.2.2 rmind if ((*swd)->sw_octx == NULL) {
832 1.16.2.2 rmind swcr_freesession(NULL, i);
833 1.16.2.2 rmind return ENOBUFS;
834 1.16.2.2 rmind }
835 1.16.2.2 rmind
836 1.16.2.2 rmind for (k = 0; k < cri->cri_klen / 8; k++)
837 1.16.2.2 rmind cri->cri_key[k] ^= HMAC_IPAD_VAL;
838 1.16.2.2 rmind
839 1.16.2.2 rmind axf->Init((*swd)->sw_ictx);
840 1.16.2.2 rmind axf->Update((*swd)->sw_ictx, cri->cri_key,
841 1.16.2.2 rmind cri->cri_klen / 8);
842 1.16.2.2 rmind axf->Update((*swd)->sw_ictx, hmac_ipad_buffer,
843 1.16.2.2 rmind HMAC_BLOCK_LEN - (cri->cri_klen / 8));
844 1.16.2.2 rmind
845 1.16.2.2 rmind for (k = 0; k < cri->cri_klen / 8; k++)
846 1.16.2.2 rmind cri->cri_key[k] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL);
847 1.16.2.2 rmind
848 1.16.2.2 rmind axf->Init((*swd)->sw_octx);
849 1.16.2.2 rmind axf->Update((*swd)->sw_octx, cri->cri_key,
850 1.16.2.2 rmind cri->cri_klen / 8);
851 1.16.2.2 rmind axf->Update((*swd)->sw_octx, hmac_opad_buffer,
852 1.16.2.2 rmind HMAC_BLOCK_LEN - (cri->cri_klen / 8));
853 1.16.2.2 rmind
854 1.16.2.2 rmind for (k = 0; k < cri->cri_klen / 8; k++)
855 1.16.2.2 rmind cri->cri_key[k] ^= HMAC_OPAD_VAL;
856 1.16.2.2 rmind (*swd)->sw_axf = axf;
857 1.16.2.2 rmind break;
858 1.16.2.2 rmind
859 1.16.2.2 rmind case CRYPTO_MD5_KPDK:
860 1.16.2.2 rmind axf = &swcr_auth_hash_key_md5;
861 1.16.2.2 rmind goto auth2common;
862 1.16.2.2 rmind
863 1.16.2.2 rmind case CRYPTO_SHA1_KPDK:
864 1.16.2.2 rmind axf = &swcr_auth_hash_key_sha1;
865 1.16.2.2 rmind auth2common:
866 1.16.2.2 rmind (*swd)->sw_ictx = malloc(axf->auth_hash->ctxsize,
867 1.16.2.2 rmind M_CRYPTO_DATA, M_NOWAIT);
868 1.16.2.2 rmind if ((*swd)->sw_ictx == NULL) {
869 1.16.2.2 rmind swcr_freesession(NULL, i);
870 1.16.2.2 rmind return ENOBUFS;
871 1.16.2.2 rmind }
872 1.16.2.2 rmind
873 1.16.2.2 rmind /* Store the key so we can "append" it to the payload */
874 1.16.2.2 rmind (*swd)->sw_octx = malloc(cri->cri_klen / 8, M_CRYPTO_DATA,
875 1.16.2.2 rmind M_NOWAIT);
876 1.16.2.2 rmind if ((*swd)->sw_octx == NULL) {
877 1.16.2.2 rmind swcr_freesession(NULL, i);
878 1.16.2.2 rmind return ENOBUFS;
879 1.16.2.2 rmind }
880 1.16.2.2 rmind
881 1.16.2.2 rmind (*swd)->sw_klen = cri->cri_klen / 8;
882 1.16.2.2 rmind bcopy(cri->cri_key, (*swd)->sw_octx, cri->cri_klen / 8);
883 1.16.2.2 rmind axf->Init((*swd)->sw_ictx);
884 1.16.2.2 rmind axf->Update((*swd)->sw_ictx, cri->cri_key,
885 1.16.2.2 rmind cri->cri_klen / 8);
886 1.16.2.2 rmind axf->Final(NULL, (*swd)->sw_ictx);
887 1.16.2.2 rmind (*swd)->sw_axf = axf;
888 1.16.2.2 rmind break;
889 1.16.2.2 rmind
890 1.16.2.2 rmind case CRYPTO_MD5:
891 1.16.2.2 rmind axf = &swcr_auth_hash_md5;
892 1.16.2.2 rmind goto auth3common;
893 1.16.2.2 rmind
894 1.16.2.2 rmind case CRYPTO_SHA1:
895 1.16.2.2 rmind axf = &swcr_auth_hash_sha1;
896 1.16.2.2 rmind auth3common:
897 1.16.2.2 rmind (*swd)->sw_ictx = malloc(axf->auth_hash->ctxsize,
898 1.16.2.2 rmind M_CRYPTO_DATA, M_NOWAIT);
899 1.16.2.2 rmind if ((*swd)->sw_ictx == NULL) {
900 1.16.2.2 rmind swcr_freesession(NULL, i);
901 1.16.2.2 rmind return ENOBUFS;
902 1.16.2.2 rmind }
903 1.16.2.2 rmind
904 1.16.2.2 rmind axf->Init((*swd)->sw_ictx);
905 1.16.2.2 rmind (*swd)->sw_axf = axf;
906 1.16.2.2 rmind break;
907 1.16.2.2 rmind
908 1.16.2.2 rmind case CRYPTO_DEFLATE_COMP:
909 1.16.2.2 rmind cxf = &swcr_comp_algo_deflate;
910 1.16.2.2 rmind (*swd)->sw_cxf = cxf;
911 1.16.2.2 rmind break;
912 1.16.2.2 rmind default:
913 1.16.2.2 rmind swcr_freesession(NULL, i);
914 1.16.2.2 rmind return EINVAL;
915 1.16.2.2 rmind }
916 1.16.2.2 rmind
917 1.16.2.2 rmind (*swd)->sw_alg = cri->cri_alg;
918 1.16.2.2 rmind cri = cri->cri_next;
919 1.16.2.2 rmind swd = &((*swd)->sw_next);
920 1.16.2.2 rmind }
921 1.16.2.2 rmind return 0;
922 1.16.2.2 rmind }
923 1.16.2.2 rmind
924 1.16.2.2 rmind /*
925 1.16.2.2 rmind * Free a session.
926 1.16.2.2 rmind */
927 1.16.2.2 rmind static int
928 1.16.2.2 rmind swcr_freesession(void *arg, u_int64_t tid)
929 1.16.2.2 rmind {
930 1.16.2.2 rmind struct swcr_data *swd;
931 1.16.2.2 rmind const struct swcr_enc_xform *txf;
932 1.16.2.2 rmind const struct swcr_auth_hash *axf;
933 1.16.2.2 rmind const struct swcr_comp_algo *cxf;
934 1.16.2.2 rmind u_int32_t sid = ((u_int32_t) tid) & 0xffffffff;
935 1.16.2.2 rmind
936 1.16.2.2 rmind if (sid > swcr_sesnum || swcr_sessions == NULL ||
937 1.16.2.2 rmind swcr_sessions[sid] == NULL)
938 1.16.2.2 rmind return EINVAL;
939 1.16.2.2 rmind
940 1.16.2.2 rmind /* Silently accept and return */
941 1.16.2.2 rmind if (sid == 0)
942 1.16.2.2 rmind return 0;
943 1.16.2.2 rmind
944 1.16.2.2 rmind while ((swd = swcr_sessions[sid]) != NULL) {
945 1.16.2.2 rmind swcr_sessions[sid] = swd->sw_next;
946 1.16.2.2 rmind
947 1.16.2.2 rmind switch (swd->sw_alg) {
948 1.16.2.2 rmind case CRYPTO_DES_CBC:
949 1.16.2.2 rmind case CRYPTO_3DES_CBC:
950 1.16.2.2 rmind case CRYPTO_BLF_CBC:
951 1.16.2.2 rmind case CRYPTO_CAST_CBC:
952 1.16.2.2 rmind case CRYPTO_SKIPJACK_CBC:
953 1.16.2.2 rmind case CRYPTO_RIJNDAEL128_CBC:
954 1.16.2.2 rmind case CRYPTO_NULL_CBC:
955 1.16.2.2 rmind txf = swd->sw_exf;
956 1.16.2.2 rmind
957 1.16.2.2 rmind if (swd->sw_kschedule)
958 1.16.2.2 rmind txf->zerokey(&(swd->sw_kschedule));
959 1.16.2.2 rmind break;
960 1.16.2.2 rmind
961 1.16.2.2 rmind case CRYPTO_MD5_HMAC:
962 1.16.2.2 rmind case CRYPTO_SHA1_HMAC:
963 1.16.2.2 rmind case CRYPTO_SHA2_HMAC:
964 1.16.2.2 rmind case CRYPTO_RIPEMD160_HMAC:
965 1.16.2.2 rmind case CRYPTO_NULL_HMAC:
966 1.16.2.2 rmind axf = swd->sw_axf;
967 1.16.2.2 rmind
968 1.16.2.2 rmind if (swd->sw_ictx) {
969 1.16.2.2 rmind bzero(swd->sw_ictx, axf->auth_hash->ctxsize);
970 1.16.2.2 rmind free(swd->sw_ictx, M_CRYPTO_DATA);
971 1.16.2.2 rmind }
972 1.16.2.2 rmind if (swd->sw_octx) {
973 1.16.2.2 rmind bzero(swd->sw_octx, axf->auth_hash->ctxsize);
974 1.16.2.2 rmind free(swd->sw_octx, M_CRYPTO_DATA);
975 1.16.2.2 rmind }
976 1.16.2.2 rmind break;
977 1.16.2.2 rmind
978 1.16.2.2 rmind case CRYPTO_MD5_KPDK:
979 1.16.2.2 rmind case CRYPTO_SHA1_KPDK:
980 1.16.2.2 rmind axf = swd->sw_axf;
981 1.16.2.2 rmind
982 1.16.2.2 rmind if (swd->sw_ictx) {
983 1.16.2.2 rmind bzero(swd->sw_ictx, axf->auth_hash->ctxsize);
984 1.16.2.2 rmind free(swd->sw_ictx, M_CRYPTO_DATA);
985 1.16.2.2 rmind }
986 1.16.2.2 rmind if (swd->sw_octx) {
987 1.16.2.2 rmind bzero(swd->sw_octx, swd->sw_klen);
988 1.16.2.2 rmind free(swd->sw_octx, M_CRYPTO_DATA);
989 1.16.2.2 rmind }
990 1.16.2.2 rmind break;
991 1.16.2.2 rmind
992 1.16.2.2 rmind case CRYPTO_MD5:
993 1.16.2.2 rmind case CRYPTO_SHA1:
994 1.16.2.2 rmind axf = swd->sw_axf;
995 1.16.2.2 rmind
996 1.16.2.2 rmind if (swd->sw_ictx)
997 1.16.2.2 rmind free(swd->sw_ictx, M_CRYPTO_DATA);
998 1.16.2.2 rmind break;
999 1.16.2.2 rmind
1000 1.16.2.2 rmind case CRYPTO_DEFLATE_COMP:
1001 1.16.2.2 rmind cxf = swd->sw_cxf;
1002 1.16.2.2 rmind break;
1003 1.16.2.2 rmind }
1004 1.16.2.2 rmind
1005 1.16.2.2 rmind FREE(swd, M_CRYPTO_DATA);
1006 1.16.2.2 rmind }
1007 1.16.2.2 rmind return 0;
1008 1.16.2.2 rmind }
1009 1.16.2.2 rmind
1010 1.16.2.2 rmind /*
1011 1.16.2.2 rmind * Process a software request.
1012 1.16.2.2 rmind */
1013 1.16.2.2 rmind static int
1014 1.16.2.2 rmind swcr_process(void *arg, struct cryptop *crp, int hint)
1015 1.16.2.2 rmind {
1016 1.16.2.2 rmind struct cryptodesc *crd;
1017 1.16.2.2 rmind struct swcr_data *sw;
1018 1.16.2.2 rmind u_int32_t lid;
1019 1.16.2.2 rmind int type;
1020 1.16.2.2 rmind
1021 1.16.2.2 rmind /* Sanity check */
1022 1.16.2.2 rmind if (crp == NULL)
1023 1.16.2.2 rmind return EINVAL;
1024 1.16.2.2 rmind
1025 1.16.2.2 rmind if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
1026 1.16.2.2 rmind crp->crp_etype = EINVAL;
1027 1.16.2.2 rmind goto done;
1028 1.16.2.2 rmind }
1029 1.16.2.2 rmind
1030 1.16.2.2 rmind lid = crp->crp_sid & 0xffffffff;
1031 1.16.2.2 rmind if (lid >= swcr_sesnum || lid == 0 || swcr_sessions[lid] == NULL) {
1032 1.16.2.2 rmind crp->crp_etype = ENOENT;
1033 1.16.2.2 rmind goto done;
1034 1.16.2.2 rmind }
1035 1.16.2.2 rmind
1036 1.16.2.2 rmind if (crp->crp_flags & CRYPTO_F_IMBUF) {
1037 1.16.2.2 rmind type = CRYPTO_BUF_MBUF;
1038 1.16.2.2 rmind } else if (crp->crp_flags & CRYPTO_F_IOV) {
1039 1.16.2.2 rmind type = CRYPTO_BUF_IOV;
1040 1.16.2.2 rmind } else {
1041 1.16.2.2 rmind type = CRYPTO_BUF_CONTIG;
1042 1.16.2.2 rmind }
1043 1.16.2.2 rmind
1044 1.16.2.2 rmind /* Go through crypto descriptors, processing as we go */
1045 1.16.2.2 rmind for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
1046 1.16.2.2 rmind /*
1047 1.16.2.2 rmind * Find the crypto context.
1048 1.16.2.2 rmind *
1049 1.16.2.2 rmind * XXX Note that the logic here prevents us from having
1050 1.16.2.2 rmind * XXX the same algorithm multiple times in a session
1051 1.16.2.2 rmind * XXX (or rather, we can but it won't give us the right
1052 1.16.2.2 rmind * XXX results). To do that, we'd need some way of differentiating
1053 1.16.2.2 rmind * XXX between the various instances of an algorithm (so we can
1054 1.16.2.2 rmind * XXX locate the correct crypto context).
1055 1.16.2.2 rmind */
1056 1.16.2.2 rmind for (sw = swcr_sessions[lid];
1057 1.16.2.2 rmind sw && sw->sw_alg != crd->crd_alg;
1058 1.16.2.2 rmind sw = sw->sw_next)
1059 1.16.2.2 rmind ;
1060 1.16.2.2 rmind
1061 1.16.2.2 rmind /* No such context ? */
1062 1.16.2.2 rmind if (sw == NULL) {
1063 1.16.2.2 rmind crp->crp_etype = EINVAL;
1064 1.16.2.2 rmind goto done;
1065 1.16.2.2 rmind }
1066 1.16.2.2 rmind
1067 1.16.2.2 rmind switch (sw->sw_alg) {
1068 1.16.2.2 rmind case CRYPTO_DES_CBC:
1069 1.16.2.2 rmind case CRYPTO_3DES_CBC:
1070 1.16.2.2 rmind case CRYPTO_BLF_CBC:
1071 1.16.2.2 rmind case CRYPTO_CAST_CBC:
1072 1.16.2.2 rmind case CRYPTO_SKIPJACK_CBC:
1073 1.16.2.2 rmind case CRYPTO_RIJNDAEL128_CBC:
1074 1.16.2.2 rmind if ((crp->crp_etype = swcr_encdec(crd, sw,
1075 1.16.2.2 rmind crp->crp_buf, type)) != 0)
1076 1.16.2.2 rmind goto done;
1077 1.16.2.2 rmind break;
1078 1.16.2.2 rmind case CRYPTO_NULL_CBC:
1079 1.16.2.2 rmind crp->crp_etype = 0;
1080 1.16.2.2 rmind break;
1081 1.16.2.2 rmind case CRYPTO_MD5_HMAC:
1082 1.16.2.2 rmind case CRYPTO_SHA1_HMAC:
1083 1.16.2.2 rmind case CRYPTO_SHA2_HMAC:
1084 1.16.2.2 rmind case CRYPTO_RIPEMD160_HMAC:
1085 1.16.2.2 rmind case CRYPTO_NULL_HMAC:
1086 1.16.2.2 rmind case CRYPTO_MD5_KPDK:
1087 1.16.2.2 rmind case CRYPTO_SHA1_KPDK:
1088 1.16.2.2 rmind case CRYPTO_MD5:
1089 1.16.2.2 rmind case CRYPTO_SHA1:
1090 1.16.2.2 rmind if ((crp->crp_etype = swcr_authcompute(crp, crd, sw,
1091 1.16.2.2 rmind crp->crp_buf, type)) != 0)
1092 1.16.2.2 rmind goto done;
1093 1.16.2.2 rmind break;
1094 1.16.2.2 rmind
1095 1.16.2.2 rmind case CRYPTO_DEFLATE_COMP:
1096 1.16.2.2 rmind if ((crp->crp_etype = swcr_compdec(crd, sw,
1097 1.16.2.2 rmind crp->crp_buf, type)) != 0)
1098 1.16.2.2 rmind goto done;
1099 1.16.2.2 rmind else
1100 1.16.2.2 rmind crp->crp_olen = (int)sw->sw_size;
1101 1.16.2.2 rmind break;
1102 1.16.2.2 rmind
1103 1.16.2.2 rmind default:
1104 1.16.2.2 rmind /* Unknown/unsupported algorithm */
1105 1.16.2.2 rmind crp->crp_etype = EINVAL;
1106 1.16.2.2 rmind goto done;
1107 1.16.2.2 rmind }
1108 1.16.2.2 rmind }
1109 1.16.2.2 rmind
1110 1.16.2.2 rmind done:
1111 1.16.2.2 rmind crypto_done(crp);
1112 1.16.2.2 rmind return 0;
1113 1.16.2.2 rmind }
1114 1.16.2.2 rmind
1115 1.16.2.2 rmind static void
1116 1.16.2.2 rmind swcr_init(void)
1117 1.16.2.2 rmind {
1118 1.16.2.2 rmind swcr_id = crypto_get_driverid(CRYPTOCAP_F_SOFTWARE);
1119 1.16.2.2 rmind if (swcr_id < 0) {
1120 1.16.2.2 rmind /* This should never happen */
1121 1.16.2.2 rmind panic("Software crypto device cannot initialize!");
1122 1.16.2.2 rmind }
1123 1.16.2.2 rmind
1124 1.16.2.2 rmind crypto_register(swcr_id, CRYPTO_DES_CBC,
1125 1.16.2.2 rmind 0, 0, swcr_newsession, swcr_freesession, swcr_process, NULL);
1126 1.16.2.2 rmind #define REGISTER(alg) \
1127 1.16.2.2 rmind crypto_register(swcr_id, alg, 0, 0, NULL, NULL, NULL, NULL)
1128 1.16.2.2 rmind
1129 1.16.2.2 rmind REGISTER(CRYPTO_3DES_CBC);
1130 1.16.2.2 rmind REGISTER(CRYPTO_BLF_CBC);
1131 1.16.2.2 rmind REGISTER(CRYPTO_CAST_CBC);
1132 1.16.2.2 rmind REGISTER(CRYPTO_SKIPJACK_CBC);
1133 1.16.2.2 rmind REGISTER(CRYPTO_NULL_CBC);
1134 1.16.2.2 rmind REGISTER(CRYPTO_MD5_HMAC);
1135 1.16.2.2 rmind REGISTER(CRYPTO_SHA1_HMAC);
1136 1.16.2.2 rmind REGISTER(CRYPTO_SHA2_HMAC);
1137 1.16.2.2 rmind REGISTER(CRYPTO_RIPEMD160_HMAC);
1138 1.16.2.2 rmind REGISTER(CRYPTO_NULL_HMAC);
1139 1.16.2.2 rmind REGISTER(CRYPTO_MD5_KPDK);
1140 1.16.2.2 rmind REGISTER(CRYPTO_SHA1_KPDK);
1141 1.16.2.2 rmind REGISTER(CRYPTO_MD5);
1142 1.16.2.2 rmind REGISTER(CRYPTO_SHA1);
1143 1.16.2.2 rmind REGISTER(CRYPTO_RIJNDAEL128_CBC);
1144 1.16.2.2 rmind REGISTER(CRYPTO_DEFLATE_COMP);
1145 1.16.2.2 rmind #undef REGISTER
1146 1.16.2.2 rmind }
1147 1.16.2.2 rmind
1148 1.16.2.2 rmind #ifdef __FreeBSD__
1149 1.16.2.2 rmind SYSINIT(cryptosoft_init, SI_SUB_PSEUDO, SI_ORDER_ANY, swcr_init, NULL)
1150 1.16.2.2 rmind #endif
1151 1.16.2.2 rmind
1152 1.16.2.2 rmind #ifdef __NetBSD__
1153 1.16.2.2 rmind /*
1154 1.16.2.2 rmind * Pseudo-device init routine for software crypto.
1155 1.16.2.2 rmind */
1156 1.16.2.2 rmind void swcryptoattach(int);
1157 1.16.2.2 rmind
1158 1.16.2.2 rmind void
1159 1.16.2.2 rmind swcryptoattach(int num)
1160 1.16.2.2 rmind {
1161 1.16.2.2 rmind
1162 1.16.2.2 rmind swcr_init();
1163 1.16.2.2 rmind }
1164 1.16.2.2 rmind #endif /* __NetBSD__ */
1165