g_bde_crypt.c revision 114153
10Sduke/*-
20Sduke * Copyright (c) 2002 Poul-Henning Kamp
30Sduke * Copyright (c) 2002 Networks Associates Technology, Inc.
40Sduke * All rights reserved.
50Sduke *
62099Srobilad * This software was developed for the FreeBSD Project by Poul-Henning Kamp
70Sduke * and NAI Labs, the Security Research Division of Network Associates, Inc.
80Sduke * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
90Sduke * DARPA CHATS research program.
100Sduke *
110Sduke * Redistribution and use in source and binary forms, with or without
120Sduke * modification, are permitted provided that the following conditions
130Sduke * are met:
140Sduke * 1. Redistributions of source code must retain the above copyright
150Sduke *    notice, this list of conditions and the following disclaimer.
160Sduke * 2. Redistributions in binary form must reproduce the above copyright
170Sduke *    notice, this list of conditions and the following disclaimer in the
180Sduke *    documentation and/or other materials provided with the distribution.
190Sduke *
200Sduke * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
210Sduke * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
220Sduke * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
230Sduke * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
240Sduke * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
250Sduke * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
260Sduke * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
270Sduke * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
280Sduke * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
290Sduke * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
300Sduke * SUCH DAMAGE.
310Sduke *
320Sduke * $FreeBSD: head/sys/geom/bde/g_bde_crypt.c 114153 2003-04-28 06:38:31Z phk $
330Sduke *
340Sduke * This source file contains the functions responsible for the crypto, keying
350Sduke * and mapping operations on the I/O requests.
360Sduke *
370Sduke */
380Sduke
390Sduke#include <sys/param.h>
400Sduke#include <sys/bio.h>
410Sduke#include <sys/lock.h>
420Sduke#include <sys/mutex.h>
430Sduke#include <sys/queue.h>
440Sduke#include <sys/malloc.h>
450Sduke#include <sys/libkern.h>
460Sduke#include <sys/endian.h>
470Sduke#include <sys/md5.h>
480Sduke
490Sduke#include <crypto/rijndael/rijndael.h>
500Sduke#include <crypto/sha2/sha2.h>
510Sduke
520Sduke#include <geom/geom.h>
530Sduke#include <geom/bde/g_bde.h>
540Sduke
550Sduke
560Sduke#define MD5_KEY
570Sduke
580Sduke/*
590Sduke * Derive kkey from mkey + sector offset.
600Sduke *
610Sduke * Security objective: Derive a potentially very large number of distinct skeys
620Sduke * from the comparatively small key material in our mkey, in such a way that
630Sduke * if one, more or even many of the kkeys are compromised, this does not
640Sduke * significantly help an attack on other kkeys and in particular does not
650Sduke * weaken or compromised the mkey.
660Sduke *
670Sduke * First we MD5 hash the sectornumber with the salt from the lock sector.
680Sduke * The salt prevents the precalculation and statistical analysis of the MD5
690Sduke * output which would be possible if we only gave it the sectornumber.
700Sduke *
710Sduke * The MD5 hash is used to pick out 16 bytes from the masterkey, which
720Sduke * are then hashed with MD5 together with the sector number.
730Sduke *
740Sduke * The resulting MD5 hash is the kkey.
750Sduke */
760Sduke
770Sdukestatic void
780Sdukeg_bde_kkey(struct g_bde_softc *sc, keyInstance *ki, int dir, off_t sector)
790Sduke{
800Sduke	u_int t;
810Sduke	MD5_CTX ct;
820Sduke	u_char buf[16];
830Sduke	u_char buf2[8];
840Sduke
850Sduke	/* We have to be architecture neutral */
860Sduke	le64enc(buf2, sector);
870Sduke
880Sduke	MD5Init(&ct);
890Sduke	MD5Update(&ct, sc->key.salt, 8);
900Sduke	MD5Update(&ct, buf2, sizeof buf2);
910Sduke	MD5Update(&ct, sc->key.salt + 8, 8);
920Sduke	MD5Final(buf, &ct);
930Sduke
940Sduke	MD5Init(&ct);
950Sduke	for (t = 0; t < 16; t++) {
960Sduke		MD5Update(&ct, &sc->key.mkey[buf[t]], 1);
970Sduke		if (t == 8)
980Sduke			MD5Update(&ct, buf2, sizeof buf2);
990Sduke	}
1000Sduke	bzero(buf2, sizeof buf2);
1010Sduke	MD5Final(buf, &ct);
1020Sduke	bzero(&ct, sizeof ct);
1030Sduke	AES_makekey(ki, dir, G_BDE_KKEYBITS, buf);
1040Sduke	bzero(buf, sizeof buf);
1050Sduke}
1060Sduke
1070Sduke/*
1080Sduke * Encryption work for read operation.
1090Sduke *
1100Sduke * Security objective: Find the kkey, find the skey, decrypt the sector data.
1110Sduke */
1120Sduke
1130Sdukevoid
1140Sdukeg_bde_crypt_read(struct g_bde_work *wp)
1150Sduke{
1160Sduke	struct g_bde_softc *sc;
1170Sduke	u_char *d;
1180Sduke	u_int n;
1190Sduke	off_t o;
1200Sduke	u_char skey[G_BDE_SKEYLEN];
1210Sduke	keyInstance ki;
1220Sduke	cipherInstance ci;
1230Sduke
1240Sduke
1250Sduke	AES_init(&ci);
1260Sduke	sc = wp->softc;
1270Sduke	o = 0;
1280Sduke	for (n = 0; o < wp->length; n++, o += sc->sectorsize) {
1290Sduke		d = (u_char *)wp->ksp->data + wp->ko + n * G_BDE_SKEYLEN;
1300Sduke		g_bde_kkey(sc, &ki, DIR_DECRYPT, wp->offset + o);
1310Sduke		AES_decrypt(&ci, &ki, d, skey, sizeof skey);
1320Sduke		d = (u_char *)wp->data + o;
1330Sduke#ifdef MD5_KEY
1340Sduke		{
1350Sduke		MD5_CTX ct;
1360Sduke		u_char rkey[16];
1370Sduke		int i;
1380Sduke
1390Sduke		MD5Init(&ct);
1400Sduke		MD5Update(&ct, d, sc->sectorsize);
1410Sduke		MD5Final(rkey, &ct);
1420Sduke		if (bcmp(rkey, skey, 16) != 0) {
1430Sduke#if 0
1440Sduke			printf("MD5_KEY failed at %jd (t=%d)\n",
1450Sduke			    (intmax_t)(wp->offset + o), time_second);
1460Sduke#endif
1470Sduke			for (i = 0; i < sc->sectorsize; i++)
1480Sduke				d[i] = 'A' + i % 26;
1490Sduke			sprintf(d, "MD5_KEY failed at %jd (t=%d)",
1500Sduke			    (intmax_t)(wp->offset + o), time_second);
1510Sduke		}
1520Sduke		}
1530Sduke#else
1540Sduke		AES_makekey(&ki, DIR_DECRYPT, G_BDE_SKEYBITS, skey);
1550Sduke		AES_decrypt(&ci, &ki, d, d, sc->sectorsize);
1560Sduke#endif
1570Sduke	}
1580Sduke	bzero(skey, sizeof skey);
1590Sduke	bzero(&ci, sizeof ci);
1600Sduke	bzero(&ki, sizeof ci);
1610Sduke}
1620Sduke
1630Sduke/*
1640Sduke * Encryption work for write operation.
1650Sduke *
1660Sduke * Security objective: Create random skey, encrypt sector data,
1670Sduke * encrypt skey with the kkey.
1680Sduke */
1690Sduke
1700Sdukevoid
1710Sdukeg_bde_crypt_write(struct g_bde_work *wp)
1720Sduke{
1730Sduke	u_char *s, *d;
1740Sduke	struct g_bde_softc *sc;
1750Sduke	u_int n;
1760Sduke	off_t o;
1770Sduke	u_char skey[G_BDE_SKEYLEN];
1780Sduke	keyInstance ki;
1790Sduke	cipherInstance ci;
1800Sduke
1810Sduke	sc = wp->softc;
1820Sduke	AES_init(&ci);
1830Sduke	o = 0;
1840Sduke	for (n = 0; o < wp->length; n++, o += sc->sectorsize) {
1850Sduke
1860Sduke		s = (u_char *)wp->data + o;
1870Sduke		d = (u_char *)wp->sp->data + o;
1880Sduke#ifdef MD5_KEY
1890Sduke		{
1900Sduke		MD5_CTX ct;
1910Sduke
1920Sduke		MD5Init(&ct);
1930Sduke		MD5Update(&ct, s, sc->sectorsize);
1940Sduke		MD5Final(skey, &ct);
1950Sduke		bcopy(s, d, sc->sectorsize);
1960Sduke		}
1970Sduke#else
1980Sduke		arc4rand(&skey, sizeof skey, 0);
1990Sduke		AES_makekey(&ki, DIR_ENCRYPT, G_BDE_SKEYBITS, skey);
2000Sduke		AES_encrypt(&ci, &ki, s, d, sc->sectorsize);
2010Sduke#endif
2020Sduke
2030Sduke		d = (u_char *)wp->ksp->data + wp->ko + n * G_BDE_SKEYLEN;
2040Sduke		g_bde_kkey(sc, &ki, DIR_ENCRYPT, wp->offset + o);
2050Sduke		AES_encrypt(&ci, &ki, skey, d, sizeof skey);
2060Sduke		bzero(skey, sizeof skey);
2070Sduke	}
2080Sduke	bzero(skey, sizeof skey);
2090Sduke	bzero(&ci, sizeof ci);
2100Sduke	bzero(&ki, sizeof ci);
2110Sduke}
2120Sduke
2130Sduke/*
2140Sduke * Encryption work for delete operation.
2150Sduke *
2160Sduke * Security objective: Write random data to the sectors.
2170Sduke *
2180Sduke * XXX: At a hit in performance we would trash the encrypted skey as well.
2190Sduke * XXX: This would add frustration to the cleaning lady attack by making
2200Sduke * XXX: deletes look like writes.
2210Sduke */
2220Sduke
2230Sdukevoid
2240Sdukeg_bde_crypt_delete(struct g_bde_work *wp)
2250Sduke{
2260Sduke	struct g_bde_softc *sc;
2270Sduke	u_char *d;
2280Sduke	off_t o;
2290Sduke	u_char skey[G_BDE_SKEYLEN];
2300Sduke	keyInstance ki;
2310Sduke	cipherInstance ci;
2320Sduke
2330Sduke	sc = wp->softc;
2340Sduke	d = wp->sp->data;
2350Sduke	AES_init(&ci);
2360Sduke	/*
2370Sduke	 * Do not unroll this loop!
2380Sduke	 * Our zone may be significantly wider than the amount of random
2390Sduke	 * bytes arc4rand likes to give in one reseeding, whereas our
2400Sduke	 * sectorsize is far more likely to be in the same range.
2410Sduke	 */
2420Sduke	for (o = 0; o < wp->length; o += sc->sectorsize) {
2430Sduke		arc4rand(d, sc->sectorsize, 0);
2440Sduke		arc4rand(&skey, sizeof skey, 0);
2450Sduke		AES_makekey(&ki, DIR_ENCRYPT, G_BDE_SKEYBITS, skey);
2460Sduke		AES_encrypt(&ci, &ki, d, d, sc->sectorsize);
2470Sduke		d += sc->sectorsize;
2480Sduke	}
2490Sduke	/*
2500Sduke	 * Having written a long random sequence to disk here, we want to
2510Sduke	 * force a reseed, to avoid weakening the next time we use random
2520Sduke	 * data for something important.
2530Sduke	 */
2540Sduke	arc4rand(&o, sizeof o, 1);
2550Sduke}
2560Sduke
2570Sduke/*
2580Sduke * Calculate the total payload size of the encrypted device.
2590Sduke *
2600Sduke * Security objectives: none.
2610Sduke *
2620Sduke * This function needs to agree with g_bde_map_sector() about things.
2630Sduke */
2640Sduke
2650Sdukeuint64_t
2660Sdukeg_bde_max_sector(struct g_bde_key *kp)
2670Sduke{
2680Sduke	uint64_t maxsect;
2690Sduke
2700Sduke	maxsect = kp->media_width;
2710Sduke	maxsect /= kp->zone_width;
2720Sduke	maxsect *= kp->zone_cont;
2730Sduke	return (maxsect);
2740Sduke}
2750Sduke
2760Sduke/*
2770Sduke * Convert an unencrypted side offset to offsets on the encrypted side.
2780Sduke *
2790Sduke * Security objective:  Make it harder to identify what sectors contain what
2800Sduke * on a "cold" disk image.
2810Sduke *
2820Sduke * We do this by adding the "keyoffset" from the lock to the physical sector
2830Sduke * number modulus the available number of sectors.  Since all physical sectors
2840Sduke * presumably look the same cold, this will do.
2850Sduke *
2860Sduke * As part of the mapping we have to skip the lock sectors which we know
2870Sduke * the physical address off.  We also truncate the work packet, respecting
2880Sduke * zone boundaries and lock sectors, so that we end up with a sequence of
2890Sduke * sectors which are physically contiguous.
2902099Srobilad *
2912099Srobilad * Shuffling things further is an option, but the incremental frustration is
2920Sduke * not currently deemed worth the run-time performance hit resulting from the
2930Sduke * increased number of disk arm movements it would incur.
2940Sduke *
2950Sduke * This function offers nothing but a trivial diversion for an attacker able
2960Sduke * to do "the cleaning lady attack" in its current static mapping form.
2970Sduke */
2980Sduke
2990Sdukevoid
3000Sdukeg_bde_map_sector(struct g_bde_work *wp)
3010Sduke{
3020Sduke
3030Sduke	u_int	zone, zoff, u, len;
3040Sduke	uint64_t ko;
3050Sduke	struct g_bde_softc *sc;
3060Sduke	struct g_bde_key *kp;
3070Sduke
3080Sduke	sc = wp->softc;
3090Sduke	kp = &sc->key;
3100Sduke
3110Sduke	/* find which zone and the offset in it */
3120Sduke	zone = wp->offset / kp->zone_cont;
3130Sduke	zoff = wp->offset % kp->zone_cont;
3140Sduke
3150Sduke	/* Calculate the offset of the key in the key sector */
3160Sduke	wp->ko = (zoff / kp->sectorsize) * G_BDE_SKEYLEN;
3170Sduke
3180Sduke	/* restrict length to that zone */
3190Sduke	len = kp->zone_cont - zoff;
3200Sduke
3210Sduke	/* ... and in general */
3220Sduke	if (len > DFLTPHYS)
3230Sduke		len = DFLTPHYS;
3240Sduke
3250Sduke	if (len < wp->length)
3260Sduke		wp->length = len;
3270Sduke
328307Sohair	/* Find physical sector address */
329307Sohair	wp->so = zone * kp->zone_width + zoff;
330307Sohair	wp->so += kp->keyoffset;
331307Sohair	wp->so %= kp->media_width;
332307Sohair	wp->so += kp->sector0;
3330Sduke
3340Sduke	/* The key sector is the last in this zone. */
3350Sduke	wp->kso = zone * kp->zone_width + kp->zone_cont;
3360Sduke	wp->kso += kp->keyoffset;
3370Sduke	wp->kso %= kp->media_width;
3380Sduke	wp->kso += kp->sector0;
3390Sduke
3400Sduke	/* Compensate for lock sectors */
3410Sduke	for (u = 0; u < G_BDE_MAXKEYS; u++) {
3420Sduke		/* Find the start of this lock sector */
3430Sduke		ko = kp->lsector[u] & ~(kp->sectorsize - 1);
3440Sduke
3450Sduke		if (wp->kso >= ko)
3460Sduke			wp->kso += kp->sectorsize;
3470Sduke
348		if (wp->so >= ko) {
349			/* lock sector before work packet */
350			wp->so += kp->sectorsize;
351		} else if ((wp->so + wp->length) > ko) {
352			/* lock sector in work packet, truncate */
353			wp->length = ko - wp->so;
354		}
355	}
356
357#if 0
358	printf("off %jd len %jd so %jd ko %jd kso %u\n",
359	    (intmax_t)wp->offset,
360	    (intmax_t)wp->length,
361	    (intmax_t)wp->so,
362	    (intmax_t)wp->kso,
363	    wp->ko);
364#endif
365}
366