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