Home | History | Annotate | Line # | Download | only in dev
cgd_crypto.c revision 1.1
      1 /* $NetBSD: cgd_crypto.c,v 1.1 2002/10/04 18:22:35 elric 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  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 /*
     40  *  Crypto Framework For cgd.c
     41  *
     42  *	This framework is temporary and awaits a more complete
     43  *	kernel wide crypto implementation.
     44  */
     45 
     46 #include <sys/cdefs.h>
     47 __KERNEL_RCSID(0, "$NetBSD: cgd_crypto.c,v 1.1 2002/10/04 18:22:35 elric Exp $");
     48 
     49 #include <sys/param.h>
     50 #include <sys/systm.h>
     51 #include <sys/malloc.h>
     52 
     53 #include <dev/cgd_crypto.h>
     54 
     55 #ifdef DIAGNOSTIC
     56 #define DIAGPANIC(x)	panic(x)
     57 #else
     58 #define DIAGPANIC(x)
     59 #endif
     60 
     61 /*
     62  * The general framework provides only one generic function.
     63  * It takes the name of an algorith and returns a struct cryptfuncs *
     64  * for it.  It is up to the initialisation routines of the algorithm
     65  * to check key size and block size.
     66  */
     67 
     68 extern struct cryptfuncs cgd_AES_funcs;
     69 extern struct cryptfuncs cgd_3des_funcs;
     70 extern struct cryptfuncs cgd_BF_funcs;
     71 
     72 struct cryptfuncs *
     73 cryptfuncs_find(char *alg)
     74 {
     75 
     76 	if (!strcmp("aes-cbc", alg))
     77 		return &cgd_AES_funcs;
     78 	if (!strcmp("3des-cbc", alg))
     79 		return &cgd_3des_funcs;
     80 	if (!strcmp("blowfish-cbc", alg))
     81 		return &cgd_BF_funcs;
     82 	return NULL;
     83 }
     84 
     85 typedef void	(*cipher_func)(void *, void *, void *, int);
     86 
     87 void
     88 cgd_cipher_uio_cbc(void *privdata, cipher_func cipher,
     89 	struct uio *dstuio, struct uio *srcuio);
     90 
     91 /*
     92  * cgd_cipher_uio_cbc takes a simple cbc cipher and iterates
     93  * it over two struct uio's.  It presumes that the cipher function
     94  * that is passed to it keeps the IV state between calls.
     95  *
     96  * We assume that the caller has ensured that each segment is evenly
     97  * divisible by the block size, which for the cgd is a valid assumption.
     98  * If we were to make this code more generic, we might need to take care
     99  * of this case, either by issuing an error or copying the data.
    100  */
    101 
    102 void
    103 cgd_cipher_uio_cbc(void *privdata, cipher_func cipher,
    104 	struct uio *dstuio, struct uio *srcuio)
    105 {
    106 	struct iovec	*dst;
    107 	struct iovec	*src;
    108 	int		 dstnum;
    109 	int		 dstoff = 0;
    110 	int		 srcnum;
    111 	int		 srcoff = 0;
    112 
    113 	dst = dstuio->uio_iov;
    114 	dstnum = dstuio->uio_iovcnt;
    115 	src = srcuio->uio_iov;
    116 	srcnum = srcuio->uio_iovcnt;
    117 	for (;;) {
    118 		int	  l = MIN(dst->iov_len - dstoff, src->iov_len - srcoff);
    119 		u_int8_t *d = (u_int8_t *)dst->iov_base + dstoff;
    120 		u_int8_t *s = (u_int8_t *)src->iov_base + srcoff;
    121 
    122 		cipher(privdata, d, s, l);
    123 
    124 		dstoff += l;
    125 		srcoff += l;
    126 		/*
    127 		 * We assume that {dst,src} == {dst,src}->iov_len,
    128 		 * because it should not be possible for it not to be.
    129 		 */
    130 		if (dstoff == dst->iov_len) {
    131 			dstoff = 0;
    132 			dstnum--;
    133 			dst++;
    134 		}
    135 		if (srcoff == src->iov_len) {
    136 			srcoff = 0;
    137 			srcnum--;
    138 			src++;
    139 		}
    140 		if (!srcnum || !dstnum)
    141 			break;
    142 	}
    143 }
    144 
    145 /*
    146  *  AES Framework
    147  */
    148 
    149 #include <crypto/rijndael/rijndael-api-fst.h>
    150 
    151 cfunc_init	cgd_cipher_aes_init;
    152 cfunc_destroy	cgd_cipher_aes_destroy;
    153 cfunc_cipher	cgd_cipher_aes_cbc;
    154 
    155 struct cryptfuncs cgd_AES_funcs = {
    156 	cgd_cipher_aes_init,
    157 	cgd_cipher_aes_destroy,
    158 	cgd_cipher_aes_cbc,
    159 };
    160 
    161 /*
    162  * NOTE: we do not store the blocksize in here, because it is not
    163  *       variable [yet], we hardcode the blocksize to 16 (128 bits).
    164  */
    165 
    166 struct aes_privdata {
    167 	keyInstance	ap_enckey;
    168 	keyInstance	ap_deckey;
    169 };
    170 
    171 struct aes_encdata {
    172 	keyInstance	*ae_key;	/* key for this direction */
    173 	u_int8_t	 ae_iv[16];	/* Initialization Vector */
    174 };
    175 
    176 static void	aes_cbc_enc_int(void *, void *, void *, int);
    177 static void	aes_cbc_dec_int(void *, void *, void *, int);
    178 
    179 caddr_t
    180 cgd_cipher_aes_init(int keylen, caddr_t key, int *blocksize)
    181 {
    182 	struct	aes_privdata *ap;
    183 
    184 	if (!blocksize)
    185 		return NULL;
    186 	if (keylen != 128 && keylen != 192 && keylen != 256)
    187 		return NULL;
    188 	if (*blocksize == -1)
    189 		*blocksize = 128;
    190 	if (*blocksize != 128)
    191 		return NULL;
    192 	ap = malloc(sizeof(*ap), M_DEVBUF, 0);
    193 	if (!ap)
    194 		return NULL;
    195 	rijndael_makeKey(&ap->ap_enckey, DIR_ENCRYPT, keylen, key);
    196 	rijndael_makeKey(&ap->ap_deckey, DIR_DECRYPT, keylen, key);
    197 	return (caddr_t)ap;
    198 }
    199 
    200 void
    201 cgd_cipher_aes_destroy(caddr_t data)
    202 {
    203 	struct aes_privdata *apd = (void *)data;
    204 
    205 	free(apd, M_DEVBUF);
    206 }
    207 
    208 void
    209 aes_cbc_enc_int(void *privdata, void *dst, void *src, int len)
    210 {
    211 	struct aes_encdata	*ae = (void *)privdata;
    212 	cipherInstance		 cipher;
    213 
    214 	rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
    215 	rijndael_blockEncrypt(&cipher, ae->ae_key, src, len * 8, dst);
    216 	memcpy(ae->ae_iv, (u_int8_t *)dst + (len - 16), 16);
    217 }
    218 
    219 void
    220 aes_cbc_dec_int(void *privdata, void *dst, void *src, int len)
    221 {
    222 	struct aes_encdata	*ae = (void *)privdata;
    223 	cipherInstance		 cipher;
    224 
    225 	rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
    226 	rijndael_blockDecrypt(&cipher, ae->ae_key, src, len * 8, dst);
    227 	memcpy(ae->ae_iv, (u_int8_t *)src + (len - 16), 16);
    228 }
    229 
    230 void
    231 cgd_cipher_aes_cbc(caddr_t privdata, struct uio *dstuio,
    232 	struct uio *srcuio, caddr_t iv, int dir)
    233 {
    234 	struct aes_privdata	*apd = (void *)privdata;
    235 	struct aes_encdata	 encd;
    236 
    237 	memcpy(encd.ae_iv, iv, 16);
    238 	switch (dir) {
    239 	case CGD_CIPHER_ENCRYPT:
    240 		encd.ae_key = &apd->ap_enckey;
    241 		cgd_cipher_uio_cbc(&encd, aes_cbc_enc_int, dstuio, srcuio);
    242 		break;
    243 	case CGD_CIPHER_DECRYPT:
    244 		encd.ae_key = &apd->ap_deckey;
    245 		cgd_cipher_uio_cbc(&encd, aes_cbc_dec_int, dstuio, srcuio);
    246 		break;
    247 	default:
    248 		DIAGPANIC("cgd_cipher_aes_cbc: unrecgnised direction");
    249 	}
    250 }
    251 
    252 /*
    253  * 3DES Framework
    254  */
    255 
    256 #include <crypto/des/des.h>
    257 
    258 cfunc_init	cgd_cipher_3des_init;
    259 cfunc_destroy	cgd_cipher_3des_destroy;
    260 cfunc_cipher	cgd_cipher_3des_cbc;
    261 
    262 struct cryptfuncs cgd_3des_funcs = {
    263 	cgd_cipher_3des_init,
    264 	cgd_cipher_3des_destroy,
    265 	cgd_cipher_3des_cbc,
    266 };
    267 
    268 struct c3des_privdata {
    269 	des_key_schedule	cp_key1;
    270 	des_key_schedule	cp_key2;
    271 	des_key_schedule	cp_key3;
    272 };
    273 
    274 static void	c3des_cbc_enc_int(void *, void *, void *, int);
    275 static void	c3des_cbc_dec_int(void *, void *, void *, int);
    276 
    277 struct c3des_encdata {
    278 	des_key_schedule	*ce_key1;
    279 	des_key_schedule	*ce_key2;
    280 	des_key_schedule	*ce_key3;
    281 	u_int8_t		ce_iv[8];
    282 };
    283 
    284 caddr_t
    285 cgd_cipher_3des_init(int keylen, caddr_t key, int *blocksize)
    286 {
    287 	struct	c3des_privdata *cp;
    288 	int	error = 0;
    289 
    290 printf("cgd_cipher_3des_init: enter (keylen=%d, blocksize=%d)\n",
    291 keylen, *blocksize);
    292 	if (!blocksize)
    293 		return NULL;
    294 	if (*blocksize == -1)
    295 		*blocksize = 64;
    296 	if (keylen != (DES_KEY_SZ * 3 * 8) || *blocksize != 64)
    297 		return NULL;
    298 printf("cgd_cipher_3des_init: about to malloc (keylen=%d, blocksize=%d)\n",
    299 keylen, *blocksize);
    300 	cp = malloc(sizeof(*cp), M_DEVBUF, 0);
    301 	if (!cp)
    302 		return NULL;
    303 printf("cgd_cipher_3des_init: successfully malloc'ed\n");
    304 	error  = des_key_sched((des_cblock *)key, cp->cp_key1);
    305 	error |= des_key_sched((des_cblock *)key + 1, cp->cp_key2);
    306 	error |= des_key_sched((des_cblock *)key + 2, cp->cp_key3);
    307 printf("cgd_cipher_3des_init: did the des_key_sched, error=%d\n", error);
    308 	if (error) {
    309 		free(cp, M_DEVBUF);
    310 		return NULL;
    311 	}
    312 	return (caddr_t)cp;
    313 }
    314 
    315 void
    316 cgd_cipher_3des_destroy(caddr_t data)
    317 {
    318 	struct c3des_privdata *cp = (void *)data;
    319 
    320 	free(cp, M_DEVBUF);
    321 }
    322 
    323 static void
    324 c3des_cbc_enc_int(void *privdata, void *dst, void *src, int len)
    325 {
    326 	struct	c3des_encdata *ce = (void *)privdata;
    327 
    328 	des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2,
    329 	    *ce->ce_key3, (des_cblock *)ce->ce_iv, 1);
    330 	memcpy(ce->ce_iv, (u_int8_t *)dst + (len - 8), 8);
    331 }
    332 
    333 static void
    334 c3des_cbc_dec_int(void *privdata, void *dst, void *src, int len)
    335 {
    336 	struct	c3des_encdata *ce = (void *)privdata;
    337 
    338 	des_ede3_cbc_encrypt(src, dst, len, *ce->ce_key1, *ce->ce_key2,
    339 	    *ce->ce_key3, (des_cblock *)ce->ce_iv, 0);
    340 	memcpy(ce->ce_iv, (u_int8_t *)src + (len - 8), 8);
    341 }
    342 
    343 void
    344 cgd_cipher_3des_cbc(caddr_t privdata, struct uio *dstuio,
    345 	struct uio *srcuio, caddr_t iv, int dir)
    346 {
    347 	struct	c3des_privdata *cp = (void *)privdata;
    348 	struct	c3des_encdata ce;
    349 
    350 	memcpy(ce.ce_iv, iv, 8);
    351 	ce.ce_key1 = &cp->cp_key1;
    352 	ce.ce_key2 = &cp->cp_key2;
    353 	ce.ce_key3 = &cp->cp_key3;
    354 	switch (dir) {
    355 	case CGD_CIPHER_ENCRYPT:
    356 		cgd_cipher_uio_cbc(&ce, c3des_cbc_enc_int, dstuio, srcuio);
    357 		break;
    358 	case CGD_CIPHER_DECRYPT:
    359 		cgd_cipher_uio_cbc(&ce, c3des_cbc_dec_int, dstuio, srcuio);
    360 		break;
    361 	default:
    362 		DIAGPANIC("cgd_cipher_3des_cbc: unrecognised direction");
    363 	}
    364 }
    365 
    366 /*
    367  * Blowfish Framework
    368  */
    369 
    370 #include <crypto/blowfish/blowfish.h>
    371 
    372 cfunc_init	cgd_cipher_bf_init;
    373 cfunc_destroy	cgd_cipher_bf_destroy;
    374 cfunc_cipher	cgd_cipher_bf_cbc;
    375 
    376 struct cryptfuncs cgd_BF_funcs = {
    377 	cgd_cipher_bf_init,
    378 	cgd_cipher_bf_destroy,
    379 	cgd_cipher_bf_cbc,
    380 };
    381 
    382 static void	bf_cbc_enc_int(void *, void *, void *, int);
    383 static void	bf_cbc_dec_int(void *, void *, void *, int);
    384 
    385 struct bf_privdata {
    386 	BF_KEY	bp_key;
    387 };
    388 
    389 struct bf_encdata {
    390 	BF_KEY		*be_key;
    391 	u_int8_t	 be_iv[8];
    392 };
    393 
    394 caddr_t
    395 cgd_cipher_bf_init(int keylen, caddr_t key, int *blocksize)
    396 {
    397 	struct	bf_privdata *bp;
    398 
    399 	if (!blocksize)
    400 		return NULL;
    401 	if (keylen < 40 || keylen > 448)
    402 		return NULL;
    403 	if (*blocksize == -1)
    404 		*blocksize = 64;
    405 	if (*blocksize != 64)
    406 		return NULL;
    407 	bp = malloc(sizeof(*bp), M_DEVBUF, 0);
    408 	if (!bp)
    409 		return NULL;
    410 	BF_set_key(&bp->bp_key, keylen, key);
    411 	return (caddr_t)bp;
    412 }
    413 
    414 void
    415 cgd_cipher_bf_destroy(caddr_t data)
    416 {
    417 	struct	bf_privdata *bp = (void *)data;
    418 
    419 	free(bp, M_DEVBUF);
    420 }
    421 
    422 void
    423 bf_cbc_enc_int(void *privdata, void *dst, void *src, int len)
    424 {
    425 	struct	bf_encdata *be = (void *)privdata;
    426 
    427 	BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 1);
    428 	memcpy(be->be_iv, (u_int8_t *)dst + (len - 8), 8);
    429 }
    430 
    431 void
    432 bf_cbc_dec_int(void *privdata, void *dst, void *src, int len)
    433 {
    434 	struct	bf_encdata *be = (void *)privdata;
    435 
    436 	BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 0);
    437 	memcpy(be->be_iv, (u_int8_t *)src + (len - 8), 8);
    438 }
    439 
    440 void
    441 cgd_cipher_bf_cbc(caddr_t privdata, struct uio *dstuio,
    442 	struct uio *srcuio, caddr_t iv, int dir)
    443 {
    444 	struct	bf_privdata *bp = (void *)privdata;
    445 	struct	bf_encdata be;
    446 
    447 	memcpy(be.be_iv, iv, 8);
    448 	be.be_key = &bp->bp_key;
    449 	switch (dir) {
    450 	case CGD_CIPHER_ENCRYPT:
    451 		cgd_cipher_uio_cbc(&be, bf_cbc_enc_int, dstuio, srcuio);
    452 		break;
    453 	case CGD_CIPHER_DECRYPT:
    454 		cgd_cipher_uio_cbc(&be, bf_cbc_dec_int, dstuio, srcuio);
    455 		break;
    456 	default:
    457 		DIAGPANIC("cgd_cipher_bf_cbc: unrecognised direction");
    458 	}
    459 
    460 }
    461