xref: /netbsd-src/sys/dev/cgd_crypto.c (revision e6c7e151de239c49d2e38720a061ed9d1fa99309)
1 /* $NetBSD: cgd_crypto.c,v 1.17 2019/12/14 16:58:38 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.17 2019/12/14 16:58:38 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 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