The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/geom/bde/g_bde_lock.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: releng/5.1/sys/geom/bde/g_bde_lock.c 113010 2003-04-03 11:33:51Z 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/lock.h>
   42 #include <sys/mutex.h>
   43 #include <sys/endian.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 
   76 void
   77 g_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 
  124 CTASSERT(NLOCK_FIELDS <= 16);
  125 
  126 static void
  127 g_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 
  146 int
  147 g_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                         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;
  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 
  216 int
  217 g_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 = 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;
  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 
  305 int
  306 g_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         le64enc(buf, input[0]);
  313         le64enc(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 
  323 int
  324 g_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] = le64dec(buf);
  334         output[1] = le64dec(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 
  354 static int
  355 g_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 
  447 int
  448 g_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 (meta != NULL && 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 }

Cache object: 679511b2e5852b5b0fabc695f34ebf1d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.