1 /* 2 * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>. 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 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in 13 * the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 #include <sys/types.h> 30 #include <sys/param.h> 31 #include <inttypes.h> 32 33 #include <fcntl.h> 34 #include <unistd.h> 35 #include <errno.h> 36 #include <string.h> 37 #include <stdio.h> 38 39 #include "crc32.h" 40 #include "tcplay.h" 41 42 int 43 tc_cipher_chain_populate_keys(struct tc_cipher_chain *cipher_chain, 44 unsigned char *key) 45 { 46 int total_key_bytes, used_key_bytes; 47 struct tc_cipher_chain *dummy_chain; 48 49 /* 50 * We need to determine the total key bytes as the key locations 51 * depend on it. 52 */ 53 total_key_bytes = 0; 54 for (dummy_chain = cipher_chain; 55 dummy_chain != NULL; 56 dummy_chain = dummy_chain->next) { 57 total_key_bytes += dummy_chain->cipher->klen; 58 } 59 60 /* 61 * Now we need to get prepare the keys, as the keys are in 62 * forward order with respect to the cipher cascade, but 63 * the actual decryption is in reverse cipher cascade order. 64 */ 65 used_key_bytes = 0; 66 for (dummy_chain = cipher_chain; 67 dummy_chain != NULL; 68 dummy_chain = dummy_chain->next) { 69 dummy_chain->key = alloc_safe_mem(dummy_chain->cipher->klen); 70 if (dummy_chain->key == NULL) { 71 tc_log(1, "tc_decrypt: Could not allocate key " 72 "memory\n"); 73 return ENOMEM; 74 } 75 76 /* XXX: here we assume XTS operation! */ 77 memcpy(dummy_chain->key, 78 key + used_key_bytes/2, 79 dummy_chain->cipher->klen/2); 80 memcpy(dummy_chain->key + dummy_chain->cipher->klen/2, 81 key + (total_key_bytes/2) + used_key_bytes/2, 82 dummy_chain->cipher->klen/2); 83 84 /* Remember how many key bytes we've seen */ 85 used_key_bytes += dummy_chain->cipher->klen; 86 } 87 88 return 0; 89 } 90 91 int 92 tc_cipher_chain_free_keys(struct tc_cipher_chain *cipher_chain) 93 { 94 for (; cipher_chain != NULL; cipher_chain = cipher_chain->next) { 95 if (cipher_chain->key != NULL) { 96 free_safe_mem(cipher_chain->key); 97 cipher_chain->key = NULL; 98 } 99 } 100 101 return 0; 102 } 103 104 int 105 tc_encrypt(struct tc_cipher_chain *cipher_chain, unsigned char *key, 106 unsigned char *iv, 107 unsigned char *in, int in_len, unsigned char *out) 108 { 109 struct tc_cipher_chain *chain_start; 110 int err; 111 112 chain_start = cipher_chain; 113 114 if ((err = tc_cipher_chain_populate_keys(cipher_chain, key))) 115 return err; 116 117 #ifdef DEBUG 118 printf("tc_encrypt: starting chain\n"); 119 #endif 120 121 /* 122 * Now process the actual decryption, in forward cascade order. 123 */ 124 for (; 125 cipher_chain != NULL; 126 cipher_chain = cipher_chain->next) { 127 #ifdef DEBUG 128 printf("tc_encrypt: Currently using cipher %s\n", 129 cipher_chain->cipher->name); 130 #endif 131 132 err = syscrypt(cipher_chain->cipher, cipher_chain->key, 133 cipher_chain->cipher->klen, iv, in, out, in_len, 1); 134 135 /* Deallocate this key, since we won't need it anymore */ 136 free_safe_mem(cipher_chain->key); 137 cipher_chain->key = NULL; 138 139 if (err != 0) { 140 tc_cipher_chain_free_keys(chain_start); 141 return err; 142 } 143 144 /* Set next input buffer as current output buffer */ 145 in = out; 146 } 147 148 tc_cipher_chain_free_keys(chain_start); 149 150 return 0; 151 } 152 153 int 154 tc_decrypt(struct tc_cipher_chain *cipher_chain, unsigned char *key, 155 unsigned char *iv, 156 unsigned char *in, int in_len, unsigned char *out) 157 { 158 struct tc_cipher_chain *chain_start; 159 int err; 160 161 chain_start = cipher_chain; 162 163 if ((err = tc_cipher_chain_populate_keys(cipher_chain, key))) 164 return err; 165 166 #ifdef DEBUG 167 printf("tc_decrypt: starting chain!\n"); 168 #endif 169 170 /* 171 * Now process the actual decryption, in reverse cascade order; so 172 * first find the last element in the chain. 173 */ 174 for (; cipher_chain->next != NULL; cipher_chain = cipher_chain->next) 175 ; 176 for (; 177 cipher_chain != NULL; 178 cipher_chain = cipher_chain->prev) { 179 #ifdef DEBUG 180 printf("tc_decrypt: Currently using cipher %s\n", 181 cipher_chain->cipher->name); 182 #endif 183 184 err = syscrypt(cipher_chain->cipher, cipher_chain->key, 185 cipher_chain->cipher->klen, iv, in, out, in_len, 0); 186 187 /* Deallocate this key, since we won't need it anymore */ 188 free_safe_mem(cipher_chain->key); 189 cipher_chain->key = NULL; 190 191 if (err != 0) { 192 tc_cipher_chain_free_keys(chain_start); 193 return err; 194 } 195 196 /* Set next input buffer as current output buffer */ 197 in = out; 198 } 199 200 tc_cipher_chain_free_keys(chain_start); 201 202 return 0; 203 } 204 205 int 206 apply_keyfiles(unsigned char *pass, size_t pass_memsz, const char *keyfiles[], 207 int nkeyfiles) 208 { 209 int pl, k; 210 unsigned char *kpool; 211 unsigned char *kdata; 212 int kpool_idx; 213 size_t i, kdata_sz; 214 uint32_t crc; 215 216 if (pass_memsz < MAX_PASSSZ) { 217 tc_log(1, "Not enough memory for password manipluation\n"); 218 return ENOMEM; 219 } 220 221 pl = strlen((char *)pass); 222 memset(pass+pl, 0, MAX_PASSSZ-pl); 223 224 if ((kpool = alloc_safe_mem(KPOOL_SZ)) == NULL) { 225 tc_log(1, "Error allocating memory for keyfile pool\n"); 226 return ENOMEM; 227 } 228 229 memset(kpool, 0, KPOOL_SZ); 230 231 for (k = 0; k < nkeyfiles; k++) { 232 #ifdef DEBUG 233 printf("Loading keyfile %s into kpool\n", keyfiles[k]); 234 #endif 235 kpool_idx = 0; 236 crc = ~0U; 237 kdata_sz = MAX_KFILE_SZ; 238 239 if ((kdata = read_to_safe_mem(keyfiles[k], 0, &kdata_sz)) == NULL) { 240 tc_log(1, "Error reading keyfile %s content\n", 241 keyfiles[k]); 242 free_safe_mem(kpool); 243 return EIO; 244 } 245 246 for (i = 0; i < kdata_sz; i++) { 247 crc = crc32_intermediate(crc, kdata[i]); 248 249 kpool[kpool_idx++] += (unsigned char)(crc >> 24); 250 kpool[kpool_idx++] += (unsigned char)(crc >> 16); 251 kpool[kpool_idx++] += (unsigned char)(crc >> 8); 252 kpool[kpool_idx++] += (unsigned char)(crc); 253 254 /* Wrap around */ 255 if (kpool_idx == KPOOL_SZ) 256 kpool_idx = 0; 257 } 258 259 free_safe_mem(kdata); 260 } 261 262 #ifdef DEBUG 263 printf("Applying kpool to passphrase\n"); 264 #endif 265 /* Apply keyfile pool to passphrase */ 266 for (i = 0; i < KPOOL_SZ; i++) 267 pass[i] += kpool[i]; 268 269 free_safe_mem(kpool); 270 271 return 0; 272 } 273