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