10d9ba1e1SAlex Hornung /*
20d9ba1e1SAlex Hornung * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
30d9ba1e1SAlex Hornung * All rights reserved.
40d9ba1e1SAlex Hornung *
50d9ba1e1SAlex Hornung * Redistribution and use in source and binary forms, with or without
60d9ba1e1SAlex Hornung * modification, are permitted provided that the following conditions
70d9ba1e1SAlex Hornung * are met:
80d9ba1e1SAlex Hornung *
90d9ba1e1SAlex Hornung * 1. Redistributions of source code must retain the above copyright
100d9ba1e1SAlex Hornung * notice, this list of conditions and the following disclaimer.
110d9ba1e1SAlex Hornung * 2. Redistributions in binary form must reproduce the above copyright
120d9ba1e1SAlex Hornung * notice, this list of conditions and the following disclaimer in
130d9ba1e1SAlex Hornung * the documentation and/or other materials provided with the
140d9ba1e1SAlex Hornung * distribution.
150d9ba1e1SAlex Hornung *
160d9ba1e1SAlex Hornung * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
170d9ba1e1SAlex Hornung * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
180d9ba1e1SAlex Hornung * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
190d9ba1e1SAlex Hornung * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
200d9ba1e1SAlex Hornung * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
210d9ba1e1SAlex Hornung * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
220d9ba1e1SAlex Hornung * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
230d9ba1e1SAlex Hornung * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
240d9ba1e1SAlex Hornung * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
250d9ba1e1SAlex Hornung * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
260d9ba1e1SAlex Hornung * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
270d9ba1e1SAlex Hornung * SUCH DAMAGE.
280d9ba1e1SAlex Hornung */
2981b79547SAlex Hornung
300d9ba1e1SAlex Hornung #include <sys/types.h>
310d9ba1e1SAlex Hornung #include <getopt.h>
320d9ba1e1SAlex Hornung #include <stdio.h>
330d9ba1e1SAlex Hornung #include <stdlib.h>
3481b79547SAlex Hornung #include <inttypes.h>
350d9ba1e1SAlex Hornung #include <errno.h>
360d9ba1e1SAlex Hornung #include <string.h>
370d9ba1e1SAlex Hornung #include <signal.h>
380d9ba1e1SAlex Hornung #include <time.h>
390d9ba1e1SAlex Hornung
400d9ba1e1SAlex Hornung #include "tcplay.h"
410d9ba1e1SAlex Hornung
4281b79547SAlex Hornung #ifndef SIGINFO
4381b79547SAlex Hornung #define SIGINFO SIGUSR1
4481b79547SAlex Hornung #endif
4581b79547SAlex Hornung
46c833cfcfSAlex Hornung #define FLAG_LONG_FDE 0xff01
47c833cfcfSAlex Hornung #define FLAG_LONG_USE_BACKUP 0xff02
48c833cfcfSAlex Hornung #define FLAG_LONG_MOD 0xff04
49c833cfcfSAlex Hornung #define FLAG_LONG_MOD_KF 0xff08
50c833cfcfSAlex Hornung #define FLAG_LONG_MOD_PRF 0xff10
51c833cfcfSAlex Hornung #define FLAG_LONG_MOD_NONE 0xff20
52c833cfcfSAlex Hornung #define FLAG_LONG_MOD_TO_FILE 0xff40
53c833cfcfSAlex Hornung #define FLAG_LONG_USE_HDR_FILE 0xfe01
54c833cfcfSAlex Hornung #define FLAG_LONG_USE_HHDR_FILE 0xfe02
55c833cfcfSAlex Hornung #define FLAG_LONG_NO_RETRIES 0xfabc
56c833cfcfSAlex Hornung
57c833cfcfSAlex Hornung
580d9ba1e1SAlex Hornung static
590d9ba1e1SAlex Hornung void
sig_handler(int sig)600d9ba1e1SAlex Hornung sig_handler(int sig)
610d9ba1e1SAlex Hornung {
620d9ba1e1SAlex Hornung if ((sig == SIGUSR1 || sig == SIGINFO) && (summary_fn != NULL))
630d9ba1e1SAlex Hornung summary_fn();
640d9ba1e1SAlex Hornung }
650d9ba1e1SAlex Hornung
660d9ba1e1SAlex Hornung static
670d9ba1e1SAlex Hornung void
usage(void)680d9ba1e1SAlex Hornung usage(void)
690d9ba1e1SAlex Hornung {
700d9ba1e1SAlex Hornung fprintf(stderr,
71c833cfcfSAlex Hornung "usage: tcplay -c -d device [-g] [-z] [-w] [-a pbkdf_hash] [-b cipher]\n"
7289e181b5SThomas Nikolajsen " [-f keyfile_hidden] [-k keyfile] [-x pbkdf_hash] [-y cipher]\n"
73*7b1e1c8eSDaniel Fojt " tcplay -i -d device [-e] [-p] [-f keyfile_hidden] [-k keyfile]\n"
74c833cfcfSAlex Hornung " [-s system_device] [--fde] [--use-backup]\n"
75c833cfcfSAlex Hornung " [--use-hdr-file=hdr_file] [--use-hidden-hdr-file=hdr_file]\n"
76*7b1e1c8eSDaniel Fojt " tcplay -m mapping -d device [-e] [-p] [-f keyfile_hidden] [-k keyfile]\n"
77c833cfcfSAlex Hornung " [-s system_device] [--fde] [--use-backup] [--allow-trim]\n"
78c833cfcfSAlex Hornung " [--use-hdr-file=hdr_file] [--use-hidden-hdr-file=hdr_file]\n"
79c833cfcfSAlex Hornung " tcplay --modify -d device [-k keyfile] [--new-keyfile=keyfile]\n"
80c833cfcfSAlex Hornung " [--new-pbkdf-prf=pbkdf_hash] [-s system_device] [--fde]\n"
81c833cfcfSAlex Hornung " [--use-backup] [--save-hdr-to-file=hdr_file] [-w]\n"
82c833cfcfSAlex Hornung " [--use-hdr-file=hdr_file] [--use-hidden-hdr-file=hdr_file]\n"
83c833cfcfSAlex Hornung " tcplay --modify -d device [-k keyfile] --restore-from-backup-hdr [-w]\n"
84c833cfcfSAlex Hornung " tcplay -j mapping\n"
85c833cfcfSAlex Hornung " tcplay -u mapping\n"
8689e181b5SThomas Nikolajsen " tcplay -h | -v\n"
8789e181b5SThomas Nikolajsen "\n"
8889e181b5SThomas Nikolajsen "Valid commands are:\n"
890d9ba1e1SAlex Hornung " -c, --create\n"
9089e181b5SThomas Nikolajsen "\t Creates a new TC volume on the device specified by -d or --device.\n"
9189e181b5SThomas Nikolajsen " -h, --help\n"
9289e181b5SThomas Nikolajsen "\t Print help message and exit.\n"
930d9ba1e1SAlex Hornung " -i, --info\n"
9489e181b5SThomas Nikolajsen "\t Gives information about the TC volume specified by -d or --device.\n"
95c833cfcfSAlex Hornung " -j <mapping name>, --info-mapped=<mapping name>\n"
96c833cfcfSAlex Hornung "\t Gives information about the mapped TC volume under the given mapping.\n"
970d9ba1e1SAlex Hornung " -m <mapping name>, --map=<mapping name>\n"
980d9ba1e1SAlex Hornung "\t Creates a dm-crypt mapping with the given name for the device\n"
9989e181b5SThomas Nikolajsen "\t specified by -d or --device.\n"
100c833cfcfSAlex Hornung " -u <mapping name>, --unmap=<mapping name>\n"
101c833cfcfSAlex Hornung "\t Removes a dm-crypt mapping with the given name.\n"
102c833cfcfSAlex Hornung " --modify\n"
103c833cfcfSAlex Hornung "\t Changes the volume's passphrase, keyfile and optionally the hashing\n"
104c833cfcfSAlex Hornung "\t function used for the PBKDF password derivation.\n"
10589e181b5SThomas Nikolajsen " -v, --version\n"
10689e181b5SThomas Nikolajsen "\t Print version message and exit.\n"
1070d9ba1e1SAlex Hornung "\n"
10889e181b5SThomas Nikolajsen "Valid options for --create are:\n"
1090d9ba1e1SAlex Hornung " -a <pbkdf prf algorithm>, --pbkdf-prf=<pbkdf prf algorithm>\n"
11089e181b5SThomas Nikolajsen "\t Specifies which hashing function to use for the PBKDF password\n"
11189e181b5SThomas Nikolajsen "\t derivation when creating a new volume.\n"
11289e181b5SThomas Nikolajsen "\t To see valid options, specify '-a help'.\n"
1130d9ba1e1SAlex Hornung " -b <cipher>, --cipher=<cipher>\n"
11489e181b5SThomas Nikolajsen "\t Specifies which cipher to use when creating a new TC volume.\n"
11589e181b5SThomas Nikolajsen "\t To see valid options, specify '-b help'.\n"
1160d9ba1e1SAlex Hornung " -g, --hidden\n"
11789e181b5SThomas Nikolajsen "\t Specifies that the newly created volume will contain a hidden volume.\n"
11889e181b5SThomas Nikolajsen " -x <pbkdf prf algorithm>, --pbkdf-prf=<pbkdf prf algorithm>\n"
11989e181b5SThomas Nikolajsen "\t Specifies which hashing function to use for the PBKDF password\n"
12089e181b5SThomas Nikolajsen "\t derivation when creating a new hidden volume. By default, the\n"
12189e181b5SThomas Nikolajsen "\t same as for the outer volume will be used.\n"
12289e181b5SThomas Nikolajsen "\t To see valid options, specify '-x help'.\n"
12389e181b5SThomas Nikolajsen " -y <cipher>, --cipher=<cipher>\n"
12489e181b5SThomas Nikolajsen "\t Specifies which cipher to use when creating a new hidden volume.\n"
12589e181b5SThomas Nikolajsen "\t By default, the same as for the outer volume will be used.\n"
12689e181b5SThomas Nikolajsen "\t To see valid options, specify '-y help'.\n"
127c833cfcfSAlex Hornung " -z, --insecure-erase\n"
128c833cfcfSAlex Hornung "\t Skips the erase of the disk. Possible security hazard.\n"
129c833cfcfSAlex Hornung " -w, --weak-keys\n"
130c833cfcfSAlex Hornung "\t Uses a weak source of entropy (urandom) for key material.\n"
131c833cfcfSAlex Hornung "\t WARNING: This is a REALLY REALLY bad idea for anything but\n"
132c833cfcfSAlex Hornung "\t testing.\n"
133c833cfcfSAlex Hornung "\n"
134c833cfcfSAlex Hornung "Valid options for --modify are:\n"
135c833cfcfSAlex Hornung " --new-keyfile=<key file>\n"
136c833cfcfSAlex Hornung "\t Specifies a key file to use for the password derivation, when\n"
137c833cfcfSAlex Hornung "\t re-encrypting the header, can appear multiple times.\n"
138c833cfcfSAlex Hornung " --new-pbkdf-prf=<pbkdf prf algorithm>\n"
139c833cfcfSAlex Hornung "\t Specifies which hashing function to use for the PBKDF password\n"
140c833cfcfSAlex Hornung "\t derivation when re-encrypting the header.\n"
141c833cfcfSAlex Hornung "\t To see valid options, specify '-a help'.\n"
142c833cfcfSAlex Hornung " -s <disk path>, --system-encryption=<disk path>\n"
143c833cfcfSAlex Hornung "\t Specifies that the disk (e.g. /dev/da0) is using system encryption.\n"
144c833cfcfSAlex Hornung " --fde\n"
145c833cfcfSAlex Hornung "\t Specifies that the disk (e.g. /dev/da0) is using full disk encryption.\n"
146c833cfcfSAlex Hornung " --use-backup\n"
147c833cfcfSAlex Hornung "\t Uses the backup headers (at the end of the volume) instead of the\n"
148c833cfcfSAlex Hornung "\t primary headers. Both normal and backup headers will be modified!\n"
149c833cfcfSAlex Hornung "\t This is useful when your primary headers have been corrupted.\n"
150c833cfcfSAlex Hornung " --use-hdr-file=<header file>\n"
151c833cfcfSAlex Hornung "\t Use the header in the specified file instead of the main header on the\n"
152c833cfcfSAlex Hornung "\t disk as source for the modify operation.\n"
153c833cfcfSAlex Hornung " --use-hidden-hdr-file=<header file>\n"
154c833cfcfSAlex Hornung "\t Use the header in the specified file instead of the hidden header on the\n"
155c833cfcfSAlex Hornung "\t disk as source for the modify operation.\n"
156c833cfcfSAlex Hornung " --restore-from-backup-hdr\n"
157c833cfcfSAlex Hornung "\t Implies --use-backup, no new PBKDF hashing function, no new keyfiles\n"
158c833cfcfSAlex Hornung "\t and no new passphrase.\n"
159c833cfcfSAlex Hornung "\t In other words, this will simply restore both headers from the backup\n"
160c833cfcfSAlex Hornung "\t header. This option cannot be used to restore from a backup header file.\n"
161c833cfcfSAlex Hornung " -w, --weak-keys\n"
162c833cfcfSAlex Hornung "\t Uses a weak source of entropy (urandom) for salt material. The\n"
163c833cfcfSAlex Hornung "\t key material is not affected, as the master keys are kept intact.\n"
164c833cfcfSAlex Hornung "\t WARNING: This is a bad idea for anything but testing.\n"
165c833cfcfSAlex Hornung " --save-hdr-backup=<header file>\n"
166c833cfcfSAlex Hornung "\t Saves the modified header in the specified file instead of updating\n"
167c833cfcfSAlex Hornung "\t the header files on disk.\n"
1680d9ba1e1SAlex Hornung "\n"
16989e181b5SThomas Nikolajsen "Valid options for --info and --map are:\n"
1700d9ba1e1SAlex Hornung " -e, --protect-hidden\n"
17189e181b5SThomas Nikolajsen "\t Protect a hidden volume when mounting the outer volume.\n"
172*7b1e1c8eSDaniel Fojt " -p, --prompt-passphrase\n"
173*7b1e1c8eSDaniel Fojt "\t Immediately prompt for a passphrase even if a keyfile is supplied.\n"
1740d9ba1e1SAlex Hornung " -s <disk path>, --system-encryption=<disk path>\n"
17589e181b5SThomas Nikolajsen "\t Specifies that the disk (e.g. /dev/da0) is using system encryption.\n"
176c833cfcfSAlex Hornung " -t, --allow-trim\n"
177c833cfcfSAlex Hornung "\t Allow discards (TRIM command) on mapped volume.\n"
178c833cfcfSAlex Hornung " --fde\n"
179c833cfcfSAlex Hornung "\t Specifies that the disk (e.g. /dev/da0) is using full disk encryption.\n"
180c833cfcfSAlex Hornung " --use-backup\n"
181c833cfcfSAlex Hornung "\t Uses the backup headers (at the end of the volume) instead of the\n"
182c833cfcfSAlex Hornung "\t primary headers.\n"
183c833cfcfSAlex Hornung "\t This is useful when your primary headers have been corrupted.\n"
184c833cfcfSAlex Hornung " --use-hdr-file=<header file>\n"
185c833cfcfSAlex Hornung "\t Use the header in the specified file instead of the main header on the\n"
186c833cfcfSAlex Hornung "\t disk.\n"
187c833cfcfSAlex Hornung " --use-hidden-hdr-file=<header file>\n"
188c833cfcfSAlex Hornung "\t Use the header in the specified file instead of the hidden header on the\n"
189c833cfcfSAlex Hornung "\t disk.\n"
1900d9ba1e1SAlex Hornung "\n"
19189e181b5SThomas Nikolajsen "Valid options common to all commands are:\n"
1920d9ba1e1SAlex Hornung " -d <device path>, --device=<device path>\n"
19389e181b5SThomas Nikolajsen "\t Specifies the path to the volume to operate on (e.g. /dev/da0s1).\n"
1940d9ba1e1SAlex Hornung " -f <key file>, --keyfile-hidden=<key file>\n"
19589e181b5SThomas Nikolajsen "\t Specifies a key file to use for the hidden volume password derivation.\n"
1960d9ba1e1SAlex Hornung "\t This option is only valid in combination with -e, --protect-hidden\n"
19789e181b5SThomas Nikolajsen "\t or -g, --hidden.\n"
19889e181b5SThomas Nikolajsen " -k <key file>, --keyfile=<key file>\n"
19989e181b5SThomas Nikolajsen "\t Specifies a key file to use for the password derivation, can appear\n"
20089e181b5SThomas Nikolajsen "\t multiple times.\n"
2010d9ba1e1SAlex Hornung );
2020d9ba1e1SAlex Hornung
203c833cfcfSAlex Hornung exit(EXIT_FAILURE);
2040d9ba1e1SAlex Hornung }
2050d9ba1e1SAlex Hornung
2060d9ba1e1SAlex Hornung static struct option longopts[] = {
2070d9ba1e1SAlex Hornung { "create", no_argument, NULL, 'c' },
2080d9ba1e1SAlex Hornung { "cipher", required_argument, NULL, 'b' },
2090d9ba1e1SAlex Hornung { "cipher-hidden", required_argument, NULL, 'y' },
2100d9ba1e1SAlex Hornung { "hidden", no_argument, NULL, 'g' },
2110d9ba1e1SAlex Hornung { "pbkdf-prf", required_argument, NULL, 'a' },
2120d9ba1e1SAlex Hornung { "pbkdf-prf-hidden", required_argument, NULL, 'x' },
2130d9ba1e1SAlex Hornung { "info", no_argument, NULL, 'i' },
214c833cfcfSAlex Hornung { "info-mapped", required_argument, NULL, 'j' },
2150d9ba1e1SAlex Hornung { "map", required_argument, NULL, 'm' },
2160d9ba1e1SAlex Hornung { "keyfile", required_argument, NULL, 'k' },
2170d9ba1e1SAlex Hornung { "keyfile-hidden", required_argument, NULL, 'f' },
2180d9ba1e1SAlex Hornung { "protect-hidden", no_argument, NULL, 'e' },
2190d9ba1e1SAlex Hornung { "device", required_argument, NULL, 'd' },
220*7b1e1c8eSDaniel Fojt { "prompt-passphrase", no_argument, NULL, 'p' },
2210d9ba1e1SAlex Hornung { "system-encryption", required_argument, NULL, 's' },
222c833cfcfSAlex Hornung { "allow-trim", no_argument, NULL, 't' },
223c833cfcfSAlex Hornung { "fde", no_argument, NULL, FLAG_LONG_FDE },
224c833cfcfSAlex Hornung { "use-backup", no_argument, NULL, FLAG_LONG_USE_BACKUP },
225c833cfcfSAlex Hornung { "use-hdr-file", required_argument, NULL, FLAG_LONG_USE_HDR_FILE },
226c833cfcfSAlex Hornung { "use-hidden-hdr-file",required_argument, NULL, FLAG_LONG_USE_HHDR_FILE },
227c833cfcfSAlex Hornung { "modify", no_argument, NULL, FLAG_LONG_MOD },
228c833cfcfSAlex Hornung { "new-keyfile", required_argument, NULL, FLAG_LONG_MOD_KF },
229c833cfcfSAlex Hornung { "new-pbkdf-prf", required_argument, NULL, FLAG_LONG_MOD_PRF },
230c833cfcfSAlex Hornung { "restore-from-backup-hdr", no_argument, NULL, FLAG_LONG_MOD_NONE },
231c833cfcfSAlex Hornung { "save-hdr-backup", required_argument, NULL, FLAG_LONG_MOD_TO_FILE },
232c833cfcfSAlex Hornung { "unmap", required_argument, NULL, 'u' },
2330d9ba1e1SAlex Hornung { "version", no_argument, NULL, 'v' },
234c833cfcfSAlex Hornung { "weak-keys", no_argument, NULL, 'w' },
235c833cfcfSAlex Hornung { "insecure-erase", no_argument, NULL, 'z' },
2360d9ba1e1SAlex Hornung { "help", no_argument, NULL, 'h' },
237c833cfcfSAlex Hornung { "no-retries", no_argument, NULL, FLAG_LONG_NO_RETRIES },
2380d9ba1e1SAlex Hornung { NULL, 0, NULL, 0 },
2390d9ba1e1SAlex Hornung };
2400d9ba1e1SAlex Hornung
241c833cfcfSAlex Hornung #define _set_str_opt(opt) \
242c833cfcfSAlex Hornung do { \
243c833cfcfSAlex Hornung if ((opts->opt = strdup_safe_mem(optarg)) == NULL) { \
244c833cfcfSAlex Hornung fprintf(stderr, "Could not allocate safe mem.\n"); \
245c833cfcfSAlex Hornung exit(EXIT_FAILURE); \
246c833cfcfSAlex Hornung } \
247c833cfcfSAlex Hornung } while(0)
248c833cfcfSAlex Hornung
2490d9ba1e1SAlex Hornung int
main(int argc,char * argv[])2500d9ba1e1SAlex Hornung main(int argc, char *argv[])
2510d9ba1e1SAlex Hornung {
252c833cfcfSAlex Hornung struct tcplay_opts *opts;
2530d9ba1e1SAlex Hornung int ch, error;
254c833cfcfSAlex Hornung int info_vol = 0, map_vol = 0,
255c833cfcfSAlex Hornung unmap_vol = 0, info_map = 0,
256c833cfcfSAlex Hornung create_vol = 0, modify_vol = 0;
2570d9ba1e1SAlex Hornung
2580d9ba1e1SAlex Hornung if ((error = tc_play_init()) != 0) {
2590d9ba1e1SAlex Hornung fprintf(stderr, "Initialization failed, exiting.");
260c833cfcfSAlex Hornung exit(EXIT_FAILURE);
2610d9ba1e1SAlex Hornung }
2620d9ba1e1SAlex Hornung
2630d9ba1e1SAlex Hornung atexit(check_and_purge_safe_mem);
2640d9ba1e1SAlex Hornung signal(SIGUSR1, sig_handler);
2650d9ba1e1SAlex Hornung signal(SIGINFO, sig_handler);
2660d9ba1e1SAlex Hornung
267c833cfcfSAlex Hornung if ((opts = opts_init()) == NULL) {
268c833cfcfSAlex Hornung fprintf(stderr, "Initialization failed (opts), exiting.");
269c833cfcfSAlex Hornung exit(EXIT_FAILURE);
270c833cfcfSAlex Hornung }
2710d9ba1e1SAlex Hornung
272c833cfcfSAlex Hornung opts->interactive = 1;
273c833cfcfSAlex Hornung
274*7b1e1c8eSDaniel Fojt while ((ch = getopt_long(argc, argv, "a:b:cd:ef:ghij:k:m:ps:tu:vwx:y:z",
2750d9ba1e1SAlex Hornung longopts, NULL)) != -1) {
2760d9ba1e1SAlex Hornung switch(ch) {
2770d9ba1e1SAlex Hornung case 'a':
278c833cfcfSAlex Hornung if (opts->prf_algo != NULL)
2790d9ba1e1SAlex Hornung usage();
280*7b1e1c8eSDaniel Fojt if ((opts->prf_algo = check_prf_algo(optarg, 0, 0)) == NULL) {
2810d9ba1e1SAlex Hornung if (strcmp(optarg, "help") == 0)
282c833cfcfSAlex Hornung exit(EXIT_SUCCESS);
2830d9ba1e1SAlex Hornung else
2840d9ba1e1SAlex Hornung usage();
2850d9ba1e1SAlex Hornung /* NOT REACHED */
2860d9ba1e1SAlex Hornung }
2870d9ba1e1SAlex Hornung break;
2880d9ba1e1SAlex Hornung case 'b':
289c833cfcfSAlex Hornung if (opts->cipher_chain != NULL)
2900d9ba1e1SAlex Hornung usage();
291c833cfcfSAlex Hornung if ((opts->cipher_chain = check_cipher_chain(optarg, 0)) == NULL) {
2920d9ba1e1SAlex Hornung if (strcmp(optarg, "help") == 0)
293c833cfcfSAlex Hornung exit(EXIT_SUCCESS);
2940d9ba1e1SAlex Hornung else
2950d9ba1e1SAlex Hornung usage();
2960d9ba1e1SAlex Hornung /* NOT REACHED */
2970d9ba1e1SAlex Hornung }
2980d9ba1e1SAlex Hornung break;
2990d9ba1e1SAlex Hornung case 'c':
3000d9ba1e1SAlex Hornung create_vol = 1;
3010d9ba1e1SAlex Hornung break;
3020d9ba1e1SAlex Hornung case 'd':
303c833cfcfSAlex Hornung _set_str_opt(dev);
3040d9ba1e1SAlex Hornung break;
3050d9ba1e1SAlex Hornung case 'e':
306c833cfcfSAlex Hornung opts->protect_hidden = 1;
3070d9ba1e1SAlex Hornung break;
3080d9ba1e1SAlex Hornung case 'f':
309c833cfcfSAlex Hornung if ((error = opts_add_keyfile_hidden(opts, optarg)) != 0) {
310c833cfcfSAlex Hornung fprintf(stderr, "Could not add keyfile: %s\n", optarg);
311c833cfcfSAlex Hornung exit(EXIT_FAILURE);
312c833cfcfSAlex Hornung }
3130d9ba1e1SAlex Hornung break;
3140d9ba1e1SAlex Hornung case 'g':
315c833cfcfSAlex Hornung opts->hidden = 1;
3160d9ba1e1SAlex Hornung break;
3170d9ba1e1SAlex Hornung case 'i':
3180d9ba1e1SAlex Hornung info_vol = 1;
3190d9ba1e1SAlex Hornung break;
320c833cfcfSAlex Hornung case 'j':
321c833cfcfSAlex Hornung info_map = 1;
322c833cfcfSAlex Hornung _set_str_opt(map_name);
323c833cfcfSAlex Hornung break;
3240d9ba1e1SAlex Hornung case 'k':
325c833cfcfSAlex Hornung if ((error = opts_add_keyfile(opts, optarg)) != 0) {
326c833cfcfSAlex Hornung fprintf(stderr, "Could not add keyfile: %s\n", optarg);
327c833cfcfSAlex Hornung exit(EXIT_FAILURE);
328c833cfcfSAlex Hornung }
3290d9ba1e1SAlex Hornung break;
3300d9ba1e1SAlex Hornung case 'm':
3310d9ba1e1SAlex Hornung map_vol = 1;
332c833cfcfSAlex Hornung _set_str_opt(map_name);
3330d9ba1e1SAlex Hornung break;
334*7b1e1c8eSDaniel Fojt case 'p':
335*7b1e1c8eSDaniel Fojt opts->prompt_passphrase = 1;
336*7b1e1c8eSDaniel Fojt break;
3370d9ba1e1SAlex Hornung case 's':
338c833cfcfSAlex Hornung opts->flags |= TC_FLAG_SYS;
339c833cfcfSAlex Hornung _set_str_opt(sys_dev);
340c833cfcfSAlex Hornung break;
341c833cfcfSAlex Hornung case 't':
342c833cfcfSAlex Hornung opts->flags |= TC_FLAG_ALLOW_TRIM;
343c833cfcfSAlex Hornung break;
344c833cfcfSAlex Hornung case 'u':
345c833cfcfSAlex Hornung unmap_vol = 1;
346c833cfcfSAlex Hornung _set_str_opt(map_name);
3470d9ba1e1SAlex Hornung break;
3480d9ba1e1SAlex Hornung case 'v':
3490d9ba1e1SAlex Hornung printf("tcplay v%d.%d\n", MAJ_VER, MIN_VER);
350c833cfcfSAlex Hornung exit(EXIT_SUCCESS);
3510d9ba1e1SAlex Hornung /* NOT REACHED */
352c833cfcfSAlex Hornung case 'w':
353c833cfcfSAlex Hornung fprintf(stderr, "WARNING: Using urandom as source of "
354c833cfcfSAlex Hornung "entropy for key material is a really bad idea.\n");
355c833cfcfSAlex Hornung opts->weak_keys_and_salt = 1;
356c833cfcfSAlex Hornung break;
3570d9ba1e1SAlex Hornung case 'x':
358c833cfcfSAlex Hornung if (opts->h_prf_algo != NULL)
3590d9ba1e1SAlex Hornung usage();
360*7b1e1c8eSDaniel Fojt if ((opts->h_prf_algo = check_prf_algo(optarg, 0, 0)) == NULL) {
3610d9ba1e1SAlex Hornung if (strcmp(optarg, "help") == 0)
362c833cfcfSAlex Hornung exit(EXIT_SUCCESS);
3630d9ba1e1SAlex Hornung else
3640d9ba1e1SAlex Hornung usage();
3650d9ba1e1SAlex Hornung /* NOT REACHED */
3660d9ba1e1SAlex Hornung }
3670d9ba1e1SAlex Hornung break;
3680d9ba1e1SAlex Hornung case 'y':
369c833cfcfSAlex Hornung if (opts->h_cipher_chain != NULL)
3700d9ba1e1SAlex Hornung usage();
371c833cfcfSAlex Hornung if ((opts->h_cipher_chain = check_cipher_chain(optarg, 0)) == NULL) {
3720d9ba1e1SAlex Hornung if (strcmp(optarg, "help") == 0)
373c833cfcfSAlex Hornung exit(EXIT_SUCCESS);
3740d9ba1e1SAlex Hornung else
3750d9ba1e1SAlex Hornung usage();
3760d9ba1e1SAlex Hornung /* NOT REACHED */
3770d9ba1e1SAlex Hornung }
3780d9ba1e1SAlex Hornung break;
379c833cfcfSAlex Hornung case 'z':
380c833cfcfSAlex Hornung opts->secure_erase = 0;
381c833cfcfSAlex Hornung break;
382c833cfcfSAlex Hornung case FLAG_LONG_FDE:
383c833cfcfSAlex Hornung opts->flags |= TC_FLAG_FDE;
384c833cfcfSAlex Hornung break;
385c833cfcfSAlex Hornung case FLAG_LONG_USE_BACKUP:
386c833cfcfSAlex Hornung opts->flags |= TC_FLAG_BACKUP;
387c833cfcfSAlex Hornung break;
388c833cfcfSAlex Hornung case FLAG_LONG_USE_HDR_FILE:
389c833cfcfSAlex Hornung opts->flags |= TC_FLAG_HDR_FROM_FILE;
390c833cfcfSAlex Hornung _set_str_opt(hdr_file_in);
391c833cfcfSAlex Hornung break;
392c833cfcfSAlex Hornung case FLAG_LONG_USE_HHDR_FILE:
393c833cfcfSAlex Hornung opts->flags |= TC_FLAG_H_HDR_FROM_FILE;
394c833cfcfSAlex Hornung _set_str_opt(h_hdr_file_in);
395c833cfcfSAlex Hornung break;
396c833cfcfSAlex Hornung case FLAG_LONG_MOD:
397c833cfcfSAlex Hornung modify_vol = 1;
398c833cfcfSAlex Hornung break;
399c833cfcfSAlex Hornung case FLAG_LONG_MOD_KF:
400c833cfcfSAlex Hornung if ((error = opts_add_keyfile_new(opts, optarg)) != 0) {
401c833cfcfSAlex Hornung fprintf(stderr, "Could not add keyfile: %s\n", optarg);
402c833cfcfSAlex Hornung exit(EXIT_FAILURE);
403c833cfcfSAlex Hornung }
404c833cfcfSAlex Hornung break;
405c833cfcfSAlex Hornung case FLAG_LONG_MOD_PRF:
406c833cfcfSAlex Hornung if (opts->new_prf_algo != NULL)
407c833cfcfSAlex Hornung usage();
408*7b1e1c8eSDaniel Fojt if ((opts->new_prf_algo = check_prf_algo(optarg, 0, 0)) == NULL) {
409c833cfcfSAlex Hornung if (strcmp(optarg, "help") == 0)
410c833cfcfSAlex Hornung exit(EXIT_SUCCESS);
411c833cfcfSAlex Hornung else
412c833cfcfSAlex Hornung usage();
413c833cfcfSAlex Hornung /* NOT REACHED */
414c833cfcfSAlex Hornung }
415c833cfcfSAlex Hornung break;
416c833cfcfSAlex Hornung case FLAG_LONG_MOD_NONE:
417c833cfcfSAlex Hornung opts->new_prf_algo = NULL;
418c833cfcfSAlex Hornung opts->flags |= TC_FLAG_ONLY_RESTORE;
419c833cfcfSAlex Hornung opts->flags |= TC_FLAG_BACKUP;
420c833cfcfSAlex Hornung break;
421c833cfcfSAlex Hornung case FLAG_LONG_MOD_TO_FILE:
422c833cfcfSAlex Hornung opts->flags |= TC_FLAG_SAVE_TO_FILE;
423c833cfcfSAlex Hornung _set_str_opt(hdr_file_out);
424c833cfcfSAlex Hornung break;
425c833cfcfSAlex Hornung case FLAG_LONG_NO_RETRIES:
426c833cfcfSAlex Hornung opts->retries = 1;
427c833cfcfSAlex Hornung break;
4280d9ba1e1SAlex Hornung case 'h':
4290d9ba1e1SAlex Hornung case '?':
4300d9ba1e1SAlex Hornung default:
4310d9ba1e1SAlex Hornung usage();
4320d9ba1e1SAlex Hornung /* NOT REACHED */
4330d9ba1e1SAlex Hornung }
4340d9ba1e1SAlex Hornung }
4350d9ba1e1SAlex Hornung
4360d9ba1e1SAlex Hornung argc -= optind;
4370d9ba1e1SAlex Hornung argv += optind;
4380d9ba1e1SAlex Hornung
4390d9ba1e1SAlex Hornung /* Check arguments */
440c833cfcfSAlex Hornung if (!(((map_vol || info_vol || create_vol || modify_vol) && opts->dev != NULL) ||
441c833cfcfSAlex Hornung ((unmap_vol || info_map) && opts->map_name != NULL)) ||
442c833cfcfSAlex Hornung (TC_FLAG_SET(opts->flags, SYS) && TC_FLAG_SET(opts->flags, FDE)) ||
443c833cfcfSAlex Hornung (map_vol + info_vol + create_vol + unmap_vol + info_map + modify_vol > 1) ||
444c833cfcfSAlex Hornung (opts->hidden && !create_vol) ||
445c833cfcfSAlex Hornung (TC_FLAG_SET(opts->flags, SYS) && (opts->sys_dev == NULL)) ||
446c833cfcfSAlex Hornung (TC_FLAG_SET(opts->flags, ONLY_RESTORE) && (opts->n_newkeyfiles > 0 || opts->new_prf_algo != NULL)) ||
447c833cfcfSAlex Hornung (TC_FLAG_SET(opts->flags, BACKUP) && (opts->sys_dev != NULL || TC_FLAG_SET(opts->flags, FDE))) ||
448c833cfcfSAlex Hornung (map_vol && (opts->map_name == NULL)) ||
449c833cfcfSAlex Hornung (unmap_vol && (opts->map_name == NULL)) ||
450c833cfcfSAlex Hornung (!modify_vol && opts->n_newkeyfiles > 0) ||
451c833cfcfSAlex Hornung (!modify_vol && opts->new_prf_algo != NULL) ||
452c833cfcfSAlex Hornung (!modify_vol && TC_FLAG_SET(opts->flags, ONLY_RESTORE)) ||
453c833cfcfSAlex Hornung (!modify_vol && TC_FLAG_SET(opts->flags, SAVE_TO_FILE)) ||
454c833cfcfSAlex Hornung (!(opts->protect_hidden || create_vol) && opts->n_hkeyfiles > 0)) {
4550d9ba1e1SAlex Hornung usage();
4560d9ba1e1SAlex Hornung /* NOT REACHED */
4570d9ba1e1SAlex Hornung }
4580d9ba1e1SAlex Hornung
4590d9ba1e1SAlex Hornung /* Create a new volume */
4600d9ba1e1SAlex Hornung if (create_vol) {
461c833cfcfSAlex Hornung error = create_volume(opts);
4620d9ba1e1SAlex Hornung if (error) {
463c833cfcfSAlex Hornung tc_log(1, "could not create new volume on %s\n", opts->dev);
4640d9ba1e1SAlex Hornung }
465c833cfcfSAlex Hornung } else if (info_map) {
466c833cfcfSAlex Hornung error = info_mapped_volume(opts);
4670d9ba1e1SAlex Hornung } else if (info_vol) {
468c833cfcfSAlex Hornung error = info_volume(opts);
4690d9ba1e1SAlex Hornung } else if (map_vol) {
470c833cfcfSAlex Hornung error = map_volume(opts);
471c833cfcfSAlex Hornung } else if (unmap_vol) {
472c833cfcfSAlex Hornung error = dm_teardown(opts->map_name, NULL);
473c833cfcfSAlex Hornung } else if (modify_vol) {
474c833cfcfSAlex Hornung error = modify_volume(opts);
4750d9ba1e1SAlex Hornung }
4760d9ba1e1SAlex Hornung
4770d9ba1e1SAlex Hornung return error;
4780d9ba1e1SAlex Hornung }
479c833cfcfSAlex Hornung
480c833cfcfSAlex Hornung #undef _set_str_opt
481