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: releng/11.0/sys/geom/bde/g_bde_lock.c 298808 2016-04-29 20:56:58Z pfg $ 33139778Simp */ 34139778Simp/* This souce file contains routines which operates on the lock sectors, both 35105464Sphk * for the kernel and the userland program gbde(1). 36105464Sphk * 37105464Sphk */ 38105464Sphk 39105464Sphk#include <sys/param.h> 40105464Sphk#include <sys/queue.h> 41105464Sphk#include <sys/lock.h> 42105464Sphk#include <sys/mutex.h> 43113010Sphk#include <sys/endian.h> 44105464Sphk#include <sys/md5.h> 45105464Sphk 46105464Sphk#ifdef _KERNEL 47105464Sphk#include <sys/malloc.h> 48105464Sphk#include <sys/systm.h> 49105464Sphk#else 50106407Sphk#include <err.h> 51106407Sphk#define CTASSERT(foo) 52106407Sphk#define KASSERT(foo, bar) do { if(!(foo)) { warn bar ; exit (1); } } while (0) 53105464Sphk#include <errno.h> 54105464Sphk#include <string.h> 55105464Sphk#include <stdlib.h> 56105464Sphk#include <stdio.h> 57105464Sphk#define g_free(foo) free(foo) 58105464Sphk#endif 59105464Sphk 60143418Sume#include <crypto/rijndael/rijndael-api-fst.h> 61292782Sallanjude#include <crypto/sha2/sha512.h> 62106407Sphk 63105464Sphk#include <geom/geom.h> 64105464Sphk#include <geom/bde/g_bde.h> 65105464Sphk 66105464Sphk/* 67106407Sphk * Hash the raw pass-phrase. 68105464Sphk * 69106407Sphk * Security objectives: produce from the pass-phrase a fixed length 70106407Sphk * bytesequence with PRN like properties in a reproducible way retaining 71106407Sphk * as much entropy from the pass-phrase as possible. 72105464Sphk * 73106407Sphk * SHA2-512 makes this easy. 74105464Sphk */ 75105464Sphk 76105464Sphkvoid 77106407Sphkg_bde_hash_pass(struct g_bde_softc *sc, const void *input, u_int len) 78105464Sphk{ 79106407Sphk SHA512_CTX cx; 80105464Sphk 81106407Sphk SHA512_Init(&cx); 82106407Sphk SHA512_Update(&cx, input, len); 83106407Sphk SHA512_Final(sc->sha2, &cx); 84105464Sphk} 85105464Sphk 86105464Sphk/* 87106407Sphk * Encode/Decode the lock structure in byte-sequence format. 88105464Sphk * 89106407Sphk * Security objectives: Store in pass-phrase dependent variant format. 90105464Sphk * 91106407Sphk * C-structure packing and byte-endianess depends on architecture, compiler 92106407Sphk * and compiler options. Writing raw structures to disk is therefore a bad 93106407Sphk * idea in these enlightend days. 94106407Sphk * 95106407Sphk * We spend a fraction of the key-material on shuffling the fields around 96106407Sphk * so they will be stored in an unpredictable sequence. 97106407Sphk * 98106407Sphk * For each byte of the key-material we derive two field indexes, and swap 99106407Sphk * the position of those two fields. 100106407Sphk * 101106407Sphk * I have not worked out the statistical properties of this shuffle, but 102106407Sphk * given that the key-material has PRN properties, the primary objective 103106407Sphk * of making it hard to figure out which bits are where in the lock sector 104106407Sphk * is sufficiently fulfilled. 105106407Sphk * 106106407Sphk * We include (and shuffle) an extra hash field in the stored version for 107106407Sphk * identification and versioning purposes. This field contains the MD5 hash 108106407Sphk * of a version identifier (currently "0000") followed by the stored lock 109106407Sphk * sector byte-sequence substituting zero bytes for the hash field. 110106407Sphk * 111106407Sphk * The stored keysequence is protected by AES/256/CBC elsewhere in the code 112106407Sphk * so the fact that the generated byte sequence has a much higher than 113106407Sphk * average density of zero bits (from the numeric fields) is not currently 114106407Sphk * a concern. 115106407Sphk * 116106407Sphk * Should this later become a concern, a simple software update and 117106407Sphk * pass-phrase change can remedy the situation. One possible solution 118106407Sphk * could be to XOR the numeric fields with a key-material derived PRN. 119106407Sphk * 120106407Sphk * The chosen shuffle algorithm only works as long as we have no more than 16 121106407Sphk * fields in the stored part of the lock structure (hence the CTASSERT below). 122105464Sphk */ 123105464Sphk 124106407SphkCTASSERT(NLOCK_FIELDS <= 16); 125106407Sphk 126106407Sphkstatic void 127120876Sphkg_bde_shuffle_lock(u_char *sha2, int *buf) 128105464Sphk{ 129107450Sphk int j, k, l; 130107450Sphk u_int u; 131105464Sphk 132106407Sphk /* Assign the fields sequential positions */ 133107450Sphk for(u = 0; u < NLOCK_FIELDS; u++) 134107450Sphk buf[u] = u; 135106407Sphk 136106407Sphk /* Then mix it all up */ 137120876Sphk for(u = 48; u < SHA512_DIGEST_LENGTH; u++) { 138120876Sphk j = sha2[u] % NLOCK_FIELDS; 139120876Sphk k = (sha2[u] / NLOCK_FIELDS) % NLOCK_FIELDS; 140106407Sphk l = buf[j]; 141106407Sphk buf[j] = buf[k]; 142106407Sphk buf[k] = l; 143106407Sphk } 144105464Sphk} 145105464Sphk 146106407Sphkint 147120876Sphkg_bde_encode_lock(u_char *sha2, struct g_bde_key *gl, u_char *ptr) 148105464Sphk{ 149106407Sphk int shuffle[NLOCK_FIELDS]; 150106407Sphk u_char *hash, *p; 151106407Sphk int i; 152106407Sphk MD5_CTX c; 153106407Sphk 154105464Sphk p = ptr; 155106407Sphk hash = NULL; 156120876Sphk g_bde_shuffle_lock(sha2, shuffle); 157106407Sphk for (i = 0; i < NLOCK_FIELDS; i++) { 158106407Sphk switch(shuffle[i]) { 159106407Sphk case 0: 160113010Sphk le64enc(p, gl->sector0); 161106407Sphk p += 8; 162106407Sphk break; 163106407Sphk case 1: 164113010Sphk le64enc(p, gl->sectorN); 165106407Sphk p += 8; 166106407Sphk break; 167106407Sphk case 2: 168113010Sphk le64enc(p, gl->keyoffset); 169106407Sphk p += 8; 170106407Sphk break; 171106407Sphk case 3: 172113010Sphk le32enc(p, gl->sectorsize); 173106407Sphk p += 4; 174106407Sphk break; 175106407Sphk case 4: 176113010Sphk le32enc(p, gl->flags); 177106407Sphk p += 4; 178106407Sphk break; 179106407Sphk case 5: 180106407Sphk case 6: 181106407Sphk case 7: 182106407Sphk case 8: 183113010Sphk le64enc(p, gl->lsector[shuffle[i] - 5]); 184106407Sphk p += 8; 185106407Sphk break; 186106407Sphk case 9: 187106407Sphk bcopy(gl->spare, p, sizeof gl->spare); 188106407Sphk p += sizeof gl->spare; 189106407Sphk break; 190106407Sphk case 10: 191106407Sphk bcopy(gl->salt, p, sizeof gl->salt); 192106407Sphk p += sizeof gl->salt; 193106407Sphk break; 194106407Sphk case 11: 195106407Sphk bcopy(gl->mkey, p, sizeof gl->mkey); 196106407Sphk p += sizeof gl->mkey; 197106407Sphk break; 198106407Sphk case 12: 199106407Sphk bzero(p, 16); 200106407Sphk hash = p; 201106407Sphk p += 16; 202106407Sphk break; 203106407Sphk } 204106407Sphk } 205106407Sphk if(ptr + G_BDE_LOCKSIZE != p) 206106407Sphk return(-1); 207106407Sphk if (hash == NULL) 208106407Sphk return(-1); 209106407Sphk MD5Init(&c); 210106407Sphk MD5Update(&c, "0000", 4); /* Versioning */ 211106407Sphk MD5Update(&c, ptr, G_BDE_LOCKSIZE); 212106407Sphk MD5Final(hash, &c); 213106407Sphk return(0); 214105464Sphk} 215105464Sphk 216106407Sphkint 217106407Sphkg_bde_decode_lock(struct g_bde_softc *sc, struct g_bde_key *gl, u_char *ptr) 218105464Sphk{ 219106407Sphk int shuffle[NLOCK_FIELDS]; 220106407Sphk u_char *p; 221106407Sphk u_char hash[16], hash2[16]; 222106407Sphk MD5_CTX c; 223106407Sphk int i; 224105464Sphk 225105464Sphk p = ptr; 226120876Sphk g_bde_shuffle_lock(sc->sha2, shuffle); 227106407Sphk for (i = 0; i < NLOCK_FIELDS; i++) { 228106407Sphk switch(shuffle[i]) { 229106407Sphk case 0: 230113010Sphk gl->sector0 = le64dec(p); 231106407Sphk p += 8; 232106407Sphk break; 233106407Sphk case 1: 234113010Sphk gl->sectorN = le64dec(p); 235106407Sphk p += 8; 236106407Sphk break; 237106407Sphk case 2: 238113010Sphk gl->keyoffset = le64dec(p); 239106407Sphk p += 8; 240106407Sphk break; 241106407Sphk case 3: 242113010Sphk gl->sectorsize = le32dec(p); 243106407Sphk p += 4; 244106407Sphk break; 245106407Sphk case 4: 246113010Sphk gl->flags = le32dec(p); 247106407Sphk p += 4; 248106407Sphk break; 249106407Sphk case 5: 250106407Sphk case 6: 251106407Sphk case 7: 252106407Sphk case 8: 253113010Sphk gl->lsector[shuffle[i] - 5] = le64dec(p); 254106407Sphk p += 8; 255106407Sphk break; 256106407Sphk case 9: 257106407Sphk bcopy(p, gl->spare, sizeof gl->spare); 258106407Sphk p += sizeof gl->spare; 259106407Sphk break; 260106407Sphk case 10: 261106407Sphk bcopy(p, gl->salt, sizeof gl->salt); 262106407Sphk p += sizeof gl->salt; 263106407Sphk break; 264106407Sphk case 11: 265106407Sphk bcopy(p, gl->mkey, sizeof gl->mkey); 266106407Sphk p += sizeof gl->mkey; 267106407Sphk break; 268106407Sphk case 12: 269106407Sphk bcopy(p, hash2, sizeof hash2); 270106407Sphk bzero(p, sizeof hash2); 271106407Sphk p += sizeof hash2; 272106407Sphk break; 273106407Sphk } 274105464Sphk } 275106407Sphk if(ptr + G_BDE_LOCKSIZE != p) 276106407Sphk return(-1); 277106407Sphk MD5Init(&c); 278106407Sphk MD5Update(&c, "0000", 4); /* Versioning */ 279106407Sphk MD5Update(&c, ptr, G_BDE_LOCKSIZE); 280106407Sphk MD5Final(hash, &c); 281106407Sphk if (bcmp(hash, hash2, sizeof hash2)) 282106407Sphk return (1); 283106407Sphk return (0); 284105464Sphk} 285105464Sphk 286105464Sphk/* 287106407Sphk * Encode/Decode the locksector address ("metadata") with key-material. 288106407Sphk * 289106407Sphk * Security objectives: Encode/Decode the metadata encrypted by key-material. 290106407Sphk * 291106407Sphk * A simple AES/128/CBC will do. We take care to always store the metadata 292298808Spfg * in the same endianness to make it MI. 293106407Sphk * 294106407Sphk * In the typical case the metadata is stored in encrypted format in sector 295106407Sphk * zero on the media, but at the users discretion or if the piece of the 296106407Sphk * device used (sector0...sectorN) does not contain sector zero, it can 297106407Sphk * be stored in a filesystem or on a PostIt. 298106407Sphk * 299106407Sphk * The inability to easily locate the lock sectors makes an attack on a 300106407Sphk * cold disk much less attractive, without unduly inconveniencing the 301106407Sphk * legitimate user who can feasibly do a brute-force scan if the metadata 302106407Sphk * was lost. 303105464Sphk */ 304105464Sphk 305105464Sphkint 306120876Sphkg_bde_keyloc_encrypt(u_char *sha2, uint64_t v0, uint64_t v1, void *output) 307105464Sphk{ 308106407Sphk u_char buf[16]; 309105464Sphk keyInstance ki; 310105464Sphk cipherInstance ci; 311105464Sphk 312120876Sphk le64enc(buf, v0); 313120876Sphk le64enc(buf + 8, v1); 314106407Sphk AES_init(&ci); 315120876Sphk AES_makekey(&ki, DIR_ENCRYPT, G_BDE_KKEYBITS, sha2 + 0); 316106407Sphk AES_encrypt(&ci, &ki, buf, output, sizeof buf); 317106407Sphk bzero(buf, sizeof buf); 318105464Sphk bzero(&ci, sizeof ci); 319105512Sphk bzero(&ki, sizeof ki); 320105464Sphk return (0); 321105464Sphk} 322105464Sphk 323105464Sphkint 324120876Sphkg_bde_keyloc_decrypt(u_char *sha2, void *input, uint64_t *output) 325105464Sphk{ 326105464Sphk keyInstance ki; 327105464Sphk cipherInstance ci; 328106407Sphk u_char buf[16]; 329105464Sphk 330106407Sphk AES_init(&ci); 331120876Sphk AES_makekey(&ki, DIR_DECRYPT, G_BDE_KKEYBITS, sha2 + 0); 332106407Sphk AES_decrypt(&ci, &ki, input, buf, sizeof buf); 333120876Sphk *output = le64dec(buf); 334106407Sphk bzero(buf, sizeof buf); 335105464Sphk bzero(&ci, sizeof ci); 336105512Sphk bzero(&ki, sizeof ki); 337120876Sphk return(0); 338105464Sphk} 339105464Sphk 340105464Sphk/* 341106407Sphk * Find and Encode/Decode lock sectors. 342106407Sphk * 343106407Sphk * Security objective: given the pass-phrase, find, decrypt, decode and 344106407Sphk * validate the lock sector contents. 345106407Sphk * 346106407Sphk * For ondisk metadata we cannot know beforehand which of the lock sectors 347106407Sphk * a given pass-phrase opens so we must try each of the metadata copies in 348106407Sphk * sector zero in turn. If metadata was passed as an argument, we don't 349106407Sphk * have this problem. 350106407Sphk * 351105464Sphk */ 352105464Sphk 353105512Sphkstatic int 354106407Sphkg_bde_decrypt_lockx(struct g_bde_softc *sc, u_char *meta, off_t mediasize, u_int sectorsize, u_int *nkey) 355105464Sphk{ 356106407Sphk u_char *buf, *q; 357105464Sphk struct g_bde_key *gl; 358120876Sphk uint64_t off, q1; 359105464Sphk int error, m, i; 360105464Sphk keyInstance ki; 361105464Sphk cipherInstance ci; 362105464Sphk 363105464Sphk gl = &sc->key; 364106407Sphk 365106407Sphk /* Try to decrypt the metadata */ 366120876Sphk error = g_bde_keyloc_decrypt(sc->sha2, meta, &off); 367105464Sphk if (error) 368120876Sphk return (error); 369105464Sphk 370138888Sbrueffer /* If it points into thin blue air, forget it */ 371120876Sphk if (off + G_BDE_LOCKSIZE > (uint64_t)mediasize) { 372120876Sphk off = 0; 373105512Sphk return (EINVAL); 374105464Sphk } 375106407Sphk 376106407Sphk /* The lock data may span two physical sectors. */ 377106407Sphk 378105464Sphk m = 1; 379120876Sphk if (off % sectorsize > sectorsize - G_BDE_LOCKSIZE) 380105464Sphk m++; 381106407Sphk 382106407Sphk /* Read the suspected sector(s) */ 383105464Sphk buf = g_read_data(sc->consumer, 384120876Sphk off - (off % sectorsize), 385105464Sphk m * sectorsize, &error); 386105464Sphk if (buf == NULL) { 387120876Sphk off = 0; 388105464Sphk return(error); 389105464Sphk } 390105464Sphk 391106407Sphk /* Find the byte-offset of the stored byte sequence */ 392120876Sphk q = buf + off % sectorsize; 393105464Sphk 394106407Sphk /* If it is all zero, somebody nuked our lock sector */ 395120876Sphk q1 = 0; 396105512Sphk for (i = 0; i < G_BDE_LOCKSIZE; i++) 397120876Sphk q1 += q[i]; 398120876Sphk if (q1 == 0) { 399120876Sphk off = 0; 400105464Sphk g_free(buf); 401105464Sphk return (ESRCH); 402105464Sphk } 403105464Sphk 404106407Sphk /* Decrypt the byte-sequence in place */ 405106407Sphk AES_init(&ci); 406106407Sphk AES_makekey(&ki, DIR_DECRYPT, 256, sc->sha2 + 16); 407106407Sphk AES_decrypt(&ci, &ki, q, q, G_BDE_LOCKSIZE); 408152966Ssobomax 409106407Sphk /* Decode the byte-sequence */ 410106407Sphk i = g_bde_decode_lock(sc, gl, q); 411106407Sphk q = NULL; 412106407Sphk if (i < 0) { 413120876Sphk off = 0; 414106407Sphk return (EDOOFUS); /* Programming error */ 415106407Sphk } else if (i > 0) { 416120876Sphk off = 0; 417106407Sphk return (ENOTDIR); /* Hash didn't match */ 418105464Sphk } 419105464Sphk 420105464Sphk bzero(buf, sectorsize * m); 421105464Sphk g_free(buf); 422105464Sphk 423106407Sphk /* If the masterkey is all zeros, user destroyed it */ 424120876Sphk q1 = 0; 425106226Sphk for (i = 0; i < (int)sizeof(gl->mkey); i++) 426120876Sphk q1 += gl->mkey[i]; 427120876Sphk if (q1 == 0) 428106407Sphk return (ENOENT); 429105464Sphk 430108052Sphk /* If we have an unsorted lock-sequence, refuse */ 431135084Sphk for (i = 0; i < G_BDE_MAXKEYS - 1; i++) 432135084Sphk if (gl->lsector[i] >= gl->lsector[i + 1]) 433135084Sphk return (EINVAL); 434108052Sphk 435106407Sphk /* Finally, find out which key was used by matching the byte offset */ 436105464Sphk for (i = 0; i < G_BDE_MAXKEYS; i++) 437120876Sphk if (nkey != NULL && off == gl->lsector[i]) 438105464Sphk *nkey = i; 439120876Sphk off = 0; 440105464Sphk return (0); 441105464Sphk} 442105512Sphk 443105512Sphkint 444106407Sphkg_bde_decrypt_lock(struct g_bde_softc *sc, u_char *keymat, u_char *meta, off_t mediasize, u_int sectorsize, u_int *nkey) 445105512Sphk{ 446105512Sphk u_char *buf, buf1[16]; 447105512Sphk int error, e, i; 448105512Sphk 449106407Sphk /* set up the key-material */ 450106407Sphk bcopy(keymat, sc->sha2, SHA512_DIGEST_LENGTH); 451106407Sphk 452106407Sphk /* If passed-in metadata is non-zero, use it */ 453105512Sphk bzero(buf1, sizeof buf1); 454112594Sphk if (meta != NULL && bcmp(buf1, meta, sizeof buf1)) 455106407Sphk return (g_bde_decrypt_lockx(sc, meta, mediasize, 456105512Sphk sectorsize, nkey)); 457105512Sphk 458106407Sphk /* Read sector zero */ 459105512Sphk buf = g_read_data(sc->consumer, 0, sectorsize, &error); 460105512Sphk if (buf == NULL) 461105512Sphk return(error); 462106407Sphk 463106407Sphk /* Try each index in turn, save indicative errors for final result */ 464106407Sphk error = EINVAL; 465105512Sphk for (i = 0; i < G_BDE_MAXKEYS; i++) { 466106407Sphk e = g_bde_decrypt_lockx(sc, buf + i * 16, mediasize, 467105512Sphk sectorsize, nkey); 468106407Sphk /* Success or destroyed master key terminates */ 469105512Sphk if (e == 0 || e == ENOENT) { 470105512Sphk error = e; 471105512Sphk break; 472105512Sphk } 473106407Sphk if (e != 0 && error == EINVAL) 474105512Sphk error = e; 475105512Sphk } 476105512Sphk g_free(buf); 477105512Sphk return (error); 478105512Sphk} 479