1/* $NetBSD: cgd_crypto.c,v 1.27 2020/07/25 22:14:35 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.27 2020/07/25 22:14:35 riastradh Exp $");
41
42#include <sys/param.h>
43#include <sys/kmem.h>
44#include <sys/systm.h>
45
46#include <dev/cgd_crypto.h>
47
48#include <crypto/adiantum/adiantum.h>
49#include <crypto/aes/aes.h>
50#include <crypto/aes/aes_cbc.h>
51#include <crypto/aes/aes_xts.h>
52#include <crypto/blowfish/blowfish.h>
53#include <crypto/des/des.h>
54
55/*
56 * The general framework provides only one generic function.
57 * It takes the name of an algorithm and returns a struct cryptfuncs *
58 * for it.  It is up to the initialisation routines of the algorithm
59 * to check key size and block size.
60 */
61
62static cfunc_init		cgd_cipher_aes_cbc_init;
63static cfunc_destroy		cgd_cipher_aes_cbc_destroy;
64static cfunc_cipher		cgd_cipher_aes_cbc;
65
66static cfunc_init		cgd_cipher_aes_xts_init;
67static cfunc_destroy		cgd_cipher_aes_xts_destroy;
68static cfunc_cipher		cgd_cipher_aes_xts;
69
70static cfunc_init		cgd_cipher_3des_init;
71static cfunc_destroy		cgd_cipher_3des_destroy;
72static cfunc_cipher		cgd_cipher_3des_cbc;
73
74static cfunc_init		cgd_cipher_bf_init;
75static cfunc_destroy		cgd_cipher_bf_destroy;
76static cfunc_cipher		cgd_cipher_bf_cbc;
77
78static cfunc_init		cgd_cipher_adiantum_init;
79static cfunc_destroy		cgd_cipher_adiantum_destroy;
80static cfunc_cipher		cgd_cipher_adiantum_crypt;
81
82static const struct cryptfuncs cf[] = {
83	{
84		.cf_name	= "aes-xts",
85		.cf_init	= cgd_cipher_aes_xts_init,
86		.cf_destroy	= cgd_cipher_aes_xts_destroy,
87		.cf_cipher	= cgd_cipher_aes_xts,
88	},
89	{
90		.cf_name	= "aes-cbc",
91		.cf_init	= cgd_cipher_aes_cbc_init,
92		.cf_destroy	= cgd_cipher_aes_cbc_destroy,
93		.cf_cipher	= cgd_cipher_aes_cbc,
94	},
95	{
96		.cf_name	= "3des-cbc",
97		.cf_init	= cgd_cipher_3des_init,
98		.cf_destroy	= cgd_cipher_3des_destroy,
99		.cf_cipher	= cgd_cipher_3des_cbc,
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	},
107	{
108		.cf_name	= "adiantum",
109		.cf_init	= cgd_cipher_adiantum_init,
110		.cf_destroy	= cgd_cipher_adiantum_destroy,
111		.cf_cipher	= cgd_cipher_adiantum_crypt,
112	},
113};
114const struct cryptfuncs *
115cryptfuncs_find(const char *alg)
116{
117
118	for (size_t i = 0; i < __arraycount(cf); i++)
119		if (strcmp(cf[i].cf_name, alg) == 0)
120			return &cf[i];
121
122	return NULL;
123}
124
125/*
126 *  AES Framework
127 */
128
129struct aes_privdata {
130	struct aesenc	ap_enckey;
131	struct aesdec	ap_deckey;
132	uint32_t	ap_nrounds;
133};
134
135static void *
136cgd_cipher_aes_cbc_init(size_t keylen, const void *key, size_t *blocksize)
137{
138	struct	aes_privdata *ap;
139
140	if (!blocksize)
141		return NULL;
142	if (keylen != 128 && keylen != 192 && keylen != 256)
143		return NULL;
144	if (*blocksize == (size_t)-1)
145		*blocksize = 128;
146	if (*blocksize != 128)
147		return NULL;
148	ap = kmem_zalloc(sizeof(*ap), KM_SLEEP);
149	switch (keylen) {
150	case 128:
151		aes_setenckey128(&ap->ap_enckey, key);
152		aes_setdeckey128(&ap->ap_deckey, key);
153		ap->ap_nrounds = AES_128_NROUNDS;
154		break;
155	case 192:
156		aes_setenckey192(&ap->ap_enckey, key);
157		aes_setdeckey192(&ap->ap_deckey, key);
158		ap->ap_nrounds = AES_192_NROUNDS;
159		break;
160	case 256:
161		aes_setenckey256(&ap->ap_enckey, key);
162		aes_setdeckey256(&ap->ap_deckey, key);
163		ap->ap_nrounds = AES_256_NROUNDS;
164		break;
165	}
166	return ap;
167}
168
169static void
170cgd_cipher_aes_cbc_destroy(void *data)
171{
172	struct aes_privdata *apd = data;
173
174	explicit_memset(apd, 0, sizeof(*apd));
175	kmem_free(apd, sizeof(*apd));
176}
177
178static void
179cgd_cipher_aes_cbc(void *privdata, void *dst, const void *src, size_t nbytes,
180    const void *blkno, int dir)
181{
182	struct aes_privdata	*apd = privdata;
183	uint8_t iv[CGD_AES_BLOCK_SIZE] __aligned(CGD_AES_BLOCK_SIZE) = {0};
184
185	/* Compute the CBC IV as AES_k(blkno).  */
186	aes_enc(&apd->ap_enckey, blkno, iv, apd->ap_nrounds);
187
188	switch (dir) {
189	case CGD_CIPHER_ENCRYPT:
190		aes_cbc_enc(&apd->ap_enckey, src, dst, nbytes, iv,
191		    apd->ap_nrounds);
192		break;
193	case CGD_CIPHER_DECRYPT:
194		aes_cbc_dec(&apd->ap_deckey, src, dst, nbytes, iv,
195		    apd->ap_nrounds);
196		break;
197	default:
198		panic("%s: unrecognised direction %d", __func__, dir);
199	}
200}
201
202/*
203 * AES-XTS
204 */
205
206struct aesxts {
207	struct aesenc	ax_enckey;
208	struct aesdec	ax_deckey;
209	struct aesenc	ax_tweakkey;
210	uint32_t	ax_nrounds;
211};
212
213static void *
214cgd_cipher_aes_xts_init(size_t keylen, const void *xtskey, size_t *blocksize)
215{
216	struct aesxts *ax;
217	const char *key, *key2; /* XTS key is made of two AES keys. */
218
219	if (!blocksize)
220		return NULL;
221	if (keylen != 256 && keylen != 512)
222		return NULL;
223	if (*blocksize == (size_t)-1)
224		*blocksize = 128;
225	if (*blocksize != 128)
226		return NULL;
227
228	ax = kmem_zalloc(sizeof(*ax), KM_SLEEP);
229	keylen /= 2;
230	key = xtskey;
231	key2 = key + keylen / CHAR_BIT;
232
233	switch (keylen) {
234	case 128:
235		aes_setenckey128(&ax->ax_enckey, key);
236		aes_setdeckey128(&ax->ax_deckey, key);
237		aes_setenckey128(&ax->ax_tweakkey, key2);
238		ax->ax_nrounds = AES_128_NROUNDS;
239		break;
240	case 256:
241		aes_setenckey256(&ax->ax_enckey, key);
242		aes_setdeckey256(&ax->ax_deckey, key);
243		aes_setenckey256(&ax->ax_tweakkey, key2);
244		ax->ax_nrounds = AES_256_NROUNDS;
245		break;
246	}
247
248	return ax;
249}
250
251static void
252cgd_cipher_aes_xts_destroy(void *cookie)
253{
254	struct aesxts *ax = cookie;
255
256	explicit_memset(ax, 0, sizeof(*ax));
257	kmem_free(ax, sizeof(*ax));
258}
259
260static void
261cgd_cipher_aes_xts(void *cookie, void *dst, const void *src, size_t nbytes,
262    const void *blkno, int dir)
263{
264	struct aesxts *ax = cookie;
265	uint8_t tweak[CGD_AES_BLOCK_SIZE];
266
267	/* Compute the initial tweak as AES_k(blkno).  */
268	aes_enc(&ax->ax_tweakkey, blkno, tweak, ax->ax_nrounds);
269
270	switch (dir) {
271	case CGD_CIPHER_ENCRYPT:
272		aes_xts_enc(&ax->ax_enckey, src, dst, nbytes, tweak,
273		    ax->ax_nrounds);
274		break;
275	case CGD_CIPHER_DECRYPT:
276		aes_xts_dec(&ax->ax_deckey, src, dst, nbytes, tweak,
277		    ax->ax_nrounds);
278		break;
279	default:
280		panic("%s: unrecognised direction %d", __func__, dir);
281	}
282}
283
284/*
285 * 3DES Framework
286 */
287
288struct c3des_privdata {
289	des_key_schedule	cp_key1;
290	des_key_schedule	cp_key2;
291	des_key_schedule	cp_key3;
292};
293
294static void *
295cgd_cipher_3des_init(size_t keylen, const void *key, size_t *blocksize)
296{
297	struct	c3des_privdata *cp;
298	int	error = 0;
299	des_cblock *block;
300
301	if (!blocksize)
302		return NULL;
303	if (*blocksize == (size_t)-1)
304		*blocksize = 64;
305	if (keylen != (DES_KEY_SZ * 3 * 8) || *blocksize != 64)
306		return NULL;
307	cp = kmem_zalloc(sizeof(*cp), KM_SLEEP);
308	block = __UNCONST(key);
309	error  = des_key_sched(block, cp->cp_key1);
310	error |= des_key_sched(block + 1, cp->cp_key2);
311	error |= des_key_sched(block + 2, cp->cp_key3);
312	if (error) {
313		explicit_memset(cp, 0, sizeof(*cp));
314		kmem_free(cp, sizeof(*cp));
315		return NULL;
316	}
317	return cp;
318}
319
320static void
321cgd_cipher_3des_destroy(void *data)
322{
323	struct c3des_privdata *cp = data;
324
325	explicit_memset(cp, 0, sizeof(*cp));
326	kmem_free(cp, sizeof(*cp));
327}
328
329static void
330cgd_cipher_3des_cbc(void *privdata, void *dst, const void *src, size_t nbytes,
331    const void *blkno, int dir)
332{
333	struct	c3des_privdata *cp = privdata;
334	des_cblock zero;
335	uint8_t iv[CGD_3DES_BLOCK_SIZE];
336
337	/* Compute the CBC IV as 3DES_k(blkno) = 3DES-CBC_k(iv=blkno, 0).  */
338	memset(&zero, 0, sizeof(zero));
339	des_ede3_cbc_encrypt(blkno, iv, CGD_3DES_BLOCK_SIZE,
340	    cp->cp_key1, cp->cp_key2, cp->cp_key3, &zero, /*encrypt*/1);
341
342	switch (dir) {
343	case CGD_CIPHER_ENCRYPT:
344		des_ede3_cbc_encrypt(src, dst, nbytes,
345		    cp->cp_key1, cp->cp_key2, cp->cp_key3,
346		    (des_cblock *)iv, /*encrypt*/1);
347		break;
348	case CGD_CIPHER_DECRYPT:
349		des_ede3_cbc_encrypt(src, dst, nbytes,
350		    cp->cp_key1, cp->cp_key2, cp->cp_key3,
351		    (des_cblock *)iv, /*encrypt*/0);
352		break;
353	default:
354		panic("%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	uint8_t		 be_iv[CGD_BF_BLOCK_SIZE];
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 = kmem_zalloc(sizeof(*bp), KM_SLEEP);
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	kmem_free(bp, sizeof(*bp));
398}
399
400static void
401cgd_cipher_bf_cbc(void *privdata, void *dst, const void *src, size_t nbytes,
402    const void *blkno, int dir)
403{
404	struct	bf_privdata *bp = privdata;
405	uint8_t zero[CGD_BF_BLOCK_SIZE], iv[CGD_BF_BLOCK_SIZE];
406
407	/* Compute the CBC IV as Blowfish_k(blkno) = BF_CBC_k(blkno, 0).  */
408	memset(zero, 0, sizeof(zero));
409	BF_cbc_encrypt(blkno, iv, CGD_BF_BLOCK_SIZE, &bp->bp_key, zero,
410	    /*encrypt*/1);
411
412	switch (dir) {
413	case CGD_CIPHER_ENCRYPT:
414		BF_cbc_encrypt(src, dst, nbytes, &bp->bp_key, iv,
415		    /*encrypt*/1);
416		break;
417	case CGD_CIPHER_DECRYPT:
418		BF_cbc_encrypt(src, dst, nbytes, &bp->bp_key, iv,
419		    /*encrypt*/0);
420		break;
421	default:
422		panic("%s: unrecognised direction %d", __func__, dir);
423	}
424}
425
426/*
427 * Adiantum
428 */
429
430static void *
431cgd_cipher_adiantum_init(size_t keylen, const void *key, size_t *blocksize)
432{
433	struct adiantum *A;
434
435	if (!blocksize)
436		return NULL;
437	if (keylen != 256)
438		return NULL;
439	if (*blocksize == (size_t)-1)
440		*blocksize = 128;
441	if (*blocksize != 128)
442		return NULL;
443
444	A = kmem_zalloc(sizeof(*A), KM_SLEEP);
445	adiantum_init(A, key);
446
447	return A;
448}
449
450static void
451cgd_cipher_adiantum_destroy(void *cookie)
452{
453	struct adiantum *A = cookie;
454
455	explicit_memset(A, 0, sizeof(*A));
456	kmem_free(A, sizeof(*A));
457}
458
459static void
460cgd_cipher_adiantum_crypt(void *cookie, void *dst, const void *src,
461    size_t nbytes, const void *blkno, int dir)
462{
463	/*
464	 * Treat the block number as a 128-bit block.  This is more
465	 * than twice as big as the largest number of reasonable
466	 * blocks, but it doesn't hurt (it would be rounded up to a
467	 * 128-bit input anyway).
468	 */
469	const unsigned tweaklen = 16;
470	struct adiantum *A = cookie;
471
472	switch (dir) {
473	case CGD_CIPHER_ENCRYPT:
474		adiantum_enc(dst, src, nbytes, blkno, tweaklen, A);
475		break;
476	case CGD_CIPHER_DECRYPT:
477		adiantum_dec(dst, src, nbytes, blkno, tweaklen, A);
478		break;
479	default:
480		panic("%s: unrecognised direction %d", __func__, dir);
481	}
482}
483