cgd_crypto.c revision 1.15 1 /* $NetBSD: cgd_crypto.c,v 1.15 2017/01/02 14:28:29 alnsn 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.15 2017/01/02 14:28:29 alnsn 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_cbc_init;
66 static cfunc_destroy cgd_cipher_aes_cbc_destroy;
67 static cfunc_cipher cgd_cipher_aes_cbc;
68 static cfunc_cipher_prep cgd_cipher_aes_cbc_prep;
69
70 static cfunc_init cgd_cipher_aes_xts_init;
71 static cfunc_destroy cgd_cipher_aes_xts_destroy;
72 static cfunc_cipher cgd_cipher_aes_xts;
73 static cfunc_cipher_prep cgd_cipher_aes_xts_prep;
74
75 static cfunc_init cgd_cipher_3des_init;
76 static cfunc_destroy cgd_cipher_3des_destroy;
77 static cfunc_cipher cgd_cipher_3des_cbc;
78 static cfunc_cipher_prep cgd_cipher_3des_cbc_prep;
79
80 static cfunc_init cgd_cipher_bf_init;
81 static cfunc_destroy cgd_cipher_bf_destroy;
82 static cfunc_cipher cgd_cipher_bf_cbc;
83 static cfunc_cipher_prep cgd_cipher_bf_cbc_prep;
84
85 static const struct cryptfuncs cf[] = {
86 {
87 .cf_name = "aes-xts",
88 .cf_init = cgd_cipher_aes_xts_init,
89 .cf_destroy = cgd_cipher_aes_xts_destroy,
90 .cf_cipher = cgd_cipher_aes_xts,
91 .cf_cipher_prep = cgd_cipher_aes_xts_prep,
92 },
93 {
94 .cf_name = "aes-cbc",
95 .cf_init = cgd_cipher_aes_cbc_init,
96 .cf_destroy = cgd_cipher_aes_cbc_destroy,
97 .cf_cipher = cgd_cipher_aes_cbc,
98 .cf_cipher_prep = cgd_cipher_aes_cbc_prep,
99 },
100 {
101 .cf_name = "3des-cbc",
102 .cf_init = cgd_cipher_3des_init,
103 .cf_destroy = cgd_cipher_3des_destroy,
104 .cf_cipher = cgd_cipher_3des_cbc,
105 .cf_cipher_prep = cgd_cipher_3des_cbc_prep,
106 },
107 {
108 .cf_name = "blowfish-cbc",
109 .cf_init = cgd_cipher_bf_init,
110 .cf_destroy = cgd_cipher_bf_destroy,
111 .cf_cipher = cgd_cipher_bf_cbc,
112 .cf_cipher_prep = cgd_cipher_bf_cbc_prep,
113 },
114 };
115 const struct cryptfuncs *
116 cryptfuncs_find(const char *alg)
117 {
118
119 for (size_t i = 0; i < __arraycount(cf); i++)
120 if (strcmp(cf[i].cf_name, alg) == 0)
121 return &cf[i];
122
123 return NULL;
124 }
125
126 typedef void (*cipher_func)(void *, void *, const void *, size_t);
127
128 static void
129 cgd_cipher_uio(void *privdata, cipher_func cipher,
130 struct uio *dstuio, struct uio *srcuio);
131
132 /*
133 * cgd_cipher_uio takes a simple cbc or xts cipher and iterates
134 * it over two struct uio's. It presumes that the cipher function
135 * that is passed to it keeps the IV state between calls.
136 *
137 * We assume that the caller has ensured that each segment is evenly
138 * divisible by the block size, which for the cgd is a valid assumption.
139 * If we were to make this code more generic, we might need to take care
140 * of this case, either by issuing an error or copying the data.
141 */
142
143 static void
144 cgd_cipher_uio(void *privdata, cipher_func cipher,
145 struct uio *dstuio, struct uio *srcuio)
146 {
147 const struct iovec *dst;
148 const struct iovec *src;
149 int dstnum;
150 int dstoff = 0;
151 int srcnum;
152 int srcoff = 0;
153
154 dst = dstuio->uio_iov;
155 dstnum = dstuio->uio_iovcnt;
156 src = srcuio->uio_iov;
157 srcnum = srcuio->uio_iovcnt;
158 for (;;) {
159 int l = MIN(dst->iov_len - dstoff, src->iov_len - srcoff);
160 u_int8_t *d = (u_int8_t *)dst->iov_base + dstoff;
161 const u_int8_t *s = (const u_int8_t *)src->iov_base + srcoff;
162
163 cipher(privdata, d, s, l);
164
165 dstoff += l;
166 srcoff += l;
167 /*
168 * We assume that {dst,src} == {dst,src}->iov_len,
169 * because it should not be possible for it not to be.
170 */
171 if (dstoff == dst->iov_len) {
172 dstoff = 0;
173 dstnum--;
174 dst++;
175 }
176 if (srcoff == src->iov_len) {
177 srcoff = 0;
178 srcnum--;
179 src++;
180 }
181 if (!srcnum || !dstnum)
182 break;
183 }
184 }
185
186 /*
187 * AES Framework
188 */
189
190 /*
191 * NOTE: we do not store the blocksize in here, because it is not
192 * variable [yet], we hardcode the blocksize to 16 (128 bits).
193 */
194
195 struct aes_privdata {
196 keyInstance ap_enckey;
197 keyInstance ap_deckey;
198 };
199
200 struct aes_encdata {
201 keyInstance *ae_key; /* key for this direction */
202 u_int8_t ae_iv[CGD_AES_BLOCK_SIZE]; /* Initialization Vector */
203 };
204
205 static void *
206 cgd_cipher_aes_cbc_init(size_t keylen, const void *key, size_t *blocksize)
207 {
208 struct aes_privdata *ap;
209
210 if (!blocksize)
211 return NULL;
212 if (keylen != 128 && keylen != 192 && keylen != 256)
213 return NULL;
214 if (*blocksize == (size_t)-1)
215 *blocksize = 128;
216 if (*blocksize != 128)
217 return NULL;
218 ap = malloc(sizeof(*ap), M_DEVBUF, 0);
219 if (!ap)
220 return NULL;
221 rijndael_makeKey(&ap->ap_enckey, DIR_ENCRYPT, keylen, key);
222 rijndael_makeKey(&ap->ap_deckey, DIR_DECRYPT, keylen, key);
223 return ap;
224 }
225
226 static void
227 cgd_cipher_aes_cbc_destroy(void *data)
228 {
229 struct aes_privdata *apd = data;
230
231 explicit_memset(apd, 0, sizeof(*apd));
232 free(apd, M_DEVBUF);
233 }
234
235 static void
236 cgd_cipher_aes_cbc_prep(void *privdata, char *iv,
237 const char *blkno_buf, size_t blocksize, int dir)
238 {
239 struct aes_privdata *apd = privdata;
240 cipherInstance cipher;
241 int cipher_ok __diagused;
242
243 cipher_ok = rijndael_cipherInit(&cipher, MODE_CBC, NULL);
244 KASSERT(cipher_ok > 0);
245 rijndael_blockEncrypt(&cipher, &apd->ap_enckey,
246 blkno_buf, blocksize * 8, iv);
247 if (blocksize > CGD_AES_BLOCK_SIZE) {
248 (void)memmove(iv, iv + blocksize - CGD_AES_BLOCK_SIZE,
249 CGD_AES_BLOCK_SIZE);
250 }
251 }
252
253 static void
254 aes_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
255 {
256 struct aes_encdata *ae = privdata;
257 cipherInstance cipher;
258 int cipher_ok __diagused;
259
260 cipher_ok = rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
261 KASSERT(cipher_ok > 0);
262 rijndael_blockEncrypt(&cipher, ae->ae_key, src, len * 8, dst);
263 (void)memcpy(ae->ae_iv, (u_int8_t *)dst +
264 (len - CGD_AES_BLOCK_SIZE), CGD_AES_BLOCK_SIZE);
265 }
266
267 static void
268 aes_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
269 {
270 struct aes_encdata *ae = privdata;
271 cipherInstance cipher;
272 int cipher_ok __diagused;
273
274 cipher_ok = rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
275 KASSERT(cipher_ok > 0);
276 rijndael_blockDecrypt(&cipher, ae->ae_key, src, len * 8, dst);
277 (void)memcpy(ae->ae_iv, (const u_int8_t *)src +
278 (len - CGD_AES_BLOCK_SIZE), CGD_AES_BLOCK_SIZE);
279 }
280
281 static void
282 cgd_cipher_aes_cbc(void *privdata, struct uio *dstuio,
283 struct uio *srcuio, const void *iv, int dir)
284 {
285 struct aes_privdata *apd = privdata;
286 struct aes_encdata encd;
287
288 (void)memcpy(encd.ae_iv, iv, CGD_AES_BLOCK_SIZE);
289 switch (dir) {
290 case CGD_CIPHER_ENCRYPT:
291 encd.ae_key = &apd->ap_enckey;
292 cgd_cipher_uio(&encd, aes_cbc_enc_int, dstuio, srcuio);
293 break;
294 case CGD_CIPHER_DECRYPT:
295 encd.ae_key = &apd->ap_deckey;
296 cgd_cipher_uio(&encd, aes_cbc_dec_int, dstuio, srcuio);
297 break;
298 default:
299 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
300 }
301 }
302
303 static void *
304 cgd_cipher_aes_xts_init(size_t keylen, const void *xtskey, size_t *blocksize)
305 {
306 struct aes_privdata *ap;
307 const char *key, *key2; /* XTS key is made of two AES keys. */
308
309 if (!blocksize)
310 return NULL;
311 if (keylen != 256 && keylen != 512)
312 return NULL;
313 if (*blocksize == (size_t)-1)
314 *blocksize = 128;
315 if (*blocksize != 128)
316 return NULL;
317 ap = malloc(2 * sizeof(*ap), M_DEVBUF, 0);
318 if (!ap)
319 return NULL;
320
321 keylen /= 2;
322 key = xtskey;
323 key2 = key + keylen / CHAR_BIT;
324
325 rijndael_makeKey(&ap[0].ap_enckey, DIR_ENCRYPT, keylen, key);
326 rijndael_makeKey(&ap[0].ap_deckey, DIR_DECRYPT, keylen, key);
327 rijndael_makeKey(&ap[1].ap_enckey, DIR_ENCRYPT, keylen, key2);
328
329 return ap;
330 }
331
332 static void
333 cgd_cipher_aes_xts_destroy(void *data)
334 {
335 struct aes_privdata *apd = data;
336
337 explicit_memset(apd, 0, 2 * sizeof(*apd));
338 free(apd, M_DEVBUF);
339 }
340
341 static void
342 cgd_cipher_aes_xts_prep(void *privdata, char *iv,
343 const char *blkno_buf, size_t blocksize, int dir)
344 {
345 struct aes_privdata *apd = privdata;
346 cipherInstance cipher;
347 int cipher_ok __diagused;
348
349 cipher_ok = rijndael_cipherInit(&cipher, MODE_ECB, NULL);
350 KASSERT(cipher_ok > 0);
351 rijndael_blockEncrypt(&cipher, &apd[1].ap_enckey,
352 blkno_buf, blocksize * 8, iv);
353 }
354
355 static void
356 aes_xts_enc_int(void *privdata, void *dst, const void *src, size_t len)
357 {
358 struct aes_encdata *ae = privdata;
359 cipherInstance cipher;
360 int cipher_ok __diagused;
361
362 cipher_ok = rijndael_cipherInit(&cipher, MODE_XTS, ae->ae_iv);
363 KASSERT(cipher_ok > 0);
364 rijndael_blockEncrypt(&cipher, ae->ae_key, src, len * 8, dst);
365 (void)memcpy(ae->ae_iv, cipher.IV, CGD_AES_BLOCK_SIZE);
366 }
367
368 static void
369 aes_xts_dec_int(void *privdata, void *dst, const void *src, size_t len)
370 {
371 struct aes_encdata *ae = privdata;
372 cipherInstance cipher;
373 int cipher_ok __diagused;
374
375 cipher_ok = rijndael_cipherInit(&cipher, MODE_XTS, ae->ae_iv);
376 KASSERT(cipher_ok > 0);
377 rijndael_blockDecrypt(&cipher, ae->ae_key, src, len * 8, dst);
378 (void)memcpy(ae->ae_iv, cipher.IV, CGD_AES_BLOCK_SIZE);
379 }
380
381 static void
382 cgd_cipher_aes_xts(void *privdata, struct uio *dstuio,
383 struct uio *srcuio, const void *iv, int dir)
384 {
385 struct aes_privdata *apd = privdata;
386 struct aes_encdata encd;
387
388 (void)memcpy(encd.ae_iv, iv, CGD_AES_BLOCK_SIZE);
389 switch (dir) {
390 case CGD_CIPHER_ENCRYPT:
391 encd.ae_key = &apd->ap_enckey;
392 cgd_cipher_uio(&encd, aes_xts_enc_int, dstuio, srcuio);
393 break;
394 case CGD_CIPHER_DECRYPT:
395 encd.ae_key = &apd->ap_deckey;
396 cgd_cipher_uio(&encd, aes_xts_dec_int, dstuio, srcuio);
397 break;
398 default:
399 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
400 }
401 }
402
403 /*
404 * 3DES Framework
405 */
406
407 struct c3des_privdata {
408 des_key_schedule cp_key1;
409 des_key_schedule cp_key2;
410 des_key_schedule cp_key3;
411 };
412
413 struct c3des_encdata {
414 des_key_schedule *ce_key1;
415 des_key_schedule *ce_key2;
416 des_key_schedule *ce_key3;
417 u_int8_t ce_iv[CGD_3DES_BLOCK_SIZE];
418 };
419
420 static void *
421 cgd_cipher_3des_init(size_t keylen, const void *key, size_t *blocksize)
422 {
423 struct c3des_privdata *cp;
424 int error = 0;
425 des_cblock *block;
426
427 if (!blocksize)
428 return NULL;
429 if (*blocksize == (size_t)-1)
430 *blocksize = 64;
431 if (keylen != (DES_KEY_SZ * 3 * 8) || *blocksize != 64)
432 return NULL;
433 cp = malloc(sizeof(*cp), M_DEVBUF, 0);
434 if (!cp)
435 return NULL;
436 block = __UNCONST(key);
437 error = des_key_sched(block, cp->cp_key1);
438 error |= des_key_sched(block + 1, cp->cp_key2);
439 error |= des_key_sched(block + 2, cp->cp_key3);
440 if (error) {
441 explicit_memset(cp, 0, sizeof(*cp));
442 free(cp, M_DEVBUF);
443 return NULL;
444 }
445 return cp;
446 }
447
448 static void
449 cgd_cipher_3des_destroy(void *data)
450 {
451 struct c3des_privdata *cp = data;
452
453 explicit_memset(cp, 0, sizeof(*cp));
454 free(cp, M_DEVBUF);
455 }
456
457 static void
458 cgd_cipher_3des_cbc_prep(void *privdata, char *iv,
459 const char *blkno_buf, size_t blocksize, int dir)
460 {
461 struct c3des_privdata *cp = privdata;
462 char zero_iv[CGD_3DES_BLOCK_SIZE];
463
464 memset(zero_iv, 0, sizeof(zero_iv));
465 des_ede3_cbc_encrypt(blkno_buf, iv, blocksize,
466 cp->cp_key1, cp->cp_key2, cp->cp_key3, (des_cblock *)zero_iv, 1);
467 if (blocksize > CGD_3DES_BLOCK_SIZE) {
468 (void)memmove(iv, iv + blocksize - CGD_3DES_BLOCK_SIZE,
469 CGD_3DES_BLOCK_SIZE);
470 }
471 }
472
473 static void
474 c3des_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
475 {
476 struct c3des_encdata *ce = privdata;
477
478 des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2,
479 *ce->ce_key3, (des_cblock *)ce->ce_iv, 1);
480 (void)memcpy(ce->ce_iv, (const u_int8_t *)dst +
481 (len - CGD_3DES_BLOCK_SIZE), CGD_3DES_BLOCK_SIZE);
482 }
483
484 static void
485 c3des_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
486 {
487 struct c3des_encdata *ce = privdata;
488
489 des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2,
490 *ce->ce_key3, (des_cblock *)ce->ce_iv, 0);
491 (void)memcpy(ce->ce_iv, (const u_int8_t *)src +
492 (len - CGD_3DES_BLOCK_SIZE), CGD_3DES_BLOCK_SIZE);
493 }
494
495 static void
496 cgd_cipher_3des_cbc(void *privdata, struct uio *dstuio,
497 struct uio *srcuio, const void *iv, int dir)
498 {
499 struct c3des_privdata *cp = privdata;
500 struct c3des_encdata ce;
501
502 (void)memcpy(ce.ce_iv, iv, CGD_3DES_BLOCK_SIZE);
503 ce.ce_key1 = &cp->cp_key1;
504 ce.ce_key2 = &cp->cp_key2;
505 ce.ce_key3 = &cp->cp_key3;
506 switch (dir) {
507 case CGD_CIPHER_ENCRYPT:
508 cgd_cipher_uio(&ce, c3des_cbc_enc_int, dstuio, srcuio);
509 break;
510 case CGD_CIPHER_DECRYPT:
511 cgd_cipher_uio(&ce, c3des_cbc_dec_int, dstuio, srcuio);
512 break;
513 default:
514 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
515 }
516 }
517
518 /*
519 * Blowfish Framework
520 */
521
522 struct bf_privdata {
523 BF_KEY bp_key;
524 };
525
526 struct bf_encdata {
527 BF_KEY *be_key;
528 u_int8_t be_iv[CGD_BF_BLOCK_SIZE];
529 };
530
531 static void *
532 cgd_cipher_bf_init(size_t keylen, const void *key, size_t *blocksize)
533 {
534 struct bf_privdata *bp;
535
536 if (!blocksize)
537 return NULL;
538 if (keylen < 40 || keylen > 448 || (keylen % 8 != 0))
539 return NULL;
540 if (*blocksize == (size_t)-1)
541 *blocksize = 64;
542 if (*blocksize != 64)
543 return NULL;
544 bp = malloc(sizeof(*bp), M_DEVBUF, 0);
545 if (!bp)
546 return NULL;
547 BF_set_key(&bp->bp_key, keylen / 8, key);
548 return bp;
549 }
550
551 static void
552 cgd_cipher_bf_destroy(void *data)
553 {
554 struct bf_privdata *bp = data;
555
556 explicit_memset(bp, 0, sizeof(*bp));
557 free(bp, M_DEVBUF);
558 }
559
560 static void
561 cgd_cipher_bf_cbc_prep(void *privdata, char *iv,
562 const char *blkno_buf, size_t blocksize, int dir)
563 {
564 struct bf_privdata *bp = privdata;
565 char zero_iv[CGD_BF_BLOCK_SIZE];
566
567 memset(zero_iv, 0, sizeof(zero_iv));
568 BF_cbc_encrypt(blkno_buf, iv, blocksize, &bp->bp_key, zero_iv, 1);
569 if (blocksize > CGD_BF_BLOCK_SIZE) {
570 (void)memmove(iv, iv + blocksize - CGD_BF_BLOCK_SIZE,
571 CGD_BF_BLOCK_SIZE);
572 }
573 }
574
575 static void
576 bf_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
577 {
578 struct bf_encdata *be = privdata;
579
580 BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 1);
581 (void)memcpy(be->be_iv, (u_int8_t *)dst +
582 (len - CGD_BF_BLOCK_SIZE), CGD_BF_BLOCK_SIZE);
583 }
584
585 static void
586 bf_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
587 {
588 struct bf_encdata *be = privdata;
589
590 BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 0);
591 (void)memcpy(be->be_iv, (const u_int8_t *)src +
592 (len - CGD_BF_BLOCK_SIZE), CGD_BF_BLOCK_SIZE);
593 }
594
595 static void
596 cgd_cipher_bf_cbc(void *privdata, struct uio *dstuio,
597 struct uio *srcuio, const void *iv, int dir)
598 {
599 struct bf_privdata *bp = privdata;
600 struct bf_encdata be;
601
602 (void)memcpy(be.be_iv, iv, CGD_BF_BLOCK_SIZE);
603 be.be_key = &bp->bp_key;
604 switch (dir) {
605 case CGD_CIPHER_ENCRYPT:
606 cgd_cipher_uio(&be, bf_cbc_enc_int, dstuio, srcuio);
607 break;
608 case CGD_CIPHER_DECRYPT:
609 cgd_cipher_uio(&be, bf_cbc_dec_int, dstuio, srcuio);
610 break;
611 default:
612 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
613 }
614
615 }
616