2 * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
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
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <sys/ioctl.h>
32 #include <sys/sysctl.h>
33 #include <crypto/cryptodev.h>
39 #include <openssl/evp.h>
53 if (sysctlbyname("kern.cryptodevallowsoft", &old, &olen, NULL, 0) < 0) {
54 perror("accessing sysctl kern.cryptodevallowsoft failed");
67 olen = nlen = sizeof(new);
69 if (sysctlbyname("kern.cryptodevallowsoft", &old, &olen, &new, nlen) < 0) {
70 perror("accessing sysctl kern.cryptodevallowsoft failed");
76 syscrypt(int cipher, unsigned char *key, size_t klen, unsigned char *iv,
77 unsigned char *in, unsigned char *out, size_t len, int do_encrypt)
79 struct session_op session;
81 int cryptodev_fd = -1, fd = -1;
83 if ((cryptodev_fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
84 perror("Could not open /dev/crypto");
87 if (ioctl(cryptodev_fd, CRIOGET, &fd) == -1) {
88 perror("CRIOGET failed");
91 memset(&session, 0, sizeof(session));
92 session.cipher = cipher;
93 session.key = (caddr_t) key;
94 session.keylen = klen;
95 if (ioctl(fd, CIOCGSESSION, &session) == -1) {
96 perror("CIOCGSESSION failed");
99 memset(&cryp, 0, sizeof(cryp));
100 cryp.ses = session.ses;
101 cryp.op = do_encrypt ? COP_ENCRYPT : COP_DECRYPT;
104 cryp.src = (caddr_t) in;
105 cryp.dst = (caddr_t) out;
106 cryp.iv = (caddr_t) iv;
108 if (ioctl(fd, CIOCCRYPT, &cryp) == -1) {
109 perror("CIOCCRYPT failed");
112 if (ioctl(fd, CIOCFSESSION, &session.ses) == -1) {
113 perror("CIOCFSESSION failed");
123 if (cryptodev_fd != -1)
130 get_cryptodev_cipher_id(struct tc_crypto_algo *cipher)
132 if (strcmp(cipher->name, "AES-128-XTS") == 0)
133 return CRYPTO_AES_XTS;
134 else if (strcmp(cipher->name, "AES-256-XTS") == 0)
135 return CRYPTO_AES_XTS;
136 else if (strcmp(cipher->name, "TWOFISH-128-XTS") == 0)
137 return CRYPTO_TWOFISH_XTS;
138 else if (strcmp(cipher->name, "TWOFISH-256-XTS") == 0)
139 return CRYPTO_TWOFISH_XTS;
140 else if (strcmp(cipher->name, "SERPENT-128-XTS") == 0)
141 return CRYPTO_SERPENT_XTS;
142 else if (strcmp(cipher->name, "SERPENT-256-XTS") == 0)
143 return CRYPTO_SERPENT_XTS;
153 OpenSSL_add_all_algorithms();
155 allowed = getallowsoft();
163 tc_cipher_chain_populate_keys(struct tc_cipher_chain *cipher_chain,
166 int total_key_bytes, used_key_bytes;
167 struct tc_cipher_chain *dummy_chain;
170 * We need to determine the total key bytes as the key locations
174 for (dummy_chain = cipher_chain;
176 dummy_chain = dummy_chain->next) {
177 total_key_bytes += dummy_chain->cipher->klen;
181 * Now we need to get prepare the keys, as the keys are in
182 * forward order with respect to the cipher cascade, but
183 * the actual decryption is in reverse cipher cascade order.
186 for (dummy_chain = cipher_chain;
188 dummy_chain = dummy_chain->next) {
189 dummy_chain->key = alloc_safe_mem(dummy_chain->cipher->klen);
190 if (dummy_chain->key == NULL) {
191 tc_log(1, "tc_decrypt: Could not allocate key "
196 /* XXX: here we assume XTS operation! */
197 memcpy(dummy_chain->key,
198 key + used_key_bytes/2,
199 dummy_chain->cipher->klen/2);
200 memcpy(dummy_chain->key + dummy_chain->cipher->klen/2,
201 key + (total_key_bytes/2) + used_key_bytes/2,
202 dummy_chain->cipher->klen/2);
204 /* Remember how many key bytes we've seen */
205 used_key_bytes += dummy_chain->cipher->klen;
212 tc_encrypt(struct tc_cipher_chain *cipher_chain, unsigned char *key,
214 unsigned char *in, int in_len, unsigned char *out)
219 if ((err = tc_cipher_chain_populate_keys(cipher_chain, key)))
223 printf("tc_encrypt: starting chain\n");
227 * Now process the actual decryption, in forward cascade order.
230 cipher_chain != NULL;
231 cipher_chain = cipher_chain->next) {
232 cipher_id = get_cryptodev_cipher_id(cipher_chain->cipher);
234 tc_log(1, "Cipher %s not found\n",
235 cipher_chain->cipher->name);
240 printf("tc_encrypt: Currently using cipher %s\n",
241 cipher_chain->cipher->name);
244 err = syscrypt(cipher_id, cipher_chain->key,
245 cipher_chain->cipher->klen, iv, in, out, in_len, 1);
247 /* Deallocate this key, since we won't need it anymore */
248 free_safe_mem(cipher_chain->key);
253 /* Set next input buffer as current output buffer */
261 tc_decrypt(struct tc_cipher_chain *cipher_chain, unsigned char *key,
263 unsigned char *in, int in_len, unsigned char *out)
268 if ((err = tc_cipher_chain_populate_keys(cipher_chain, key)))
272 printf("tc_decrypt: starting chain!\n");
276 * Now process the actual decryption, in reverse cascade order; so
277 * first find the last element in the chain.
279 for (; cipher_chain->next != NULL; cipher_chain = cipher_chain->next)
282 cipher_chain != NULL;
283 cipher_chain = cipher_chain->prev) {
284 cipher_id = get_cryptodev_cipher_id(cipher_chain->cipher);
286 tc_log(1, "Cipher %s not found\n",
287 cipher_chain->cipher->name);
292 printf("tc_decrypt: Currently using cipher %s\n",
293 cipher_chain->cipher->name);
296 err = syscrypt(cipher_id, cipher_chain->key,
297 cipher_chain->cipher->klen, iv, in, out, in_len, 0);
299 /* Deallocate this key, since we won't need it anymore */
300 free_safe_mem(cipher_chain->key);
305 /* Set next input buffer as current output buffer */
313 pbkdf2(const char *pass, int passlen, const unsigned char *salt, int saltlen,
314 int iter, const char *hash_name, int keylen, unsigned char *out)
319 md = EVP_get_digestbyname(hash_name);
321 printf("Hash %s not found\n", hash_name);
324 r = PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, md,
328 printf("Error in PBKDF2\n");
336 apply_keyfiles(unsigned char *pass, size_t pass_memsz, const char *keyfiles[],
340 unsigned char *kpool;
341 unsigned char *kdata;
346 if (pass_memsz < MAX_PASSSZ) {
347 tc_log(1, "Not enough memory for password manipluation\n");
352 memset(pass+pl, 0, MAX_PASSSZ-pl);
354 if ((kpool = alloc_safe_mem(KPOOL_SZ)) == NULL) {
355 tc_log(1, "Error allocating memory for keyfile pool\n");
359 memset(kpool, 0, KPOOL_SZ);
361 for (k = 0; k < nkeyfiles; k++) {
363 printf("Loading keyfile %s into kpool\n", keyfiles[k]);
367 kdata_sz = MAX_KFILE_SZ;
369 if ((kdata = read_to_safe_mem(keyfiles[k], 0, &kdata_sz)) == NULL) {
370 tc_log(1, "Error reading keyfile %s content\n",
372 free_safe_mem(kpool);
376 for (i = 0; i < kdata_sz; i++) {
377 crc = crc32_intermediate(crc, kdata[i]);
379 kpool[kpool_idx++] += (unsigned char)(crc >> 24);
380 kpool[kpool_idx++] += (unsigned char)(crc >> 16);
381 kpool[kpool_idx++] += (unsigned char)(crc >> 8);
382 kpool[kpool_idx++] += (unsigned char)(crc);
385 if (kpool_idx == KPOOL_SZ)
389 free_safe_mem(kdata);
393 printf("Applying kpool to passphrase\n");
395 /* Apply keyfile pool to passphrase */
396 for (i = 0; i < KPOOL_SZ; i++)
399 free_safe_mem(kpool);