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