1 /* $NetBSD: cgd_crypto.c,v 1.8 2007/12/15 00:39:26 perry Exp $ */
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Roland C. Dowdeswell.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
33 * Crypto Framework For cgd.c
35 * This framework is temporary and awaits a more complete
36 * kernel wide crypto implementation.
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: cgd_crypto.c,v 1.8 2007/12/15 00:39:26 perry Exp $");
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/malloc.h>
46 #include <dev/cgd_crypto.h>
49 #define DIAGPANIC(x) panic x
55 * The general framework provides only one generic function.
56 * It takes the name of an algorith and returns a struct cryptfuncs *
57 * for it. It is up to the initialisation routines of the algorithm
58 * to check key size and block size.
61 extern struct cryptfuncs cgd_AES_funcs
;
62 extern struct cryptfuncs cgd_3des_funcs
;
63 extern struct cryptfuncs cgd_BF_funcs
;
66 cryptfuncs_find(const char *alg
)
69 if (!strcmp("aes-cbc", alg
))
70 return &cgd_AES_funcs
;
71 if (!strcmp("3des-cbc", alg
))
72 return &cgd_3des_funcs
;
73 if (!strcmp("blowfish-cbc", alg
))
78 typedef void (*cipher_func
)(void *, void *, const void *, size_t);
81 cgd_cipher_uio_cbc(void *privdata
, cipher_func cipher
,
82 struct uio
*dstuio
, struct uio
*srcuio
);
85 * cgd_cipher_uio_cbc takes a simple cbc cipher and iterates
86 * it over two struct uio's. It presumes that the cipher function
87 * that is passed to it keeps the IV state between calls.
89 * We assume that the caller has ensured that each segment is evenly
90 * divisible by the block size, which for the cgd is a valid assumption.
91 * If we were to make this code more generic, we might need to take care
92 * of this case, either by issuing an error or copying the data.
96 cgd_cipher_uio_cbc(void *privdata
, cipher_func cipher
,
97 struct uio
*dstuio
, struct uio
*srcuio
)
106 dst
= dstuio
->uio_iov
;
107 dstnum
= dstuio
->uio_iovcnt
;
108 src
= srcuio
->uio_iov
;
109 srcnum
= srcuio
->uio_iovcnt
;
111 int l
= MIN(dst
->iov_len
- dstoff
, src
->iov_len
- srcoff
);
112 u_int8_t
*d
= (u_int8_t
*)dst
->iov_base
+ dstoff
;
113 u_int8_t
*s
= (u_int8_t
*)src
->iov_base
+ srcoff
;
115 cipher(privdata
, d
, s
, l
);
120 * We assume that {dst,src} == {dst,src}->iov_len,
121 * because it should not be possible for it not to be.
123 if (dstoff
== dst
->iov_len
) {
128 if (srcoff
== src
->iov_len
) {
133 if (!srcnum
|| !dstnum
)
142 #include <crypto/rijndael/rijndael-api-fst.h>
144 cfunc_init cgd_cipher_aes_init
;
145 cfunc_destroy cgd_cipher_aes_destroy
;
146 cfunc_cipher cgd_cipher_aes_cbc
;
148 struct cryptfuncs cgd_AES_funcs
= {
150 cgd_cipher_aes_destroy
,
155 * NOTE: we do not store the blocksize in here, because it is not
156 * variable [yet], we hardcode the blocksize to 16 (128 bits).
159 struct aes_privdata
{
160 keyInstance ap_enckey
;
161 keyInstance ap_deckey
;
165 keyInstance
*ae_key
; /* key for this direction */
166 u_int8_t ae_iv
[16]; /* Initialization Vector */
169 static void aes_cbc_enc_int(void *, void *, const void *, size_t);
170 static void aes_cbc_dec_int(void *, void *, const void *, size_t);
173 cgd_cipher_aes_init(size_t keylen
, const void *key
, size_t *blocksize
)
175 struct aes_privdata
*ap
;
179 if (keylen
!= 128 && keylen
!= 192 && keylen
!= 256)
181 if (*blocksize
== (size_t)-1)
183 if (*blocksize
!= 128)
185 ap
= malloc(sizeof(*ap
), M_DEVBUF
, 0);
188 rijndael_makeKey(&ap
->ap_enckey
, DIR_ENCRYPT
, keylen
, key
);
189 rijndael_makeKey(&ap
->ap_deckey
, DIR_DECRYPT
, keylen
, key
);
194 cgd_cipher_aes_destroy(void *data
)
196 struct aes_privdata
*apd
= data
;
198 (void)memset(apd
, 0, sizeof(*apd
));
203 aes_cbc_enc_int(void *privdata
, void *dst
, const void *src
, size_t len
)
205 struct aes_encdata
*ae
= privdata
;
206 cipherInstance cipher
;
208 rijndael_cipherInit(&cipher
, MODE_CBC
, ae
->ae_iv
);
209 rijndael_blockEncrypt(&cipher
, ae
->ae_key
, src
, len
* 8, dst
);
210 (void)memcpy(ae
->ae_iv
, (u_int8_t
*)dst
+ (len
- 16), 16);
214 aes_cbc_dec_int(void *privdata
, void *dst
, const void *src
, size_t len
)
216 struct aes_encdata
*ae
= privdata
;
217 cipherInstance cipher
;
219 rijndael_cipherInit(&cipher
, MODE_CBC
, ae
->ae_iv
);
220 rijndael_blockDecrypt(&cipher
, ae
->ae_key
, src
, len
* 8, dst
);
221 (void)memcpy(ae
->ae_iv
, (const u_int8_t
*)src
+ (len
- 16), 16);
225 cgd_cipher_aes_cbc(void *privdata
, struct uio
*dstuio
,
226 struct uio
*srcuio
, void *iv
, int dir
)
228 struct aes_privdata
*apd
= privdata
;
229 struct aes_encdata encd
;
231 (void)memcpy(encd
.ae_iv
, iv
, 16);
233 case CGD_CIPHER_ENCRYPT
:
234 encd
.ae_key
= &apd
->ap_enckey
;
235 cgd_cipher_uio_cbc(&encd
, aes_cbc_enc_int
, dstuio
, srcuio
);
237 case CGD_CIPHER_DECRYPT
:
238 encd
.ae_key
= &apd
->ap_deckey
;
239 cgd_cipher_uio_cbc(&encd
, aes_cbc_dec_int
, dstuio
, srcuio
);
242 DIAGPANIC(("%s: unrecognised direction %d", __func__
, dir
));
250 #include <crypto/des/des.h>
252 cfunc_init cgd_cipher_3des_init
;
253 cfunc_destroy cgd_cipher_3des_destroy
;
254 cfunc_cipher cgd_cipher_3des_cbc
;
256 struct cryptfuncs cgd_3des_funcs
= {
257 cgd_cipher_3des_init
,
258 cgd_cipher_3des_destroy
,
262 struct c3des_privdata
{
263 des_key_schedule cp_key1
;
264 des_key_schedule cp_key2
;
265 des_key_schedule cp_key3
;
268 static void c3des_cbc_enc_int(void *, void *, const void *, size_t);
269 static void c3des_cbc_dec_int(void *, void *, const void *, size_t);
271 struct c3des_encdata
{
272 des_key_schedule
*ce_key1
;
273 des_key_schedule
*ce_key2
;
274 des_key_schedule
*ce_key3
;
279 cgd_cipher_3des_init(size_t keylen
, const void *key
, size_t *blocksize
)
281 struct c3des_privdata
*cp
;
287 if (*blocksize
== (size_t)-1)
289 if (keylen
!= (DES_KEY_SZ
* 3 * 8) || *blocksize
!= 64)
291 cp
= malloc(sizeof(*cp
), M_DEVBUF
, 0);
294 block
= __UNCONST(key
);
295 error
= des_key_sched(block
, cp
->cp_key1
);
296 error
|= des_key_sched(block
+ 1, cp
->cp_key2
);
297 error
|= des_key_sched(block
+ 2, cp
->cp_key3
);
299 (void)memset(cp
, 0, sizeof(*cp
));
307 cgd_cipher_3des_destroy(void *data
)
309 struct c3des_privdata
*cp
= data
;
311 (void)memset(cp
, 0, sizeof(*cp
));
316 c3des_cbc_enc_int(void *privdata
, void *dst
, const void *src
, size_t len
)
318 struct c3des_encdata
*ce
= privdata
;
320 des_ede3_cbc_encrypt(src
, dst
, len
, *ce
->ce_key1
, *ce
->ce_key2
,
321 *ce
->ce_key3
, (des_cblock
*)ce
->ce_iv
, 1);
322 (void)memcpy(ce
->ce_iv
, (const u_int8_t
*)dst
+ (len
- 8), 8);
326 c3des_cbc_dec_int(void *privdata
, void *dst
, const void *src
, size_t len
)
328 struct c3des_encdata
*ce
= privdata
;
330 des_ede3_cbc_encrypt(src
, dst
, len
, *ce
->ce_key1
, *ce
->ce_key2
,
331 *ce
->ce_key3
, (des_cblock
*)ce
->ce_iv
, 0);
332 (void)memcpy(ce
->ce_iv
, (const u_int8_t
*)src
+ (len
- 8), 8);
336 cgd_cipher_3des_cbc(void *privdata
, struct uio
*dstuio
,
337 struct uio
*srcuio
, void *iv
, int dir
)
339 struct c3des_privdata
*cp
= privdata
;
340 struct c3des_encdata ce
;
342 (void)memcpy(ce
.ce_iv
, iv
, 8);
343 ce
.ce_key1
= &cp
->cp_key1
;
344 ce
.ce_key2
= &cp
->cp_key2
;
345 ce
.ce_key3
= &cp
->cp_key3
;
347 case CGD_CIPHER_ENCRYPT
:
348 cgd_cipher_uio_cbc(&ce
, c3des_cbc_enc_int
, dstuio
, srcuio
);
350 case CGD_CIPHER_DECRYPT
:
351 cgd_cipher_uio_cbc(&ce
, c3des_cbc_dec_int
, dstuio
, srcuio
);
354 DIAGPANIC(("%s: unrecognised direction %d", __func__
, dir
));
362 #include <crypto/blowfish/blowfish.h>
364 cfunc_init cgd_cipher_bf_init
;
365 cfunc_destroy cgd_cipher_bf_destroy
;
366 cfunc_cipher cgd_cipher_bf_cbc
;
368 struct cryptfuncs cgd_BF_funcs
= {
370 cgd_cipher_bf_destroy
,
374 static void bf_cbc_enc_int(void *, void *, const void *, size_t);
375 static void bf_cbc_dec_int(void *, void *, const void *, size_t);
387 cgd_cipher_bf_init(size_t keylen
, const void *key
, size_t *blocksize
)
389 struct bf_privdata
*bp
;
393 if (keylen
< 40 || keylen
> 448 || (keylen
% 8 != 0))
395 if (*blocksize
== (size_t)-1)
397 if (*blocksize
!= 64)
399 bp
= malloc(sizeof(*bp
), M_DEVBUF
, 0);
402 BF_set_key(&bp
->bp_key
, keylen
/ 8, key
);
407 cgd_cipher_bf_destroy(void *data
)
409 struct bf_privdata
*bp
= data
;
411 (void)memset(bp
, 0, sizeof(*bp
));
416 bf_cbc_enc_int(void *privdata
, void *dst
, const void *src
, size_t len
)
418 struct bf_encdata
*be
= privdata
;
420 BF_cbc_encrypt(src
, dst
, len
, be
->be_key
, be
->be_iv
, 1);
421 (void)memcpy(be
->be_iv
, (u_int8_t
*)dst
+ (len
- 8), 8);
425 bf_cbc_dec_int(void *privdata
, void *dst
, const void *src
, size_t len
)
427 struct bf_encdata
*be
= privdata
;
429 BF_cbc_encrypt(src
, dst
, len
, be
->be_key
, be
->be_iv
, 0);
430 (void)memcpy(be
->be_iv
, (const u_int8_t
*)src
+ (len
- 8), 8);
434 cgd_cipher_bf_cbc(void *privdata
, struct uio
*dstuio
,
435 struct uio
*srcuio
, void *iv
, int dir
)
437 struct bf_privdata
*bp
= privdata
;
438 struct bf_encdata be
;
440 (void)memcpy(be
.be_iv
, iv
, 8);
441 be
.be_key
= &bp
->bp_key
;
443 case CGD_CIPHER_ENCRYPT
:
444 cgd_cipher_uio_cbc(&be
, bf_cbc_enc_int
, dstuio
, srcuio
);
446 case CGD_CIPHER_DECRYPT
:
447 cgd_cipher_uio_cbc(&be
, bf_cbc_dec_int
, dstuio
, srcuio
);
450 DIAGPANIC(("%s: unrecognised direction %d", __func__
, dir
));