"Fossies" - the Fresh Open Source Software Archive

Member "cryptsetup-2.4.3/lib/luks1/af.c" (13 Jan 2022, 4348 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 "af.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * AFsplitter - Anti forensic information splitter
    3  *
    4  * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
    5  * Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
    6  *
    7  * AFsplitter diffuses information over a large stripe of data,
    8  * therefore supporting secure data destruction.
    9  *
   10  * This program is free software; you can redistribute it and/or
   11  * modify it under the terms of the GNU General Public License
   12  * as published by the Free Software Foundation; either version 2
   13  * of the License, or (at your option) any later version.
   14  *
   15  * This program is distributed in the hope that it will be useful,
   16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18  * GNU Library General Public License for more details.
   19  *
   20  * You should have received a copy of the GNU General Public License
   21  * along with this program; if not, write to the Free Software
   22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   23  */
   24 
   25 #include <stddef.h>
   26 #include <stdlib.h>
   27 #include <string.h>
   28 #include <errno.h>
   29 #include "internal.h"
   30 #include "af.h"
   31 
   32 static void XORblock(const char *src1, const char *src2, char *dst, size_t n)
   33 {
   34     size_t j;
   35 
   36     for (j = 0; j < n; j++)
   37         dst[j] = src1[j] ^ src2[j];
   38 }
   39 
   40 static int hash_buf(const char *src, char *dst, uint32_t iv,
   41             size_t len, const char *hash_name)
   42 {
   43     struct crypt_hash *hd = NULL;
   44     char *iv_char = (char *)&iv;
   45     int r;
   46 
   47     iv = be32_to_cpu(iv);
   48     if (crypt_hash_init(&hd, hash_name))
   49         return -EINVAL;
   50 
   51     if ((r = crypt_hash_write(hd, iv_char, sizeof(uint32_t))))
   52         goto out;
   53 
   54     if ((r = crypt_hash_write(hd, src, len)))
   55         goto out;
   56 
   57     r = crypt_hash_final(hd, dst, len);
   58 out:
   59     crypt_hash_destroy(hd);
   60     return r;
   61 }
   62 
   63 /*
   64  * diffuse: Information spreading over the whole dataset with
   65  * the help of hash function.
   66  */
   67 static int diffuse(char *src, char *dst, size_t size, const char *hash_name)
   68 {
   69     int r, hash_size = crypt_hash_size(hash_name);
   70     unsigned int digest_size;
   71     unsigned int i, blocks, padding;
   72 
   73     if (hash_size <= 0)
   74         return -EINVAL;
   75     digest_size = hash_size;
   76 
   77     blocks = size / digest_size;
   78     padding = size % digest_size;
   79 
   80     for (i = 0; i < blocks; i++) {
   81         r = hash_buf(src + digest_size * i,
   82                 dst + digest_size * i,
   83                 i, (size_t)digest_size, hash_name);
   84         if (r < 0)
   85             return r;
   86     }
   87 
   88     if (padding) {
   89         r = hash_buf(src + digest_size * i,
   90                 dst + digest_size * i,
   91                 i, (size_t)padding, hash_name);
   92         if (r < 0)
   93             return r;
   94     }
   95 
   96     return 0;
   97 }
   98 
   99 /*
  100  * Information splitting. The amount of data is multiplied by
  101  * blocknumbers. The same blocksize and blocknumbers values
  102  * must be supplied to AF_merge to recover information.
  103  */
  104 int AF_split(struct crypt_device *ctx, const char *src, char *dst,
  105          size_t blocksize, unsigned int blocknumbers, const char *hash)
  106 {
  107     unsigned int i;
  108     char *bufblock;
  109     int r;
  110 
  111     bufblock = crypt_safe_alloc(blocksize);
  112     if (!bufblock)
  113         return -ENOMEM;
  114 
  115     /* process everything except the last block */
  116     for (i = 0; i < blocknumbers - 1; i++) {
  117         r = crypt_random_get(ctx, dst + blocksize * i, blocksize, CRYPT_RND_NORMAL);
  118         if (r < 0)
  119             goto out;
  120 
  121         XORblock(dst + blocksize * i, bufblock, bufblock, blocksize);
  122         r = diffuse(bufblock, bufblock, blocksize, hash);
  123         if (r < 0)
  124             goto out;
  125     }
  126     /* the last block is computed */
  127     XORblock(src, bufblock, dst + blocksize * i, blocksize);
  128     r = 0;
  129 out:
  130     crypt_safe_free(bufblock);
  131     return r;
  132 }
  133 
  134 int AF_merge(struct crypt_device *ctx __attribute__((unused)), const char *src, char *dst,
  135          size_t blocksize, unsigned int blocknumbers, const char *hash)
  136 {
  137     unsigned int i;
  138     char *bufblock;
  139     int r;
  140 
  141     bufblock = crypt_safe_alloc(blocksize);
  142     if (!bufblock)
  143         return -ENOMEM;
  144 
  145     for(i = 0; i < blocknumbers - 1; i++) {
  146         XORblock(src + blocksize * i, bufblock, bufblock, blocksize);
  147         r = diffuse(bufblock, bufblock, blocksize, hash);
  148         if (r < 0)
  149             goto out;
  150     }
  151     XORblock(src + blocksize * i, bufblock, dst, blocksize);
  152     r = 0;
  153 out:
  154     crypt_safe_free(bufblock);
  155     return r;
  156 }
  157 
  158 /* Size of final split data including sector alignment */
  159 size_t AF_split_sectors(size_t blocksize, unsigned int blocknumbers)
  160 {
  161     size_t af_size;
  162 
  163     /* data material * stripes */
  164     af_size = blocksize * blocknumbers;
  165 
  166     /* round up to sector */
  167     af_size = (af_size + (SECTOR_SIZE - 1)) / SECTOR_SIZE;
  168 
  169     return af_size;
  170 }