"Fossies" - the Fresh Open Source Software Archive

Member "cryptsetup-2.4.3/lib/crypto_backend/crypto_storage.c" (13 Jan 2022, 8140 Bytes) of package /linux/misc/cryptsetup-2.4.3.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "crypto_storage.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.3.6_vs_2.4.0.

    1 /*
    2  * Generic wrapper for storage encryption modes and Initial Vectors
    3  * (reimplementation of some functions from Linux dm-crypt kernel)
    4  *
    5  * Copyright (C) 2014-2021 Milan Broz
    6  *
    7  * This file is free software; you can redistribute it and/or
    8  * modify it under the terms of the GNU Lesser General Public
    9  * License as published by the Free Software Foundation; either
   10  * version 2.1 of the License, or (at your option) any later version.
   11  *
   12  * This file is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15  * Lesser General Public License for more details.
   16  *
   17  * You should have received a copy of the GNU Lesser General Public
   18  * License along with this file; if not, write to the Free Software
   19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   20  */
   21 
   22 #include <stdlib.h>
   23 #include <errno.h>
   24 #include <strings.h>
   25 #include "bitops.h"
   26 #include "crypto_backend.h"
   27 
   28 #define SECTOR_SHIFT    9
   29 
   30 /*
   31  * Internal IV helper
   32  * IV documentation: https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
   33  */
   34 struct crypt_sector_iv {
   35     enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI, IV_PLAIN64BE, IV_EBOIV } type;
   36     int iv_size;
   37     char *iv;
   38     struct crypt_cipher *cipher;
   39     int shift;
   40 };
   41 
   42 /* Block encryption storage context */
   43 struct crypt_storage {
   44     size_t sector_size;
   45     unsigned iv_shift;
   46     struct crypt_cipher *cipher;
   47     struct crypt_sector_iv cipher_iv;
   48 };
   49 
   50 static int int_log2(unsigned int x)
   51 {
   52     int r = 0;
   53     for (x >>= 1; x > 0; x >>= 1)
   54         r++;
   55     return r;
   56 }
   57 
   58 static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
   59              const char *cipher_name, const char *mode_name,
   60              const char *iv_name, const void *key, size_t key_length,
   61              size_t sector_size)
   62 {
   63     int r;
   64 
   65     memset(ctx, 0, sizeof(*ctx));
   66 
   67     ctx->iv_size = crypt_cipher_ivsize(cipher_name, mode_name);
   68     if (ctx->iv_size < 0 || (strcmp(mode_name, "ecb") && ctx->iv_size < 8))
   69         return -ENOENT;
   70 
   71     if (!strcmp(cipher_name, "cipher_null") ||
   72         !strcmp(mode_name, "ecb")) {
   73         if (iv_name)
   74             return -EINVAL;
   75         ctx->type = IV_NONE;
   76         ctx->iv_size = 0;
   77         return 0;
   78     } else if (!iv_name) {
   79         return -EINVAL;
   80     } else if (!strcasecmp(iv_name, "null")) {
   81         ctx->type = IV_NULL;
   82     } else if (!strcasecmp(iv_name, "plain64")) {
   83         ctx->type = IV_PLAIN64;
   84     } else if (!strcasecmp(iv_name, "plain64be")) {
   85         ctx->type = IV_PLAIN64BE;
   86     } else if (!strcasecmp(iv_name, "plain")) {
   87         ctx->type = IV_PLAIN;
   88     } else if (!strncasecmp(iv_name, "essiv:", 6)) {
   89         struct crypt_hash *h = NULL;
   90         char *hash_name = strchr(iv_name, ':');
   91         int hash_size;
   92         char tmp[256];
   93 
   94         if (!hash_name)
   95             return -EINVAL;
   96 
   97         hash_size = crypt_hash_size(++hash_name);
   98         if (hash_size < 0)
   99             return -ENOENT;
  100 
  101         if ((unsigned)hash_size > sizeof(tmp))
  102             return -EINVAL;
  103 
  104         if (crypt_hash_init(&h, hash_name))
  105             return -EINVAL;
  106 
  107         r = crypt_hash_write(h, key, key_length);
  108         if (r) {
  109             crypt_hash_destroy(h);
  110             return r;
  111         }
  112 
  113         r = crypt_hash_final(h, tmp, hash_size);
  114         crypt_hash_destroy(h);
  115         if (r) {
  116             crypt_backend_memzero(tmp, sizeof(tmp));
  117             return r;
  118         }
  119 
  120         r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb",
  121                       tmp, hash_size);
  122         crypt_backend_memzero(tmp, sizeof(tmp));
  123         if (r)
  124             return r;
  125 
  126         ctx->type = IV_ESSIV;
  127     } else if (!strncasecmp(iv_name, "benbi", 5)) {
  128         int log = int_log2(ctx->iv_size);
  129         if (log > SECTOR_SHIFT)
  130             return -EINVAL;
  131 
  132         ctx->type = IV_BENBI;
  133         ctx->shift = SECTOR_SHIFT - log;
  134     } else if (!strncasecmp(iv_name, "eboiv", 5)) {
  135         r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb",
  136                       key, key_length);
  137         if (r)
  138             return r;
  139 
  140         ctx->type = IV_EBOIV;
  141         ctx->shift = int_log2(sector_size);
  142     } else
  143         return -ENOENT;
  144 
  145     ctx->iv = malloc(ctx->iv_size);
  146     if (!ctx->iv)
  147         return -ENOMEM;
  148 
  149     return 0;
  150 }
  151 
  152 static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector)
  153 {
  154     uint64_t val;
  155 
  156     switch (ctx->type) {
  157     case IV_NONE:
  158         break;
  159     case IV_NULL:
  160         memset(ctx->iv, 0, ctx->iv_size);
  161         break;
  162     case IV_PLAIN:
  163         memset(ctx->iv, 0, ctx->iv_size);
  164         *(uint32_t *)ctx->iv = cpu_to_le32(sector & 0xffffffff);
  165         break;
  166     case IV_PLAIN64:
  167         memset(ctx->iv, 0, ctx->iv_size);
  168         *(uint64_t *)ctx->iv = cpu_to_le64(sector);
  169         break;
  170     case IV_PLAIN64BE:
  171         memset(ctx->iv, 0, ctx->iv_size);
  172         *(uint64_t *)&ctx->iv[ctx->iv_size - sizeof(uint64_t)] = cpu_to_be64(sector);
  173         break;
  174     case IV_ESSIV:
  175         memset(ctx->iv, 0, ctx->iv_size);
  176         *(uint64_t *)ctx->iv = cpu_to_le64(sector);
  177         return crypt_cipher_encrypt(ctx->cipher,
  178             ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
  179         break;
  180     case IV_BENBI:
  181         memset(ctx->iv, 0, ctx->iv_size);
  182         val = cpu_to_be64((sector << ctx->shift) + 1);
  183         memcpy(ctx->iv + ctx->iv_size - sizeof(val), &val, sizeof(val));
  184         break;
  185     case IV_EBOIV:
  186         memset(ctx->iv, 0, ctx->iv_size);
  187         *(uint64_t *)ctx->iv = cpu_to_le64(sector << ctx->shift);
  188         return crypt_cipher_encrypt(ctx->cipher,
  189             ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
  190         break;
  191     default:
  192         return -EINVAL;
  193     }
  194 
  195     return 0;
  196 }
  197 
  198 static void crypt_sector_iv_destroy(struct crypt_sector_iv *ctx)
  199 {
  200     if (ctx->type == IV_ESSIV || ctx->type == IV_EBOIV)
  201         crypt_cipher_destroy(ctx->cipher);
  202 
  203     if (ctx->iv) {
  204         memset(ctx->iv, 0, ctx->iv_size);
  205         free(ctx->iv);
  206     }
  207 
  208     memset(ctx, 0, sizeof(*ctx));
  209 }
  210 
  211 /* Block encryption storage wrappers */
  212 
  213 int crypt_storage_init(struct crypt_storage **ctx,
  214                size_t sector_size,
  215                const char *cipher,
  216                const char *cipher_mode,
  217                const void *key, size_t key_length,
  218                bool large_iv)
  219 {
  220     struct crypt_storage *s;
  221     char mode_name[64];
  222     char *cipher_iv = NULL;
  223     int r = -EIO;
  224 
  225     if (sector_size < (1 << SECTOR_SHIFT) ||
  226         sector_size > (1 << (SECTOR_SHIFT + 3)) ||
  227         sector_size & (sector_size - 1))
  228         return -EINVAL;
  229 
  230     s = malloc(sizeof(*s));
  231     if (!s)
  232         return -ENOMEM;
  233     memset(s, 0, sizeof(*s));
  234 
  235     /* Remove IV if present */
  236     strncpy(mode_name, cipher_mode, sizeof(mode_name));
  237     mode_name[sizeof(mode_name) - 1] = 0;
  238     cipher_iv = strchr(mode_name, '-');
  239     if (cipher_iv) {
  240         *cipher_iv = '\0';
  241         cipher_iv++;
  242     }
  243 
  244     r = crypt_cipher_init(&s->cipher, cipher, mode_name, key, key_length);
  245     if (r) {
  246         crypt_storage_destroy(s);
  247         return r;
  248     }
  249 
  250     r = crypt_sector_iv_init(&s->cipher_iv, cipher, mode_name, cipher_iv, key, key_length, sector_size);
  251     if (r) {
  252         crypt_storage_destroy(s);
  253         return r;
  254     }
  255 
  256     s->sector_size = sector_size;
  257     s->iv_shift = large_iv ? int_log2(sector_size) - SECTOR_SHIFT : 0;
  258 
  259     *ctx = s;
  260     return 0;
  261 }
  262 
  263 int crypt_storage_decrypt(struct crypt_storage *ctx,
  264                uint64_t iv_offset,
  265                uint64_t length, char *buffer)
  266 {
  267     uint64_t i;
  268     int r = 0;
  269 
  270     if (length & (ctx->sector_size - 1))
  271         return -EINVAL;
  272 
  273     if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
  274         return -EINVAL;
  275 
  276     for (i = 0; i < length; i += ctx->sector_size) {
  277         r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
  278         if (r)
  279             break;
  280         r = crypt_cipher_decrypt(ctx->cipher,
  281                      &buffer[i],
  282                      &buffer[i],
  283                      ctx->sector_size,
  284                      ctx->cipher_iv.iv,
  285                      ctx->cipher_iv.iv_size);
  286         if (r)
  287             break;
  288     }
  289 
  290     return r;
  291 }
  292 
  293 int crypt_storage_encrypt(struct crypt_storage *ctx,
  294                uint64_t iv_offset,
  295                uint64_t length, char *buffer)
  296 {
  297     uint64_t i;
  298     int r = 0;
  299 
  300     if (length & (ctx->sector_size - 1))
  301         return -EINVAL;
  302 
  303     if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
  304         return -EINVAL;
  305 
  306     for (i = 0; i < length; i += ctx->sector_size) {
  307         r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
  308         if (r)
  309             break;
  310         r = crypt_cipher_encrypt(ctx->cipher,
  311                      &buffer[i],
  312                      &buffer[i],
  313                      ctx->sector_size,
  314                      ctx->cipher_iv.iv,
  315                      ctx->cipher_iv.iv_size);
  316         if (r)
  317             break;
  318     }
  319 
  320     return r;
  321 }
  322 
  323 void crypt_storage_destroy(struct crypt_storage *ctx)
  324 {
  325     if (!ctx)
  326         return;
  327 
  328     crypt_sector_iv_destroy(&ctx->cipher_iv);
  329 
  330     if (ctx->cipher)
  331         crypt_cipher_destroy(ctx->cipher);
  332 
  333     memset(ctx, 0, sizeof(*ctx));
  334     free(ctx);
  335 }
  336 
  337 bool crypt_storage_kernel_only(struct crypt_storage *ctx)
  338 {
  339     return crypt_cipher_kernel_only(ctx->cipher);
  340 }