Home | History | Annotate | Line # | Download | only in dev
cgd_crypto.c revision 1.15.16.2
      1 /* $NetBSD: cgd_crypto.c,v 1.15.16.2 2020/04/13 08:04:18 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.2 2020/04/13 08:04:18 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 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