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_crypto.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-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
    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/11.2/sys/geom/eli/g_eli_crypto.c 293306 2016-01-07 05:47:34Z allanjude $");
   29 
   30 #include <sys/param.h>
   31 #ifdef _KERNEL
   32 #include <sys/systm.h>
   33 #include <sys/kernel.h>
   34 #include <sys/malloc.h>
   35 #else
   36 #include <stdint.h>
   37 #include <string.h>
   38 #include <strings.h>
   39 #include <errno.h>
   40 #include <assert.h>
   41 #include <openssl/evp.h>
   42 #define _OpenSSL_
   43 #endif
   44 #include <geom/eli/g_eli.h>
   45 
   46 #ifdef _KERNEL
   47 MALLOC_DECLARE(M_ELI);
   48 
   49 static int
   50 g_eli_crypto_done(struct cryptop *crp)
   51 {
   52 
   53         crp->crp_opaque = (void *)crp;
   54         wakeup(crp);
   55         return (0);
   56 }
   57 
   58 static int
   59 g_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize,
   60     const u_char *key, size_t keysize)
   61 {
   62         struct cryptoini cri;
   63         struct cryptop *crp;
   64         struct cryptodesc *crd;
   65         uint64_t sid;
   66         u_char *p;
   67         int error;
   68 
   69         KASSERT(algo != CRYPTO_AES_XTS,
   70             ("%s: CRYPTO_AES_XTS unexpected here", __func__));
   71 
   72         bzero(&cri, sizeof(cri));
   73         cri.cri_alg = algo;
   74         cri.cri_key = __DECONST(void *, key);
   75         cri.cri_klen = keysize;
   76         error = crypto_newsession(&sid, &cri, CRYPTOCAP_F_SOFTWARE);
   77         if (error != 0)
   78                 return (error);
   79         p = malloc(sizeof(*crp) + sizeof(*crd), M_ELI, M_NOWAIT | M_ZERO);
   80         if (p == NULL) {
   81                 crypto_freesession(sid);
   82                 return (ENOMEM);
   83         }
   84         crp = (struct cryptop *)p;      p += sizeof(*crp);
   85         crd = (struct cryptodesc *)p;   p += sizeof(*crd);
   86 
   87         crd->crd_skip = 0;
   88         crd->crd_len = datasize;
   89         crd->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
   90         if (enc)
   91                 crd->crd_flags |= CRD_F_ENCRYPT;
   92         crd->crd_alg = algo;
   93         crd->crd_key = __DECONST(void *, key);
   94         crd->crd_klen = keysize;
   95         bzero(crd->crd_iv, sizeof(crd->crd_iv));
   96         crd->crd_next = NULL;
   97 
   98         crp->crp_sid = sid;
   99         crp->crp_ilen = datasize;
  100         crp->crp_olen = datasize;
  101         crp->crp_opaque = NULL;
  102         crp->crp_callback = g_eli_crypto_done;
  103         crp->crp_buf = (void *)data;
  104         crp->crp_flags = CRYPTO_F_CBIFSYNC;
  105         crp->crp_desc = crd;
  106 
  107         error = crypto_dispatch(crp);
  108         if (error == 0) {
  109                 while (crp->crp_opaque == NULL)
  110                         tsleep(crp, PRIBIO, "geli", hz / 5);
  111                 error = crp->crp_etype;
  112         }
  113 
  114         free(crp, M_ELI);
  115         crypto_freesession(sid);
  116         return (error);
  117 }
  118 #else   /* !_KERNEL */
  119 static int
  120 g_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize,
  121     const u_char *key, size_t keysize)
  122 {
  123         EVP_CIPHER_CTX ctx;
  124         const EVP_CIPHER *type;
  125         u_char iv[keysize];
  126         int outsize;
  127 
  128         assert(algo != CRYPTO_AES_XTS);
  129 
  130         switch (algo) {
  131         case CRYPTO_NULL_CBC:
  132                 type = EVP_enc_null();
  133                 break;
  134         case CRYPTO_AES_CBC:
  135                 switch (keysize) {
  136                 case 128:
  137                         type = EVP_aes_128_cbc();
  138                         break;
  139                 case 192:
  140                         type = EVP_aes_192_cbc();
  141                         break;
  142                 case 256:
  143                         type = EVP_aes_256_cbc();
  144                         break;
  145                 default:
  146                         return (EINVAL);
  147                 }
  148                 break;
  149         case CRYPTO_BLF_CBC:
  150                 type = EVP_bf_cbc();
  151                 break;
  152 #ifndef OPENSSL_NO_CAMELLIA
  153         case CRYPTO_CAMELLIA_CBC:
  154                 switch (keysize) {
  155                 case 128:
  156                         type = EVP_camellia_128_cbc();
  157                         break;
  158                 case 192:
  159                         type = EVP_camellia_192_cbc();
  160                         break;
  161                 case 256:
  162                         type = EVP_camellia_256_cbc();
  163                         break;
  164                 default:
  165                         return (EINVAL);
  166                 }
  167                 break;
  168 #endif
  169         case CRYPTO_3DES_CBC:
  170                 type = EVP_des_ede3_cbc();
  171                 break;
  172         default:
  173                 return (EINVAL);
  174         }
  175 
  176         EVP_CIPHER_CTX_init(&ctx);
  177 
  178         EVP_CipherInit_ex(&ctx, type, NULL, NULL, NULL, enc);
  179         EVP_CIPHER_CTX_set_key_length(&ctx, keysize / 8);
  180         EVP_CIPHER_CTX_set_padding(&ctx, 0);
  181         bzero(iv, sizeof(iv));
  182         EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, enc);
  183 
  184         if (EVP_CipherUpdate(&ctx, data, &outsize, data, datasize) == 0) {
  185                 EVP_CIPHER_CTX_cleanup(&ctx);
  186                 return (EINVAL);
  187         }
  188         assert(outsize == (int)datasize);
  189 
  190         if (EVP_CipherFinal_ex(&ctx, data + outsize, &outsize) == 0) {
  191                 EVP_CIPHER_CTX_cleanup(&ctx);
  192                 return (EINVAL);
  193         }
  194         assert(outsize == 0);
  195 
  196         EVP_CIPHER_CTX_cleanup(&ctx);
  197         return (0);
  198 }
  199 #endif  /* !_KERNEL */
  200 
  201 int
  202 g_eli_crypto_encrypt(u_int algo, u_char *data, size_t datasize,
  203     const u_char *key, size_t keysize)
  204 {
  205 
  206         /* We prefer AES-CBC for metadata protection. */
  207         if (algo == CRYPTO_AES_XTS)
  208                 algo = CRYPTO_AES_CBC;
  209 
  210         return (g_eli_crypto_cipher(algo, 1, data, datasize, key, keysize));
  211 }
  212 
  213 int
  214 g_eli_crypto_decrypt(u_int algo, u_char *data, size_t datasize,
  215     const u_char *key, size_t keysize)
  216 {
  217 
  218         /* We prefer AES-CBC for metadata protection. */
  219         if (algo == CRYPTO_AES_XTS)
  220                 algo = CRYPTO_AES_CBC;
  221 
  222         return (g_eli_crypto_cipher(algo, 0, data, datasize, key, keysize));
  223 }

Cache object: ae149457c5aaab6f042fc61acabcc7bc


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