Merge branch 'reenc' of https://code.google.com/p/cryptsetup into reenc
[platform/upstream/cryptsetup.git] / src / crypt_reencrypt.c
1 /*
2  * crypt_reencrypt - crypt utility for offline reencryption
3  *
4  * Copyright (C) 2012 Milan Broz All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * version 2 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19
20 /* The code works as follows:
21  *  - create backup (detached) headers fo old and new device
22  *  - mark original device unusable
23  *  - maps two devices, one with old header one with new onto
24  *    the _same_ underlying device
25  *  - with direct-io reads old device and copy to new device in defined steps
26  *  - keps simple off in file (allows restart)
27  *  - there is several windows when corruption can happen
28  *
29  * null target
30  * dmsetup create x --table "0 $(blockdev --getsz DEV) crypt cipher_null-ecb-null - 0 DEV 0"
31  */
32 #include <string.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stdint.h>
36 #include <stdarg.h>
37 #include <inttypes.h>
38 #include <errno.h>
39 #include <unistd.h>
40 #include <sys/stat.h>
41 #include <sys/ioctl.h>
42 #include <linux/fs.h>
43 #include <fcntl.h>
44 #include <limits.h>
45 #include <signal.h>
46 #include <libcryptsetup.h>
47 #include <popt.h>
48
49 #include "cryptsetup.h"
50
51 static int opt_verbose = 0;
52 static int opt_debug = 0;
53 static const char *opt_cipher = NULL;
54 static const char *opt_hash = NULL;
55 static const char *opt_key_file = NULL;
56 static int opt_iteration_time = 1000;
57 static int opt_batch_mode = 0;
58 static int opt_version_mode = 0;
59 static int opt_random = 0;
60 static int opt_urandom = 0;
61 static int opt_bsize = 4;
62 static int opt_new = 0;
63 static const char *opt_new_file = NULL;
64
65 static const char **action_argv;
66 sigset_t signals_open;
67
68 struct {
69         char *device;
70         char *device_uuid;
71         uint64_t device_size;
72         uint64_t device_offset;
73         uint64_t device_shift;
74
75         int in_progress:1;
76         enum { FORWARD = 0, BACKWARD = 1 } reencrypt_direction;
77
78         char header_file_org[PATH_MAX];
79         char header_file_new[PATH_MAX];
80         char log_file[PATH_MAX];
81
82         char crypt_path_org[PATH_MAX];
83         char crypt_path_new[PATH_MAX];
84         int log_fd;
85
86         char *password;
87         size_t passwordLen;
88         int keyslot;
89 } rnc;
90
91 char MAGIC[]   = {'L','U','K','S', 0xba, 0xbe};
92 char NOMAGIC[] = {'L','U','K','S', 0xde, 0xad};
93 int  MAGIC_L = 6;
94
95 typedef enum {
96         MAKE_UNUSABLE,
97         MAKE_USABLE,
98         CHECK_UNUSABLE
99 } header_magic;
100
101 __attribute__((format(printf, 5, 6)))
102 static void clogger(struct crypt_device *cd, int level, const char *file,
103                    int line, const char *format, ...)
104 {
105         va_list argp;
106         char *target = NULL;
107
108         va_start(argp, format);
109
110         if (vasprintf(&target, format, argp) > 0) {
111                 if (level >= 0) {
112                         crypt_log(cd, level, target);
113                 } else if (opt_debug)
114                         printf("# %s\n", target);
115         }
116
117         va_end(argp);
118         free(target);
119 }
120
121 static void _log(int level, const char *msg, void *usrptr __attribute__((unused)))
122 {
123         switch(level) {
124
125         case CRYPT_LOG_NORMAL:
126                 fputs(msg, stdout);
127                 break;
128         case CRYPT_LOG_VERBOSE:
129                 if (opt_verbose)
130                         fputs(msg, stdout);
131                 break;
132         case CRYPT_LOG_ERROR:
133                 fputs(msg, stderr);
134                 break;
135         case CRYPT_LOG_DEBUG:
136                 if (opt_debug)
137                         printf("# %s\n", msg);
138                 break;
139         default:
140                 fprintf(stderr, "Internal error on logging class for msg: %s", msg);
141                 break;
142         }
143 }
144
145 static void _quiet_log(int level, const char *msg, void *usrptr)
146 {
147         if (!opt_verbose && (level == CRYPT_LOG_ERROR || level == CRYPT_LOG_NORMAL))
148                 level = CRYPT_LOG_VERBOSE;
149         _log(level, msg, usrptr);
150 }
151
152 static int alignment(int fd)
153 {
154         int alignment;
155
156         alignment = fpathconf(fd, _PC_REC_XFER_ALIGN);
157         if (alignment < 0)
158                 alignment = 4096;
159         return alignment;
160 }
161
162 static int device_magic(header_magic set_magic)
163 {
164         char *buf = NULL;
165         size_t block_size = 512;
166         int r, devfd;
167         ssize_t s;
168
169         devfd = open(rnc.device, O_RDWR | O_DIRECT);
170         if (devfd == -1)
171                 return errno == EBUSY ? -EBUSY : -EINVAL;
172
173         if (posix_memalign((void *)&buf, alignment(devfd), block_size)) {
174                 r = -ENOMEM;
175                 goto out;
176         }
177
178         s = read(devfd, buf, block_size);
179         if (s < 0 || s != block_size) {
180                 log_verbose(_("Cannot read device %s.\n"), rnc.device);
181                 close(devfd);
182                 return -EIO;
183         }
184
185         if (set_magic == MAKE_UNUSABLE && !memcmp(buf, MAGIC, MAGIC_L)) {
186                 log_dbg("Marking LUKS device %s unusable.", rnc.device);
187                 memcpy(buf, NOMAGIC, MAGIC_L);
188                 r = 0;
189
190         } else if (set_magic == MAKE_USABLE && !memcmp(buf, NOMAGIC, MAGIC_L)) {
191                 log_dbg("Marking LUKS device %s usable.", rnc.device);
192                 memcpy(buf, MAGIC, MAGIC_L);
193                 r = 0;
194         } else if (set_magic == CHECK_UNUSABLE) {
195                 r = memcmp(buf, NOMAGIC, MAGIC_L) ? -EINVAL : 0;
196                 if (!r)
197                         rnc.device_uuid = strndup(&buf[0xa8], 40);
198                 goto out;
199         } else
200                 r = -EINVAL;
201
202         if (!r) {
203                 if (lseek(devfd, 0, SEEK_SET) == -1)
204                         goto out;
205                 s = write(devfd, buf, block_size);
206                 if (s < 0 || s != block_size) {
207                         log_verbose(_("Cannot write device %s.\n"), rnc.device);
208                         r = -EIO;
209                 }
210         } else
211                 log_dbg("LUKS signature check failed for %s.", rnc.device);
212 out:
213         if (buf)
214                 memset(buf, 0, block_size);
215         free(buf);
216         close(devfd);
217         return r;
218 }
219
220 static int create_empty_header(const char *new_file, uint64_t size)
221 {
222         int fd, r = 0;
223         char *buf;
224
225         log_dbg("Creating empty file %s of size %lu.", new_file, (unsigned long)size);
226
227         if (!(buf = malloc(size)))
228                 return -ENOMEM;
229         memset(buf, 0, size);
230
231         fd = creat(new_file, S_IRUSR|S_IWUSR);
232         if(fd == -1) {
233                 free(buf);
234                 return -EINVAL;
235         }
236
237         if (write(fd, buf, size) < size)
238                 r = -EIO;
239
240         close(fd);
241         free(buf);
242         return r;
243 }
244
245 static int write_log(void)
246 {
247         static char buf[512];
248         ssize_t r;
249
250         //log_dbg("Updating LUKS reencryption log offset %" PRIu64 ".", offset);
251         memset(buf, 0, sizeof(buf));
252         snprintf(buf, sizeof(buf), "# LUKS reencryption log, DO NOT EDIT OR DELETE.\n"
253                 "version = %d\nUUID = %s\ndirection = %d\n"
254                 "offset = %" PRIu64 "\nshift = %" PRIu64 "\n# EOF\n",
255                 1, rnc.device_uuid, rnc.reencrypt_direction,
256                 rnc.device_offset, rnc.device_shift);
257
258         lseek(rnc.log_fd, 0, SEEK_SET);
259         r = write(rnc.log_fd, buf, sizeof(buf));
260         if (r < 0 || r != sizeof(buf))
261                 return -EIO;
262
263         return 0;
264 }
265
266 static int parse_line_log(const char *line)
267 {
268         uint64_t u64;
269         int i;
270         char s[64];
271
272         /* comment */
273         if (*line == '#')
274                 return 0;
275
276         if (sscanf(line, "version = %d", &i) == 1) {
277                 if (i != 1) {
278                         log_dbg("Log: Unexpected version = %i", i);
279                         return -EINVAL;
280                 }
281         } else if (sscanf(line, "UUID = %40s", s) == 1) {
282                 if (!rnc.device_uuid || strcmp(rnc.device_uuid, s)) {
283                         log_dbg("Log: Unexpected UUID %s", s);
284                         return -EINVAL;
285                 }
286         } else if (sscanf(line, "direction = %d", &i) == 1) {
287                 log_dbg("Log: direction = %i", i);
288                 rnc.reencrypt_direction = i;
289         } else if (sscanf(line, "offset = %" PRIu64, &u64) == 1) {
290                 log_dbg("Log: offset = %" PRIu64, u64);
291                 rnc.device_offset = u64;
292         } else if (sscanf(line, "shift = %" PRIu64, &u64) == 1) {
293                 log_dbg("Log: shift = %" PRIu64, u64);
294                 rnc.device_shift = u64;
295         } else
296                 return -EINVAL;
297
298         return 0;
299 }
300
301 static int parse_log(void)
302 {
303         static char buf[512];
304         char *start, *end;
305         ssize_t s;
306
307         s = read(rnc.log_fd, buf, sizeof(buf));
308         if (s == -1)
309                 return -EIO;
310
311         buf[511] = '\0';
312         start = buf;
313         do {
314                 end = strchr(start, '\n');
315                 if (end) {
316                         *end++ = '\0';
317                         if (parse_line_log(start)) {
318                                 log_err("Wrong log format.\n");
319                                 return -EINVAL;
320                         }
321                 }
322
323                 start = end;
324         } while (start);
325
326         return 0;
327 }
328
329 static int open_log(void)
330 {
331         struct stat st;
332
333         if(stat(rnc.log_file, &st) < 0) {
334                 log_dbg("Creating LUKS reencryption log file %s.", rnc.log_file);
335
336                 // FIXME: move that somewhere else
337                 rnc.reencrypt_direction = BACKWARD;
338
339                 rnc.log_fd = open(rnc.log_file, O_RDWR|O_CREAT|O_DIRECT, S_IRUSR|S_IWUSR);
340                 if (rnc.log_fd == -1)
341                         return -EINVAL;
342                 if (write_log() < 0)
343                         return -EIO;
344         } else {
345                 log_dbg("Log file %s exists, restarting.", rnc.log_file);
346                 rnc.log_fd = open(rnc.log_file, O_RDWR|O_DIRECT);
347                 if (rnc.log_fd == -1)
348                         return -EINVAL;
349                 rnc.in_progress = 1;
350         }
351
352         /* Be sure it is correct format */
353         return parse_log();
354 }
355
356 static void close_log(void)
357 {
358         log_dbg("Closing LUKS reencryption log file %s.", rnc.log_file);
359         if (rnc.log_fd != -1)
360                 close(rnc.log_fd);
361 }
362
363 static int activate_luks_headers(void)
364 {
365         struct crypt_device *cd = NULL, *cd_new = NULL;
366         int r;
367
368         log_dbg("Activating LUKS devices from headers.");
369
370         if ((r = crypt_init(&cd, rnc.header_file_org)) ||
371             (r = crypt_load(cd, CRYPT_LUKS1, NULL)) ||
372             (r = crypt_set_data_device(cd, rnc.device)))
373                 goto out;
374
375         if ((r = crypt_activate_by_passphrase(cd, rnc.header_file_org,
376                 CRYPT_ANY_SLOT, rnc.password, rnc.passwordLen,
377                 CRYPT_ACTIVATE_READONLY|CRYPT_ACTIVATE_PRIVATE)) < 0)
378                 goto out;
379
380         if ((r = crypt_init(&cd_new, rnc.header_file_new)) ||
381             (r = crypt_load(cd_new, CRYPT_LUKS1, NULL)) ||
382             (r = crypt_set_data_device(cd_new, rnc.device)))
383                 goto out;
384
385         if ((r = crypt_activate_by_passphrase(cd_new, rnc.header_file_new,
386                 CRYPT_ANY_SLOT, rnc.password, rnc.passwordLen,
387                 CRYPT_ACTIVATE_SHARED|CRYPT_ACTIVATE_PRIVATE)) < 0)
388                 goto out;
389 out:
390         crypt_free(cd);
391         crypt_free(cd_new);
392         return r;
393 }
394
395 static int backup_luks_headers(void)
396 {
397         struct crypt_device *cd = NULL, *cd_new = NULL;
398         struct crypt_params_luks1 params = {0};
399         char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
400         int r;
401
402         log_dbg("Creating LUKS header backup for device %s.", rnc.device);
403         if ((r = crypt_init(&cd, rnc.device)) ||
404             (r = crypt_load(cd, CRYPT_LUKS1, NULL)))
405                 goto out;
406
407         crypt_set_confirm_callback(cd, NULL, NULL);
408         if ((r = crypt_header_backup(cd, CRYPT_LUKS1, rnc.header_file_org)))
409                 goto out;
410
411         if ((r = create_empty_header(rnc.header_file_new,
412                                      crypt_get_data_offset(cd) * 512)))
413                 goto out;
414
415         params.hash = opt_hash ?: DEFAULT_LUKS1_HASH;
416         params.data_alignment = crypt_get_data_offset(cd);
417         params.data_device = rnc.device;
418
419         if ((r = crypt_init(&cd_new, rnc.header_file_new)))
420                 goto out;
421
422         if (opt_random)
423                 crypt_set_rng_type(cd_new, CRYPT_RNG_RANDOM);
424         else if (opt_urandom)
425                 crypt_set_rng_type(cd_new, CRYPT_RNG_URANDOM);
426
427         if (opt_iteration_time)
428                 crypt_set_iteration_time(cd_new, opt_iteration_time);
429
430         if (opt_cipher) {
431                 r = crypt_parse_name_and_mode(opt_cipher, cipher, NULL, cipher_mode);
432                 if (r < 0) {
433                         log_err(_("No known cipher specification pattern detected.\n"));
434                         goto out;
435                 }
436         }
437
438         if ((r = crypt_format(cd_new, CRYPT_LUKS1,
439                         opt_cipher ? cipher : crypt_get_cipher(cd),
440                         opt_cipher ? cipher_mode : crypt_get_cipher_mode(cd),
441                         crypt_get_uuid(cd),
442                         NULL, crypt_get_volume_key_size(cd), &params)))
443                 goto out;
444
445         if ((r = crypt_keyslot_add_by_volume_key(cd_new, rnc.keyslot,
446                                 NULL, 0, rnc.password, rnc.passwordLen)) < 0)
447                 goto out;
448
449 out:
450         crypt_free(cd);
451         crypt_free(cd_new);
452         return r;
453 }
454
455 static void remove_headers(void)
456 {
457         struct crypt_device *cd = NULL;
458
459         if (crypt_init(&cd, NULL))
460                 return;
461         crypt_set_log_callback(cd, _quiet_log, NULL);
462         (void)crypt_deactivate(cd, rnc.header_file_org);
463         (void)crypt_deactivate(cd, rnc.header_file_new);
464         crypt_free(cd);
465 }
466
467 static int restore_luks_header(const char *backup)
468 {
469         struct crypt_device *cd = NULL;
470         int r;
471
472         r = crypt_init(&cd, rnc.device);
473
474         if (r == 0) {
475                 crypt_set_confirm_callback(cd, NULL, NULL);
476                 r = crypt_header_restore(cd, CRYPT_LUKS1, backup);
477         }
478
479         crypt_free(cd);
480         return r;
481 }
482
483 static int copy_data_forward(int fd_old, int fd_new, size_t block_size, void *buf)
484 {
485         ssize_t s1, s2;
486         int j;
487
488         log_err("Reencrypting [");
489         j = 0;
490         while (rnc.device_offset < rnc.device_size) {
491                 s1 = read(fd_old, buf, block_size);
492                 if (s1 < 0 || (s1 != block_size && (rnc.device_offset + s1) != rnc.device_size)) {
493                         log_err("Read error, expecting %d, got %d.\n", (int)block_size, (int)s1);
494                         return -EIO;
495                 }
496                 s2 = write(fd_new, buf, s1);
497                 if (s2 < 0) {
498                         log_err("Write error, expecting %d, got %d.\n", (int)block_size, (int)s2);
499                         return -EIO;
500                 }
501                 rnc.device_offset += s1;
502                 if (write_log() < 0) {
503                         log_err("Log write error, some data are perhaps lost.\n");
504                         return -EIO;
505                 }
506
507                 if (rnc.device_offset > (j * (rnc.device_size / 10))) {
508                         log_err("-");
509                         j++;
510                 }
511         }
512         log_err("] Done.\n");
513
514         return 0;
515 }
516
517 static int copy_data_backward(int fd_old, int fd_new, size_t block_size, void *buf)
518 {
519         ssize_t s1, s2, working_offset, working_block;
520         int j;
521
522         log_err("Reencrypting [");
523         j = 10;
524
525         while (rnc.device_offset) {
526                 if (rnc.device_offset < block_size) {
527                         working_offset = 0;
528                         working_block = rnc.device_offset;
529                 } else {
530                         working_offset = rnc.device_offset - block_size;
531                         working_block = block_size;
532                 }
533
534                 if (lseek(fd_old, working_offset, SEEK_SET) < 0 ||
535                     lseek(fd_new, working_offset, SEEK_SET) < 0)
536                         return -EIO;
537 //log_err("off: %06d, size %06d\n", working_offset, block_size);
538
539                 s1 = read(fd_old, buf, working_block);
540                 if (s1 < 0 || (s1 != working_block)) {
541                         log_err("Read error, expecting %d, got %d.\n", (int)block_size, (int)s1);
542                         return -EIO;
543                 }
544                 s2 = write(fd_new, buf, working_block);
545                 if (s2 < 0) {
546                         log_err("Write error, expecting %d, got %d.\n", (int)block_size, (int)s2);
547                         return -EIO;
548                 }
549                 rnc.device_offset -= s1;
550                 if (write_log() < 0) {
551                         log_err("Log write error, some data are perhaps lost.\n");
552                         return -EIO;
553                 }
554
555                 if (rnc.device_offset < (j * (rnc.device_size / 10))) {
556                         log_err("-");
557                         j--;
558                 }
559         }
560         log_err("] Done.\n");
561
562         return 0;
563 }
564
565 static int copy_data(void)
566 {
567         size_t block_size = opt_bsize * 1024 * 1024;
568         int fd_old = -1, fd_new = -1;
569         int r = -EINVAL;
570         void *buf = NULL;
571
572         fd_old = open(rnc.crypt_path_org, O_RDONLY | O_DIRECT);
573         if (fd_old == -1)
574                 goto out;
575
576         fd_new = open(rnc.crypt_path_new, O_WRONLY | O_DIRECT);
577         if (fd_new == -1)
578                 goto out;
579
580         if (lseek(fd_old, rnc.device_offset, SEEK_SET) == -1)
581                 goto out;
582
583         if (lseek(fd_new, rnc.device_offset, SEEK_SET) == -1)
584                 goto out;
585
586         /* Check size */
587         if (ioctl(fd_old, BLKGETSIZE64, &rnc.device_size) < 0)
588                 goto out;
589
590         if (posix_memalign((void *)&buf, alignment(fd_new), block_size)) {
591                 r = -ENOMEM;
592                 goto out;
593         }
594
595         // FIXME: all this should be in init
596         if (!rnc.in_progress && rnc.reencrypt_direction == BACKWARD)
597                 rnc.device_offset = rnc.device_size;
598
599         if (rnc.reencrypt_direction == FORWARD)
600                 r = copy_data_forward(fd_old, fd_new, block_size, buf);
601         else
602                 r = copy_data_backward(fd_old, fd_new, block_size, buf);
603
604         if (r < 0)
605                 log_err("ERROR during reencryption.\n");
606 out:
607         if (fd_old != -1)
608                 close(fd_old);
609         if (fd_new != -1)
610                 close(fd_new);
611         free(buf);
612         return r;
613 }
614
615 static int initialize_uuid(void)
616 {
617         struct crypt_device *cd = NULL;
618         int r;
619
620         /* Try to load LUKS from device */
621         if ((r = crypt_init(&cd, rnc.device)))
622                 return r;
623         crypt_set_log_callback(cd, _quiet_log, NULL);
624         r = crypt_load(cd, CRYPT_LUKS1, NULL);
625         if (!r)
626                 rnc.device_uuid = strdup(crypt_get_uuid(cd));
627         else
628                 /* Reencryption already in progress - magic header? */
629                 r = device_magic(CHECK_UNUSABLE);
630
631         crypt_free(cd);
632         return r;
633 }
634
635 static int initialize_passphrase(const char *device)
636 {
637         struct crypt_device *cd = NULL;
638         int r;
639
640         if ((r = crypt_init(&cd, device)) ||
641             (r = crypt_load(cd, CRYPT_LUKS1, NULL)) ||
642             (r = crypt_set_data_device(cd, rnc.device)))
643                 goto out;
644
645         if ((r = crypt_get_key(_("Enter LUKS passphrase: "),
646                           &rnc.password, &rnc.passwordLen,
647                           0, 0, opt_key_file,
648                           0, 0, cd)) <0)
649                 goto out;
650
651         if ((r = crypt_activate_by_passphrase(cd, NULL,
652                 CRYPT_ANY_SLOT, rnc.password, rnc.passwordLen, 0) < 0))
653                 goto out;
654
655         if (r >= 0) {
656                 rnc.keyslot = r;
657                 r = 0;
658         }
659 out:
660         crypt_free(cd);
661         return r;
662 }
663
664 static int initialize_context(const char *device)
665 {
666         log_dbg("Initialising reencryption context.");
667
668         rnc.log_fd =-1;
669
670         if (!(rnc.device = strndup(device, PATH_MAX)))
671                 return -ENOMEM;
672 /*
673         if (opt_new_file && !create_uuid()) {
674                 log_err("Cannot create fake header.\n");
675                 return -EINVAL;
676         }
677 */
678         if (initialize_uuid()) {
679                 log_err("No header found on device.\n");
680                 return -EINVAL;
681         }
682
683         /* Prepare device names */
684         if (snprintf(rnc.log_file, PATH_MAX,
685                      "LUKS-%s.log", rnc.device_uuid) < 0)
686                 return -ENOMEM;
687         if (snprintf(rnc.header_file_org, PATH_MAX,
688                      "LUKS-%s.org", rnc.device_uuid) < 0)
689                 return -ENOMEM;
690         if (snprintf(rnc.header_file_new, PATH_MAX,
691                      "LUKS-%s.new", rnc.device_uuid) < 0)
692                 return -ENOMEM;
693
694         /* Paths to encrypted devices */
695         if (snprintf(rnc.crypt_path_org, PATH_MAX,
696                      "%s/%s", crypt_get_dir(), rnc.header_file_org) < 0)
697                 return -ENOMEM;
698         if (snprintf(rnc.crypt_path_new, PATH_MAX,
699                      "%s/%s", crypt_get_dir(), rnc.header_file_new) < 0)
700                 return -ENOMEM;
701
702         remove_headers();
703
704         /* Block ctrl+c */
705         // FIXME: add some routine to handle it
706         sigemptyset(&signals_open);
707         sigaddset(&signals_open, SIGINT);
708         sigprocmask(SIG_SETMASK, &signals_open, NULL);
709
710         return open_log();
711 }
712
713 static void destroy_context(void)
714 {
715         log_dbg("Destroying reencryption context.");
716
717         close_log();
718         remove_headers();
719
720         if ((rnc.reencrypt_direction == FORWARD &&
721              rnc.device_offset == rnc.device_size) ||
722              rnc.device_offset == 0) {
723                 unlink(rnc.log_file);
724                 unlink(rnc.header_file_org);
725                 unlink(rnc.header_file_new);
726         }
727
728         crypt_safe_free(rnc.password);
729
730         free(rnc.device);
731         free(rnc.device_uuid);
732
733         sigprocmask(SIG_UNBLOCK, &signals_open, NULL);
734 }
735
736 int run_reencrypt(const char *device)
737 {
738         int r = -EINVAL;
739
740         if (initialize_context(device))
741                 goto out;
742
743         log_dbg("Running reencryption.");
744
745         if (!rnc.in_progress) {
746                 if ((r = initialize_passphrase(rnc.device)) ||
747                     (r = backup_luks_headers()) ||
748                     (r = device_magic(MAKE_UNUSABLE)))
749                         goto out;
750         } else {
751                 if ((r = initialize_passphrase(rnc.header_file_org)))
752                         goto out;
753         }
754
755         if ((r = activate_luks_headers()))
756                 goto out;
757
758         if ((r = copy_data()))
759                 goto out;
760
761         r = restore_luks_header(rnc.header_file_new);
762 out:
763         destroy_context();
764         return r;
765 }
766
767 static __attribute__ ((noreturn)) void usage(poptContext popt_context,
768                                              int exitcode, const char *error,
769                                              const char *more)
770 {
771         poptPrintUsage(popt_context, stderr, 0);
772         if (error)
773                 log_err("%s: %s\n", more, error);
774         poptFreeContext(popt_context);
775         exit(exitcode);
776 }
777
778 static void help(poptContext popt_context,
779                  enum poptCallbackReason reason __attribute__((unused)),
780                  struct poptOption *key,
781                  const char *arg __attribute__((unused)),
782                  void *data __attribute__((unused)))
783 {
784         usage(popt_context, EXIT_SUCCESS, NULL, NULL);
785 }
786
787 static void _dbg_version_and_cmd(int argc, const char **argv)
788 {
789         int i;
790
791         log_std("# %s %s processing \"", PACKAGE_NAME, PACKAGE_VERSION);
792         for (i = 0; i < argc; i++) {
793                 if (i)
794                         log_std(" ");
795                 log_std("%s", argv[i]);
796         }
797         log_std("\"\n");
798 }
799
800 int main(int argc, const char **argv)
801 {
802         static struct poptOption popt_help_options[] = {
803                 { NULL,    '\0', POPT_ARG_CALLBACK, help, 0, NULL,                         NULL },
804                 { "help",  '?',  POPT_ARG_NONE,     NULL, 0, N_("Show this help message"), NULL },
805                 { "usage", '\0', POPT_ARG_NONE,     NULL, 0, N_("Display brief usage"),    NULL },
806                 POPT_TABLEEND
807         };
808         static struct poptOption popt_options[] = {
809                 { NULL,                '\0', POPT_ARG_INCLUDE_TABLE, popt_help_options, 0, N_("Help options:"), NULL },
810                 { "version",           '\0', POPT_ARG_NONE, &opt_version_mode,          0, N_("Print package version"), NULL },
811                 { "verbose",           'v',  POPT_ARG_NONE, &opt_verbose,               0, N_("Shows more detailed error messages"), NULL },
812                 { "debug",             '\0', POPT_ARG_NONE, &opt_debug,                 0, N_("Show debug messages"), NULL },
813                 { "block-size",        'B',  POPT_ARG_INT, &opt_bsize,                  0, N_("Reencryption block size"), N_("MB") },
814                 { "new-header",        'N',  POPT_ARG_INT, &opt_new,                    0, N_("Create new header, need size on the end of device"), N_("MB") },
815                 { "new-crypt",         'f',  POPT_ARG_STRING, &opt_new_file,            0, N_("Log suffix for new reencryption file."), NULL },
816                 { "cipher",            'c',  POPT_ARG_STRING, &opt_cipher,              0, N_("The cipher used to encrypt the disk (see /proc/crypto)"), NULL },
817                 { "hash",              'h',  POPT_ARG_STRING, &opt_hash,                0, N_("The hash used to create the encryption key from the passphrase"), NULL },
818                 { "key-file",          'd',  POPT_ARG_STRING, &opt_key_file,            0, N_("Read the key from a file."), NULL },
819                 { "iter-time",         'i',  POPT_ARG_INT, &opt_iteration_time,         0, N_("PBKDF2 iteration time for LUKS (in ms)"), N_("msecs") },
820                 { "batch-mode",        'q',  POPT_ARG_NONE, &opt_batch_mode,            0, N_("Do not ask for confirmation"), NULL },
821                 { "use-random",        '\0', POPT_ARG_NONE, &opt_random,                0, N_("Use /dev/random for generating volume key."), NULL },
822                 { "use-urandom",       '\0', POPT_ARG_NONE, &opt_urandom,               0, N_("Use /dev/urandom for generating volume key."), NULL },
823                 POPT_TABLEEND
824         };
825         poptContext popt_context;
826         int r;
827
828         crypt_set_log_callback(NULL, _log, NULL);
829         log_err("WARNING: this is experimental code, it can completely break your data.\n");
830
831         setlocale(LC_ALL, "");
832         bindtextdomain(PACKAGE, LOCALEDIR);
833         textdomain(PACKAGE);
834
835         popt_context = poptGetContext(PACKAGE, argc, argv, popt_options, 0);
836         poptSetOtherOptionHelp(popt_context,
837                                N_("[OPTION...] <device>]"));
838
839         while((r = poptGetNextOpt(popt_context)) > 0) {
840                 if (r < 0)
841                         break;
842         }
843
844         if (r < -1)
845                 usage(popt_context, EXIT_FAILURE, poptStrerror(r),
846                       poptBadOption(popt_context, POPT_BADOPTION_NOALIAS));
847         if (opt_version_mode) {
848                 log_std("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
849                 poptFreeContext(popt_context);
850                 exit(EXIT_SUCCESS);
851         }
852
853         action_argv = poptGetArgs(popt_context);
854         if(!action_argv)
855                 usage(popt_context, EXIT_FAILURE, _("Argument required."),
856                       poptGetInvocationName(popt_context));
857
858         if (opt_random && opt_urandom)
859                 usage(popt_context, EXIT_FAILURE, _("Only one of --use-[u]random options is allowed."),
860                       poptGetInvocationName(popt_context));
861
862         if (opt_new && !opt_new_file)
863                 usage(popt_context, EXIT_FAILURE, _("You have to use -f with -N."),
864                       poptGetInvocationName(popt_context));
865
866         if (opt_debug) {
867                 opt_verbose = 1;
868                 crypt_set_debug_level(-1);
869                 _dbg_version_and_cmd(argc, argv);
870         }
871
872         r = run_reencrypt(action_argv[0]);
873
874         poptFreeContext(popt_context);
875
876         /* Translate exit code to simple codes */
877         switch (r) {
878         case 0:         r = EXIT_SUCCESS; break;
879         case -EEXIST:
880         case -EBUSY:    r = 5; break;
881         case -ENOTBLK:
882         case -ENODEV:   r = 4; break;
883         case -ENOMEM:   r = 3; break;
884         case -EPERM:    r = 2; break;
885         case -EINVAL:
886         case -ENOENT:
887         case -ENOSYS:
888         default:        r = EXIT_FAILURE;
889         }
890         return r;
891 }