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