g_bde_crypt.c revision 111964
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: head/sys/geom/bde/g_bde_crypt.c 111964 2003-03-07 19:09:46Z phk $
33105464Sphk *
34105464Sphk * 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/stdint.h>
41105464Sphk#include <sys/bio.h>
42105464Sphk#include <sys/lock.h>
43105464Sphk#include <sys/mutex.h>
44105464Sphk#include <sys/queue.h>
45105464Sphk#include <sys/malloc.h>
46105464Sphk#include <sys/libkern.h>
47105464Sphk#include <sys/md5.h>
48105464Sphk
49106407Sphk#include <crypto/rijndael/rijndael.h>
50106407Sphk#include <crypto/sha2/sha2.h>
51106407Sphk
52105464Sphk#include <geom/geom.h>
53105464Sphk#include <geom/bde/g_bde.h>
54105464Sphk
55105464Sphk
56105464Sphk/*
57105464Sphk * Derive kkey from mkey + sector offset.
58105464Sphk *
59105464Sphk * Security objective: Derive a potentially very large number of distinct skeys
60105464Sphk * from the comparatively small key material in our mkey, in such a way that
61105464Sphk * if one, more or even many of the kkeys are compromised, this does not
62105464Sphk * significantly help an attack on other kkeys and in particular does not
63105464Sphk * weaken or compromised the mkey.
64105464Sphk *
65106226Sphk * First we MD5 hash the sectornumber with the salt from the lock sector.
66106226Sphk * The salt prevents the precalculation and statistical analysis of the MD5
67106226Sphk * output which would be possible if we only gave it the sectornumber.
68105464Sphk *
69106226Sphk * The MD5 hash is used to pick out 16 bytes from the masterkey, which
70106226Sphk * are then hashed with MD5 together with the sector number.
71105464Sphk *
72106226Sphk * The resulting MD5 hash is the kkey.
73105464Sphk */
74105464Sphk
75105464Sphkstatic void
76105464Sphkg_bde_kkey(struct g_bde_softc *sc, keyInstance *ki, int dir, off_t sector)
77105464Sphk{
78106226Sphk	u_int t;
79105464Sphk	MD5_CTX ct;
80106226Sphk	u_char buf[16];
81106407Sphk	u_char buf2[8];
82105464Sphk
83106407Sphk	/* We have to be architecture neutral */
84106407Sphk	g_enc_le8(buf2, sector);
85106407Sphk
86105464Sphk	MD5Init(&ct);
87106226Sphk	MD5Update(&ct, sc->key.salt, 8);
88106407Sphk	MD5Update(&ct, buf2, sizeof buf2);
89106226Sphk	MD5Update(&ct, sc->key.salt + 8, 8);
90106226Sphk	MD5Final(buf, &ct);
91106226Sphk
92106226Sphk	MD5Init(&ct);
93106226Sphk	for (t = 0; t < 16; t++) {
94106226Sphk		MD5Update(&ct, &sc->key.mkey[buf[t]], 1);
95106226Sphk		if (t == 8)
96106407Sphk			MD5Update(&ct, buf2, sizeof buf2);
97105464Sphk	}
98106407Sphk	bzero(buf2, sizeof buf2);
99105464Sphk	MD5Final(buf, &ct);
100105464Sphk	bzero(&ct, sizeof ct);
101105464Sphk	AES_makekey(ki, dir, G_BDE_KKEYBITS, buf);
102105464Sphk	bzero(buf, sizeof buf);
103105464Sphk}
104105464Sphk
105105464Sphk/*
106105464Sphk * Encryption work for read operation.
107105464Sphk *
108105464Sphk * Security objective: Find the kkey, find the skey, decrypt the sector data.
109105464Sphk */
110105464Sphk
111105464Sphkvoid
112105464Sphkg_bde_crypt_read(struct g_bde_work *wp)
113105464Sphk{
114105464Sphk	struct g_bde_softc *sc;
115105464Sphk	u_char *d;
116105464Sphk	u_int n;
117105464Sphk	off_t o;
118105464Sphk	u_char skey[G_BDE_SKEYLEN];
119105464Sphk	keyInstance ki;
120105464Sphk	cipherInstance ci;
121105464Sphk
122105464Sphk
123105464Sphk	AES_init(&ci);
124105464Sphk	sc = wp->softc;
125105464Sphk	o = 0;
126105464Sphk	for (n = 0; o < wp->length; n++, o += sc->sectorsize) {
127105464Sphk		d = (u_char *)wp->ksp->data + wp->ko + n * G_BDE_SKEYLEN;
128105464Sphk		g_bde_kkey(sc, &ki, DIR_DECRYPT, wp->offset + o);
129105464Sphk		AES_decrypt(&ci, &ki, d, skey, sizeof skey);
130105464Sphk		d = (u_char *)wp->data + o;
131105464Sphk		AES_makekey(&ki, DIR_DECRYPT, G_BDE_SKEYBITS, skey);
132105464Sphk		AES_decrypt(&ci, &ki, d, d, sc->sectorsize);
133105464Sphk	}
134105464Sphk	bzero(skey, sizeof skey);
135105464Sphk	bzero(&ci, sizeof ci);
136105464Sphk	bzero(&ki, sizeof ci);
137105464Sphk}
138105464Sphk
139105464Sphk/*
140105464Sphk * Encryption work for write operation.
141105464Sphk *
142105464Sphk * Security objective: Create random skey, encrypt sector data,
143105464Sphk * encrypt skey with the kkey.
144105464Sphk */
145105464Sphk
146105464Sphkvoid
147105464Sphkg_bde_crypt_write(struct g_bde_work *wp)
148105464Sphk{
149105464Sphk	u_char *s, *d;
150105464Sphk	struct g_bde_softc *sc;
151105464Sphk	u_int n;
152105464Sphk	off_t o;
153105464Sphk	u_char skey[G_BDE_SKEYLEN];
154105464Sphk	keyInstance ki;
155105464Sphk	cipherInstance ci;
156105464Sphk
157105464Sphk	sc = wp->softc;
158105464Sphk	AES_init(&ci);
159105464Sphk	o = 0;
160105464Sphk	for (n = 0; o < wp->length; n++, o += sc->sectorsize) {
161105464Sphk
162105464Sphk		s = (u_char *)wp->data + o;
163105464Sphk		d = (u_char *)wp->sp->data + o;
164105464Sphk		arc4rand(&skey, sizeof skey, 0);
165105464Sphk		AES_makekey(&ki, DIR_ENCRYPT, G_BDE_SKEYBITS, skey);
166105464Sphk		AES_encrypt(&ci, &ki, s, d, sc->sectorsize);
167105464Sphk
168105464Sphk		d = (u_char *)wp->ksp->data + wp->ko + n * G_BDE_SKEYLEN;
169105464Sphk		g_bde_kkey(sc, &ki, DIR_ENCRYPT, wp->offset + o);
170105464Sphk		AES_encrypt(&ci, &ki, skey, d, sizeof skey);
171105464Sphk		bzero(skey, sizeof skey);
172105464Sphk	}
173105464Sphk	bzero(skey, sizeof skey);
174105464Sphk	bzero(&ci, sizeof ci);
175105464Sphk	bzero(&ki, sizeof ci);
176105464Sphk}
177105464Sphk
178105464Sphk/*
179105464Sphk * Encryption work for delete operation.
180105464Sphk *
181105464Sphk * Security objective: Write random data to the sectors.
182105464Sphk *
183105464Sphk * XXX: At a hit in performance we would trash the encrypted skey as well.
184105464Sphk * XXX: This would add frustration to the cleaning lady attack by making
185105464Sphk * XXX: deletes look like writes.
186105464Sphk */
187105464Sphk
188105464Sphkvoid
189105464Sphkg_bde_crypt_delete(struct g_bde_work *wp)
190105464Sphk{
191105464Sphk	struct g_bde_softc *sc;
192105464Sphk	u_char *d;
193105464Sphk	off_t o;
194107451Sphk	u_char skey[G_BDE_SKEYLEN];
195107451Sphk	keyInstance ki;
196107451Sphk	cipherInstance ci;
197105464Sphk
198105464Sphk	sc = wp->softc;
199105464Sphk	d = wp->sp->data;
200107451Sphk	AES_init(&ci);
201105464Sphk	/*
202105464Sphk	 * Do not unroll this loop!
203105464Sphk	 * Our zone may be significantly wider than the amount of random
204105464Sphk	 * bytes arc4rand likes to give in one reseeding, whereas our
205105464Sphk	 * sectorsize is far more likely to be in the same range.
206105464Sphk	 */
207105464Sphk	for (o = 0; o < wp->length; o += sc->sectorsize) {
208105464Sphk		arc4rand(d, sc->sectorsize, 0);
209107451Sphk		arc4rand(&skey, sizeof skey, 0);
210107451Sphk		AES_makekey(&ki, DIR_ENCRYPT, G_BDE_SKEYBITS, skey);
211107451Sphk		AES_encrypt(&ci, &ki, d, d, sc->sectorsize);
212105464Sphk		d += sc->sectorsize;
213105464Sphk	}
214105464Sphk	/*
215105464Sphk	 * Having written a long random sequence to disk here, we want to
216105464Sphk	 * force a reseed, to avoid weakening the next time we use random
217105464Sphk	 * data for something important.
218105464Sphk	 */
219105464Sphk	arc4rand(&o, sizeof o, 1);
220105464Sphk}
221105464Sphk
222105464Sphk/*
223105464Sphk * Calculate the total payload size of the encrypted device.
224105464Sphk *
225105464Sphk * Security objectives: none.
226105464Sphk *
227105464Sphk * This function needs to agree with g_bde_map_sector() about things.
228105464Sphk */
229105464Sphk
230105464Sphkuint64_t
231105464Sphkg_bde_max_sector(struct g_bde_key *kp)
232105464Sphk{
233105464Sphk	uint64_t maxsect;
234105464Sphk
235105464Sphk	maxsect = kp->media_width;
236105464Sphk	maxsect /= kp->zone_width;
237105464Sphk	maxsect *= kp->zone_cont;
238105464Sphk	return (maxsect);
239105464Sphk}
240105464Sphk
241105464Sphk/*
242105464Sphk * Convert an unencrypted side offset to offsets on the encrypted side.
243105464Sphk *
244105464Sphk * Security objective:  Make it harder to identify what sectors contain what
245105464Sphk * on a "cold" disk image.
246105464Sphk *
247105464Sphk * We do this by adding the "keyoffset" from the lock to the physical sector
248108558Sphk * number modulus the available number of sectors.  Since all physical sectors
249108558Sphk * presumably look the same cold, this will do.
250105464Sphk *
251108558Sphk * As part of the mapping we have to skip the lock sectors which we know
252108558Sphk * the physical address off.  We also truncate the work packet, respecting
253108558Sphk * zone boundaries and lock sectors, so that we end up with a sequence of
254108558Sphk * sectors which are physically contiguous.
255108558Sphk *
256105464Sphk * Shuffling things further is an option, but the incremental frustration is
257105464Sphk * not currently deemed worth the run-time performance hit resulting from the
258105464Sphk * increased number of disk arm movements it would incur.
259105464Sphk *
260105464Sphk * This function offers nothing but a trivial diversion for an attacker able
261105464Sphk * to do "the cleaning lady attack" in its current static mapping form.
262105464Sphk */
263105464Sphk
264105464Sphkvoid
265108558Sphkg_bde_map_sector(struct g_bde_work *wp)
266105464Sphk{
267105464Sphk
268108558Sphk	u_int	zone, zoff, u, len;
269108558Sphk	uint64_t ko;
270108558Sphk	struct g_bde_softc *sc;
271108558Sphk	struct g_bde_key *kp;
272105464Sphk
273108558Sphk	sc = wp->softc;
274108558Sphk	kp = &sc->key;
275105464Sphk
276108558Sphk	/* find which zone and the offset in it */
277108558Sphk	zone = wp->offset / kp->zone_cont;
278108558Sphk	zoff = wp->offset % kp->zone_cont;
279105464Sphk
280108558Sphk	/* Calculate the offset of the key in the key sector */
281108558Sphk	wp->ko = (zoff / kp->sectorsize) * G_BDE_SKEYLEN;
282105464Sphk
283108558Sphk	/* restrict length to that zone */
284108558Sphk	len = kp->zone_cont - zoff;
285111964Sphk
286111964Sphk	/* ... and in general */
287111964Sphk	if (len > DFLTPHYS)
288111964Sphk		len = DFLTPHYS;
289111964Sphk
290108558Sphk	if (len < wp->length)
291108558Sphk		wp->length = len;
292105464Sphk
293108558Sphk	/* Find physical sector address */
294108558Sphk	wp->so = zone * kp->zone_width + zoff;
295108558Sphk	wp->so += kp->keyoffset;
296108558Sphk	wp->so %= kp->media_width;
297108558Sphk	wp->so += kp->sector0;
298108558Sphk
299105464Sphk	/* The key sector is the last in this zone. */
300108558Sphk	wp->kso = zone * kp->zone_width + kp->zone_cont;
301108558Sphk	wp->kso += kp->keyoffset;
302108558Sphk	wp->kso %= kp->media_width;
303108558Sphk	wp->kso += kp->sector0;
304105464Sphk
305108558Sphk	/* Compensate for lock sectors */
306108558Sphk	for (u = 0; u < G_BDE_MAXKEYS; u++) {
307108558Sphk		/* Find the start of this lock sector */
308108558Sphk		ko = kp->lsector[u] & ~(kp->sectorsize - 1);
309105464Sphk
310108558Sphk		if (wp->kso >= ko)
311108558Sphk			wp->kso += kp->sectorsize;
312105464Sphk
313108558Sphk		if (wp->so >= ko) {
314108558Sphk			/* lock sector before work packet */
315108558Sphk			wp->so += kp->sectorsize;
316108558Sphk		} else if ((wp->so + wp->length) > ko) {
317108558Sphk			/* lock sector in work packet, truncate */
318108558Sphk			wp->length = ko - wp->so;
319108558Sphk		}
320108558Sphk	}
321108558Sphk
322105464Sphk#if 0
323108558Sphk	printf("off %jd len %jd so %jd ko %jd kso %u\n",
324108558Sphk	    (intmax_t)wp->offset,
325108558Sphk	    (intmax_t)wp->length,
326108558Sphk	    (intmax_t)wp->so,
327108558Sphk	    (intmax_t)wp->kso,
328108558Sphk	    wp->ko);
329105464Sphk#endif
330105464Sphk}
331