1/*- 2 * Copyright (c) 2002 Poul-Henning Kamp 3 * Copyright (c) 2002 Networks Associates Technology, Inc. 4 * All rights reserved. 5 * 6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp 7 * and NAI Labs, the Security Research Division of Network Associates, Inc. 8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 9 * DARPA CHATS research program. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 *
|
32 * $FreeBSD: head/sys/geom/bde/g_bde_crypt.c 113010 2003-04-03 11:33:51Z phk $
|
32 * $FreeBSD: head/sys/geom/bde/g_bde_crypt.c 114153 2003-04-28 06:38:31Z phk $ |
33 * 34 * This source file contains the functions responsible for the crypto, keying 35 * and mapping operations on the I/O requests. 36 * 37 */ 38 39#include <sys/param.h> 40#include <sys/bio.h> 41#include <sys/lock.h> 42#include <sys/mutex.h> 43#include <sys/queue.h> 44#include <sys/malloc.h> 45#include <sys/libkern.h> 46#include <sys/endian.h> 47#include <sys/md5.h> 48 49#include <crypto/rijndael/rijndael.h> 50#include <crypto/sha2/sha2.h> 51 52#include <geom/geom.h> 53#include <geom/bde/g_bde.h> 54 55
|
56#define MD5_KEY 57 |
58/* 59 * Derive kkey from mkey + sector offset. 60 * 61 * Security objective: Derive a potentially very large number of distinct skeys 62 * from the comparatively small key material in our mkey, in such a way that 63 * if one, more or even many of the kkeys are compromised, this does not 64 * significantly help an attack on other kkeys and in particular does not 65 * weaken or compromised the mkey. 66 * 67 * First we MD5 hash the sectornumber with the salt from the lock sector. 68 * The salt prevents the precalculation and statistical analysis of the MD5 69 * output which would be possible if we only gave it the sectornumber. 70 * 71 * The MD5 hash is used to pick out 16 bytes from the masterkey, which 72 * are then hashed with MD5 together with the sector number. 73 * 74 * The resulting MD5 hash is the kkey. 75 */ 76 77static void 78g_bde_kkey(struct g_bde_softc *sc, keyInstance *ki, int dir, off_t sector) 79{ 80 u_int t; 81 MD5_CTX ct; 82 u_char buf[16]; 83 u_char buf2[8]; 84 85 /* We have to be architecture neutral */ 86 le64enc(buf2, sector); 87 88 MD5Init(&ct); 89 MD5Update(&ct, sc->key.salt, 8); 90 MD5Update(&ct, buf2, sizeof buf2); 91 MD5Update(&ct, sc->key.salt + 8, 8); 92 MD5Final(buf, &ct); 93 94 MD5Init(&ct); 95 for (t = 0; t < 16; t++) { 96 MD5Update(&ct, &sc->key.mkey[buf[t]], 1); 97 if (t == 8) 98 MD5Update(&ct, buf2, sizeof buf2); 99 } 100 bzero(buf2, sizeof buf2); 101 MD5Final(buf, &ct); 102 bzero(&ct, sizeof ct); 103 AES_makekey(ki, dir, G_BDE_KKEYBITS, buf); 104 bzero(buf, sizeof buf); 105} 106 107/* 108 * Encryption work for read operation. 109 * 110 * Security objective: Find the kkey, find the skey, decrypt the sector data. 111 */ 112 113void 114g_bde_crypt_read(struct g_bde_work *wp) 115{ 116 struct g_bde_softc *sc; 117 u_char *d; 118 u_int n; 119 off_t o; 120 u_char skey[G_BDE_SKEYLEN]; 121 keyInstance ki; 122 cipherInstance ci; 123 124 125 AES_init(&ci); 126 sc = wp->softc; 127 o = 0; 128 for (n = 0; o < wp->length; n++, o += sc->sectorsize) { 129 d = (u_char *)wp->ksp->data + wp->ko + n * G_BDE_SKEYLEN; 130 g_bde_kkey(sc, &ki, DIR_DECRYPT, wp->offset + o); 131 AES_decrypt(&ci, &ki, d, skey, sizeof skey); 132 d = (u_char *)wp->data + o;
|
133#ifdef MD5_KEY 134 { 135 MD5_CTX ct; 136 u_char rkey[16]; 137 int i; 138 139 MD5Init(&ct); 140 MD5Update(&ct, d, sc->sectorsize); 141 MD5Final(rkey, &ct); 142 if (bcmp(rkey, skey, 16) != 0) { 143#if 0 144 printf("MD5_KEY failed at %jd (t=%d)\n", 145 (intmax_t)(wp->offset + o), time_second); 146#endif 147 for (i = 0; i < sc->sectorsize; i++) 148 d[i] = 'A' + i % 26; 149 sprintf(d, "MD5_KEY failed at %jd (t=%d)", 150 (intmax_t)(wp->offset + o), time_second); 151 } 152 } 153#else |
154 AES_makekey(&ki, DIR_DECRYPT, G_BDE_SKEYBITS, skey); 155 AES_decrypt(&ci, &ki, d, d, sc->sectorsize);
|
156#endif |
157 } 158 bzero(skey, sizeof skey); 159 bzero(&ci, sizeof ci); 160 bzero(&ki, sizeof ci); 161} 162 163/* 164 * Encryption work for write operation. 165 * 166 * Security objective: Create random skey, encrypt sector data, 167 * encrypt skey with the kkey. 168 */ 169 170void 171g_bde_crypt_write(struct g_bde_work *wp) 172{ 173 u_char *s, *d; 174 struct g_bde_softc *sc; 175 u_int n; 176 off_t o; 177 u_char skey[G_BDE_SKEYLEN]; 178 keyInstance ki; 179 cipherInstance ci; 180 181 sc = wp->softc; 182 AES_init(&ci); 183 o = 0; 184 for (n = 0; o < wp->length; n++, o += sc->sectorsize) { 185 186 s = (u_char *)wp->data + o; 187 d = (u_char *)wp->sp->data + o;
|
188#ifdef MD5_KEY 189 { 190 MD5_CTX ct; 191 192 MD5Init(&ct); 193 MD5Update(&ct, s, sc->sectorsize); 194 MD5Final(skey, &ct); 195 bcopy(s, d, sc->sectorsize); 196 } 197#else |
198 arc4rand(&skey, sizeof skey, 0); 199 AES_makekey(&ki, DIR_ENCRYPT, G_BDE_SKEYBITS, skey); 200 AES_encrypt(&ci, &ki, s, d, sc->sectorsize);
|
201#endif |
202 203 d = (u_char *)wp->ksp->data + wp->ko + n * G_BDE_SKEYLEN; 204 g_bde_kkey(sc, &ki, DIR_ENCRYPT, wp->offset + o); 205 AES_encrypt(&ci, &ki, skey, d, sizeof skey); 206 bzero(skey, sizeof skey); 207 } 208 bzero(skey, sizeof skey); 209 bzero(&ci, sizeof ci); 210 bzero(&ki, sizeof ci); 211} 212 213/* 214 * Encryption work for delete operation. 215 * 216 * Security objective: Write random data to the sectors. 217 * 218 * XXX: At a hit in performance we would trash the encrypted skey as well. 219 * XXX: This would add frustration to the cleaning lady attack by making 220 * XXX: deletes look like writes. 221 */ 222 223void 224g_bde_crypt_delete(struct g_bde_work *wp) 225{ 226 struct g_bde_softc *sc; 227 u_char *d; 228 off_t o; 229 u_char skey[G_BDE_SKEYLEN]; 230 keyInstance ki; 231 cipherInstance ci; 232 233 sc = wp->softc; 234 d = wp->sp->data; 235 AES_init(&ci); 236 /* 237 * Do not unroll this loop! 238 * Our zone may be significantly wider than the amount of random 239 * bytes arc4rand likes to give in one reseeding, whereas our 240 * sectorsize is far more likely to be in the same range. 241 */ 242 for (o = 0; o < wp->length; o += sc->sectorsize) { 243 arc4rand(d, sc->sectorsize, 0); 244 arc4rand(&skey, sizeof skey, 0); 245 AES_makekey(&ki, DIR_ENCRYPT, G_BDE_SKEYBITS, skey); 246 AES_encrypt(&ci, &ki, d, d, sc->sectorsize); 247 d += sc->sectorsize; 248 } 249 /* 250 * Having written a long random sequence to disk here, we want to 251 * force a reseed, to avoid weakening the next time we use random 252 * data for something important. 253 */ 254 arc4rand(&o, sizeof o, 1); 255} 256 257/* 258 * Calculate the total payload size of the encrypted device. 259 * 260 * Security objectives: none. 261 * 262 * This function needs to agree with g_bde_map_sector() about things. 263 */ 264 265uint64_t 266g_bde_max_sector(struct g_bde_key *kp) 267{ 268 uint64_t maxsect; 269 270 maxsect = kp->media_width; 271 maxsect /= kp->zone_width; 272 maxsect *= kp->zone_cont; 273 return (maxsect); 274} 275 276/* 277 * Convert an unencrypted side offset to offsets on the encrypted side. 278 * 279 * Security objective: Make it harder to identify what sectors contain what 280 * on a "cold" disk image. 281 * 282 * We do this by adding the "keyoffset" from the lock to the physical sector 283 * number modulus the available number of sectors. Since all physical sectors 284 * presumably look the same cold, this will do. 285 * 286 * As part of the mapping we have to skip the lock sectors which we know 287 * the physical address off. We also truncate the work packet, respecting 288 * zone boundaries and lock sectors, so that we end up with a sequence of 289 * sectors which are physically contiguous. 290 * 291 * Shuffling things further is an option, but the incremental frustration is 292 * not currently deemed worth the run-time performance hit resulting from the 293 * increased number of disk arm movements it would incur. 294 * 295 * This function offers nothing but a trivial diversion for an attacker able 296 * to do "the cleaning lady attack" in its current static mapping form. 297 */ 298 299void 300g_bde_map_sector(struct g_bde_work *wp) 301{ 302 303 u_int zone, zoff, u, len; 304 uint64_t ko; 305 struct g_bde_softc *sc; 306 struct g_bde_key *kp; 307 308 sc = wp->softc; 309 kp = &sc->key; 310 311 /* find which zone and the offset in it */ 312 zone = wp->offset / kp->zone_cont; 313 zoff = wp->offset % kp->zone_cont; 314 315 /* Calculate the offset of the key in the key sector */ 316 wp->ko = (zoff / kp->sectorsize) * G_BDE_SKEYLEN; 317 318 /* restrict length to that zone */ 319 len = kp->zone_cont - zoff; 320 321 /* ... and in general */ 322 if (len > DFLTPHYS) 323 len = DFLTPHYS; 324 325 if (len < wp->length) 326 wp->length = len; 327 328 /* Find physical sector address */ 329 wp->so = zone * kp->zone_width + zoff; 330 wp->so += kp->keyoffset; 331 wp->so %= kp->media_width; 332 wp->so += kp->sector0; 333 334 /* The key sector is the last in this zone. */ 335 wp->kso = zone * kp->zone_width + kp->zone_cont; 336 wp->kso += kp->keyoffset; 337 wp->kso %= kp->media_width; 338 wp->kso += kp->sector0; 339 340 /* Compensate for lock sectors */ 341 for (u = 0; u < G_BDE_MAXKEYS; u++) { 342 /* Find the start of this lock sector */ 343 ko = kp->lsector[u] & ~(kp->sectorsize - 1); 344 345 if (wp->kso >= ko) 346 wp->kso += kp->sectorsize; 347 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}
|