g_bde_lock.c revision 108052
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_lock.c 108052 2002-12-18 19:57:27Z phk $
33 *
34 * This souce file contains routines which operates on the lock sectors, both
35 * for the kernel and the userland program gbde(1).
36 *
37 */
38
39#include <sys/param.h>
40#include <sys/queue.h>
41#include <sys/stdint.h>
42#include <sys/lock.h>
43#include <sys/mutex.h>
44#include <sys/md5.h>
45
46#ifdef _KERNEL
47#include <sys/malloc.h>
48#include <sys/systm.h>
49#else
50#include <err.h>
51#define CTASSERT(foo)
52#define KASSERT(foo, bar) do { if(!(foo)) { warn bar ; exit (1); } } while (0)
53#include <errno.h>
54#include <string.h>
55#include <stdlib.h>
56#include <stdio.h>
57#define g_free(foo)	free(foo)
58#endif
59
60#include <crypto/rijndael/rijndael.h>
61#include <crypto/sha2/sha2.h>
62
63#include <geom/geom.h>
64#include <geom/bde/g_bde.h>
65
66/*
67 * Hash the raw pass-phrase.
68 *
69 * Security objectives: produce from the pass-phrase a fixed length
70 * bytesequence with PRN like properties in a reproducible way retaining
71 * as much entropy from the pass-phrase as possible.
72 *
73 * SHA2-512 makes this easy.
74 */
75
76void
77g_bde_hash_pass(struct g_bde_softc *sc, const void *input, u_int len)
78{
79	SHA512_CTX cx;
80
81	SHA512_Init(&cx);
82	SHA512_Update(&cx, input, len);
83	SHA512_Final(sc->sha2, &cx);
84}
85
86/*
87 * Encode/Decode the lock structure in byte-sequence format.
88 *
89 * Security objectives: Store in pass-phrase dependent variant format.
90 *
91 * C-structure packing and byte-endianess depends on architecture, compiler
92 * and compiler options.  Writing raw structures to disk is therefore a bad
93 * idea in these enlightend days.
94 *
95 * We spend a fraction of the key-material on shuffling the fields around
96 * so they will be stored in an unpredictable sequence.
97 *
98 * For each byte of the key-material we derive two field indexes, and swap
99 * the position of those two fields.
100 *
101 * I have not worked out the statistical properties of this shuffle, but
102 * given that the key-material has PRN properties, the primary objective
103 * of making it hard to figure out which bits are where in the lock sector
104 * is sufficiently fulfilled.
105 *
106 * We include (and shuffle) an extra hash field in the stored version for
107 * identification and versioning purposes.  This field contains the MD5 hash
108 * of a version identifier (currently "0000") followed by the stored lock
109 * sector byte-sequence substituting zero bytes for the hash field.
110 *
111 * The stored keysequence is protected by AES/256/CBC elsewhere in the code
112 * so the fact that the generated byte sequence has a much higher than
113 * average density of zero bits (from the numeric fields) is not currently
114 * a concern.
115 *
116 * Should this later become a concern, a simple software update and
117 * pass-phrase change can remedy the situation.  One possible solution
118 * could be to XOR the numeric fields with a key-material derived PRN.
119 *
120 * The chosen shuffle algorithm only works as long as we have no more than 16
121 * fields in the stored part of the lock structure (hence the CTASSERT below).
122 */
123
124CTASSERT(NLOCK_FIELDS <= 16);
125
126static void
127g_bde_shuffle_lock(struct g_bde_softc *sc, int *buf)
128{
129	int j, k, l;
130	u_int u;
131
132	/* Assign the fields sequential positions */
133	for(u = 0; u < NLOCK_FIELDS; u++)
134		buf[u] = u;
135
136	/* Then mix it all up */
137	for(u = 48; u < sizeof(sc->sha2); u++) {
138		j = sc->sha2[u] % NLOCK_FIELDS;
139		k = (sc->sha2[u] / NLOCK_FIELDS) % NLOCK_FIELDS;
140		l = buf[j];
141		buf[j] = buf[k];
142		buf[k] = l;
143	}
144}
145
146int
147g_bde_encode_lock(struct g_bde_softc *sc, struct g_bde_key *gl, u_char *ptr)
148{
149	int shuffle[NLOCK_FIELDS];
150	u_char *hash, *p;
151	int i;
152	MD5_CTX c;
153
154	p = ptr;
155	hash = NULL;
156	g_bde_shuffle_lock(sc, shuffle);
157	for (i = 0; i < NLOCK_FIELDS; i++) {
158		switch(shuffle[i]) {
159		case 0:
160			g_enc_le8(p, gl->sector0);
161			p += 8;
162			break;
163		case 1:
164			g_enc_le8(p, gl->sectorN);
165			p += 8;
166			break;
167		case 2:
168			g_enc_le8(p, gl->keyoffset);
169			p += 8;
170			break;
171		case 3:
172			g_enc_le4(p, gl->sectorsize);
173			p += 4;
174			break;
175		case 4:
176			g_enc_le4(p, gl->flags);
177			p += 4;
178			break;
179		case 5:
180		case 6:
181		case 7:
182		case 8:
183			g_enc_le8(p, gl->lsector[shuffle[i] - 5]);
184			p += 8;
185			break;
186		case 9:
187			bcopy(gl->spare, p, sizeof gl->spare);
188			p += sizeof gl->spare;
189			break;
190		case 10:
191			bcopy(gl->salt, p, sizeof gl->salt);
192			p += sizeof gl->salt;
193			break;
194		case 11:
195			bcopy(gl->mkey, p, sizeof gl->mkey);
196			p += sizeof gl->mkey;
197			break;
198		case 12:
199			bzero(p, 16);
200			hash = p;
201			p += 16;
202			break;
203		}
204	}
205	if(ptr + G_BDE_LOCKSIZE != p)
206		return(-1);
207	if (hash == NULL)
208		return(-1);
209	MD5Init(&c);
210	MD5Update(&c, "0000", 4);	/* Versioning */
211	MD5Update(&c, ptr, G_BDE_LOCKSIZE);
212	MD5Final(hash, &c);
213	return(0);
214}
215
216int
217g_bde_decode_lock(struct g_bde_softc *sc, struct g_bde_key *gl, u_char *ptr)
218{
219	int shuffle[NLOCK_FIELDS];
220	u_char *p;
221	u_char hash[16], hash2[16];
222	MD5_CTX c;
223	int i;
224
225	p = ptr;
226	g_bde_shuffle_lock(sc, shuffle);
227	for (i = 0; i < NLOCK_FIELDS; i++) {
228		switch(shuffle[i]) {
229		case 0:
230			gl->sector0 = g_dec_le8(p);
231			p += 8;
232			break;
233		case 1:
234			gl->sectorN = g_dec_le8(p);
235			p += 8;
236			break;
237		case 2:
238			gl->keyoffset = g_dec_le8(p);
239			p += 8;
240			break;
241		case 3:
242			gl->sectorsize = g_dec_le4(p);
243			p += 4;
244			break;
245		case 4:
246			gl->flags = g_dec_le4(p);
247			p += 4;
248			break;
249		case 5:
250		case 6:
251		case 7:
252		case 8:
253			gl->lsector[shuffle[i] - 5] = g_dec_le8(p);
254			p += 8;
255			break;
256		case 9:
257			bcopy(p, gl->spare, sizeof gl->spare);
258			p += sizeof gl->spare;
259			break;
260		case 10:
261			bcopy(p, gl->salt, sizeof gl->salt);
262			p += sizeof gl->salt;
263			break;
264		case 11:
265			bcopy(p, gl->mkey, sizeof gl->mkey);
266			p += sizeof gl->mkey;
267			break;
268		case 12:
269			bcopy(p, hash2, sizeof hash2);
270			bzero(p, sizeof hash2);
271			p += sizeof hash2;
272			break;
273		}
274	}
275	if(ptr + G_BDE_LOCKSIZE != p)
276		return(-1);
277	MD5Init(&c);
278	MD5Update(&c, "0000", 4);	/* Versioning */
279	MD5Update(&c, ptr, G_BDE_LOCKSIZE);
280	MD5Final(hash, &c);
281	if (bcmp(hash, hash2, sizeof hash2))
282		return (1);
283	return (0);
284}
285
286/*
287 * Encode/Decode the locksector address ("metadata") with key-material.
288 *
289 * Security objectives: Encode/Decode the metadata encrypted by key-material.
290 *
291 * A simple AES/128/CBC will do.  We take care to always store the metadata
292 * in the same endianess to make it MI.
293 *
294 * In the typical case the metadata is stored in encrypted format in sector
295 * zero on the media, but at the users discretion or if the piece of the
296 * device used (sector0...sectorN) does not contain sector zero, it can
297 * be stored in a filesystem or on a PostIt.
298 *
299 * The inability to easily locate the lock sectors makes an attack on a
300 * cold disk much less attractive, without unduly inconveniencing the
301 * legitimate user who can feasibly do a brute-force scan if the metadata
302 * was lost.
303 */
304
305int
306g_bde_keyloc_encrypt(struct g_bde_softc *sc, uint64_t *input, void *output)
307{
308	u_char buf[16];
309	keyInstance ki;
310	cipherInstance ci;
311
312	g_enc_le8(buf, input[0]);
313	g_enc_le8(buf + 8, input[1]);
314	AES_init(&ci);
315	AES_makekey(&ki, DIR_ENCRYPT, G_BDE_KKEYBITS, sc->sha2 + 0);
316	AES_encrypt(&ci, &ki, buf, output, sizeof buf);
317	bzero(buf, sizeof buf);
318	bzero(&ci, sizeof ci);
319	bzero(&ki, sizeof ki);
320	return (0);
321}
322
323int
324g_bde_keyloc_decrypt(struct g_bde_softc *sc, void *input, uint64_t *output)
325{
326	keyInstance ki;
327	cipherInstance ci;
328	u_char buf[16];
329
330	AES_init(&ci);
331	AES_makekey(&ki, DIR_DECRYPT, G_BDE_KKEYBITS, sc->sha2 + 0);
332	AES_decrypt(&ci, &ki, input, buf, sizeof buf);
333	output[0] = g_dec_le8(buf);
334	output[1] = g_dec_le8(buf + 8);
335	bzero(buf, sizeof buf);
336	bzero(&ci, sizeof ci);
337	bzero(&ki, sizeof ki);
338	return (0);
339}
340
341/*
342 * Find and Encode/Decode lock sectors.
343 *
344 * Security objective: given the pass-phrase, find, decrypt, decode and
345 * validate the lock sector contents.
346 *
347 * For ondisk metadata we cannot know beforehand which of the lock sectors
348 * a given pass-phrase opens so we must try each of the metadata copies in
349 * sector zero in turn.  If metadata was passed as an argument, we don't
350 * have this problem.
351 *
352 */
353
354static int
355g_bde_decrypt_lockx(struct g_bde_softc *sc, u_char *meta, off_t mediasize, u_int sectorsize, u_int *nkey)
356{
357	u_char *buf, *q;
358	struct g_bde_key *gl;
359	uint64_t off[2];
360	int error, m, i;
361	keyInstance ki;
362	cipherInstance ci;
363
364	gl = &sc->key;
365
366	/* Try to decrypt the metadata */
367	error = g_bde_keyloc_decrypt(sc, meta, off);
368	if (error)
369		return(error);
370
371	/* loose the random part */
372	off[1] = 0;
373
374	/* If it points ito thin blue air, forget it */
375	if (off[0] + G_BDE_LOCKSIZE > (uint64_t)mediasize) {
376		off[0] = 0;
377		return (EINVAL);
378	}
379
380	/* The lock data may span two physical sectors. */
381
382	m = 1;
383	if (off[0] % sectorsize > sectorsize - G_BDE_LOCKSIZE)
384		m++;
385
386	/* Read the suspected sector(s) */
387	buf = g_read_data(sc->consumer,
388		off[0] - (off[0] % sectorsize),
389		m * sectorsize, &error);
390	if (buf == NULL) {
391		off[0] = 0;
392		return(error);
393	}
394
395	/* Find the byte-offset of the stored byte sequence */
396	q = buf + off[0] % sectorsize;
397
398	/* If it is all zero, somebody nuked our lock sector */
399	for (i = 0; i < G_BDE_LOCKSIZE; i++)
400		off[1] += q[i];
401	if (off[1] == 0) {
402		off[0] = 0;
403		g_free(buf);
404		return (ESRCH);
405	}
406
407	/* Decrypt the byte-sequence in place */
408	AES_init(&ci);
409	AES_makekey(&ki, DIR_DECRYPT, 256, sc->sha2 + 16);
410	AES_decrypt(&ci, &ki, q, q, G_BDE_LOCKSIZE);
411
412	/* Decode the byte-sequence */
413	i = g_bde_decode_lock(sc, gl, q);
414	q = NULL;
415	if (i < 0) {
416		off[0] = 0;
417		return (EDOOFUS);	/* Programming error */
418	} else if (i > 0) {
419		off[0] = 0;
420		return (ENOTDIR);	/* Hash didn't match */
421	}
422
423	bzero(buf, sectorsize * m);
424	g_free(buf);
425
426	/* If the masterkey is all zeros, user destroyed it */
427	off[1] = 0;
428	for (i = 0; i < (int)sizeof(gl->mkey); i++)
429		off[1] += gl->mkey[i];
430	if (off[1] == 0)
431		return (ENOENT);
432
433	/* If we have an unsorted lock-sequence, refuse */
434	if (gl->lsector[0] > gl->lsector[1] ||
435	    gl->lsector[1] > gl->lsector[2] ||
436	    gl->lsector[2] > gl->lsector[3])
437		return (EINVAL);
438
439	/* Finally, find out which key was used by matching the byte offset */
440	for (i = 0; i < G_BDE_MAXKEYS; i++)
441		if (nkey != NULL && off[0] == gl->lsector[i])
442			*nkey = i;
443	off[0] = 0;
444	return (0);
445}
446
447int
448g_bde_decrypt_lock(struct g_bde_softc *sc, u_char *keymat, u_char *meta, off_t mediasize, u_int sectorsize, u_int *nkey)
449{
450	u_char *buf, buf1[16];
451	int error, e, i;
452
453	/* set up the key-material */
454	bcopy(keymat, sc->sha2, SHA512_DIGEST_LENGTH);
455
456	/* If passed-in metadata is non-zero, use it */
457	bzero(buf1, sizeof buf1);
458	if (bcmp(buf1, meta, sizeof buf1))
459		return (g_bde_decrypt_lockx(sc, meta, mediasize,
460		    sectorsize, nkey));
461
462	/* Read sector zero */
463	buf = g_read_data(sc->consumer, 0, sectorsize, &error);
464	if (buf == NULL)
465		return(error);
466
467	/* Try each index in turn, save indicative errors for final result */
468	error = EINVAL;
469	for (i = 0; i < G_BDE_MAXKEYS; i++) {
470		e = g_bde_decrypt_lockx(sc, buf + i * 16, mediasize,
471		    sectorsize, nkey);
472		/* Success or destroyed master key terminates */
473		if (e == 0 || e == ENOENT) {
474			error = e;
475			break;
476		}
477		if (e != 0 && error == EINVAL)
478			error = e;
479	}
480	g_free(buf);
481	return (error);
482}
483