1 /* 2 * AFsplitter - Anti forensic information splitter 3 * Copyright 2004, Clemens Fruhwirth <clemens@endorphin.org> 4 * Copyright (C) 2009 Red Hat, Inc. All rights reserved. 5 * 6 * AFsplitter diffuses information over a large stripe of data, 7 * therefor supporting secure data destruction. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License 11 * version 2 as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 */ 22 23 #include <stddef.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <netinet/in.h> 27 #include <errno.h> 28 #include <openssl/evp.h> 29 #include "random.h" 30 31 static void XORblock(char const *src1, char const *src2, char *dst, size_t n) 32 { 33 size_t j; 34 35 for(j = 0; j < n; ++j) 36 dst[j] = src1[j] ^ src2[j]; 37 } 38 39 static int hash_buf(char *src, char *dst, uint32_t iv, int len, const EVP_MD *hash_id) 40 { 41 EVP_MD_CTX *mdctx; 42 unsigned char digest[128]; 43 44 iv = htonl(iv); 45 46 mdctx = EVP_MD_CTX_new(); 47 EVP_DigestInit_ex(mdctx, hash_id, NULL); 48 EVP_DigestUpdate(mdctx, (unsigned char *)&iv, sizeof(iv)); 49 EVP_DigestUpdate(mdctx, src, len); 50 EVP_DigestFinal(mdctx, digest, NULL); 51 memcpy(dst, digest, len); 52 53 EVP_MD_CTX_free(mdctx); 54 55 return 0; 56 } 57 58 /* diffuse: Information spreading over the whole dataset with 59 * the help of hash function. 60 */ 61 62 static int diffuse(char *src, char *dst, size_t size, const EVP_MD *hash_id) 63 { 64 unsigned int digest_size = EVP_MD_size(hash_id); 65 unsigned int i, blocks, padding; 66 67 blocks = size / digest_size; 68 padding = size % digest_size; 69 70 for (i = 0; i < blocks; i++) 71 if(hash_buf(src + digest_size * i, 72 dst + digest_size * i, 73 i, digest_size, hash_id)) 74 return 1; 75 76 if(padding) 77 if(hash_buf(src + digest_size * i, 78 dst + digest_size * i, 79 i, padding, hash_id)) 80 return 1; 81 82 return 0; 83 } 84 85 /* 86 * Information splitting. The amount of data is multiplied by 87 * blocknumbers. The same blocksize and blocknumbers values 88 * must be supplied to AF_merge to recover information. 89 */ 90 91 int AF_split(char *src, char *dst, size_t blocksize, unsigned int blocknumbers, const char *hash) 92 { 93 unsigned int i; 94 char *bufblock; 95 int r = -EINVAL; 96 const EVP_MD *hash_id; 97 98 OpenSSL_add_all_digests(); 99 if (!(hash_id = EVP_get_digestbyname(hash))) 100 return -EINVAL; 101 102 if((bufblock = calloc(blocksize, 1)) == NULL) return -ENOMEM; 103 104 /* process everything except the last block */ 105 for(i=0; i<blocknumbers-1; i++) { 106 r = getRandom(dst+(blocksize*i),blocksize); 107 if(r < 0) goto out; 108 109 XORblock(dst+(blocksize*i),bufblock,bufblock,blocksize); 110 if(diffuse(bufblock, bufblock, blocksize, hash_id)) 111 goto out; 112 } 113 /* the last block is computed */ 114 XORblock(src,bufblock,dst+(i*blocksize),blocksize); 115 r = 0; 116 out: 117 free(bufblock); 118 return r; 119 } 120 121 int AF_merge(char *src, char *dst, size_t blocksize, unsigned int blocknumbers, const char *hash) 122 { 123 unsigned int i; 124 char *bufblock; 125 int r = -EINVAL; 126 const EVP_MD *hash_id; 127 128 OpenSSL_add_all_digests(); 129 if (!(hash_id = EVP_get_digestbyname(hash))) 130 return -EINVAL; 131 132 if((bufblock = calloc(blocksize, 1)) == NULL) return -ENOMEM; 133 134 memset(bufblock,0,blocksize); 135 for(i=0; i<blocknumbers-1; i++) { 136 XORblock(src+(blocksize*i),bufblock,bufblock,blocksize); 137 if(diffuse(bufblock, bufblock, blocksize, hash_id)) 138 goto out; 139 } 140 XORblock(src + blocksize * i, bufblock, dst, blocksize); 141 r = 0; 142 out: 143 free(bufblock); 144 return 0; 145 } 146