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>
47 if ((sig == SIGUSR1 || sig == SIGINFO) && (summary_fn != NULL))
56 "Usage: tcplay <command> [options]\n"
57 "Valid commands and its arguments are:\n"
59 "\t Creates a new TC volume on the device specified by -d or --device\n"
61 "\t Gives information about the TC volume specified by -d or --device\n"
62 " -m <mapping name>, --map=<mapping name>\n"
63 "\t Creates a dm-crypt mapping with the given name for the device\n"
64 "\t specified by -d or --device\n"
66 "Valid options and its arguments for 'create' are:\n"
67 " -a <pbkdf prf algorithm>, --pbkdf-prf=<pbkdf prf algorithm>\n"
68 "\t specifies which hashing function to use for the PBKDF password\n"
69 "\t derivation when creating a new volume\n"
70 "\t To see valid options, specify -a help\n"
71 " -b <cipher>, --cipher=<cipher>\n"
72 "\t specifies which cipher to use when creating a new TC volume\n"
73 "\t To see valid options, specify -b help\n"
74 " -x <pbkdf prf algorithm>, --pbkdf-prf=<pbkdf prf algorithm>\n"
75 "\t specifies which hashing function to use for the PBKDF password\n"
76 "\t derivation when creating a new hidden volume. By default, the\n"
77 "\t same as for the outer volume will be used\n"
78 "\t To see valid options, specify -a help\n"
79 " -y <cipher>, --cipher=<cipher>\n"
80 "\t specifies which cipher to use when creating a new hidden volume.\n"
81 "\t By default, the same as for the outer volume will be used\n"
82 "\t To see valid options, specify -b help\n"
84 "\t specifies that the newly created volume will contain a hidden volume\n"
86 "Valid options and its arguments for 'info' and 'map' are:\n"
87 " -e, --protect-hidden\n"
88 "\t protect a hidden volume when mounting the outer volume\n"
89 " -s <disk path>, --system-encryption=<disk path>\n"
90 "\t specifies that the disk (e.g. /dev/da0) is using system encryption\n"
92 "Valid options and its arguments common to all commands are:\n"
93 " -d <device path>, --device=<device path>\n"
94 "\t specifies the path to the volume to operate on (e.g. /dev/da0s1)\n"
95 " -k <key file>, --keyfile=<key file>\n"
96 "\t specifies a key file to use for the password derivation, can appear\n"
98 " -f <key file>, --keyfile-hidden=<key file>\n"
99 "\t specifies a key file to use for the hidden volume password derivation\n"
100 "\t This option is only valid in combination with -e, --protect-hidden\n"
101 "\t or -g, --hidden\n"
107 static struct option longopts[] = {
108 { "create", no_argument, NULL, 'c' },
109 { "cipher", required_argument, NULL, 'b' },
110 { "cipher-hidden", required_argument, NULL, 'y' },
111 { "hidden", no_argument, NULL, 'g' },
112 { "pbkdf-prf", required_argument, NULL, 'a' },
113 { "pbkdf-prf-hidden", required_argument, NULL, 'x' },
114 { "info", no_argument, NULL, 'i' },
115 { "map", required_argument, NULL, 'm' },
116 { "keyfile", required_argument, NULL, 'k' },
117 { "keyfile-hidden", required_argument, NULL, 'f' },
118 { "protect-hidden", no_argument, NULL, 'e' },
119 { "device", required_argument, NULL, 'd' },
120 { "system-encryption", required_argument, NULL, 's' },
121 { "version", no_argument, NULL, 'v' },
122 { "help", no_argument, NULL, 'h' },
123 { NULL, 0, NULL, 0 },
127 main(int argc, char *argv[])
129 const char *dev = NULL, *sys_dev = NULL, *map_name = NULL;
130 const char *keyfiles[MAX_KEYFILES];
131 const char *h_keyfiles[MAX_KEYFILES];
135 int sflag = 0, info_vol = 0, map_vol = 0, protect_hidden = 0,
136 create_vol = 0, contain_hidden = 0;
137 struct pbkdf_prf_algo *prf = NULL;
138 struct tc_cipher_chain *cipher_chain = NULL;
139 struct pbkdf_prf_algo *h_prf = NULL;
140 struct tc_cipher_chain *h_cipher_chain = NULL;
142 if ((error = tc_play_init()) != 0) {
143 fprintf(stderr, "Initialization failed, exiting.");
147 atexit(check_and_purge_safe_mem);
148 signal(SIGUSR1, sig_handler);
149 signal(SIGINFO, sig_handler);
154 while ((ch = getopt_long(argc, argv, "a:b:cd:efgh:ik:m:s:vx:y:",
155 longopts, NULL)) != -1) {
160 if ((prf = check_prf_algo(optarg, 0)) == NULL) {
161 if (strcmp(optarg, "help") == 0)
169 if (cipher_chain != NULL)
171 if ((cipher_chain = check_cipher_chain(optarg, 0)) == NULL) {
172 if (strcmp(optarg, "help") == 0)
189 h_keyfiles[n_hkeyfiles++] = optarg;
198 keyfiles[nkeyfiles++] = optarg;
209 printf("tcplay v%d.%d\n", MAJ_VER, MIN_VER);
215 if ((h_prf = check_prf_algo(optarg, 0)) == NULL) {
216 if (strcmp(optarg, "help") == 0)
224 if (h_cipher_chain != NULL)
226 if ((h_cipher_chain = check_cipher_chain(optarg, 0)) == NULL) {
227 if (strcmp(optarg, "help") == 0)
245 /* Check arguments */
246 if (!((map_vol || info_vol || create_vol) && dev != NULL) ||
247 (map_vol && info_vol) ||
248 (map_vol && create_vol) ||
249 (create_vol && info_vol) ||
250 (contain_hidden && !create_vol) ||
251 (sflag && (sys_dev == NULL)) ||
252 (map_vol && (map_name == NULL)) ||
253 (!(protect_hidden || create_vol) && n_hkeyfiles > 0)) {
258 /* Create a new volume */
260 error = create_volume(dev, contain_hidden, keyfiles, nkeyfiles,
261 h_keyfiles, n_hkeyfiles, prf, cipher_chain, h_prf,
262 h_cipher_chain, NULL, NULL,
263 0, 1 /* interactive */);
265 tc_log(1, "could not create new volume on %s\n", dev);
267 } else if (info_vol) {
268 error = info_volume(dev, sflag, sys_dev, protect_hidden,
269 keyfiles, nkeyfiles, h_keyfiles, n_hkeyfiles, NULL, NULL,
270 1 /* interactive */, DEFAULT_RETRIES, 0);
271 } else if (map_vol) {
272 error = map_volume(map_name,
273 dev, sflag, sys_dev, protect_hidden,
274 keyfiles, nkeyfiles, h_keyfiles, n_hkeyfiles, NULL, NULL,
275 1 /* interactive */, DEFAULT_RETRIES, 0);