xref: /netbsd-src/sys/dev/cgd_crypto.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1 /* $NetBSD: cgd_crypto.c,v 1.13 2015/04/25 12:55:04 riastradh 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.13 2015/04/25 12:55:04 riastradh 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 #include <crypto/rijndael/rijndael-api-fst.h>
49 #include <crypto/des/des.h>
50 #include <crypto/blowfish/blowfish.h>
51 
52 #ifdef DIAGNOSTIC
53 #define DIAGPANIC(x)	panic x
54 #else
55 #define DIAGPANIC(x)
56 #endif
57 
58 /*
59  * The general framework provides only one generic function.
60  * It takes the name of an algorith and returns a struct cryptfuncs *
61  * for it.  It is up to the initialisation routines of the algorithm
62  * to check key size and block size.
63  */
64 
65 static cfunc_init	cgd_cipher_aes_init;
66 static cfunc_destroy	cgd_cipher_aes_destroy;
67 static cfunc_cipher	cgd_cipher_aes_cbc;
68 
69 static cfunc_init	cgd_cipher_3des_init;
70 static cfunc_destroy	cgd_cipher_3des_destroy;
71 static cfunc_cipher	cgd_cipher_3des_cbc;
72 
73 static cfunc_init	cgd_cipher_bf_init;
74 static cfunc_destroy	cgd_cipher_bf_destroy;
75 static cfunc_cipher	cgd_cipher_bf_cbc;
76 
77 static const struct cryptfuncs cf[] = {
78 	{
79 		.cf_name	= "aes-cbc",
80 		.cf_init	= cgd_cipher_aes_init,
81 		.cf_destroy	= cgd_cipher_aes_destroy,
82 		.cf_cipher	= cgd_cipher_aes_cbc,
83 	},
84 	{
85 		.cf_name	= "3des-cbc",
86 		.cf_init	= cgd_cipher_3des_init,
87 		.cf_destroy	= cgd_cipher_3des_destroy,
88 		.cf_cipher	= cgd_cipher_3des_cbc,
89 	},
90 	{
91 		.cf_name	= "blowfish-cbc",
92 		.cf_init	= cgd_cipher_bf_init,
93 		.cf_destroy	= cgd_cipher_bf_destroy,
94 		.cf_cipher	= cgd_cipher_bf_cbc,
95 	},
96 };
97 const struct cryptfuncs *
98 cryptfuncs_find(const char *alg)
99 {
100 
101 	for (size_t i = 0; i < __arraycount(cf); i++)
102 		if (strcmp(cf[i].cf_name, alg) == 0)
103 			return &cf[i];
104 
105 	return NULL;
106 }
107 
108 typedef void	(*cipher_func)(void *, void *, const void *, size_t);
109 
110 static void
111 cgd_cipher_uio_cbc(void *privdata, cipher_func cipher,
112 	struct uio *dstuio, struct uio *srcuio);
113 
114 /*
115  * cgd_cipher_uio_cbc takes a simple cbc cipher and iterates
116  * it over two struct uio's.  It presumes that the cipher function
117  * that is passed to it keeps the IV state between calls.
118  *
119  * We assume that the caller has ensured that each segment is evenly
120  * divisible by the block size, which for the cgd is a valid assumption.
121  * If we were to make this code more generic, we might need to take care
122  * of this case, either by issuing an error or copying the data.
123  */
124 
125 static void
126 cgd_cipher_uio_cbc(void *privdata, cipher_func cipher,
127     struct uio *dstuio, struct uio *srcuio)
128 {
129 	const struct iovec	*dst;
130 	const struct iovec	*src;
131 	int		 dstnum;
132 	int		 dstoff = 0;
133 	int		 srcnum;
134 	int		 srcoff = 0;
135 
136 	dst = dstuio->uio_iov;
137 	dstnum = dstuio->uio_iovcnt;
138 	src = srcuio->uio_iov;
139 	srcnum = srcuio->uio_iovcnt;
140 	for (;;) {
141 		int	  l = MIN(dst->iov_len - dstoff, src->iov_len - srcoff);
142 		u_int8_t *d = (u_int8_t *)dst->iov_base + dstoff;
143 		const u_int8_t *s = (const u_int8_t *)src->iov_base + srcoff;
144 
145 		cipher(privdata, d, s, l);
146 
147 		dstoff += l;
148 		srcoff += l;
149 		/*
150 		 * We assume that {dst,src} == {dst,src}->iov_len,
151 		 * because it should not be possible for it not to be.
152 		 */
153 		if (dstoff == dst->iov_len) {
154 			dstoff = 0;
155 			dstnum--;
156 			dst++;
157 		}
158 		if (srcoff == src->iov_len) {
159 			srcoff = 0;
160 			srcnum--;
161 			src++;
162 		}
163 		if (!srcnum || !dstnum)
164 			break;
165 	}
166 }
167 
168 /*
169  *  AES Framework
170  */
171 
172 /*
173  * NOTE: we do not store the blocksize in here, because it is not
174  *       variable [yet], we hardcode the blocksize to 16 (128 bits).
175  */
176 
177 struct aes_privdata {
178 	keyInstance	ap_enckey;
179 	keyInstance	ap_deckey;
180 };
181 
182 struct aes_encdata {
183 	keyInstance	*ae_key;	/* key for this direction */
184 	u_int8_t	 ae_iv[16];	/* Initialization Vector */
185 };
186 
187 static void *
188 cgd_cipher_aes_init(size_t keylen, const void *key, size_t *blocksize)
189 {
190 	struct	aes_privdata *ap;
191 
192 	if (!blocksize)
193 		return NULL;
194 	if (keylen != 128 && keylen != 192 && keylen != 256)
195 		return NULL;
196 	if (*blocksize == (size_t)-1)
197 		*blocksize = 128;
198 	if (*blocksize != 128)
199 		return NULL;
200 	ap = malloc(sizeof(*ap), M_DEVBUF, 0);
201 	if (!ap)
202 		return NULL;
203 	rijndael_makeKey(&ap->ap_enckey, DIR_ENCRYPT, keylen, key);
204 	rijndael_makeKey(&ap->ap_deckey, DIR_DECRYPT, keylen, key);
205 	return ap;
206 }
207 
208 static void
209 cgd_cipher_aes_destroy(void *data)
210 {
211 	struct aes_privdata *apd = data;
212 
213 	explicit_memset(apd, 0, sizeof(*apd));
214 	free(apd, M_DEVBUF);
215 }
216 
217 static void
218 aes_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
219 {
220 	struct aes_encdata	*ae = privdata;
221 	cipherInstance		 cipher;
222 
223 	rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
224 	rijndael_blockEncrypt(&cipher, ae->ae_key, src, len * 8, dst);
225 	(void)memcpy(ae->ae_iv, (u_int8_t *)dst + (len - 16), 16);
226 }
227 
228 static void
229 aes_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
230 {
231 	struct aes_encdata	*ae = privdata;
232 	cipherInstance		 cipher;
233 
234 	rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
235 	rijndael_blockDecrypt(&cipher, ae->ae_key, src, len * 8, dst);
236 	(void)memcpy(ae->ae_iv, (const u_int8_t *)src + (len - 16), 16);
237 }
238 
239 static void
240 cgd_cipher_aes_cbc(void *privdata, struct uio *dstuio,
241     struct uio *srcuio, const void *iv, int dir)
242 {
243 	struct aes_privdata	*apd = privdata;
244 	struct aes_encdata	 encd;
245 
246 	(void)memcpy(encd.ae_iv, iv, 16);
247 	switch (dir) {
248 	case CGD_CIPHER_ENCRYPT:
249 		encd.ae_key = &apd->ap_enckey;
250 		cgd_cipher_uio_cbc(&encd, aes_cbc_enc_int, dstuio, srcuio);
251 		break;
252 	case CGD_CIPHER_DECRYPT:
253 		encd.ae_key = &apd->ap_deckey;
254 		cgd_cipher_uio_cbc(&encd, aes_cbc_dec_int, dstuio, srcuio);
255 		break;
256 	default:
257 		DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
258 	}
259 }
260 
261 /*
262  * 3DES Framework
263  */
264 
265 struct c3des_privdata {
266 	des_key_schedule	cp_key1;
267 	des_key_schedule	cp_key2;
268 	des_key_schedule	cp_key3;
269 };
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 static 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 		explicit_memset(cp, 0, sizeof(*cp));
300 		free(cp, M_DEVBUF);
301 		return NULL;
302 	}
303 	return cp;
304 }
305 
306 static void
307 cgd_cipher_3des_destroy(void *data)
308 {
309 	struct c3des_privdata *cp = data;
310 
311 	explicit_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 static void
336 cgd_cipher_3des_cbc(void *privdata, struct uio *dstuio,
337 	struct uio *srcuio, const 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 struct bf_privdata {
363 	BF_KEY	bp_key;
364 };
365 
366 struct bf_encdata {
367 	BF_KEY		*be_key;
368 	u_int8_t	 be_iv[8];
369 };
370 
371 static void *
372 cgd_cipher_bf_init(size_t keylen, const void *key, size_t *blocksize)
373 {
374 	struct	bf_privdata *bp;
375 
376 	if (!blocksize)
377 		return NULL;
378 	if (keylen < 40 || keylen > 448 || (keylen % 8 != 0))
379 		return NULL;
380 	if (*blocksize == (size_t)-1)
381 		*blocksize = 64;
382 	if (*blocksize != 64)
383 		return NULL;
384 	bp = malloc(sizeof(*bp), M_DEVBUF, 0);
385 	if (!bp)
386 		return NULL;
387 	BF_set_key(&bp->bp_key, keylen / 8, key);
388 	return bp;
389 }
390 
391 static void
392 cgd_cipher_bf_destroy(void *data)
393 {
394 	struct	bf_privdata *bp = data;
395 
396 	explicit_memset(bp, 0, sizeof(*bp));
397 	free(bp, M_DEVBUF);
398 }
399 
400 static void
401 bf_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
402 {
403 	struct	bf_encdata *be = privdata;
404 
405 	BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 1);
406 	(void)memcpy(be->be_iv, (u_int8_t *)dst + (len - 8), 8);
407 }
408 
409 static void
410 bf_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
411 {
412 	struct	bf_encdata *be = privdata;
413 
414 	BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 0);
415 	(void)memcpy(be->be_iv, (const u_int8_t *)src + (len - 8), 8);
416 }
417 
418 static void
419 cgd_cipher_bf_cbc(void *privdata, struct uio *dstuio,
420     struct uio *srcuio, const void *iv, int dir)
421 {
422 	struct	bf_privdata *bp = privdata;
423 	struct	bf_encdata be;
424 
425 	(void)memcpy(be.be_iv, iv, 8);
426 	be.be_key = &bp->bp_key;
427 	switch (dir) {
428 	case CGD_CIPHER_ENCRYPT:
429 		cgd_cipher_uio_cbc(&be, bf_cbc_enc_int, dstuio, srcuio);
430 		break;
431 	case CGD_CIPHER_DECRYPT:
432 		cgd_cipher_uio_cbc(&be, bf_cbc_dec_int, dstuio, srcuio);
433 		break;
434 	default:
435 		DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
436 	}
437 
438 }
439