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 = tc_cipher_chain_klen(cipher_chain); 54 55 /* 56 * Now we need to get prepare the keys, as the keys are in 57 * forward order with respect to the cipher cascade, but 58 * the actual decryption is in reverse cipher cascade order. 59 */ 60 used_key_bytes = 0; 61 for (dummy_chain = cipher_chain; 62 dummy_chain != NULL; 63 dummy_chain = dummy_chain->next) { 64 dummy_chain->key = alloc_safe_mem(dummy_chain->cipher->klen); 65 if (dummy_chain->key == NULL) { 66 tc_log(1, "tc_decrypt: Could not allocate key " 67 "memory\n"); 68 return ENOMEM; 69 } 70 71 /* XXX: here we assume XTS operation! */ 72 memcpy(dummy_chain->key, 73 key + used_key_bytes/2, 74 dummy_chain->cipher->klen/2); 75 memcpy(dummy_chain->key + dummy_chain->cipher->klen/2, 76 key + (total_key_bytes/2) + used_key_bytes/2, 77 dummy_chain->cipher->klen/2); 78 79 /* Remember how many key bytes we've seen */ 80 used_key_bytes += dummy_chain->cipher->klen; 81 } 82 83 return 0; 84 } 85 86 int 87 tc_cipher_chain_free_keys(struct tc_cipher_chain *cipher_chain) 88 { 89 for (; cipher_chain != NULL; cipher_chain = cipher_chain->next) { 90 if (cipher_chain->key != NULL) { 91 free_safe_mem(cipher_chain->key); 92 cipher_chain->key = NULL; 93 } 94 } 95 96 return 0; 97 } 98 99 int 100 tc_encrypt(struct tc_cipher_chain *cipher_chain, unsigned char *key, 101 unsigned char *iv, 102 unsigned char *in, int in_len, unsigned char *out) 103 { 104 struct tc_cipher_chain *chain_start; 105 int err; 106 107 chain_start = cipher_chain; 108 109 if ((err = tc_cipher_chain_populate_keys(cipher_chain, key))) 110 return err; 111 112 #ifdef DEBUG 113 printf("tc_encrypt: starting chain\n"); 114 #endif 115 116 /* 117 * Now process the actual decryption, in forward cascade order. 118 */ 119 for (; 120 cipher_chain != NULL; 121 cipher_chain = cipher_chain->next) { 122 #ifdef DEBUG 123 printf("tc_encrypt: Currently using cipher %s\n", 124 cipher_chain->cipher->name); 125 #endif 126 127 err = syscrypt(cipher_chain->cipher, cipher_chain->key, 128 cipher_chain->cipher->klen, iv, in, out, in_len, 1); 129 130 /* Deallocate this key, since we won't need it anymore */ 131 free_safe_mem(cipher_chain->key); 132 cipher_chain->key = NULL; 133 134 if (err != 0) { 135 tc_cipher_chain_free_keys(chain_start); 136 return err; 137 } 138 139 /* Set next input buffer as current output buffer */ 140 in = out; 141 } 142 143 tc_cipher_chain_free_keys(chain_start); 144 145 return 0; 146 } 147 148 int 149 tc_decrypt(struct tc_cipher_chain *cipher_chain, unsigned char *key, 150 unsigned char *iv, 151 unsigned char *in, int in_len, unsigned char *out) 152 { 153 struct tc_cipher_chain *chain_start; 154 int err; 155 156 chain_start = cipher_chain; 157 158 if ((err = tc_cipher_chain_populate_keys(cipher_chain, key))) 159 return err; 160 161 #ifdef DEBUG 162 printf("tc_decrypt: starting chain!\n"); 163 #endif 164 165 /* 166 * Now process the actual decryption, in reverse cascade order; so 167 * first find the last element in the chain. 168 */ 169 for (; cipher_chain->next != NULL; cipher_chain = cipher_chain->next) 170 ; 171 for (; 172 cipher_chain != NULL; 173 cipher_chain = cipher_chain->prev) { 174 #ifdef DEBUG 175 printf("tc_decrypt: Currently using cipher %s\n", 176 cipher_chain->cipher->name); 177 #endif 178 179 err = syscrypt(cipher_chain->cipher, cipher_chain->key, 180 cipher_chain->cipher->klen, iv, in, out, in_len, 0); 181 182 /* Deallocate this key, since we won't need it anymore */ 183 free_safe_mem(cipher_chain->key); 184 cipher_chain->key = NULL; 185 186 if (err != 0) { 187 tc_cipher_chain_free_keys(chain_start); 188 return err; 189 } 190 191 /* Set next input buffer as current output buffer */ 192 in = out; 193 } 194 195 tc_cipher_chain_free_keys(chain_start); 196 197 return 0; 198 } 199 200 int 201 apply_keyfiles(unsigned char *pass, size_t pass_memsz, const char *keyfiles[], 202 int nkeyfiles) 203 { 204 int pl, k; 205 unsigned char *kpool; 206 unsigned char *kdata; 207 int kpool_idx; 208 size_t i, kdata_sz; 209 uint32_t crc; 210 211 if (pass_memsz < MAX_PASSSZ) { 212 tc_log(1, "Not enough memory for password manipulation\n"); 213 return ENOMEM; 214 } 215 216 pl = strlen((char *)pass); 217 memset(pass+pl, 0, MAX_PASSSZ-pl); 218 219 if ((kpool = alloc_safe_mem(KPOOL_SZ)) == NULL) { 220 tc_log(1, "Error allocating memory for keyfile pool\n"); 221 return ENOMEM; 222 } 223 224 memset(kpool, 0, KPOOL_SZ); 225 226 for (k = 0; k < nkeyfiles; k++) { 227 #ifdef DEBUG 228 printf("Loading keyfile %s into kpool\n", keyfiles[k]); 229 #endif 230 kpool_idx = 0; 231 crc = ~0U; 232 kdata_sz = MAX_KFILE_SZ; 233 234 if ((kdata = read_to_safe_mem(keyfiles[k], 0, &kdata_sz)) == NULL) { 235 tc_log(1, "Error reading keyfile %s content\n", 236 keyfiles[k]); 237 free_safe_mem(kpool); 238 return EIO; 239 } 240 241 for (i = 0; i < kdata_sz; i++) { 242 crc = crc32_intermediate(crc, kdata[i]); 243 244 kpool[kpool_idx++] += (unsigned char)(crc >> 24); 245 kpool[kpool_idx++] += (unsigned char)(crc >> 16); 246 kpool[kpool_idx++] += (unsigned char)(crc >> 8); 247 kpool[kpool_idx++] += (unsigned char)(crc); 248 249 /* Wrap around */ 250 if (kpool_idx == KPOOL_SZ) 251 kpool_idx = 0; 252 } 253 254 free_safe_mem(kdata); 255 } 256 257 #ifdef DEBUG 258 printf("Applying kpool to passphrase\n"); 259 #endif 260 /* Apply keyfile pool to passphrase */ 261 for (i = 0; i < KPOOL_SZ; i++) 262 pass[i] += kpool[i]; 263 264 free_safe_mem(kpool); 265 266 return 0; 267 } 268