syscons,vt: improve phrasing in kern.vty man page description
[freebsd-src.git] / sys / geom / bde / g_bde_lock.c
blob05b68edf34600739cac2e5987107e69cab8890f0
1 /*-
2 * Copyright (c) 2002 Poul-Henning Kamp
3 * Copyright (c) 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
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.
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.
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.
32 * $FreeBSD$
34 /* This souce file contains routines which operates on the lock sectors, both
35 * for the kernel and the userland program gbde(1).
39 #include <sys/param.h>
40 #include <sys/queue.h>
41 #include <sys/lock.h>
42 #include <sys/mutex.h>
43 #include <sys/endian.h>
44 #include <sys/md5.h>
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
60 #include <crypto/rijndael/rijndael-api-fst.h>
61 #include <crypto/sha2/sha512.h>
63 #include <geom/geom.h>
64 #include <geom/bde/g_bde.h>
67 * Hash the raw pass-phrase.
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.
73 * SHA2-512 makes this easy.
76 void
77 g_bde_hash_pass(struct g_bde_softc *sc, const void *input, u_int len)
79 SHA512_CTX cx;
81 SHA512_Init(&cx);
82 SHA512_Update(&cx, input, len);
83 SHA512_Final(sc->sha2, &cx);
87 * Encode/Decode the lock structure in byte-sequence format.
89 * Security objectives: Store in pass-phrase dependent variant format.
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.
95 * We spend a fraction of the key-material on shuffling the fields around
96 * so they will be stored in an unpredictable sequence.
98 * For each byte of the key-material we derive two field indexes, and swap
99 * the position of those two fields.
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.
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.
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.
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.
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).
124 CTASSERT(NLOCK_FIELDS <= 16);
126 static void
127 g_bde_shuffle_lock(u_char *sha2, int *buf)
129 int j, k, l;
130 u_int u;
132 /* Assign the fields sequential positions */
133 for(u = 0; u < NLOCK_FIELDS; u++)
134 buf[u] = u;
136 /* Then mix it all up */
137 for(u = 48; u < SHA512_DIGEST_LENGTH; u++) {
138 j = sha2[u] % NLOCK_FIELDS;
139 k = (sha2[u] / NLOCK_FIELDS) % NLOCK_FIELDS;
140 l = buf[j];
141 buf[j] = buf[k];
142 buf[k] = l;
147 g_bde_encode_lock(u_char *sha2, struct g_bde_key *gl, u_char *ptr)
149 int shuffle[NLOCK_FIELDS];
150 u_char *hash, *p;
151 int i;
152 MD5_CTX c;
154 p = ptr;
155 hash = NULL;
156 g_bde_shuffle_lock(sha2, shuffle);
157 for (i = 0; i < NLOCK_FIELDS; i++) {
158 switch(shuffle[i]) {
159 case 0:
160 le64enc(p, gl->sector0);
161 p += 8;
162 break;
163 case 1:
164 le64enc(p, gl->sectorN);
165 p += 8;
166 break;
167 case 2:
168 le64enc(p, gl->keyoffset);
169 p += 8;
170 break;
171 case 3:
172 le32enc(p, gl->sectorsize);
173 p += 4;
174 break;
175 case 4:
176 le32enc(p, gl->flags);
177 p += 4;
178 break;
179 case 5:
180 case 6:
181 case 7:
182 case 8:
183 le64enc(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;
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);
217 g_bde_decode_lock(struct g_bde_softc *sc, struct g_bde_key *gl, u_char *ptr)
219 int shuffle[NLOCK_FIELDS];
220 u_char *p;
221 u_char hash[16], hash2[16];
222 MD5_CTX c;
223 int i;
225 p = ptr;
226 g_bde_shuffle_lock(sc->sha2, shuffle);
227 for (i = 0; i < NLOCK_FIELDS; i++) {
228 switch(shuffle[i]) {
229 case 0:
230 gl->sector0 = le64dec(p);
231 p += 8;
232 break;
233 case 1:
234 gl->sectorN = le64dec(p);
235 p += 8;
236 break;
237 case 2:
238 gl->keyoffset = le64dec(p);
239 p += 8;
240 break;
241 case 3:
242 gl->sectorsize = le32dec(p);
243 p += 4;
244 break;
245 case 4:
246 gl->flags = le32dec(p);
247 p += 4;
248 break;
249 case 5:
250 case 6:
251 case 7:
252 case 8:
253 gl->lsector[shuffle[i] - 5] = le64dec(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;
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);
287 * Encode/Decode the locksector address ("metadata") with key-material.
289 * Security objectives: Encode/Decode the metadata encrypted by key-material.
291 * A simple AES/128/CBC will do. We take care to always store the metadata
292 * in the same endianness to make it MI.
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.
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.
306 g_bde_keyloc_encrypt(u_char *sha2, uint64_t v0, uint64_t v1, void *output)
308 u_char buf[16];
309 keyInstance ki;
310 cipherInstance ci;
312 le64enc(buf, v0);
313 le64enc(buf + 8, v1);
314 AES_init(&ci);
315 AES_makekey(&ki, DIR_ENCRYPT, G_BDE_KKEYBITS, 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);
324 g_bde_keyloc_decrypt(u_char *sha2, void *input, uint64_t *output)
326 keyInstance ki;
327 cipherInstance ci;
328 u_char buf[16];
330 AES_init(&ci);
331 AES_makekey(&ki, DIR_DECRYPT, G_BDE_KKEYBITS, sha2 + 0);
332 AES_decrypt(&ci, &ki, input, buf, sizeof buf);
333 *output = le64dec(buf);
334 bzero(buf, sizeof buf);
335 bzero(&ci, sizeof ci);
336 bzero(&ki, sizeof ki);
337 return(0);
341 * Find and Encode/Decode lock sectors.
343 * Security objective: given the pass-phrase, find, decrypt, decode and
344 * validate the lock sector contents.
346 * For ondisk metadata we cannot know beforehand which of the lock sectors
347 * a given pass-phrase opens so we must try each of the metadata copies in
348 * sector zero in turn. If metadata was passed as an argument, we don't
349 * have this problem.
353 static int
354 g_bde_decrypt_lockx(struct g_bde_softc *sc, u_char *meta, off_t mediasize, u_int sectorsize, u_int *nkey)
356 u_char *buf, *q;
357 struct g_bde_key *gl;
358 uint64_t off, q1;
359 int error, m, i;
360 keyInstance ki;
361 cipherInstance ci;
363 gl = &sc->key;
365 /* Try to decrypt the metadata */
366 error = g_bde_keyloc_decrypt(sc->sha2, meta, &off);
367 if (error)
368 return (error);
370 /* If it points into thin blue air, forget it */
371 if (off + G_BDE_LOCKSIZE > (uint64_t)mediasize) {
372 off = 0;
373 return (EINVAL);
376 /* The lock data may span two physical sectors. */
378 m = 1;
379 if (off % sectorsize > sectorsize - G_BDE_LOCKSIZE)
380 m++;
382 /* Read the suspected sector(s) */
383 buf = g_read_data(sc->consumer,
384 off - (off % sectorsize),
385 m * sectorsize, &error);
386 if (buf == NULL) {
387 off = 0;
388 return(error);
391 /* Find the byte-offset of the stored byte sequence */
392 q = buf + off % sectorsize;
394 /* If it is all zero, somebody nuked our lock sector */
395 q1 = 0;
396 for (i = 0; i < G_BDE_LOCKSIZE; i++)
397 q1 += q[i];
398 if (q1 == 0) {
399 off = 0;
400 g_free(buf);
401 return (ESRCH);
404 /* Decrypt the byte-sequence in place */
405 AES_init(&ci);
406 AES_makekey(&ki, DIR_DECRYPT, 256, sc->sha2 + 16);
407 AES_decrypt(&ci, &ki, q, q, G_BDE_LOCKSIZE);
409 /* Decode the byte-sequence */
410 i = g_bde_decode_lock(sc, gl, q);
411 q = NULL;
412 if (i < 0) {
413 off = 0;
414 return (EDOOFUS); /* Programming error */
415 } else if (i > 0) {
416 off = 0;
417 return (ENOTDIR); /* Hash didn't match */
420 bzero(buf, sectorsize * m);
421 g_free(buf);
423 /* If the masterkey is all zeros, user destroyed it */
424 q1 = 0;
425 for (i = 0; i < (int)sizeof(gl->mkey); i++)
426 q1 += gl->mkey[i];
427 if (q1 == 0)
428 return (ENOENT);
430 /* If we have an unsorted lock-sequence, refuse */
431 for (i = 0; i < G_BDE_MAXKEYS - 1; i++)
432 if (gl->lsector[i] >= gl->lsector[i + 1])
433 return (EINVAL);
435 /* Finally, find out which key was used by matching the byte offset */
436 for (i = 0; i < G_BDE_MAXKEYS; i++)
437 if (nkey != NULL && off == gl->lsector[i])
438 *nkey = i;
439 off = 0;
440 return (0);
444 g_bde_decrypt_lock(struct g_bde_softc *sc, u_char *keymat, u_char *meta, off_t mediasize, u_int sectorsize, u_int *nkey)
446 u_char *buf, buf1[16];
447 int error, e, i;
449 /* set up the key-material */
450 bcopy(keymat, sc->sha2, SHA512_DIGEST_LENGTH);
452 /* If passed-in metadata is non-zero, use it */
453 bzero(buf1, sizeof buf1);
454 if (meta != NULL && bcmp(buf1, meta, sizeof buf1))
455 return (g_bde_decrypt_lockx(sc, meta, mediasize,
456 sectorsize, nkey));
458 /* Read sector zero */
459 buf = g_read_data(sc->consumer, 0, sectorsize, &error);
460 if (buf == NULL)
461 return(error);
463 /* Try each index in turn, save indicative errors for final result */
464 error = EINVAL;
465 for (i = 0; i < G_BDE_MAXKEYS; i++) {
466 e = g_bde_decrypt_lockx(sc, buf + i * 16, mediasize,
467 sectorsize, nkey);
468 /* Success or destroyed master key terminates */
469 if (e == 0 || e == ENOENT) {
470 error = e;
471 break;
473 if (e != 0 && error == EINVAL)
474 error = e;
476 g_free(buf);
477 return (error);