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

Cache object: 01ff7b6715dee5a9c317424050283ac4


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