cgd_crypto.c revision 1.22 1 /* $NetBSD: cgd_crypto.c,v 1.22 2020/06/13 18:40:14 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.22 2020/06/13 18:40:14 riastradh Exp $");
41
42 #include <sys/param.h>
43 #include <sys/kmem.h>
44 #include <sys/systm.h>
45
46 #include <dev/cgd_crypto.h>
47
48 #include <crypto/blowfish/blowfish.h>
49 #include <crypto/des/des.h>
50 #include <crypto/rijndael/rijndael-api-fst.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 struct aes_privdata {
177 keyInstance ap_enckey;
178 keyInstance ap_deckey;
179 };
180
181 struct aes_encdata {
182 keyInstance *ae_key; /* key for this direction */
183 uint8_t ae_iv[CGD_AES_BLOCK_SIZE]; /* Initialization Vector */
184 };
185
186 static void *
187 cgd_cipher_aes_cbc_init(size_t keylen, const void *key, size_t *blocksize)
188 {
189 struct aes_privdata *ap;
190
191 if (!blocksize)
192 return NULL;
193 if (keylen != 128 && keylen != 192 && keylen != 256)
194 return NULL;
195 if (*blocksize == (size_t)-1)
196 *blocksize = 128;
197 if (*blocksize != 128)
198 return NULL;
199 ap = kmem_zalloc(sizeof(*ap), KM_SLEEP);
200 rijndael_makeKey(&ap->ap_enckey, DIR_ENCRYPT, keylen, key);
201 rijndael_makeKey(&ap->ap_deckey, DIR_DECRYPT, keylen, key);
202 return ap;
203 }
204
205 static void
206 cgd_cipher_aes_cbc_destroy(void *data)
207 {
208 struct aes_privdata *apd = data;
209
210 explicit_memset(apd, 0, sizeof(*apd));
211 kmem_free(apd, sizeof(*apd));
212 }
213
214 static void
215 aes_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
216 {
217 struct aes_encdata *ae = privdata;
218 cipherInstance cipher;
219 int cipher_ok __diagused;
220
221 cipher_ok = rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
222 KASSERT(cipher_ok > 0);
223 rijndael_blockEncrypt(&cipher, ae->ae_key, src, /*inputbits*/len * 8,
224 dst);
225 (void)memcpy(ae->ae_iv, (uint8_t *)dst +
226 (len - CGD_AES_BLOCK_SIZE), CGD_AES_BLOCK_SIZE);
227 }
228
229 static void
230 aes_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
231 {
232 struct aes_encdata *ae = privdata;
233 cipherInstance cipher;
234 int cipher_ok __diagused;
235
236 cipher_ok = rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
237 KASSERT(cipher_ok > 0);
238 rijndael_blockDecrypt(&cipher, ae->ae_key, src, /*inputbits*/len * 8,
239 dst);
240 (void)memcpy(ae->ae_iv, (const uint8_t *)src +
241 (len - CGD_AES_BLOCK_SIZE), CGD_AES_BLOCK_SIZE);
242 }
243
244 static void
245 cgd_cipher_aes_cbc(void *privdata, struct uio *dstuio,
246 struct uio *srcuio, const void *iv, int dir)
247 {
248 struct aes_privdata *apd = privdata;
249 struct aes_encdata encd;
250 cipherInstance cipher;
251 int cipher_ok __diagused;
252
253 /* Compute the CBC IV as AES_k(iv). */
254 cipher_ok = rijndael_cipherInit(&cipher, MODE_ECB, NULL);
255 KASSERT(cipher_ok > 0);
256 rijndael_blockEncrypt(&cipher, &apd->ap_enckey, iv, /*inputbits*/128,
257 encd.ae_iv);
258
259 switch (dir) {
260 case CGD_CIPHER_ENCRYPT:
261 encd.ae_key = &apd->ap_enckey;
262 cgd_cipher_uio(&encd, aes_cbc_enc_int, dstuio, srcuio);
263 break;
264 case CGD_CIPHER_DECRYPT:
265 encd.ae_key = &apd->ap_deckey;
266 cgd_cipher_uio(&encd, aes_cbc_dec_int, dstuio, srcuio);
267 break;
268 default:
269 panic("%s: unrecognised direction %d", __func__, dir);
270 }
271 }
272
273 /*
274 * AES-XTS
275 */
276
277 struct aesxts {
278 keyInstance ax_enckey;
279 keyInstance ax_deckey;
280 keyInstance ax_tweakkey;
281 };
282
283 struct aesxts_state {
284 struct aesxts *axs_keys;
285 uint8_t axs_tweak[CGD_AES_BLOCK_SIZE];
286 };
287
288 static void *
289 cgd_cipher_aes_xts_init(size_t keylen, const void *xtskey, size_t *blocksize)
290 {
291 struct aesxts *ax;
292 const char *key, *key2; /* XTS key is made of two AES keys. */
293
294 if (!blocksize)
295 return NULL;
296 if (keylen != 256 && keylen != 512)
297 return NULL;
298 if (*blocksize == (size_t)-1)
299 *blocksize = 128;
300 if (*blocksize != 128)
301 return NULL;
302
303 ax = kmem_zalloc(sizeof(*ax), KM_SLEEP);
304 keylen /= 2;
305 key = xtskey;
306 key2 = key + keylen / CHAR_BIT;
307
308 rijndael_makeKey(&ax->ax_enckey, DIR_ENCRYPT, keylen, key);
309 rijndael_makeKey(&ax->ax_deckey, DIR_DECRYPT, keylen, key);
310 rijndael_makeKey(&ax->ax_tweakkey, DIR_ENCRYPT, keylen, key2);
311
312 return ax;
313 }
314
315 static void
316 cgd_cipher_aes_xts_destroy(void *cookie)
317 {
318 struct aesxts *ax = cookie;
319
320 explicit_memset(ax, 0, sizeof(*ax));
321 kmem_free(ax, sizeof(*ax));
322 }
323
324 static void
325 aes_xts_enc_int(void *state, void *dst, const void *src, size_t len)
326 {
327 struct aesxts_state *axs = state;
328 cipherInstance cipher;
329 int cipher_ok __diagused;
330
331 cipher_ok = rijndael_cipherInit(&cipher, MODE_XTS, axs->axs_tweak);
332 KASSERT(cipher_ok > 0);
333 rijndael_blockEncrypt(&cipher, &axs->axs_keys->ax_enckey, src,
334 /*inputbits*/len * 8, dst);
335 memcpy(axs->axs_tweak, cipher.IV, CGD_AES_BLOCK_SIZE);
336 }
337
338 static void
339 aes_xts_dec_int(void *state, void *dst, const void *src, size_t len)
340 {
341 struct aesxts_state *axs = state;
342 cipherInstance cipher;
343 int cipher_ok __diagused;
344
345 cipher_ok = rijndael_cipherInit(&cipher, MODE_XTS, axs->axs_tweak);
346 KASSERT(cipher_ok > 0);
347 rijndael_blockDecrypt(&cipher, &axs->axs_keys->ax_deckey, src,
348 /*inputbits*/len * 8, dst);
349 memcpy(axs->axs_tweak, cipher.IV, CGD_AES_BLOCK_SIZE);
350 }
351
352 static void
353 cgd_cipher_aes_xts(void *cookie, struct uio *dstuio, struct uio *srcuio,
354 const void *iv, int dir)
355 {
356 struct aesxts *ax = cookie;
357 struct aesxts_state axs = { .axs_keys = ax };
358 cipherInstance cipher;
359 int cipher_ok __diagused;
360
361 cipher_ok = rijndael_cipherInit(&cipher, MODE_ECB, NULL);
362 KASSERT(cipher_ok > 0);
363 rijndael_blockEncrypt(&cipher, &ax->ax_tweakkey, iv, /*inputbits*/128,
364 axs.axs_tweak);
365
366 switch (dir) {
367 case CGD_CIPHER_ENCRYPT:
368 cgd_cipher_uio(&axs, aes_xts_enc_int, dstuio, srcuio);
369 break;
370 case CGD_CIPHER_DECRYPT:
371 cgd_cipher_uio(&axs, aes_xts_dec_int, dstuio, srcuio);
372 break;
373 default:
374 panic("%s: unrecognised direction %d", __func__, dir);
375 }
376 }
377
378 /*
379 * 3DES Framework
380 */
381
382 struct c3des_privdata {
383 des_key_schedule cp_key1;
384 des_key_schedule cp_key2;
385 des_key_schedule cp_key3;
386 };
387
388 struct c3des_encdata {
389 des_key_schedule *ce_key1;
390 des_key_schedule *ce_key2;
391 des_key_schedule *ce_key3;
392 uint8_t ce_iv[CGD_3DES_BLOCK_SIZE];
393 };
394
395 static void *
396 cgd_cipher_3des_init(size_t keylen, const void *key, size_t *blocksize)
397 {
398 struct c3des_privdata *cp;
399 int error = 0;
400 des_cblock *block;
401
402 if (!blocksize)
403 return NULL;
404 if (*blocksize == (size_t)-1)
405 *blocksize = 64;
406 if (keylen != (DES_KEY_SZ * 3 * 8) || *blocksize != 64)
407 return NULL;
408 cp = kmem_zalloc(sizeof(*cp), KM_SLEEP);
409 block = __UNCONST(key);
410 error = des_key_sched(block, cp->cp_key1);
411 error |= des_key_sched(block + 1, cp->cp_key2);
412 error |= des_key_sched(block + 2, cp->cp_key3);
413 if (error) {
414 explicit_memset(cp, 0, sizeof(*cp));
415 kmem_free(cp, sizeof(*cp));
416 return NULL;
417 }
418 return cp;
419 }
420
421 static void
422 cgd_cipher_3des_destroy(void *data)
423 {
424 struct c3des_privdata *cp = data;
425
426 explicit_memset(cp, 0, sizeof(*cp));
427 kmem_free(cp, sizeof(*cp));
428 }
429
430 static void
431 c3des_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
432 {
433 struct c3des_encdata *ce = privdata;
434
435 des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2,
436 *ce->ce_key3, (des_cblock *)ce->ce_iv, /*encrypt*/1);
437 (void)memcpy(ce->ce_iv, (const uint8_t *)dst +
438 (len - CGD_3DES_BLOCK_SIZE), CGD_3DES_BLOCK_SIZE);
439 }
440
441 static void
442 c3des_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
443 {
444 struct c3des_encdata *ce = privdata;
445
446 des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2,
447 *ce->ce_key3, (des_cblock *)ce->ce_iv, /*encrypt*/0);
448 (void)memcpy(ce->ce_iv, (const uint8_t *)src +
449 (len - CGD_3DES_BLOCK_SIZE), CGD_3DES_BLOCK_SIZE);
450 }
451
452 static void
453 cgd_cipher_3des_cbc(void *privdata, struct uio *dstuio,
454 struct uio *srcuio, const void *iv, int dir)
455 {
456 struct c3des_privdata *cp = privdata;
457 struct c3des_encdata ce;
458 des_cblock zero;
459
460 /* Compute the CBC IV as 3DES_k(iv) = 3DES-CBC_k(iv, 0). */
461 memset(&zero, 0, sizeof(zero));
462 des_ede3_cbc_encrypt(iv, ce.ce_iv, CGD_3DES_BLOCK_SIZE,
463 cp->cp_key1, cp->cp_key2, cp->cp_key3, &zero, /*encrypt*/1);
464
465 ce.ce_key1 = &cp->cp_key1;
466 ce.ce_key2 = &cp->cp_key2;
467 ce.ce_key3 = &cp->cp_key3;
468 switch (dir) {
469 case CGD_CIPHER_ENCRYPT:
470 cgd_cipher_uio(&ce, c3des_cbc_enc_int, dstuio, srcuio);
471 break;
472 case CGD_CIPHER_DECRYPT:
473 cgd_cipher_uio(&ce, c3des_cbc_dec_int, dstuio, srcuio);
474 break;
475 default:
476 panic("%s: unrecognised direction %d", __func__, dir);
477 }
478 }
479
480 /*
481 * Blowfish Framework
482 */
483
484 struct bf_privdata {
485 BF_KEY bp_key;
486 };
487
488 struct bf_encdata {
489 BF_KEY *be_key;
490 uint8_t be_iv[CGD_BF_BLOCK_SIZE];
491 };
492
493 static void *
494 cgd_cipher_bf_init(size_t keylen, const void *key, size_t *blocksize)
495 {
496 struct bf_privdata *bp;
497
498 if (!blocksize)
499 return NULL;
500 if (keylen < 40 || keylen > 448 || (keylen % 8 != 0))
501 return NULL;
502 if (*blocksize == (size_t)-1)
503 *blocksize = 64;
504 if (*blocksize != 64)
505 return NULL;
506 bp = kmem_zalloc(sizeof(*bp), KM_SLEEP);
507 if (!bp)
508 return NULL;
509 BF_set_key(&bp->bp_key, keylen / 8, key);
510 return bp;
511 }
512
513 static void
514 cgd_cipher_bf_destroy(void *data)
515 {
516 struct bf_privdata *bp = data;
517
518 explicit_memset(bp, 0, sizeof(*bp));
519 kmem_free(bp, sizeof(*bp));
520 }
521
522 static void
523 bf_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
524 {
525 struct bf_encdata *be = privdata;
526
527 BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, /*encrypt*/1);
528 (void)memcpy(be->be_iv, (uint8_t *)dst +
529 (len - CGD_BF_BLOCK_SIZE), CGD_BF_BLOCK_SIZE);
530 }
531
532 static void
533 bf_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
534 {
535 struct bf_encdata *be = privdata;
536
537 BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, /*encrypt*/0);
538 (void)memcpy(be->be_iv, (const uint8_t *)src +
539 (len - CGD_BF_BLOCK_SIZE), CGD_BF_BLOCK_SIZE);
540 }
541
542 static void
543 cgd_cipher_bf_cbc(void *privdata, struct uio *dstuio,
544 struct uio *srcuio, const void *iv, int dir)
545 {
546 struct bf_privdata *bp = privdata;
547 struct bf_encdata be;
548 char zero_iv[CGD_BF_BLOCK_SIZE];
549
550 /* Compute the CBC IV as Blowfish_k(iv) = BF_CBC_k(iv, 0). */
551 memset(zero_iv, 0, sizeof(zero_iv));
552 BF_cbc_encrypt(iv, be.be_iv, CGD_BF_BLOCK_SIZE, &bp->bp_key, zero_iv,
553 /*encrypt*/1);
554
555 be.be_key = &bp->bp_key;
556 switch (dir) {
557 case CGD_CIPHER_ENCRYPT:
558 cgd_cipher_uio(&be, bf_cbc_enc_int, dstuio, srcuio);
559 break;
560 case CGD_CIPHER_DECRYPT:
561 cgd_cipher_uio(&be, bf_cbc_dec_int, dstuio, srcuio);
562 break;
563 default:
564 panic("%s: unrecognised direction %d", __func__, dir);
565 }
566
567 }
568