xref: /netbsd-src/sys/dev/cgd_crypto.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /* $NetBSD: cgd_crypto.c,v 1.9 2008/04/28 20:23:46 martin Exp $ */
2 
3 /*-
4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Roland C. Dowdeswell.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  *  Crypto Framework For cgd.c
34  *
35  *	This framework is temporary and awaits a more complete
36  *	kernel wide crypto implementation.
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: cgd_crypto.c,v 1.9 2008/04/28 20:23:46 martin Exp $");
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/malloc.h>
45 
46 #include <dev/cgd_crypto.h>
47 
48 #ifdef DIAGNOSTIC
49 #define DIAGPANIC(x)	panic x
50 #else
51 #define DIAGPANIC(x)
52 #endif
53 
54 /*
55  * The general framework provides only one generic function.
56  * It takes the name of an algorith and returns a struct cryptfuncs *
57  * for it.  It is up to the initialisation routines of the algorithm
58  * to check key size and block size.
59  */
60 
61 extern struct cryptfuncs cgd_AES_funcs;
62 extern struct cryptfuncs cgd_3des_funcs;
63 extern struct cryptfuncs cgd_BF_funcs;
64 
65 struct cryptfuncs *
66 cryptfuncs_find(const char *alg)
67 {
68 
69 	if (!strcmp("aes-cbc", alg))
70 		return &cgd_AES_funcs;
71 	if (!strcmp("3des-cbc", alg))
72 		return &cgd_3des_funcs;
73 	if (!strcmp("blowfish-cbc", alg))
74 		return &cgd_BF_funcs;
75 	return NULL;
76 }
77 
78 typedef void	(*cipher_func)(void *, void *, const void *, size_t);
79 
80 void
81 cgd_cipher_uio_cbc(void *privdata, cipher_func cipher,
82 	struct uio *dstuio, struct uio *srcuio);
83 
84 /*
85  * cgd_cipher_uio_cbc takes a simple cbc cipher and iterates
86  * it over two struct uio's.  It presumes that the cipher function
87  * that is passed to it keeps the IV state between calls.
88  *
89  * We assume that the caller has ensured that each segment is evenly
90  * divisible by the block size, which for the cgd is a valid assumption.
91  * If we were to make this code more generic, we might need to take care
92  * of this case, either by issuing an error or copying the data.
93  */
94 
95 void
96 cgd_cipher_uio_cbc(void *privdata, cipher_func cipher,
97     struct uio *dstuio, struct uio *srcuio)
98 {
99 	struct iovec	*dst;
100 	struct iovec	*src;
101 	int		 dstnum;
102 	int		 dstoff = 0;
103 	int		 srcnum;
104 	int		 srcoff = 0;
105 
106 	dst = dstuio->uio_iov;
107 	dstnum = dstuio->uio_iovcnt;
108 	src = srcuio->uio_iov;
109 	srcnum = srcuio->uio_iovcnt;
110 	for (;;) {
111 		int	  l = MIN(dst->iov_len - dstoff, src->iov_len - srcoff);
112 		u_int8_t *d = (u_int8_t *)dst->iov_base + dstoff;
113 		u_int8_t *s = (u_int8_t *)src->iov_base + srcoff;
114 
115 		cipher(privdata, d, s, l);
116 
117 		dstoff += l;
118 		srcoff += l;
119 		/*
120 		 * We assume that {dst,src} == {dst,src}->iov_len,
121 		 * because it should not be possible for it not to be.
122 		 */
123 		if (dstoff == dst->iov_len) {
124 			dstoff = 0;
125 			dstnum--;
126 			dst++;
127 		}
128 		if (srcoff == src->iov_len) {
129 			srcoff = 0;
130 			srcnum--;
131 			src++;
132 		}
133 		if (!srcnum || !dstnum)
134 			break;
135 	}
136 }
137 
138 /*
139  *  AES Framework
140  */
141 
142 #include <crypto/rijndael/rijndael-api-fst.h>
143 
144 cfunc_init	cgd_cipher_aes_init;
145 cfunc_destroy	cgd_cipher_aes_destroy;
146 cfunc_cipher	cgd_cipher_aes_cbc;
147 
148 struct cryptfuncs cgd_AES_funcs = {
149 	cgd_cipher_aes_init,
150 	cgd_cipher_aes_destroy,
151 	cgd_cipher_aes_cbc,
152 };
153 
154 /*
155  * NOTE: we do not store the blocksize in here, because it is not
156  *       variable [yet], we hardcode the blocksize to 16 (128 bits).
157  */
158 
159 struct aes_privdata {
160 	keyInstance	ap_enckey;
161 	keyInstance	ap_deckey;
162 };
163 
164 struct aes_encdata {
165 	keyInstance	*ae_key;	/* key for this direction */
166 	u_int8_t	 ae_iv[16];	/* Initialization Vector */
167 };
168 
169 static void	aes_cbc_enc_int(void *, void *, const void *, size_t);
170 static void	aes_cbc_dec_int(void *, void *, const void *, size_t);
171 
172 void *
173 cgd_cipher_aes_init(size_t keylen, const void *key, size_t *blocksize)
174 {
175 	struct	aes_privdata *ap;
176 
177 	if (!blocksize)
178 		return NULL;
179 	if (keylen != 128 && keylen != 192 && keylen != 256)
180 		return NULL;
181 	if (*blocksize == (size_t)-1)
182 		*blocksize = 128;
183 	if (*blocksize != 128)
184 		return NULL;
185 	ap = malloc(sizeof(*ap), M_DEVBUF, 0);
186 	if (!ap)
187 		return NULL;
188 	rijndael_makeKey(&ap->ap_enckey, DIR_ENCRYPT, keylen, key);
189 	rijndael_makeKey(&ap->ap_deckey, DIR_DECRYPT, keylen, key);
190 	return ap;
191 }
192 
193 void
194 cgd_cipher_aes_destroy(void *data)
195 {
196 	struct aes_privdata *apd = data;
197 
198 	(void)memset(apd, 0, sizeof(*apd));
199 	free(apd, M_DEVBUF);
200 }
201 
202 void
203 aes_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
204 {
205 	struct aes_encdata	*ae = privdata;
206 	cipherInstance		 cipher;
207 
208 	rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
209 	rijndael_blockEncrypt(&cipher, ae->ae_key, src, len * 8, dst);
210 	(void)memcpy(ae->ae_iv, (u_int8_t *)dst + (len - 16), 16);
211 }
212 
213 void
214 aes_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
215 {
216 	struct aes_encdata	*ae = privdata;
217 	cipherInstance		 cipher;
218 
219 	rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
220 	rijndael_blockDecrypt(&cipher, ae->ae_key, src, len * 8, dst);
221 	(void)memcpy(ae->ae_iv, (const u_int8_t *)src + (len - 16), 16);
222 }
223 
224 void
225 cgd_cipher_aes_cbc(void *privdata, struct uio *dstuio,
226     struct uio *srcuio, void *iv, int dir)
227 {
228 	struct aes_privdata	*apd = privdata;
229 	struct aes_encdata	 encd;
230 
231 	(void)memcpy(encd.ae_iv, iv, 16);
232 	switch (dir) {
233 	case CGD_CIPHER_ENCRYPT:
234 		encd.ae_key = &apd->ap_enckey;
235 		cgd_cipher_uio_cbc(&encd, aes_cbc_enc_int, dstuio, srcuio);
236 		break;
237 	case CGD_CIPHER_DECRYPT:
238 		encd.ae_key = &apd->ap_deckey;
239 		cgd_cipher_uio_cbc(&encd, aes_cbc_dec_int, dstuio, srcuio);
240 		break;
241 	default:
242 		DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
243 	}
244 }
245 
246 /*
247  * 3DES Framework
248  */
249 
250 #include <crypto/des/des.h>
251 
252 cfunc_init	cgd_cipher_3des_init;
253 cfunc_destroy	cgd_cipher_3des_destroy;
254 cfunc_cipher	cgd_cipher_3des_cbc;
255 
256 struct cryptfuncs cgd_3des_funcs = {
257 	cgd_cipher_3des_init,
258 	cgd_cipher_3des_destroy,
259 	cgd_cipher_3des_cbc,
260 };
261 
262 struct c3des_privdata {
263 	des_key_schedule	cp_key1;
264 	des_key_schedule	cp_key2;
265 	des_key_schedule	cp_key3;
266 };
267 
268 static void	c3des_cbc_enc_int(void *, void *, const void *, size_t);
269 static void	c3des_cbc_dec_int(void *, void *, const void *, size_t);
270 
271 struct c3des_encdata {
272 	des_key_schedule	*ce_key1;
273 	des_key_schedule	*ce_key2;
274 	des_key_schedule	*ce_key3;
275 	u_int8_t		ce_iv[8];
276 };
277 
278 void *
279 cgd_cipher_3des_init(size_t keylen, const void *key, size_t *blocksize)
280 {
281 	struct	c3des_privdata *cp;
282 	int	error = 0;
283 	des_cblock *block;
284 
285 	if (!blocksize)
286 		return NULL;
287 	if (*blocksize == (size_t)-1)
288 		*blocksize = 64;
289 	if (keylen != (DES_KEY_SZ * 3 * 8) || *blocksize != 64)
290 		return NULL;
291 	cp = malloc(sizeof(*cp), M_DEVBUF, 0);
292 	if (!cp)
293 		return NULL;
294 	block = __UNCONST(key);
295 	error  = des_key_sched(block, cp->cp_key1);
296 	error |= des_key_sched(block + 1, cp->cp_key2);
297 	error |= des_key_sched(block + 2, cp->cp_key3);
298 	if (error) {
299 		(void)memset(cp, 0, sizeof(*cp));
300 		free(cp, M_DEVBUF);
301 		return NULL;
302 	}
303 	return cp;
304 }
305 
306 void
307 cgd_cipher_3des_destroy(void *data)
308 {
309 	struct c3des_privdata *cp = data;
310 
311 	(void)memset(cp, 0, sizeof(*cp));
312 	free(cp, M_DEVBUF);
313 }
314 
315 static void
316 c3des_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
317 {
318 	struct	c3des_encdata *ce = privdata;
319 
320 	des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2,
321 	    *ce->ce_key3, (des_cblock *)ce->ce_iv, 1);
322 	(void)memcpy(ce->ce_iv, (const u_int8_t *)dst + (len - 8), 8);
323 }
324 
325 static void
326 c3des_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
327 {
328 	struct	c3des_encdata *ce = privdata;
329 
330 	des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2,
331 	    *ce->ce_key3, (des_cblock *)ce->ce_iv, 0);
332 	(void)memcpy(ce->ce_iv, (const u_int8_t *)src + (len - 8), 8);
333 }
334 
335 void
336 cgd_cipher_3des_cbc(void *privdata, struct uio *dstuio,
337 	struct uio *srcuio, void *iv, int dir)
338 {
339 	struct	c3des_privdata *cp = privdata;
340 	struct	c3des_encdata ce;
341 
342 	(void)memcpy(ce.ce_iv, iv, 8);
343 	ce.ce_key1 = &cp->cp_key1;
344 	ce.ce_key2 = &cp->cp_key2;
345 	ce.ce_key3 = &cp->cp_key3;
346 	switch (dir) {
347 	case CGD_CIPHER_ENCRYPT:
348 		cgd_cipher_uio_cbc(&ce, c3des_cbc_enc_int, dstuio, srcuio);
349 		break;
350 	case CGD_CIPHER_DECRYPT:
351 		cgd_cipher_uio_cbc(&ce, c3des_cbc_dec_int, dstuio, srcuio);
352 		break;
353 	default:
354 		DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
355 	}
356 }
357 
358 /*
359  * Blowfish Framework
360  */
361 
362 #include <crypto/blowfish/blowfish.h>
363 
364 cfunc_init	cgd_cipher_bf_init;
365 cfunc_destroy	cgd_cipher_bf_destroy;
366 cfunc_cipher	cgd_cipher_bf_cbc;
367 
368 struct cryptfuncs cgd_BF_funcs = {
369 	cgd_cipher_bf_init,
370 	cgd_cipher_bf_destroy,
371 	cgd_cipher_bf_cbc,
372 };
373 
374 static void	bf_cbc_enc_int(void *, void *, const void *, size_t);
375 static void	bf_cbc_dec_int(void *, void *, const void *, size_t);
376 
377 struct bf_privdata {
378 	BF_KEY	bp_key;
379 };
380 
381 struct bf_encdata {
382 	BF_KEY		*be_key;
383 	u_int8_t	 be_iv[8];
384 };
385 
386 void *
387 cgd_cipher_bf_init(size_t keylen, const void *key, size_t *blocksize)
388 {
389 	struct	bf_privdata *bp;
390 
391 	if (!blocksize)
392 		return NULL;
393 	if (keylen < 40 || keylen > 448 || (keylen % 8 != 0))
394 		return NULL;
395 	if (*blocksize == (size_t)-1)
396 		*blocksize = 64;
397 	if (*blocksize != 64)
398 		return NULL;
399 	bp = malloc(sizeof(*bp), M_DEVBUF, 0);
400 	if (!bp)
401 		return NULL;
402 	BF_set_key(&bp->bp_key, keylen / 8, key);
403 	return bp;
404 }
405 
406 void
407 cgd_cipher_bf_destroy(void *data)
408 {
409 	struct	bf_privdata *bp = data;
410 
411 	(void)memset(bp, 0, sizeof(*bp));
412 	free(bp, M_DEVBUF);
413 }
414 
415 void
416 bf_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
417 {
418 	struct	bf_encdata *be = privdata;
419 
420 	BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 1);
421 	(void)memcpy(be->be_iv, (u_int8_t *)dst + (len - 8), 8);
422 }
423 
424 void
425 bf_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
426 {
427 	struct	bf_encdata *be = privdata;
428 
429 	BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 0);
430 	(void)memcpy(be->be_iv, (const u_int8_t *)src + (len - 8), 8);
431 }
432 
433 void
434 cgd_cipher_bf_cbc(void *privdata, struct uio *dstuio,
435     struct uio *srcuio, void *iv, int dir)
436 {
437 	struct	bf_privdata *bp = privdata;
438 	struct	bf_encdata be;
439 
440 	(void)memcpy(be.be_iv, iv, 8);
441 	be.be_key = &bp->bp_key;
442 	switch (dir) {
443 	case CGD_CIPHER_ENCRYPT:
444 		cgd_cipher_uio_cbc(&be, bf_cbc_enc_int, dstuio, srcuio);
445 		break;
446 	case CGD_CIPHER_DECRYPT:
447 		cgd_cipher_uio_cbc(&be, bf_cbc_dec_int, dstuio, srcuio);
448 		break;
449 	default:
450 		DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
451 	}
452 
453 }
454