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
30 #include <sys/types.h>
43 #define SIGINFO SIGUSR1
50 if ((sig == SIGUSR1 || sig == SIGINFO) && (summary_fn != NULL))
59 "usage: tcplay -c -d device [-g] [-a pbkdb_hash] [-b cipher]\n"
60 " [-f keyfile_hidden] [-k keyfile] [-x pbkdf_hash] [-y cipher]\n"
61 " tcplay -i -d device [-e] [-f keyfile_hidden] [-k keyfile]\n"
62 " [-s system_devcie]\n"
63 " tcplay -m mapping -d device [-e] [-f keyfile_hidden] [-k keyfile]\n"
64 " [-s system_device]\n"
67 "Valid commands are:\n"
69 "\t Creates a new TC volume on the device specified by -d or --device.\n"
71 "\t Print help message and exit.\n"
73 "\t Gives information about the TC volume specified by -d or --device.\n"
74 " -m <mapping name>, --map=<mapping name>\n"
75 "\t Creates a dm-crypt mapping with the given name for the device\n"
76 "\t specified by -d or --device.\n"
78 "\t Print version message and exit.\n"
80 "Valid options for --create are:\n"
81 " -a <pbkdf prf algorithm>, --pbkdf-prf=<pbkdf prf algorithm>\n"
82 "\t Specifies which hashing function to use for the PBKDF password\n"
83 "\t derivation when creating a new volume.\n"
84 "\t To see valid options, specify '-a help'.\n"
85 " -b <cipher>, --cipher=<cipher>\n"
86 "\t Specifies which cipher to use when creating a new TC volume.\n"
87 "\t To see valid options, specify '-b help'.\n"
89 "\t Specifies that the newly created volume will contain a hidden volume.\n"
90 " -x <pbkdf prf algorithm>, --pbkdf-prf=<pbkdf prf algorithm>\n"
91 "\t Specifies which hashing function to use for the PBKDF password\n"
92 "\t derivation when creating a new hidden volume. By default, the\n"
93 "\t same as for the outer volume will be used.\n"
94 "\t To see valid options, specify '-x help'.\n"
95 " -y <cipher>, --cipher=<cipher>\n"
96 "\t Specifies which cipher to use when creating a new hidden volume.\n"
97 "\t By default, the same as for the outer volume will be used.\n"
98 "\t To see valid options, specify '-y help'.\n"
100 "Valid options for --info and --map are:\n"
101 " -e, --protect-hidden\n"
102 "\t Protect a hidden volume when mounting the outer volume.\n"
103 " -s <disk path>, --system-encryption=<disk path>\n"
104 "\t Specifies that the disk (e.g. /dev/da0) is using system encryption.\n"
106 "Valid options common to all commands are:\n"
107 " -d <device path>, --device=<device path>\n"
108 "\t Specifies the path to the volume to operate on (e.g. /dev/da0s1).\n"
109 " -f <key file>, --keyfile-hidden=<key file>\n"
110 "\t Specifies a key file to use for the hidden volume password derivation.\n"
111 "\t This option is only valid in combination with -e, --protect-hidden\n"
112 "\t or -g, --hidden.\n"
113 " -k <key file>, --keyfile=<key file>\n"
114 "\t Specifies a key file to use for the password derivation, can appear\n"
115 "\t multiple times.\n"
121 static struct option longopts[] = {
122 { "create", no_argument, NULL, 'c' },
123 { "cipher", required_argument, NULL, 'b' },
124 { "cipher-hidden", required_argument, NULL, 'y' },
125 { "hidden", no_argument, NULL, 'g' },
126 { "pbkdf-prf", required_argument, NULL, 'a' },
127 { "pbkdf-prf-hidden", required_argument, NULL, 'x' },
128 { "info", no_argument, NULL, 'i' },
129 { "map", required_argument, NULL, 'm' },
130 { "keyfile", required_argument, NULL, 'k' },
131 { "keyfile-hidden", required_argument, NULL, 'f' },
132 { "protect-hidden", no_argument, NULL, 'e' },
133 { "device", required_argument, NULL, 'd' },
134 { "system-encryption", required_argument, NULL, 's' },
135 { "version", no_argument, NULL, 'v' },
136 { "help", no_argument, NULL, 'h' },
137 { NULL, 0, NULL, 0 },
141 main(int argc, char *argv[])
143 const char *dev = NULL, *sys_dev = NULL, *map_name = NULL;
144 const char *keyfiles[MAX_KEYFILES];
145 const char *h_keyfiles[MAX_KEYFILES];
149 int sflag = 0, info_vol = 0, map_vol = 0, protect_hidden = 0,
150 create_vol = 0, contain_hidden = 0;
151 struct pbkdf_prf_algo *prf = NULL;
152 struct tc_cipher_chain *cipher_chain = NULL;
153 struct pbkdf_prf_algo *h_prf = NULL;
154 struct tc_cipher_chain *h_cipher_chain = NULL;
156 if ((error = tc_play_init()) != 0) {
157 fprintf(stderr, "Initialization failed, exiting.");
161 atexit(check_and_purge_safe_mem);
162 signal(SIGUSR1, sig_handler);
163 signal(SIGINFO, sig_handler);
168 while ((ch = getopt_long(argc, argv, "a:b:cd:ef:ghik:m:s:vx:y:",
169 longopts, NULL)) != -1) {
174 if ((prf = check_prf_algo(optarg, 0)) == NULL) {
175 if (strcmp(optarg, "help") == 0)
183 if (cipher_chain != NULL)
185 if ((cipher_chain = check_cipher_chain(optarg, 0)) == NULL) {
186 if (strcmp(optarg, "help") == 0)
203 h_keyfiles[n_hkeyfiles++] = optarg;
212 keyfiles[nkeyfiles++] = optarg;
223 printf("tcplay v%d.%d\n", MAJ_VER, MIN_VER);
229 if ((h_prf = check_prf_algo(optarg, 0)) == NULL) {
230 if (strcmp(optarg, "help") == 0)
238 if (h_cipher_chain != NULL)
240 if ((h_cipher_chain = check_cipher_chain(optarg, 0)) == NULL) {
241 if (strcmp(optarg, "help") == 0)
259 /* Check arguments */
260 if (!((map_vol || info_vol || create_vol) && dev != NULL) ||
261 (map_vol && info_vol) ||
262 (map_vol && create_vol) ||
263 (create_vol && info_vol) ||
264 (contain_hidden && !create_vol) ||
265 (sflag && (sys_dev == NULL)) ||
266 (map_vol && (map_name == NULL)) ||
267 (!(protect_hidden || create_vol) && n_hkeyfiles > 0)) {
272 /* Create a new volume */
274 error = create_volume(dev, contain_hidden, keyfiles, nkeyfiles,
275 h_keyfiles, n_hkeyfiles, prf, cipher_chain, h_prf,
276 h_cipher_chain, NULL, NULL,
277 0, 1 /* interactive */);
279 tc_log(1, "could not create new volume on %s\n", dev);
281 } else if (info_vol) {
282 error = info_volume(dev, sflag, sys_dev, protect_hidden,
283 keyfiles, nkeyfiles, h_keyfiles, n_hkeyfiles, NULL, NULL,
284 1 /* interactive */, DEFAULT_RETRIES, 0);
285 } else if (map_vol) {
286 error = map_volume(map_name,
287 dev, sflag, sys_dev, protect_hidden,
288 keyfiles, nkeyfiles, h_keyfiles, n_hkeyfiles, NULL, NULL,
289 1 /* interactive */, DEFAULT_RETRIES, 0);