No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / cgd_crypto.c
blob30c5515bc6fc6e29b6cb725c08ee4f3284d4d93b
1 /* $NetBSD: cgd_crypto.c,v 1.8 2007/12/15 00:39:26 perry Exp $ */
3 /*-
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
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
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.
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>
48 #ifdef DIAGNOSTIC
49 #define DIAGPANIC(x) panic x
50 #else
51 #define DIAGPANIC(x)
52 #endif
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;
65 struct cryptfuncs *
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))
74 return &cgd_BF_funcs;
75 return NULL;
78 typedef void (*cipher_func)(void *, void *, const void *, size_t);
80 void
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.
95 void
96 cgd_cipher_uio_cbc(void *privdata, cipher_func cipher,
97 struct uio *dstuio, struct uio *srcuio)
99 struct iovec *dst;
100 struct iovec *src;
101 int dstnum;
102 int dstoff = 0;
103 int srcnum;
104 int srcoff = 0;
106 dst = dstuio->uio_iov;
107 dstnum = dstuio->uio_iovcnt;
108 src = srcuio->uio_iov;
109 srcnum = srcuio->uio_iovcnt;
110 for (;;) {
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);
117 dstoff += l;
118 srcoff += 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) {
124 dstoff = 0;
125 dstnum--;
126 dst++;
128 if (srcoff == src->iov_len) {
129 srcoff = 0;
130 srcnum--;
131 src++;
133 if (!srcnum || !dstnum)
134 break;
139 * AES Framework
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 = {
149 cgd_cipher_aes_init,
150 cgd_cipher_aes_destroy,
151 cgd_cipher_aes_cbc,
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;
164 struct aes_encdata {
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);
172 void *
173 cgd_cipher_aes_init(size_t keylen, const void *key, size_t *blocksize)
175 struct aes_privdata *ap;
177 if (!blocksize)
178 return NULL;
179 if (keylen != 128 && keylen != 192 && keylen != 256)
180 return NULL;
181 if (*blocksize == (size_t)-1)
182 *blocksize = 128;
183 if (*blocksize != 128)
184 return NULL;
185 ap = malloc(sizeof(*ap), M_DEVBUF, 0);
186 if (!ap)
187 return NULL;
188 rijndael_makeKey(&ap->ap_enckey, DIR_ENCRYPT, keylen, key);
189 rijndael_makeKey(&ap->ap_deckey, DIR_DECRYPT, keylen, key);
190 return ap;
193 void
194 cgd_cipher_aes_destroy(void *data)
196 struct aes_privdata *apd = data;
198 (void)memset(apd, 0, sizeof(*apd));
199 free(apd, M_DEVBUF);
202 void
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);
213 void
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);
224 void
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);
232 switch (dir) {
233 case CGD_CIPHER_ENCRYPT:
234 encd.ae_key = &apd->ap_enckey;
235 cgd_cipher_uio_cbc(&encd, aes_cbc_enc_int, dstuio, srcuio);
236 break;
237 case CGD_CIPHER_DECRYPT:
238 encd.ae_key = &apd->ap_deckey;
239 cgd_cipher_uio_cbc(&encd, aes_cbc_dec_int, dstuio, srcuio);
240 break;
241 default:
242 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
247 * 3DES Framework
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,
259 cgd_cipher_3des_cbc,
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;
275 u_int8_t ce_iv[8];
278 void *
279 cgd_cipher_3des_init(size_t keylen, const void *key, size_t *blocksize)
281 struct c3des_privdata *cp;
282 int error = 0;
283 des_cblock *block;
285 if (!blocksize)
286 return NULL;
287 if (*blocksize == (size_t)-1)
288 *blocksize = 64;
289 if (keylen != (DES_KEY_SZ * 3 * 8) || *blocksize != 64)
290 return NULL;
291 cp = malloc(sizeof(*cp), M_DEVBUF, 0);
292 if (!cp)
293 return NULL;
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);
298 if (error) {
299 (void)memset(cp, 0, sizeof(*cp));
300 free(cp, M_DEVBUF);
301 return NULL;
303 return cp;
306 void
307 cgd_cipher_3des_destroy(void *data)
309 struct c3des_privdata *cp = data;
311 (void)memset(cp, 0, sizeof(*cp));
312 free(cp, M_DEVBUF);
315 static void
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);
325 static void
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);
335 void
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;
346 switch (dir) {
347 case CGD_CIPHER_ENCRYPT:
348 cgd_cipher_uio_cbc(&ce, c3des_cbc_enc_int, dstuio, srcuio);
349 break;
350 case CGD_CIPHER_DECRYPT:
351 cgd_cipher_uio_cbc(&ce, c3des_cbc_dec_int, dstuio, srcuio);
352 break;
353 default:
354 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
359 * Blowfish Framework
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 = {
369 cgd_cipher_bf_init,
370 cgd_cipher_bf_destroy,
371 cgd_cipher_bf_cbc,
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);
377 struct bf_privdata {
378 BF_KEY bp_key;
381 struct bf_encdata {
382 BF_KEY *be_key;
383 u_int8_t be_iv[8];
386 void *
387 cgd_cipher_bf_init(size_t keylen, const void *key, size_t *blocksize)
389 struct bf_privdata *bp;
391 if (!blocksize)
392 return NULL;
393 if (keylen < 40 || keylen > 448 || (keylen % 8 != 0))
394 return NULL;
395 if (*blocksize == (size_t)-1)
396 *blocksize = 64;
397 if (*blocksize != 64)
398 return NULL;
399 bp = malloc(sizeof(*bp), M_DEVBUF, 0);
400 if (!bp)
401 return NULL;
402 BF_set_key(&bp->bp_key, keylen / 8, key);
403 return bp;
406 void
407 cgd_cipher_bf_destroy(void *data)
409 struct bf_privdata *bp = data;
411 (void)memset(bp, 0, sizeof(*bp));
412 free(bp, M_DEVBUF);
415 void
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);
424 void
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);
433 void
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;
442 switch (dir) {
443 case CGD_CIPHER_ENCRYPT:
444 cgd_cipher_uio_cbc(&be, bf_cbc_enc_int, dstuio, srcuio);
445 break;
446 case CGD_CIPHER_DECRYPT:
447 cgd_cipher_uio_cbc(&be, bf_cbc_dec_int, dstuio, srcuio);
448 break;
449 default:
450 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));