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

Cache object: 27cce2631d4fa593da9e1f5bc301f9ea


[ 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.