1/* $NetBSD: cgd_crypto.c,v 1.13 2015/04/25 12:55:04 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.13 2015/04/25 12:55:04 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#ifdef DIAGNOSTIC
53#define DIAGPANIC(x) panic x
54#else
55#define DIAGPANIC(x)
56#endif
57
58/*
59 * The general framework provides only one generic function.
60 * It takes the name of an algorith and returns a struct cryptfuncs *
61 * for it. It is up to the initialisation routines of the algorithm
62 * to check key size and block size.
63 */
64
65static cfunc_init cgd_cipher_aes_init;
66static cfunc_destroy cgd_cipher_aes_destroy;
67static cfunc_cipher cgd_cipher_aes_cbc;
68
69static cfunc_init cgd_cipher_3des_init;
70static cfunc_destroy cgd_cipher_3des_destroy;
71static cfunc_cipher cgd_cipher_3des_cbc;
72
73static cfunc_init cgd_cipher_bf_init;
74static cfunc_destroy cgd_cipher_bf_destroy;
75static cfunc_cipher cgd_cipher_bf_cbc;
76
77static const struct cryptfuncs cf[] = {
78 {
79 .cf_name = "aes-cbc",
80 .cf_init = cgd_cipher_aes_init,
81 .cf_destroy = cgd_cipher_aes_destroy,
82 .cf_cipher = cgd_cipher_aes_cbc,
83 },
84 {
85 .cf_name = "3des-cbc",
86 .cf_init = cgd_cipher_3des_init,
87 .cf_destroy = cgd_cipher_3des_destroy,
88 .cf_cipher = cgd_cipher_3des_cbc,
89 },
90 {
91 .cf_name = "blowfish-cbc",
92 .cf_init = cgd_cipher_bf_init,
93 .cf_destroy = cgd_cipher_bf_destroy,
94 .cf_cipher = cgd_cipher_bf_cbc,
95 },
96};
97const struct cryptfuncs *
98cryptfuncs_find(const char *alg)
99{
100
101 for (size_t i = 0; i < __arraycount(cf); i++)
102 if (strcmp(cf[i].cf_name, alg) == 0)
103 return &cf[i];
104
105 return NULL;
106}
107
108typedef void (*cipher_func)(void *, void *, const void *, size_t);
109
110static void
111cgd_cipher_uio_cbc(void *privdata, cipher_func cipher,
112 struct uio *dstuio, struct uio *srcuio);
113
114/*
115 * cgd_cipher_uio_cbc takes a simple cbc cipher and iterates
116 * it over two struct uio's. It presumes that the cipher function
117 * that is passed to it keeps the IV state between calls.
118 *
119 * We assume that the caller has ensured that each segment is evenly
120 * divisible by the block size, which for the cgd is a valid assumption.
121 * If we were to make this code more generic, we might need to take care
122 * of this case, either by issuing an error or copying the data.
123 */
124
125static void
126cgd_cipher_uio_cbc(void *privdata, cipher_func cipher,
127 struct uio *dstuio, struct uio *srcuio)
128{
129 const struct iovec *dst;
130 const struct iovec *src;
131 int dstnum;
132 int dstoff = 0;
133 int srcnum;
134 int srcoff = 0;
135
136 dst = dstuio->uio_iov;
137 dstnum = dstuio->uio_iovcnt;
138 src = srcuio->uio_iov;
139 srcnum = srcuio->uio_iovcnt;
140 for (;;) {
141 int l = MIN(dst->iov_len - dstoff, src->iov_len - srcoff);
142 u_int8_t *d = (u_int8_t *)dst->iov_base + dstoff;
143 const u_int8_t *s = (const u_int8_t *)src->iov_base + srcoff;
144
145 cipher(privdata, d, s, l);
146
147 dstoff += l;
148 srcoff += l;
149 /*
150 * We assume that {dst,src} == {dst,src}->iov_len,
151 * because it should not be possible for it not to be.
152 */
153 if (dstoff == dst->iov_len) {
154 dstoff = 0;
155 dstnum--;
156 dst++;
157 }
158 if (srcoff == src->iov_len) {
159 srcoff = 0;
160 srcnum--;
161 src++;
162 }
163 if (!srcnum || !dstnum)
164 break;
165 }
166}
167
168/*
169 * AES Framework
170 */
171
172/*
173 * NOTE: we do not store the blocksize in here, because it is not
174 * variable [yet], we hardcode the blocksize to 16 (128 bits).
175 */
176
177struct aes_privdata {
178 keyInstance ap_enckey;
179 keyInstance ap_deckey;
180};
181
182struct aes_encdata {
183 keyInstance *ae_key; /* key for this direction */
184 u_int8_t ae_iv[16]; /* Initialization Vector */
185};
186
187static void *
188cgd_cipher_aes_init(size_t keylen, const void *key, size_t *blocksize)
189{
190 struct aes_privdata *ap;
191
192 if (!blocksize)
193 return NULL;
194 if (keylen != 128 && keylen != 192 && keylen != 256)
195 return NULL;
196 if (*blocksize == (size_t)-1)
197 *blocksize = 128;
198 if (*blocksize != 128)
199 return NULL;
200 ap = malloc(sizeof(*ap), M_DEVBUF, 0);
201 if (!ap)
202 return NULL;
203 rijndael_makeKey(&ap->ap_enckey, DIR_ENCRYPT, keylen, key);
204 rijndael_makeKey(&ap->ap_deckey, DIR_DECRYPT, keylen, key);
205 return ap;
206}
207
208static void
209cgd_cipher_aes_destroy(void *data)
210{
211 struct aes_privdata *apd = data;
212
213 explicit_memset(apd, 0, sizeof(*apd));
214 free(apd, M_DEVBUF);
215}
216
217static void
218aes_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
219{
220 struct aes_encdata *ae = privdata;
221 cipherInstance cipher;
222
223 rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
224 rijndael_blockEncrypt(&cipher, ae->ae_key, src, len * 8, dst);
225 (void)memcpy(ae->ae_iv, (u_int8_t *)dst + (len - 16), 16);
226}
227
228static void
229aes_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
230{
231 struct aes_encdata *ae = privdata;
232 cipherInstance cipher;
233
234 rijndael_cipherInit(&cipher, MODE_CBC, ae->ae_iv);
235 rijndael_blockDecrypt(&cipher, ae->ae_key, src, len * 8, dst);
236 (void)memcpy(ae->ae_iv, (const u_int8_t *)src + (len - 16), 16);
237}
238
239static void
240cgd_cipher_aes_cbc(void *privdata, struct uio *dstuio,
241 struct uio *srcuio, const void *iv, int dir)
242{
243 struct aes_privdata *apd = privdata;
244 struct aes_encdata encd;
245
246 (void)memcpy(encd.ae_iv, iv, 16);
247 switch (dir) {
248 case CGD_CIPHER_ENCRYPT:
249 encd.ae_key = &apd->ap_enckey;
250 cgd_cipher_uio_cbc(&encd, aes_cbc_enc_int, dstuio, srcuio);
251 break;
252 case CGD_CIPHER_DECRYPT:
253 encd.ae_key = &apd->ap_deckey;
254 cgd_cipher_uio_cbc(&encd, aes_cbc_dec_int, dstuio, srcuio);
255 break;
256 default:
257 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
258 }
259}
260
261/*
262 * 3DES Framework
263 */
264
265struct c3des_privdata {
266 des_key_schedule cp_key1;
267 des_key_schedule cp_key2;
268 des_key_schedule cp_key3;
269};
270
271struct 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];
276};
277
278static void *
279cgd_cipher_3des_init(size_t keylen, const void *key, size_t *blocksize)
280{
281 struct c3des_privdata *cp;
282 int error = 0;
283 des_cblock *block;
284
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 explicit_memset(cp, 0, sizeof(*cp));
300 free(cp, M_DEVBUF);
301 return NULL;
302 }
303 return cp;
304}
305
306static void
307cgd_cipher_3des_destroy(void *data)
308{
309 struct c3des_privdata *cp = data;
310
311 explicit_memset(cp, 0, sizeof(*cp));
312 free(cp, M_DEVBUF);
313}
314
315static void
316c3des_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
317{
318 struct c3des_encdata *ce = privdata;
319
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);
323}
324
325static void
326c3des_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
327{
328 struct c3des_encdata *ce = privdata;
329
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);
333}
334
335static void
336cgd_cipher_3des_cbc(void *privdata, struct uio *dstuio,
337 struct uio *srcuio, const void *iv, int dir)
338{
339 struct c3des_privdata *cp = privdata;
340 struct c3des_encdata ce;
341
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));
355 }
356}
357
358/*
359 * Blowfish Framework
360 */
361
362struct bf_privdata {
363 BF_KEY bp_key;
364};
365
366struct bf_encdata {
367 BF_KEY *be_key;
368 u_int8_t be_iv[8];
369};
370
371static void *
372cgd_cipher_bf_init(size_t keylen, const void *key, size_t *blocksize)
373{
374 struct bf_privdata *bp;
375
376 if (!blocksize)
377 return NULL;
378 if (keylen < 40 || keylen > 448 || (keylen % 8 != 0))
379 return NULL;
380 if (*blocksize == (size_t)-1)
381 *blocksize = 64;
382 if (*blocksize != 64)
383 return NULL;
384 bp = malloc(sizeof(*bp), M_DEVBUF, 0);
385 if (!bp)
386 return NULL;
387 BF_set_key(&bp->bp_key, keylen / 8, key);
388 return bp;
389}
390
391static void
392cgd_cipher_bf_destroy(void *data)
393{
394 struct bf_privdata *bp = data;
395
396 explicit_memset(bp, 0, sizeof(*bp));
397 free(bp, M_DEVBUF);
398}
399
400static void
401bf_cbc_enc_int(void *privdata, void *dst, const void *src, size_t len)
402{
403 struct bf_encdata *be = privdata;
404
405 BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 1);
406 (void)memcpy(be->be_iv, (u_int8_t *)dst + (len - 8), 8);
407}
408
409static void
410bf_cbc_dec_int(void *privdata, void *dst, const void *src, size_t len)
411{
412 struct bf_encdata *be = privdata;
413
414 BF_cbc_encrypt(src, dst, len, be->be_key, be->be_iv, 0);
415 (void)memcpy(be->be_iv, (const u_int8_t *)src + (len - 8), 8);
416}
417
418static void
419cgd_cipher_bf_cbc(void *privdata, struct uio *dstuio,
420 struct uio *srcuio, const void *iv, int dir)
421{
422 struct bf_privdata *bp = privdata;
423 struct bf_encdata be;
424
425 (void)memcpy(be.be_iv, iv, 8);
426 be.be_key = &bp->bp_key;
427 switch (dir) {
428 case CGD_CIPHER_ENCRYPT:
429 cgd_cipher_uio_cbc(&be, bf_cbc_enc_int, dstuio, srcuio);
430 break;
431 case CGD_CIPHER_DECRYPT:
432 cgd_cipher_uio_cbc(&be, bf_cbc_dec_int, dstuio, srcuio);
433 break;
434 default:
435 DIAGPANIC(("%s: unrecognised direction %d", __func__, dir));
436 }
437
438}
439