Skip to content
Newer
Older
100644 277 lines (235 sloc) 6.37 KB
31d65e4 @bwalex Improve support for different cipher methods
authored Jul 2, 2011
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 <sys/ioctl.h>
32 #include <sys/sysctl.h>
33 #include <crypto/cryptodev.h>
34
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <openssl/evp.h>
40
41 #include "crc32.h"
42 #include "tc-play.h"
43
44 static
45 int
46 getallowsoft(void)
47 {
48 int old;
49 size_t olen;
50
51 olen = sizeof(old);
52
53 if (sysctlbyname("kern.cryptodevallowsoft", &old, &olen, NULL, 0) < 0) {
54 perror("accessing sysctl kern.cryptodevallowsoft failed");
55 }
56
57 return old;
58 }
59
60 static
61 void
62 setallowsoft(int new)
63 {
64 int old;
65 size_t olen, nlen;
66
67 olen = nlen = sizeof(new);
68
69 if (sysctlbyname("kern.cryptodevallowsoft", &old, &olen, &new, nlen) < 0) {
70 perror("accessing sysctl kern.cryptodevallowsoft failed");
71 }
72 }
73
74 static
75 int
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)
78 {
79 struct session_op session;
80 struct crypt_op cryp;
81 int cryptodev_fd = -1, fd = -1;
82
83 if ((cryptodev_fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
84 perror("Could not open /dev/crypto");
85 goto err;
86 }
87 if (ioctl(cryptodev_fd, CRIOGET, &fd) == -1) {
88 perror("CRIOGET failed");
89 goto err;
90 }
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");
97 goto err;
98 }
99 memset(&cryp, 0, sizeof(cryp));
100 cryp.ses = session.ses;
101 cryp.op = do_encrypt ? COP_ENCRYPT : COP_DECRYPT;
102 cryp.flags = 0;
103 cryp.len = len;
104 cryp.src = (caddr_t) in;
105 cryp.dst = (caddr_t) out;
106 cryp.iv = (caddr_t) iv;
107 cryp.mac = 0;
108 if (ioctl(fd, CIOCCRYPT, &cryp) == -1) {
109 perror("CIOCCRYPT failed");
110 goto err;
111 }
112 if (ioctl(fd, CIOCFSESSION, &session.ses) == -1) {
113 perror("CIOCFSESSION failed");
114 goto err;
115 }
116 close(fd);
117 close(cryptodev_fd);
118 return (0);
119
120 err:
121 if (fd != -1)
122 close(fd);
123 if (cryptodev_fd != -1)
124 close(cryptodev_fd);
125 return (-1);
126 }
127
128 static
129 int
130 get_cryptodev_cipher_id(struct tc_crypto_algo *cipher)
131 {
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
137 return -1;
138 }
139
140 int
141 tc_crypto_init(void)
142 {
143 int allowed;
144
145 OpenSSL_add_all_algorithms();
146
147 allowed = getallowsoft();
148 if (allowed == 0)
149 setallowsoft(1);
150
151 return 0;
152 }
153
154 int
155 tc_encrypt(struct tc_crypto_algo *cipher, unsigned char *key,
156 unsigned char *iv,
157 unsigned char *in, int in_len, unsigned char *out)
158 {
159 int cipher_id;
160
161 cipher_id = get_cryptodev_cipher_id(cipher);
162 if (cipher_id < 0) {
163 fprintf(stderr, "Cipher %s not found\n", cipher->name);
164 return ENOENT;
165 }
166
167 return syscrypt(cipher_id, key, cipher->klen, iv, in, out, in_len, 1);
168 }
169
170 int
171 tc_decrypt(struct tc_crypto_algo *cipher, unsigned char *key,
172 unsigned char *iv,
173 unsigned char *in, int in_len, unsigned char *out)
174 {
175 int cipher_id;
176
177 cipher_id = get_cryptodev_cipher_id(cipher);
178 if (cipher_id < 0) {
179 fprintf(stderr, "Cipher %s not found\n", cipher->name);
180 return ENOENT;
181 }
182
183 return syscrypt(cipher_id, key, cipher->klen, iv, in, out, in_len, 0);
184 }
185
186 int
187 pbkdf2(const char *pass, int passlen, const unsigned char *salt, int saltlen,
188 int iter, const char *hash_name, int keylen, unsigned char *out)
189 {
190 const EVP_MD *md;
191 int r;
192
193 md = EVP_get_digestbyname(hash_name);
194 if (md == NULL) {
195 printf("Hash %s not found\n", hash_name);
196 return ENOENT;
197 }
198 r = PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, md,
199 keylen, out);
200
201 if (r == 0) {
202 printf("Error in PBKDF2\n");
203 return EINVAL;
204 }
205
206 return 0;
207 }
208
209 int
210 apply_keyfiles(unsigned char *pass, size_t pass_memsz, const char *keyfiles[],
211 int nkeyfiles)
212 {
213 int pl, k;
214 unsigned char *kpool;
215 unsigned char *kdata;
216 int kpool_idx;
217 size_t i, kdata_sz;
218 uint32_t crc;
219
220 if (pass_memsz < MAX_PASSSZ) {
221 fprintf(stderr, "Not enough memory for password manipluation\n");
222 return ENOMEM;
223 }
224
225 pl = strlen(pass);
226 memset(pass+pl, 0, MAX_PASSSZ-pl);
227
228 if ((kpool = alloc_safe_mem(KPOOL_SZ)) == NULL) {
229 fprintf(stderr, "Error allocating memory for keyfile pool\n");
230 return ENOMEM;
231 }
232
233 memset(kpool, 0, KPOOL_SZ);
234
235 for (k = 0; k < nkeyfiles; k++) {
236 #ifdef DEBUG
237 printf("Loading keyfile %s into kpool\n", keyfiles[k]);
238 #endif
239 kpool_idx = 0;
240 crc = ~0U;
241 kdata_sz = MAX_KFILE_SZ;
242
243 if ((kdata = read_to_safe_mem(keyfiles[k], 0, &kdata_sz)) == NULL) {
244 fprintf(stderr, "Error reading keyfile %s content\n",
245 keyfiles[k]);
246 free_safe_mem(kpool);
247 return EIO;
248 }
249
250 for (i = 0; i < kdata_sz; i++) {
251 crc = crc32_intermediate(crc, kdata[i]);
252
253 kpool[kpool_idx++] += (unsigned char)(crc >> 24);
254 kpool[kpool_idx++] += (unsigned char)(crc >> 16);
255 kpool[kpool_idx++] += (unsigned char)(crc >> 8);
256 kpool[kpool_idx++] += (unsigned char)(crc);
257
258 /* Wrap around */
259 if (kpool_idx == KPOOL_SZ)
260 kpool_idx = 0;
261 }
262
263 free_safe_mem(kdata);
264 }
265
266 #ifdef DEBUG
267 printf("Applying kpool to passphrase\n");
268 #endif
269 /* Apply keyfile pool to passphrase */
270 for (i = 0; i < KPOOL_SZ; i++)
271 pass[i] += kpool[i];
272
273 free_safe_mem(kpool);
274
275 return 0;
276 }
Something went wrong with that request. Please try again.