1105464Sphk/*-
2105464Sphk * Copyright (c) 2002 Poul-Henning Kamp
3105464Sphk * Copyright (c) 2002 Networks Associates Technology, Inc.
4105464Sphk * All rights reserved.
5105464Sphk *
6105464Sphk * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7105464Sphk * and NAI Labs, the Security Research Division of Network Associates, Inc.
8105464Sphk * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9105464Sphk * DARPA CHATS research program.
10105464Sphk *
11105464Sphk * Redistribution and use in source and binary forms, with or without
12105464Sphk * modification, are permitted provided that the following conditions
13105464Sphk * are met:
14105464Sphk * 1. Redistributions of source code must retain the above copyright
15105464Sphk *    notice, this list of conditions and the following disclaimer.
16105464Sphk * 2. Redistributions in binary form must reproduce the above copyright
17105464Sphk *    notice, this list of conditions and the following disclaimer in the
18105464Sphk *    documentation and/or other materials provided with the distribution.
19105464Sphk *
20105464Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21105464Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22105464Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23105464Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24105464Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25105464Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26105464Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27105464Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28105464Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29105464Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30105464Sphk * SUCH DAMAGE.
31105464Sphk *
32105464Sphk * $FreeBSD$
33139778Simp */
34139778Simp/* This source file contains the functions responsible for the crypto, keying
35105464Sphk * and mapping operations on the I/O requests.
36105464Sphk *
37105464Sphk */
38105464Sphk
39105464Sphk#include <sys/param.h>
40105464Sphk#include <sys/bio.h>
41105464Sphk#include <sys/lock.h>
42105464Sphk#include <sys/mutex.h>
43105464Sphk#include <sys/queue.h>
44105464Sphk#include <sys/malloc.h>
45105464Sphk#include <sys/libkern.h>
46113010Sphk#include <sys/endian.h>
47105464Sphk#include <sys/md5.h>
48105464Sphk
49143418Sume#include <crypto/rijndael/rijndael-api-fst.h>
50106407Sphk#include <crypto/sha2/sha2.h>
51106407Sphk
52105464Sphk#include <geom/geom.h>
53105464Sphk#include <geom/bde/g_bde.h>
54105464Sphk
55114167Sphk/*
56114167Sphk * XXX: Debugging DO NOT ENABLE
57114167Sphk */
58114167Sphk#undef MD5_KEY
59105464Sphk
60105464Sphk/*
61105464Sphk * Derive kkey from mkey + sector offset.
62105464Sphk *
63105464Sphk * Security objective: Derive a potentially very large number of distinct skeys
64105464Sphk * from the comparatively small key material in our mkey, in such a way that
65105464Sphk * if one, more or even many of the kkeys are compromised, this does not
66105464Sphk * significantly help an attack on other kkeys and in particular does not
67148192Sphk * weaken or compromise the mkey.
68105464Sphk *
69106226Sphk * First we MD5 hash the sectornumber with the salt from the lock sector.
70106226Sphk * The salt prevents the precalculation and statistical analysis of the MD5
71106226Sphk * output which would be possible if we only gave it the sectornumber.
72105464Sphk *
73106226Sphk * The MD5 hash is used to pick out 16 bytes from the masterkey, which
74106226Sphk * are then hashed with MD5 together with the sector number.
75105464Sphk *
76106226Sphk * The resulting MD5 hash is the kkey.
77105464Sphk */
78105464Sphk
79105464Sphkstatic void
80105464Sphkg_bde_kkey(struct g_bde_softc *sc, keyInstance *ki, int dir, off_t sector)
81105464Sphk{
82106226Sphk	u_int t;
83105464Sphk	MD5_CTX ct;
84106226Sphk	u_char buf[16];
85106407Sphk	u_char buf2[8];
86105464Sphk
87106407Sphk	/* We have to be architecture neutral */
88113010Sphk	le64enc(buf2, sector);
89106407Sphk
90105464Sphk	MD5Init(&ct);
91106226Sphk	MD5Update(&ct, sc->key.salt, 8);
92106407Sphk	MD5Update(&ct, buf2, sizeof buf2);
93106226Sphk	MD5Update(&ct, sc->key.salt + 8, 8);
94106226Sphk	MD5Final(buf, &ct);
95106226Sphk
96106226Sphk	MD5Init(&ct);
97106226Sphk	for (t = 0; t < 16; t++) {
98106226Sphk		MD5Update(&ct, &sc->key.mkey[buf[t]], 1);
99106226Sphk		if (t == 8)
100106407Sphk			MD5Update(&ct, buf2, sizeof buf2);
101105464Sphk	}
102106407Sphk	bzero(buf2, sizeof buf2);
103105464Sphk	MD5Final(buf, &ct);
104105464Sphk	bzero(&ct, sizeof ct);
105105464Sphk	AES_makekey(ki, dir, G_BDE_KKEYBITS, buf);
106105464Sphk	bzero(buf, sizeof buf);
107105464Sphk}
108105464Sphk
109105464Sphk/*
110105464Sphk * Encryption work for read operation.
111105464Sphk *
112105464Sphk * Security objective: Find the kkey, find the skey, decrypt the sector data.
113105464Sphk */
114105464Sphk
115105464Sphkvoid
116105464Sphkg_bde_crypt_read(struct g_bde_work *wp)
117105464Sphk{
118105464Sphk	struct g_bde_softc *sc;
119105464Sphk	u_char *d;
120105464Sphk	u_int n;
121105464Sphk	off_t o;
122105464Sphk	u_char skey[G_BDE_SKEYLEN];
123105464Sphk	keyInstance ki;
124105464Sphk	cipherInstance ci;
125105464Sphk
126105464Sphk
127105464Sphk	AES_init(&ci);
128105464Sphk	sc = wp->softc;
129105464Sphk	o = 0;
130105464Sphk	for (n = 0; o < wp->length; n++, o += sc->sectorsize) {
131105464Sphk		d = (u_char *)wp->ksp->data + wp->ko + n * G_BDE_SKEYLEN;
132105464Sphk		g_bde_kkey(sc, &ki, DIR_DECRYPT, wp->offset + o);
133105464Sphk		AES_decrypt(&ci, &ki, d, skey, sizeof skey);
134105464Sphk		d = (u_char *)wp->data + o;
135105464Sphk		AES_makekey(&ki, DIR_DECRYPT, G_BDE_SKEYBITS, skey);
136105464Sphk		AES_decrypt(&ci, &ki, d, d, sc->sectorsize);
137105464Sphk	}
138105464Sphk	bzero(skey, sizeof skey);
139105464Sphk	bzero(&ci, sizeof ci);
140119809Sphk	bzero(&ki, sizeof ki);
141105464Sphk}
142105464Sphk
143105464Sphk/*
144105464Sphk * Encryption work for write operation.
145105464Sphk *
146105464Sphk * Security objective: Create random skey, encrypt sector data,
147105464Sphk * encrypt skey with the kkey.
148105464Sphk */
149105464Sphk
150105464Sphkvoid
151105464Sphkg_bde_crypt_write(struct g_bde_work *wp)
152105464Sphk{
153105464Sphk	u_char *s, *d;
154105464Sphk	struct g_bde_softc *sc;
155105464Sphk	u_int n;
156105464Sphk	off_t o;
157105464Sphk	u_char skey[G_BDE_SKEYLEN];
158105464Sphk	keyInstance ki;
159105464Sphk	cipherInstance ci;
160105464Sphk
161105464Sphk	sc = wp->softc;
162105464Sphk	AES_init(&ci);
163105464Sphk	o = 0;
164105464Sphk	for (n = 0; o < wp->length; n++, o += sc->sectorsize) {
165105464Sphk
166105464Sphk		s = (u_char *)wp->data + o;
167105464Sphk		d = (u_char *)wp->sp->data + o;
168115505Sphk		arc4rand(skey, sizeof skey, 0);
169105464Sphk		AES_makekey(&ki, DIR_ENCRYPT, G_BDE_SKEYBITS, skey);
170105464Sphk		AES_encrypt(&ci, &ki, s, d, sc->sectorsize);
171105464Sphk
172105464Sphk		d = (u_char *)wp->ksp->data + wp->ko + n * G_BDE_SKEYLEN;
173105464Sphk		g_bde_kkey(sc, &ki, DIR_ENCRYPT, wp->offset + o);
174105464Sphk		AES_encrypt(&ci, &ki, skey, d, sizeof skey);
175105464Sphk		bzero(skey, sizeof skey);
176105464Sphk	}
177105464Sphk	bzero(skey, sizeof skey);
178105464Sphk	bzero(&ci, sizeof ci);
179119891Sphk	bzero(&ki, sizeof ki);
180105464Sphk}
181105464Sphk
182105464Sphk/*
183105464Sphk * Encryption work for delete operation.
184105464Sphk *
185105464Sphk * Security objective: Write random data to the sectors.
186105464Sphk *
187105464Sphk * XXX: At a hit in performance we would trash the encrypted skey as well.
188105464Sphk * XXX: This would add frustration to the cleaning lady attack by making
189105464Sphk * XXX: deletes look like writes.
190105464Sphk */
191105464Sphk
192105464Sphkvoid
193105464Sphkg_bde_crypt_delete(struct g_bde_work *wp)
194105464Sphk{
195105464Sphk	struct g_bde_softc *sc;
196105464Sphk	u_char *d;
197105464Sphk	off_t o;
198107451Sphk	u_char skey[G_BDE_SKEYLEN];
199107451Sphk	keyInstance ki;
200107451Sphk	cipherInstance ci;
201105464Sphk
202105464Sphk	sc = wp->softc;
203105464Sphk	d = wp->sp->data;
204107451Sphk	AES_init(&ci);
205105464Sphk	/*
206105464Sphk	 * Do not unroll this loop!
207105464Sphk	 * Our zone may be significantly wider than the amount of random
208105464Sphk	 * bytes arc4rand likes to give in one reseeding, whereas our
209105464Sphk	 * sectorsize is far more likely to be in the same range.
210105464Sphk	 */
211105464Sphk	for (o = 0; o < wp->length; o += sc->sectorsize) {
212105464Sphk		arc4rand(d, sc->sectorsize, 0);
213115505Sphk		arc4rand(skey, sizeof skey, 0);
214107451Sphk		AES_makekey(&ki, DIR_ENCRYPT, G_BDE_SKEYBITS, skey);
215107451Sphk		AES_encrypt(&ci, &ki, d, d, sc->sectorsize);
216105464Sphk		d += sc->sectorsize;
217105464Sphk	}
218105464Sphk	/*
219105464Sphk	 * Having written a long random sequence to disk here, we want to
220105464Sphk	 * force a reseed, to avoid weakening the next time we use random
221105464Sphk	 * data for something important.
222105464Sphk	 */
223105464Sphk	arc4rand(&o, sizeof o, 1);
224105464Sphk}
225105464Sphk
226105464Sphk/*
227105464Sphk * Calculate the total payload size of the encrypted device.
228105464Sphk *
229105464Sphk * Security objectives: none.
230105464Sphk *
231105464Sphk * This function needs to agree with g_bde_map_sector() about things.
232105464Sphk */
233105464Sphk
234105464Sphkuint64_t
235105464Sphkg_bde_max_sector(struct g_bde_key *kp)
236105464Sphk{
237105464Sphk	uint64_t maxsect;
238105464Sphk
239105464Sphk	maxsect = kp->media_width;
240105464Sphk	maxsect /= kp->zone_width;
241105464Sphk	maxsect *= kp->zone_cont;
242105464Sphk	return (maxsect);
243105464Sphk}
244105464Sphk
245105464Sphk/*
246105464Sphk * Convert an unencrypted side offset to offsets on the encrypted side.
247105464Sphk *
248105464Sphk * Security objective:  Make it harder to identify what sectors contain what
249105464Sphk * on a "cold" disk image.
250105464Sphk *
251105464Sphk * We do this by adding the "keyoffset" from the lock to the physical sector
252108558Sphk * number modulus the available number of sectors.  Since all physical sectors
253108558Sphk * presumably look the same cold, this will do.
254105464Sphk *
255108558Sphk * As part of the mapping we have to skip the lock sectors which we know
256108558Sphk * the physical address off.  We also truncate the work packet, respecting
257108558Sphk * zone boundaries and lock sectors, so that we end up with a sequence of
258108558Sphk * sectors which are physically contiguous.
259108558Sphk *
260105464Sphk * Shuffling things further is an option, but the incremental frustration is
261105464Sphk * not currently deemed worth the run-time performance hit resulting from the
262105464Sphk * increased number of disk arm movements it would incur.
263105464Sphk *
264105464Sphk * This function offers nothing but a trivial diversion for an attacker able
265105464Sphk * to do "the cleaning lady attack" in its current static mapping form.
266105464Sphk */
267105464Sphk
268105464Sphkvoid
269108558Sphkg_bde_map_sector(struct g_bde_work *wp)
270105464Sphk{
271105464Sphk
272108558Sphk	u_int	zone, zoff, u, len;
273108558Sphk	uint64_t ko;
274108558Sphk	struct g_bde_softc *sc;
275108558Sphk	struct g_bde_key *kp;
276105464Sphk
277108558Sphk	sc = wp->softc;
278108558Sphk	kp = &sc->key;
279105464Sphk
280108558Sphk	/* find which zone and the offset in it */
281108558Sphk	zone = wp->offset / kp->zone_cont;
282108558Sphk	zoff = wp->offset % kp->zone_cont;
283105464Sphk
284108558Sphk	/* Calculate the offset of the key in the key sector */
285108558Sphk	wp->ko = (zoff / kp->sectorsize) * G_BDE_SKEYLEN;
286105464Sphk
287108558Sphk	/* restrict length to that zone */
288108558Sphk	len = kp->zone_cont - zoff;
289111964Sphk
290111964Sphk	/* ... and in general */
291111964Sphk	if (len > DFLTPHYS)
292111964Sphk		len = DFLTPHYS;
293111964Sphk
294108558Sphk	if (len < wp->length)
295108558Sphk		wp->length = len;
296105464Sphk
297108558Sphk	/* Find physical sector address */
298108558Sphk	wp->so = zone * kp->zone_width + zoff;
299108558Sphk	wp->so += kp->keyoffset;
300108558Sphk	wp->so %= kp->media_width;
301114251Sphk	if (wp->so + wp->length > kp->media_width)
302114251Sphk		wp->length = kp->media_width - wp->so;
303108558Sphk	wp->so += kp->sector0;
304108558Sphk
305105464Sphk	/* The key sector is the last in this zone. */
306108558Sphk	wp->kso = zone * kp->zone_width + kp->zone_cont;
307108558Sphk	wp->kso += kp->keyoffset;
308108558Sphk	wp->kso %= kp->media_width;
309108558Sphk	wp->kso += kp->sector0;
310105464Sphk
311108558Sphk	/* Compensate for lock sectors */
312108558Sphk	for (u = 0; u < G_BDE_MAXKEYS; u++) {
313108558Sphk		/* Find the start of this lock sector */
314135085Sphk		ko = kp->lsector[u] & ~((uint64_t)kp->sectorsize - 1);
315105464Sphk
316108558Sphk		if (wp->kso >= ko)
317108558Sphk			wp->kso += kp->sectorsize;
318105464Sphk
319108558Sphk		if (wp->so >= ko) {
320108558Sphk			/* lock sector before work packet */
321108558Sphk			wp->so += kp->sectorsize;
322108558Sphk		} else if ((wp->so + wp->length) > ko) {
323108558Sphk			/* lock sector in work packet, truncate */
324108558Sphk			wp->length = ko - wp->so;
325108558Sphk		}
326108558Sphk	}
327108558Sphk
328105464Sphk#if 0
329108558Sphk	printf("off %jd len %jd so %jd ko %jd kso %u\n",
330108558Sphk	    (intmax_t)wp->offset,
331108558Sphk	    (intmax_t)wp->length,
332108558Sphk	    (intmax_t)wp->so,
333108558Sphk	    (intmax_t)wp->kso,
334108558Sphk	    wp->ko);
335105464Sphk#endif
336114251Sphk	KASSERT(wp->so + wp->length <= kp->sectorN,
337114543Sphk	    ("wp->so (%jd) + wp->length (%jd) > EOM (%jd), offset = %jd",
338114251Sphk	    (intmax_t)wp->so,
339114251Sphk	    (intmax_t)wp->length,
340114251Sphk	    (intmax_t)kp->sectorN,
341114251Sphk	    (intmax_t)wp->offset));
342114251Sphk
343114251Sphk	KASSERT(wp->kso + kp->sectorsize <= kp->sectorN,
344114543Sphk	    ("wp->kso (%jd) + kp->sectorsize > EOM (%jd), offset = %jd",
345114251Sphk	    (intmax_t)wp->kso,
346114251Sphk	    (intmax_t)kp->sectorN,
347114251Sphk	    (intmax_t)wp->offset));
348114251Sphk
349114251Sphk	KASSERT(wp->so >= kp->sector0,
350114543Sphk	    ("wp->so (%jd) < BOM (%jd), offset = %jd",
351114251Sphk	    (intmax_t)wp->so,
352114251Sphk	    (intmax_t)kp->sector0,
353114251Sphk	    (intmax_t)wp->offset));
354114251Sphk
355114251Sphk	KASSERT(wp->kso >= kp->sector0,
356114543Sphk	    ("wp->kso (%jd) <BOM (%jd), offset = %jd",
357114251Sphk	    (intmax_t)wp->kso,
358114251Sphk	    (intmax_t)kp->sector0,
359114251Sphk	    (intmax_t)wp->offset));
360105464Sphk}
361