Add basic TCRYPT library.
[platform/upstream/cryptsetup.git] / lib / tcrypt / tcrypt.c
1 /*
2  * TCRYPT compatible volume handling
3  *
4  * Copyright (C) 2012, Red Hat, Inc. All rights reserved.
5  * Copyright (C) 2012, Milan Broz
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <fcntl.h>
26 #include <assert.h>
27
28 #include "libcryptsetup.h"
29 #include "tcrypt.h"
30 #include "internal.h"
31
32 /* TCRYPT PBKDF variants */
33 static struct {
34         char *name;
35         char *hash;
36         unsigned int iterations;
37 } tcrypt_kdf[] = {
38         { "pbkdf2", "ripemd160", 2000 },
39         { "pbkdf2", "ripemd160", 1000 },
40         { "pbkdf2", "sha512",    1000 },
41         { "pbkdf2", "whirlpool", 1000 },
42         { NULL,     NULL,           0 }
43 };
44
45 /* TCRYPT cipher variants */
46 static struct {
47         const char *cipher[3];
48         const char *mode;
49         int key_size;
50 } tcrypt_cipher[] = {
51         { { "aes",     NULL,      NULL      }, "xts-plain64", 64 },
52         { { "twofish", NULL,      NULL      }, "xts-plain64", 64 },
53         { { "serpent", NULL,      NULL      }, "xts-plain64", 64 },
54         { { "aes",     "twofish", "serpent" }, "xts-plain64", 64 },
55         { { "serpent", "twofish", "aes"     }, "xts-plain64", 64 },
56         { { "twofish", "aes",     NULL      }, "xts-plain64", 64 },
57         { { "aes",     "serpent", NULL      }, "xts-plain64", 64 },
58         { { "serpent", "twofish", NULL      }, "xts-plain64", 64 },
59         { { "aes",     NULL,      NULL      }, "lrw-benbi",   48 },
60         { { "twofish", NULL,      NULL      }, "lrw-benbi",   48 },
61         { { "serpent", NULL,      NULL      }, "lrw-benbi",   48 },
62         { { "aes",     "twofish", "serpent" }, "lrw-benbi",   48 },
63         { { "serpent", "twofish", "aes"     }, "lrw-benbi",   48 },
64         { { "twofish", "aes",     NULL      }, "lrw-benbi",   48 },
65         { { "aes",     "serpent", NULL      }, "lrw-benbi",   48 },
66         { { "serpent", "twofish", NULL      }, "lrw-benbi",   48 },
67         { { NULL,      NULL,      NULL      }, NULL,           0 }
68 };
69
70 static void hdr_info(struct crypt_device *cd, struct tcrypt_phdr *hdr,
71                      struct crypt_params_tcrypt *params)
72 {
73         log_dbg("Version: %d, required %d", (int)hdr->d.version, (int)hdr->d.version_tc);
74
75         log_dbg("Hidden size: %" PRIu64, hdr->d.hidden_volume_size);
76         log_dbg("Volume size: %" PRIu64, hdr->d.volume_size);
77
78         log_dbg("Sector size: %" PRIu64, hdr->d.sector_size);
79         log_dbg("Flags: %d", (int)hdr->d.flags);
80         log_dbg("MK: offset %d, size %d", (int)hdr->d.mk_offset, (int)hdr->d.mk_size);
81         log_dbg("KDF: PBKDF2, hash %s", params->hash_name);
82         log_dbg("Cipher: %s%s%s%s%s-%s",
83                 params->cipher[0],
84                 params->cipher[1] ? "-" : "", params->cipher[1] ?: "",
85                 params->cipher[2] ? "-" : "", params->cipher[2] ?: "",
86                 params->mode);
87 }
88
89 static int hdr_from_disk(struct tcrypt_phdr *hdr,
90                          struct crypt_params_tcrypt *params,
91                          int kdf_index, int cipher_index)
92 {
93         uint32_t crc32;
94         size_t size;
95
96         /* Check CRC32 of header */
97         size = TCRYPT_HDR_LEN - sizeof(hdr->d.keys) - sizeof(hdr->d.header_crc32);
98         crc32 = crypt_crc32(~0, (unsigned char*)&hdr->d, size) ^ ~0;
99         if (be16_to_cpu(hdr->d.version) > 3 &&
100             crc32 != be32_to_cpu(hdr->d.header_crc32)) {
101                 log_dbg("TCRYPT header CRC32 mismatch.");
102                 return -EINVAL;
103         }
104
105         /* Check CRC32 of keys */
106         crc32 = crypt_crc32(~0, (unsigned char*)hdr->d.keys, sizeof(hdr->d.keys)) ^ ~0;
107         if (crc32 != be32_to_cpu(hdr->d.keys_crc32)) {
108                 log_dbg("TCRYPT keys CRC32 mismatch.");
109                 return -EINVAL;
110         }
111
112         /* Convert header to cpu format */
113         hdr->d.version  =  be16_to_cpu(hdr->d.version);
114         hdr->d.version_tc = le16_to_cpu(hdr->d.version_tc); // ???
115
116         hdr->d.keys_crc32 = be32_to_cpu(hdr->d.keys_crc32);
117
118         hdr->d.hidden_volume_size = be64_to_cpu(hdr->d.hidden_volume_size);
119         hdr->d.volume_size        = be64_to_cpu(hdr->d.volume_size);
120
121         hdr->d.mk_offset = be64_to_cpu(hdr->d.mk_offset);
122         if (!hdr->d.mk_offset)
123                 hdr->d.mk_offset = 512;
124
125         hdr->d.mk_size = be64_to_cpu(hdr->d.mk_size);
126
127         hdr->d.flags = be32_to_cpu(hdr->d.flags);
128
129         hdr->d.sector_size = be32_to_cpu(hdr->d.sector_size);
130         if (!hdr->d.sector_size)
131                 hdr->d.sector_size = 512;
132
133         hdr->d.header_crc32 = be32_to_cpu(hdr->d.header_crc32);
134
135         /* Set params */
136         params->passphrase = NULL;
137         params->passphrase_size = 0;
138
139         params->hash_name  = tcrypt_kdf[kdf_index].hash;
140
141         params->cipher[0]  = tcrypt_cipher[cipher_index].cipher[0];
142         params->cipher[1]  = tcrypt_cipher[cipher_index].cipher[1];
143         params->cipher[2]  = tcrypt_cipher[cipher_index].cipher[2];
144         params->mode     = tcrypt_cipher[cipher_index].mode;
145         params->key_size = tcrypt_cipher[cipher_index].key_size;
146
147         return 0;
148 }
149
150 static int decrypt_hdr_one(const char *name, const char *mode,
151                            const char *key, size_t key_size,
152                            struct tcrypt_phdr *hdr)
153 {
154         char iv[TCRYPT_HDR_IV_LEN] = {};
155         char mode_name[MAX_CIPHER_LEN];
156         struct crypt_cipher *cipher;
157         void *buf = &hdr->e;
158         char *c;
159         int r;
160
161         /* Remove IV if present */
162         strncpy(mode_name, mode, MAX_CIPHER_LEN);
163         c = strchr(mode_name, '-');
164         if (c)
165                 *c = '\0';
166
167         if (!strncmp(mode, "lrw", 3))
168                 iv[15] = 1;
169
170         r = crypt_cipher_init(&cipher, name, mode_name, key, key_size);
171         if (r < 0)
172                 return r;
173
174         r = crypt_cipher_decrypt(cipher, buf, buf, TCRYPT_HDR_LEN,
175                                  iv, TCRYPT_HDR_IV_LEN);
176         crypt_cipher_destroy(cipher);
177
178         return r;
179 }
180
181 static void copy_key(char *out_key, const char *key, int key_num,
182                      int ks, int ki, const char *mode)
183 {
184         if (!strncmp(mode, "xts", 3)) {
185                 int ks2 = ks / 2;
186                 memcpy(out_key, &key[ks2 * ki], ks2);
187                 memcpy(&out_key[ks2], &key[ks2 * (++key_num + ki)], ks2);
188         } else if (!strncmp(mode, "lrw", 3)) {
189                 /* First is LRW index key */
190                 ki++;
191                 ks -= TCRYPT_LRW_IKEY_LEN;
192                 memcpy(out_key, &key[ks * ki], ks);
193                 memcpy(&out_key[ks * ki], key, TCRYPT_LRW_IKEY_LEN);
194         }
195 }
196
197 static int top_cipher(const char *cipher[3])
198 {
199         if (cipher[2])
200                 return 2;
201
202         if (cipher[1])
203                 return 1;
204
205         return 0;
206 }
207
208 static int decrypt_hdr(struct crypt_device *cd, struct tcrypt_phdr *hdr,
209                         const char *key)
210 {
211         char one_key[TCRYPT_HDR_KEY_LEN];
212         struct tcrypt_phdr hdr2;
213         int i, j, r;
214
215         for (i = 0; tcrypt_cipher[i].cipher[0]; i++) {
216                 log_dbg("TCRYPT:  trying cipher: %s%s%s%s%s-%s.",
217                         tcrypt_cipher[i].cipher[0],
218                         tcrypt_cipher[i].cipher[1] ? "-" : "", tcrypt_cipher[i].cipher[1] ?: "",
219                         tcrypt_cipher[i].cipher[2] ? "-" : "", tcrypt_cipher[i].cipher[2] ?: "",
220                         tcrypt_cipher[i].mode);
221
222                 memcpy(&hdr2.e, &hdr->e, TCRYPT_HDR_LEN);
223
224                 for (j = 2; j >= 0 ; j--) {
225                         if (!tcrypt_cipher[i].cipher[j])
226                                 continue;
227                         copy_key(one_key, key, top_cipher(tcrypt_cipher[i].cipher),
228                                  tcrypt_cipher[i].key_size,
229                                  j, tcrypt_cipher[i].mode);
230                         r = decrypt_hdr_one(tcrypt_cipher[i].cipher[j],
231                                             tcrypt_cipher[i].mode, one_key,
232                                             tcrypt_cipher[i].key_size, &hdr2);
233                         if (r < 0)
234                                 break;
235                 }
236
237                 if (!strncmp(hdr2.d.magic, TCRYPT_HDR_MAGIC, TCRYPT_HDR_MAGIC_LEN)) {
238                         log_dbg("TCRYPT: Signature magic detected.");
239                         memcpy(&hdr->e, &hdr2.e, TCRYPT_HDR_LEN);
240                         memset(&hdr2.e, 0, TCRYPT_HDR_LEN);
241                         r = i;
242                         break;
243                 }
244                 r = -EPERM;
245         }
246
247         memset(one_key, 0, sizeof(*one_key));
248         return r;
249 }
250
251 static int TCRYPT_init_hdr(struct crypt_device *cd,
252                            struct tcrypt_phdr *hdr,
253                            struct crypt_params_tcrypt *params,
254                            const char *passphrase,
255                            size_t passphrase_size)
256 {
257         char *key;
258         int r, i;
259
260         if (posix_memalign((void*)&key, crypt_getpagesize(), TCRYPT_HDR_KEY_LEN))
261                 return -ENOMEM;
262
263         for (i = 0; tcrypt_kdf[i].name; i++) {
264                 /* Derive header key */
265                 log_dbg("TCRYPT: trying KDF: %s-%s-%d.",
266                         tcrypt_kdf[i].name, tcrypt_kdf[i].hash, tcrypt_kdf[i].iterations);
267                 r = crypt_pbkdf(tcrypt_kdf[i].name, tcrypt_kdf[i].hash,
268                                 passphrase, passphrase_size,
269                                 hdr->salt, TCRYPT_HDR_SALT_LEN,
270                                 key, TCRYPT_HDR_KEY_LEN,
271                                 tcrypt_kdf[i].iterations);
272                 if (r < 0)
273                         break;
274
275                 /* Decrypt header */
276                 r = decrypt_hdr(cd, hdr, key);
277                 if (r != -EPERM)
278                         break;
279         }
280         free(key);
281
282         if (r < 0)
283                 return r;
284
285         r = hdr_from_disk(hdr, params, i, r);
286         if (r < 0)
287                 return r;
288
289         hdr_info(cd, hdr, params);
290         return 0;
291 }
292
293 int TCRYPT_read_phdr(struct crypt_device *cd,
294                      struct tcrypt_phdr *hdr,
295                      struct crypt_params_tcrypt *params,
296                      const char *passphrase,
297                      size_t passphrase_size,
298                      uint32_t flags)
299 {
300         struct device *device = crypt_metadata_device(cd);
301         ssize_t hdr_size = sizeof(struct tcrypt_phdr);
302         int devfd = 0, r;
303
304         assert(sizeof(struct tcrypt_phdr) == 512);
305
306         log_dbg("Reading TCRYPT header of size %d bytes from device %s.",
307                 hdr_size, device_path(device));
308
309         devfd = open(device_path(device), O_RDONLY | O_DIRECT);
310         if (devfd == -1) {
311                 log_err(cd, _("Cannot open device %s.\n"), device_path(device));
312                 return -EINVAL;
313         }
314
315         if ((flags & CRYPT_TCRYPT_HIDDEN_HEADER) &&
316             lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET, SEEK_SET) < 0) {
317                 log_err(cd, _("Cannot seek to hidden header for %s.\n"), device_path(device));
318                 r = -EIO;
319                 goto out;
320         }
321
322         if (read_blockwise(devfd, device_block_size(device), hdr, hdr_size) == hdr_size) {
323                 params->flags = flags;
324                 r = TCRYPT_init_hdr(cd, hdr, params, passphrase, passphrase_size);
325         } else
326                 r = -EIO;
327 out:
328         close(devfd);
329         return r;
330 }
331
332 int TCRYPT_activate(struct crypt_device *cd,
333                      const char *name,
334                      struct tcrypt_phdr *hdr,
335                      struct crypt_params_tcrypt *params,
336                      uint32_t flags)
337 {
338         char cipher[MAX_CIPHER_LEN], dm_name[PATH_MAX], dm_dev_name[PATH_MAX];
339         struct device *device = NULL;
340         int i, r;
341         struct crypt_dm_active_device dmd = {
342                 .target = DM_CRYPT,
343                 .size   = 0,
344                 .data_device = crypt_data_device(cd),
345                 .u.crypt  = {
346                         .cipher = cipher,
347                         .offset = crypt_get_data_offset(cd),
348                         .iv_offset = crypt_get_iv_offset(cd),
349                 }
350         };
351
352         r = device_block_adjust(cd, dmd.data_device, DEV_EXCL,
353                                 dmd.u.crypt.offset, &dmd.size, &dmd.flags);
354         if (r)
355                 return r;
356
357         dmd.u.crypt.vk = crypt_alloc_volume_key(params->key_size, NULL);
358         if (!dmd.u.crypt.vk)
359                 return -ENOMEM;
360
361         for (i = 2; i >= 0; i--) {
362
363                 if (!params->cipher[i])
364                         continue;
365
366                 if (i == 0) {
367                         strncpy(dm_name, name, sizeof(dm_name));
368                         dmd.flags = flags;
369                 } else {
370                         snprintf(dm_name, sizeof(dm_name), "%s_%d", name, i);
371                         dmd.flags = flags | CRYPT_ACTIVATE_PRIVATE;
372                 }
373
374                 snprintf(cipher, sizeof(cipher), "%s-%s",
375                          params->cipher[i], params->mode);
376                 copy_key(dmd.u.crypt.vk->key, hdr->d.keys,
377                          top_cipher(params->cipher),
378                          params->key_size, i, params->mode);
379
380                 if (top_cipher(params->cipher) != i) {
381                         snprintf(dm_dev_name, sizeof(dm_dev_name), "%s/%s_%d",
382                                  dm_get_dir(), name, i + 1);
383                         r = device_alloc(&device, dm_dev_name);
384                         if (r)
385                                 break;
386                         dmd.data_device = device;
387                         dmd.u.crypt.offset = 0;
388                 }
389
390                 log_dbg("Trying to activate TCRYPT device %s using cipher %s.",
391                         dm_name, dmd.u.crypt.cipher);
392                 r = dm_create_device(cd, dm_name, CRYPT_TCRYPT, &dmd, 0);
393
394                 device_free(device);
395                 device = NULL;
396
397                 if (r)
398                         break;
399         }
400
401         if (!r && !(dm_flags() & DM_PLAIN64_SUPPORTED)) {
402                 log_err(cd, _("Kernel doesn't support plain64 IV.\n"));
403                 r = -ENOTSUP;
404         }
405
406         crypt_free_volume_key(dmd.u.crypt.vk);
407         return r;
408 }