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/eli/g_eli_key.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) 2005-2011 Pawel Jakub Dawidek <pawel@dawidek.net>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/10.0/sys/geom/eli/g_eli_key.c 238114 2012-07-04 17:43:25Z pjd $");
   29 
   30 #include <sys/param.h>
   31 #ifdef _KERNEL
   32 #include <sys/malloc.h>
   33 #include <sys/systm.h>
   34 #include <geom/geom.h>
   35 #else
   36 #include <stdio.h>
   37 #include <stdint.h>
   38 #include <stdlib.h>
   39 #include <string.h>
   40 #include <strings.h>
   41 #include <errno.h>
   42 #endif
   43 
   44 #include <geom/eli/g_eli.h>
   45 
   46 #ifdef _KERNEL
   47 MALLOC_DECLARE(M_ELI);
   48 #endif
   49 
   50 /*
   51  * Verify if the given 'key' is correct.
   52  * Return 1 if it is correct and 0 otherwise.
   53  */
   54 static int
   55 g_eli_mkey_verify(const unsigned char *mkey, const unsigned char *key)
   56 {
   57         const unsigned char *odhmac;    /* On-disk HMAC. */
   58         unsigned char chmac[SHA512_MDLEN];      /* Calculated HMAC. */
   59         unsigned char hmkey[SHA512_MDLEN];      /* Key for HMAC. */
   60 
   61         /*
   62          * The key for HMAC calculations is: hmkey = HMAC_SHA512(Derived-Key, 0)
   63          */
   64         g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x00", 1, hmkey, 0);
   65 
   66         odhmac = mkey + G_ELI_DATAIVKEYLEN;
   67 
   68         /* Calculate HMAC from Data-Key and IV-Key. */
   69         g_eli_crypto_hmac(hmkey, sizeof(hmkey), mkey, G_ELI_DATAIVKEYLEN,
   70             chmac, 0);
   71 
   72         bzero(hmkey, sizeof(hmkey));
   73 
   74         /*
   75          * Compare calculated HMAC with HMAC from metadata.
   76          * If two HMACs are equal, 'key' is correct.
   77          */
   78         return (!bcmp(odhmac, chmac, SHA512_MDLEN));
   79 }
   80 
   81 /*
   82  * Calculate HMAC from Data-Key and IV-Key.
   83  */
   84 void
   85 g_eli_mkey_hmac(unsigned char *mkey, const unsigned char *key)
   86 {
   87         unsigned char hmkey[SHA512_MDLEN];      /* Key for HMAC. */
   88         unsigned char *odhmac;  /* On-disk HMAC. */
   89 
   90         /*
   91          * The key for HMAC calculations is: hmkey = HMAC_SHA512(Derived-Key, 0)
   92          */
   93         g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x00", 1, hmkey, 0);
   94 
   95         odhmac = mkey + G_ELI_DATAIVKEYLEN;
   96         /* Calculate HMAC from Data-Key and IV-Key. */
   97         g_eli_crypto_hmac(hmkey, sizeof(hmkey), mkey, G_ELI_DATAIVKEYLEN,
   98             odhmac, 0);
   99 
  100         bzero(hmkey, sizeof(hmkey));
  101 }
  102 
  103 /*
  104  * Find and decrypt Master Key encrypted with 'key'.
  105  * Return decrypted Master Key number in 'nkeyp' if not NULL.
  106  * Return 0 on success, > 0 on failure, -1 on bad key.
  107  */
  108 int
  109 g_eli_mkey_decrypt(const struct g_eli_metadata *md, const unsigned char *key,
  110     unsigned char *mkey, unsigned *nkeyp)
  111 {
  112         unsigned char tmpmkey[G_ELI_MKEYLEN];
  113         unsigned char enckey[SHA512_MDLEN];     /* Key for encryption. */
  114         const unsigned char *mmkey;
  115         int bit, error, nkey;
  116 
  117         if (nkeyp != NULL)
  118                 *nkeyp = -1;
  119 
  120         /*
  121          * The key for encryption is: enckey = HMAC_SHA512(Derived-Key, 1)
  122          */
  123         g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x01", 1, enckey, 0);
  124 
  125         mmkey = md->md_mkeys;
  126         for (nkey = 0; nkey < G_ELI_MAXMKEYS; nkey++, mmkey += G_ELI_MKEYLEN) {
  127                 bit = (1 << nkey);
  128                 if (!(md->md_keys & bit))
  129                         continue;
  130                 bcopy(mmkey, tmpmkey, G_ELI_MKEYLEN);
  131                 error = g_eli_crypto_decrypt(md->md_ealgo, tmpmkey,
  132                     G_ELI_MKEYLEN, enckey, md->md_keylen);
  133                 if (error != 0) {
  134                         bzero(tmpmkey, sizeof(tmpmkey));
  135                         bzero(enckey, sizeof(enckey));
  136                         return (error);
  137                 }
  138                 if (g_eli_mkey_verify(tmpmkey, key)) {
  139                         bcopy(tmpmkey, mkey, G_ELI_DATAIVKEYLEN);
  140                         bzero(tmpmkey, sizeof(tmpmkey));
  141                         bzero(enckey, sizeof(enckey));
  142                         if (nkeyp != NULL)
  143                                 *nkeyp = nkey;
  144                         return (0);
  145                 }
  146         }
  147         bzero(enckey, sizeof(enckey));
  148         bzero(tmpmkey, sizeof(tmpmkey));
  149         return (-1);
  150 }
  151 
  152 /*
  153  * Encrypt the Master-Key and calculate HMAC to be able to verify it in the
  154  * future.
  155  */
  156 int
  157 g_eli_mkey_encrypt(unsigned algo, const unsigned char *key, unsigned keylen,
  158     unsigned char *mkey)
  159 {
  160         unsigned char enckey[SHA512_MDLEN];     /* Key for encryption. */
  161         int error;
  162 
  163         /*
  164          * To calculate HMAC, the whole key (G_ELI_USERKEYLEN bytes long) will
  165          * be used.
  166          */
  167         g_eli_mkey_hmac(mkey, key);
  168         /*
  169          * The key for encryption is: enckey = HMAC_SHA512(Derived-Key, 1)
  170          */
  171         g_eli_crypto_hmac(key, G_ELI_USERKEYLEN, "\x01", 1, enckey, 0);
  172         /*
  173          * Encrypt the Master-Key and HMAC() result with the given key (this
  174          * time only 'keylen' bits from the key are used).
  175          */
  176         error = g_eli_crypto_encrypt(algo, mkey, G_ELI_MKEYLEN, enckey, keylen);
  177 
  178         bzero(enckey, sizeof(enckey));
  179 
  180         return (error);
  181 }
  182 
  183 #ifdef _KERNEL
  184 /*
  185  * When doing encryption only, copy IV key and encryption key.
  186  * When doing encryption and authentication, copy IV key, generate encryption
  187  * key and generate authentication key.
  188  */
  189 void
  190 g_eli_mkey_propagate(struct g_eli_softc *sc, const unsigned char *mkey)
  191 {
  192 
  193         /* Remember the Master Key. */
  194         bcopy(mkey, sc->sc_mkey, sizeof(sc->sc_mkey));
  195 
  196         bcopy(mkey, sc->sc_ivkey, sizeof(sc->sc_ivkey));
  197         mkey += sizeof(sc->sc_ivkey);
  198 
  199         /*
  200          * The authentication key is: akey = HMAC_SHA512(Data-Key, 0x11)
  201          */
  202         if ((sc->sc_flags & G_ELI_FLAG_AUTH) != 0) {
  203                 g_eli_crypto_hmac(mkey, G_ELI_MAXKEYLEN, "\x11", 1,
  204                     sc->sc_akey, 0);
  205         } else {
  206                 arc4rand(sc->sc_akey, sizeof(sc->sc_akey), 0);
  207         }
  208 
  209         /* Initialize encryption keys. */
  210         g_eli_key_init(sc);
  211 
  212         if ((sc->sc_flags & G_ELI_FLAG_AUTH) != 0) {
  213                 /*
  214                  * Precalculate SHA256 for HMAC key generation.
  215                  * This is expensive operation and we can do it only once now or
  216                  * for every access to sector, so now will be much better.
  217                  */
  218                 SHA256_Init(&sc->sc_akeyctx);
  219                 SHA256_Update(&sc->sc_akeyctx, sc->sc_akey,
  220                     sizeof(sc->sc_akey));
  221         }
  222         /*
  223          * Precalculate SHA256 for IV generation.
  224          * This is expensive operation and we can do it only once now or for
  225          * every access to sector, so now will be much better.
  226          */
  227         switch (sc->sc_ealgo) {
  228         case CRYPTO_AES_XTS:
  229                 break;
  230         default:
  231                 SHA256_Init(&sc->sc_ivctx);
  232                 SHA256_Update(&sc->sc_ivctx, sc->sc_ivkey,
  233                     sizeof(sc->sc_ivkey));
  234                 break;
  235         }
  236 }
  237 #endif

Cache object: 0a83fcfcccfe08ac6ef5e9371156d310


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