cgd_crypto.c revision 1.14 1 /* $NetBSD: cgd_crypto.c,v 1.14 2016/12/11 00:20:49 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.14 2016/12/11 00:20:49 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[16]; /* 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 > 16)
248 (void)memmove(iv, iv + blocksize - 16, 16);
249 }
250
251 static void
252 aes_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
253 {
254 struct aes_encdata *ae = privdata;
255 cipherInstance cipher;
256 int cipher_ok __diagused;
257
258 cipher_ok = rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
259 KASSERT(cipher_ok > 0);
260 rijndael_blockEncrypt(&cipher, ae->ae_key, src, len * 8, dst);
261 (void)memcpy(ae->ae_iv, (u_int8_t *)dst + (len - 16), 16);
262 }
263
264 static void
265 aes_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
266 {
267 struct aes_encdata *ae = privdata;
268 cipherInstance cipher;
269 int cipher_ok __diagused;
270
271 cipher_ok = rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
272 KASSERT(cipher_ok > 0);
273 rijndael_blockDecrypt(&cipher, ae->ae_key, src, len * 8, dst);
274 (void)memcpy(ae->ae_iv, (const u_int8_t *)src + (len - 16), 16);
275 }
276
277 static void
278 cgd_cipher_aes_cbc(void *privdata, struct uio *dstuio,
279 struct uio *srcuio, const void *iv, int dir)
280 {
281 struct aes_privdata *apd = privdata;
282 struct aes_encdata encd;
283
284 (void)memcpy(encd.ae_iv, iv, 16);
285 switch (dir) {
286 case CGD_CIPHER_ENCRYPT:
287 encd.ae_key = &apd->ap_enckey;
288 cgd_cipher_uio(&encd, aes_cbc_enc_int, dstuio, srcuio);
289 break;
290 case CGD_CIPHER_DECRYPT:
291 encd.ae_key = &apd->ap_deckey;
292 cgd_cipher_uio(&encd, aes_cbc_dec_int, dstuio, srcuio);
293 break;
294 default:
295 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
296 }
297 }
298
299 static void *
300 cgd_cipher_aes_xts_init(size_t keylen, const void *xtskey, size_t *blocksize)
301 {
302 struct aes_privdata *ap;
303 const char *key, *key2; /* XTS key is made of two AES keys. */
304
305 if (!blocksize)
306 return NULL;
307 if (keylen != 256 && keylen != 512)
308 return NULL;
309 if (*blocksize == (size_t)-1)
310 *blocksize = 128;
311 if (*blocksize != 128)
312 return NULL;
313 ap = malloc(2 * sizeof(*ap), M_DEVBUF, 0);
314 if (!ap)
315 return NULL;
316
317 keylen /= 2;
318 key = xtskey;
319 key2 = key + keylen / CHAR_BIT;
320
321 rijndael_makeKey(&ap[0].ap_enckey, DIR_ENCRYPT, keylen, key);
322 rijndael_makeKey(&ap[0].ap_deckey, DIR_DECRYPT, keylen, key);
323 rijndael_makeKey(&ap[1].ap_enckey, DIR_ENCRYPT, keylen, key2);
324
325 return ap;
326 }
327
328 static void
329 cgd_cipher_aes_xts_destroy(void *data)
330 {
331 struct aes_privdata *apd = data;
332
333 explicit_memset(apd, 0, 2 * sizeof(*apd));
334 free(apd, M_DEVBUF);
335 }
336
337 static void
338 cgd_cipher_aes_xts_prep(void *privdata, char *iv,
339 const char *blkno_buf, size_t blocksize, int dir)
340 {
341 struct aes_privdata *apd = privdata;
342 cipherInstance cipher;
343 int cipher_ok __diagused;
344
345 cipher_ok = rijndael_cipherInit(&cipher, MODE_ECB, NULL);
346 KASSERT(cipher_ok > 0);
347 rijndael_blockEncrypt(&cipher, &apd[1].ap_enckey,
348 blkno_buf, blocksize * 8, iv);
349 }
350
351 static void
352 aes_xts_enc_int(void *privdata, void *dst, const void *src, size_t len)
353 {
354 struct aes_encdata *ae = privdata;
355 cipherInstance cipher;
356 int cipher_ok __diagused;
357
358 cipher_ok = rijndael_cipherInit(&cipher, MODE_XTS, ae->ae_iv);
359 KASSERT(cipher_ok > 0);
360 rijndael_blockEncrypt(&cipher, ae->ae_key, src, len * 8, dst);
361 (void)memcpy(ae->ae_iv, cipher.IV, 16);
362 }
363
364 static void
365 aes_xts_dec_int(void *privdata, void *dst, const void *src, size_t len)
366 {
367 struct aes_encdata *ae = privdata;
368 cipherInstance cipher;
369 int cipher_ok __diagused;
370
371 cipher_ok = rijndael_cipherInit(&cipher, MODE_XTS, ae->ae_iv);
372 KASSERT(cipher_ok > 0);
373 rijndael_blockDecrypt(&cipher, ae->ae_key, src, len * 8, dst);
374 (void)memcpy(ae->ae_iv, cipher.IV, 16);
375 }
376
377 static void
378 cgd_cipher_aes_xts(void *privdata, struct uio *dstuio,
379 struct uio *srcuio, const void *iv, int dir)
380 {
381 struct aes_privdata *apd = privdata;
382 struct aes_encdata encd;
383
384 (void)memcpy(encd.ae_iv, iv, 16);
385 switch (dir) {
386 case CGD_CIPHER_ENCRYPT:
387 encd.ae_key = &apd->ap_enckey;
388 cgd_cipher_uio(&encd, aes_xts_enc_int, dstuio, srcuio);
389 break;
390 case CGD_CIPHER_DECRYPT:
391 encd.ae_key = &apd->ap_deckey;
392 cgd_cipher_uio(&encd, aes_xts_dec_int, dstuio, srcuio);
393 break;
394 default:
395 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
396 }
397 }
398
399 /*
400 * 3DES Framework
401 */
402
403 struct c3des_privdata {
404 des_key_schedule cp_key1;
405 des_key_schedule cp_key2;
406 des_key_schedule cp_key3;
407 };
408
409 struct c3des_encdata {
410 des_key_schedule *ce_key1;
411 des_key_schedule *ce_key2;
412 des_key_schedule *ce_key3;
413 u_int8_t ce_iv[8];
414 };
415
416 static void *
417 cgd_cipher_3des_init(size_t keylen, const void *key, size_t *blocksize)
418 {
419 struct c3des_privdata *cp;
420 int error = 0;
421 des_cblock *block;
422
423 if (!blocksize)
424 return NULL;
425 if (*blocksize == (size_t)-1)
426 *blocksize = 64;
427 if (keylen != (DES_KEY_SZ * 3 * 8) || *blocksize != 64)
428 return NULL;
429 cp = malloc(sizeof(*cp), M_DEVBUF, 0);
430 if (!cp)
431 return NULL;
432 block = __UNCONST(key);
433 error = des_key_sched(block, cp->cp_key1);
434 error |= des_key_sched(block + 1, cp->cp_key2);
435 error |= des_key_sched(block + 2, cp->cp_key3);
436 if (error) {
437 explicit_memset(cp, 0, sizeof(*cp));
438 free(cp, M_DEVBUF);
439 return NULL;
440 }
441 return cp;
442 }
443
444 static void
445 cgd_cipher_3des_destroy(void *data)
446 {
447 struct c3des_privdata *cp = data;
448
449 explicit_memset(cp, 0, sizeof(*cp));
450 free(cp, M_DEVBUF);
451 }
452
453 static void
454 cgd_cipher_3des_cbc_prep(void *privdata, char *iv,
455 const char *blkno_buf, size_t blocksize, int dir)
456 {
457 struct c3des_privdata *cp = privdata;
458 char zero_iv[8];
459
460 memset(zero_iv, 0, sizeof(zero_iv));
461 des_ede3_cbc_encrypt(blkno_buf, iv, blocksize,
462 cp->cp_key1, cp->cp_key2, cp->cp_key3, (des_cblock *)zero_iv, 1);
463 if (blocksize > 8)
464 (void)memmove(iv, iv + blocksize - 8, 8);
465 }
466
467 static void
468 c3des_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
469 {
470 struct c3des_encdata *ce = privdata;
471
472 des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2,
473 *ce->ce_key3, (des_cblock *)ce->ce_iv, 1);
474 (void)memcpy(ce->ce_iv, (const u_int8_t *)dst + (len - 8), 8);
475 }
476
477 static void
478 c3des_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
479 {
480 struct c3des_encdata *ce = privdata;
481
482 des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2,
483 *ce->ce_key3, (des_cblock *)ce->ce_iv, 0);
484 (void)memcpy(ce->ce_iv, (const u_int8_t *)src + (len - 8), 8);
485 }
486
487 static void
488 cgd_cipher_3des_cbc(void *privdata, struct uio *dstuio,
489 struct uio *srcuio, const void *iv, int dir)
490 {
491 struct c3des_privdata *cp = privdata;
492 struct c3des_encdata ce;
493
494 (void)memcpy(ce.ce_iv, iv, 8);
495 ce.ce_key1 = &cp->cp_key1;
496 ce.ce_key2 = &cp->cp_key2;
497 ce.ce_key3 = &cp->cp_key3;
498 switch (dir) {
499 case CGD_CIPHER_ENCRYPT:
500 cgd_cipher_uio(&ce, c3des_cbc_enc_int, dstuio, srcuio);
501 break;
502 case CGD_CIPHER_DECRYPT:
503 cgd_cipher_uio(&ce, c3des_cbc_dec_int, dstuio, srcuio);
504 break;
505 default:
506 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
507 }
508 }
509
510 /*
511 * Blowfish Framework
512 */
513
514 struct bf_privdata {
515 BF_KEY bp_key;
516 };
517
518 struct bf_encdata {
519 BF_KEY *be_key;
520 u_int8_t be_iv[8];
521 };
522
523 static void *
524 cgd_cipher_bf_init(size_t keylen, const void *key, size_t *blocksize)
525 {
526 struct bf_privdata *bp;
527
528 if (!blocksize)
529 return NULL;
530 if (keylen < 40 || keylen > 448 || (keylen % 8 != 0))
531 return NULL;
532 if (*blocksize == (size_t)-1)
533 *blocksize = 64;
534 if (*blocksize != 64)
535 return NULL;
536 bp = malloc(sizeof(*bp), M_DEVBUF, 0);
537 if (!bp)
538 return NULL;
539 BF_set_key(&bp->bp_key, keylen / 8, key);
540 return bp;
541 }
542
543 static void
544 cgd_cipher_bf_destroy(void *data)
545 {
546 struct bf_privdata *bp = data;
547
548 explicit_memset(bp, 0, sizeof(*bp));
549 free(bp, M_DEVBUF);
550 }
551
552 static void
553 cgd_cipher_bf_cbc_prep(void *privdata, char *iv,
554 const char *blkno_buf, size_t blocksize, int dir)
555 {
556 struct bf_privdata *bp = privdata;
557 char zero_iv[8];
558
559 memset(zero_iv, 0, sizeof(zero_iv));
560 BF_cbc_encrypt(blkno_buf, iv, blocksize, &bp->bp_key, zero_iv, 1);
561 if (blocksize > 8)
562 (void)memmove(iv, iv + blocksize - 8, 8);
563 }
564
565 static void
566 bf_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
567 {
568 struct bf_encdata *be = privdata;
569
570 BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 1);
571 (void)memcpy(be->be_iv, (u_int8_t *)dst + (len - 8), 8);
572 }
573
574 static void
575 bf_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
576 {
577 struct bf_encdata *be = privdata;
578
579 BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 0);
580 (void)memcpy(be->be_iv, (const u_int8_t *)src + (len - 8), 8);
581 }
582
583 static void
584 cgd_cipher_bf_cbc(void *privdata, struct uio *dstuio,
585 struct uio *srcuio, const void *iv, int dir)
586 {
587 struct bf_privdata *bp = privdata;
588 struct bf_encdata be;
589
590 (void)memcpy(be.be_iv, iv, 8);
591 be.be_key = &bp->bp_key;
592 switch (dir) {
593 case CGD_CIPHER_ENCRYPT:
594 cgd_cipher_uio(&be, bf_cbc_enc_int, dstuio, srcuio);
595 break;
596 case CGD_CIPHER_DECRYPT:
597 cgd_cipher_uio(&be, bf_cbc_dec_int, dstuio, srcuio);
598 break;
599 default:
600 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
601 }
602
603 }
604