Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

bugfix, support for different cipher for hidden vol

* Fix a bug that caused blksz in create_volume to become corrupt, due to
  a stack overflow. Use a temporary int64_t for dehumanize_number
  instead of directly using the size_t blksz.

* Add support to use a different cipher and prf hash for the hidden
  volume than for the outer volume.
  • Loading branch information...
commit c4608da1644886503d60506377f57e6fb086acef 1 parent 6b3d19e
Alex Hornung authored
53 main.c
@@ -62,7 +62,8 @@ usage(void)
62 62 " -m <mapping name>, --map=<mapping name>\n"
63 63 "\t Creates a dm-crypt mapping with the given name for the device\n"
64 64 "\t specified by -d or --device\n"
65   - "\nValid options and its arguments for 'create' are:\n"
  65 + "\n"
  66 + "Valid options and its arguments for 'create' are:\n"
66 67 " -a <pbkdf prf algorithm>, --pbkdf-prf=<pbkdf prf algorithm>\n"
67 68 "\t specifies which hashing function to use for the PBKDF password\n"
68 69 "\t derivation when creating a new volume\n"
@@ -70,14 +71,25 @@ usage(void)
70 71 " -b <cipher>, --cipher=<cipher>\n"
71 72 "\t specifies which cipher to use when creating a new TC volume\n"
72 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"
73 83 " -g, --hidden\n"
74 84 "\t specifies that the newly created volume will contain a hidden volume\n"
75   - "\nValid options and its arguments for 'info' and 'map' are:\n"
  85 + "\n"
  86 + "Valid options and its arguments for 'info' and 'map' are:\n"
76 87 " -e, --protect-hidden\n"
77 88 "\t protect a hidden volume when mounting the outer volume\n"
78 89 " -s <disk path>, --system-encryption=<disk path>\n"
79 90 "\t specifies that the disk (e.g. /dev/da0) is using system encryption\n"
80   - "\nValid options and its arguments common to all commands are:\n"
  91 + "\n"
  92 + "Valid options and its arguments common to all commands are:\n"
81 93 " -d <device path>, --device=<device path>\n"
82 94 "\t specifies the path to the volume to operate on (e.g. /dev/da0s1)\n"
83 95 " -k <key file>, --keyfile=<key file>\n"
@@ -95,8 +107,10 @@ usage(void)
95 107 static struct option longopts[] = {
96 108 { "create", no_argument, NULL, 'c' },
97 109 { "cipher", required_argument, NULL, 'b' },
  110 + { "cipher-hidden", required_argument, NULL, 'y' },
98 111 { "hidden", no_argument, NULL, 'g' },
99 112 { "pbkdf-prf", required_argument, NULL, 'a' },
  113 + { "pbkdf-prf-hidden", required_argument, NULL, 'x' },
100 114 { "info", no_argument, NULL, 'i' },
101 115 { "map", required_argument, NULL, 'm' },
102 116 { "keyfile", required_argument, NULL, 'k' },
@@ -122,6 +136,8 @@ main(int argc, char *argv[])
122 136 create_vol = 0, contain_hidden = 0;
123 137 struct pbkdf_prf_algo *prf = NULL;
124 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;
125 141
126 142 if ((error = tc_play_init()) != 0) {
127 143 fprintf(stderr, "Initialization failed, exiting.");
@@ -135,8 +151,8 @@ main(int argc, char *argv[])
135 151 nkeyfiles = 0;
136 152 n_hkeyfiles = 0;
137 153
138   - while ((ch = getopt_long(argc, argv, "a:b:cd:efgh:ik:m:s:v", longopts,
139   - NULL)) != -1) {
  154 + while ((ch = getopt_long(argc, argv, "a:b:cd:efgh:ik:m:s:vx:y:",
  155 + longopts, NULL)) != -1) {
140 156 switch(ch) {
141 157 case 'a':
142 158 if (prf != NULL)
@@ -146,6 +162,7 @@ main(int argc, char *argv[])
146 162 exit(0);
147 163 else
148 164 usage();
  165 + /* NOT REACHED */
149 166 }
150 167 break;
151 168 case 'b':
@@ -156,6 +173,7 @@ main(int argc, char *argv[])
156 173 exit(0);
157 174 else
158 175 usage();
  176 + /* NOT REACHED */
159 177 }
160 178 break;
161 179 case 'c':
@@ -191,6 +209,28 @@ main(int argc, char *argv[])
191 209 printf("tcplay v%d.%d\n", MAJ_VER, MIN_VER);
192 210 exit(0);
193 211 /* NOT REACHED */
  212 + case 'x':
  213 + if (h_prf != NULL)
  214 + usage();
  215 + if ((h_prf = check_prf_algo(optarg, 0)) == NULL) {
  216 + if (strcmp(optarg, "help") == 0)
  217 + exit(0);
  218 + else
  219 + usage();
  220 + /* NOT REACHED */
  221 + }
  222 + break;
  223 + case 'y':
  224 + if (h_cipher_chain != NULL)
  225 + usage();
  226 + if ((h_cipher_chain = check_cipher_chain(optarg, 0)) == NULL) {
  227 + if (strcmp(optarg, "help") == 0)
  228 + exit(0);
  229 + else
  230 + usage();
  231 + /* NOT REACHED */
  232 + }
  233 + break;
194 234 case 'h':
195 235 case '?':
196 236 default:
@@ -218,7 +258,8 @@ main(int argc, char *argv[])
218 258 /* Create a new volume */
219 259 if (create_vol) {
220 260 error = create_volume(dev, contain_hidden, keyfiles, nkeyfiles,
221   - h_keyfiles, n_hkeyfiles, prf, cipher_chain, NULL, NULL,
  261 + h_keyfiles, n_hkeyfiles, prf, cipher_chain, h_prf,
  262 + h_cipher_chain, NULL, NULL,
222 263 0, 1 /* interactive */);
223 264 if (error) {
224 265 tc_log(1, "could not create new volume on %s\n", dev);
15 tcplay.3
@@ -92,6 +92,8 @@ typedef struct tc_api_opts {
92 92 /* Fields for creation */
93 93 char *tc_cipher;
94 94 char *tc_prf_hash;
  95 + char *tc_cipher_hidden;
  96 + char *tc_prf_hash_hidden;
95 97 size_t tc_size_hidden_in_blocks;
96 98 char *tc_passphrase_hidden;
97 99 const char **tc_keyfiles_hidden;
@@ -140,7 +142,18 @@ respectively.
140 142 If
141 143 .Fa tc_size_hidden_in_blocks
142 144 is not zero, a hidden volume of the given size will be created, using
143   -the passphrase and keyfiles specified by
  145 +the cipher specified by
  146 +.Fa tc_cipher_hidden
  147 +and the pbkdf2 prf hash algorithm specified by
  148 +.Fa tc_prf_hash_hidden .
  149 +If
  150 +.Fa tc_cipher_hidden
  151 +or
  152 +.Fa tc_prf_hash_hidden
  153 +are
  154 +.Dv NULL ,
  155 +the same algorithm as for the outer volume will be used.
  156 +The passphrase and keyfiles used are specified by
144 157 .Fa tc_passphrase_hidden
145 158 and
146 159 .Fa tc_keyfiles_hidden
27 tcplay.8
@@ -20,14 +20,11 @@
20 20 .\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 21 .\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 22 .\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23   -.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24   -INDIRECT,
  23 +.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 24 .\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 25 .\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27   -.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28   -CAUSED
29   -.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30   -LIABILITY,
  26 +.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27 +.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 28 .\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 29 .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 30 .\" SUCH DAMAGE.
@@ -121,6 +118,24 @@ Specifies with cipher algorithm or cascade of ciphers to use
121 118 to encrypt the new volume.
122 119 To see which algorithms are supported, specify
123 120 .Fl -cipher Ns = Ns Ar help .
  121 +.It Fl x Ar pbkdf_hash , Fl -pbkdf-prf-hidden Ns = Ns Ar pbkdf_hash
  122 +Specifies with hash algorithm to use for the PBKDF2 password
  123 +derivation for the hidden volume.
  124 +Only valid in conjunction with
  125 +.Fl -hidden .
  126 +If no algorithm is specified, the same as for the outer volume
  127 +will be used.
  128 +To see which algorithms are supported, specify
  129 +.Fl -pbkdf-prf-hidden Ns = Ns Ar help .
  130 +.It Fl y Ar cipher , Fl -cipher-hidden Ns = Ns Ar cipher
  131 +Specifies with cipher algorithm or cascade of ciphers to use
  132 +to encrypt the hidden volume on the new TrueCrypt volume.
  133 +Only valid in conjunction with
  134 +.Fl -hidden .
  135 +If no cipher is specified, the same as for the outer volume
  136 +will be used.
  137 +To see which algorithms are supported, specify
  138 +.Fl -cipher-hidden Ns = Ns Ar help .
124 139 .It Fl g, Fl -hidden
125 140 Specifies that the newly created volume will contain a hidden
126 141 volume.
17 tcplay.c
@@ -348,20 +348,26 @@ process_hdr(const char *dev, unsigned char *pass, int passlen,
348 348 int
349 349 create_volume(const char *dev, int hidden, const char *keyfiles[], int nkeyfiles,
350 350 const char *h_keyfiles[], int n_hkeyfiles, struct pbkdf_prf_algo *prf_algo,
351   - struct tc_cipher_chain *cipher_chain, char *passphrase, char *h_passphrase,
352   - size_t hidden_blocks_in, int interactive)
  351 + struct tc_cipher_chain *cipher_chain, struct pbkdf_prf_algo *h_prf_algo,
  352 + struct tc_cipher_chain *h_cipher_chain, char *passphrase,
  353 + char *h_passphrase, size_t hidden_blocks_in, int interactive)
353 354 {
354 355 char *pass, *pass_again;
355 356 char *h_pass = NULL;
356 357 char buf[1024];
357 358 size_t blocks, blksz, hidden_blocks;
358 359 struct tchdr_enc *ehdr, *hehdr;
  360 + int64_t tmp;
359 361 int error, r;
360 362
361 363 if (cipher_chain == NULL)
362 364 cipher_chain = tc_cipher_chains[0];
363 365 if (prf_algo == NULL)
364 366 prf_algo = &pbkdf_prf_algos[0];
  367 + if (h_cipher_chain == NULL)
  368 + h_cipher_chain = cipher_chain;
  369 + if (h_prf_algo == NULL)
  370 + h_prf_algo = prf_algo;
365 371
366 372 if ((error = get_disk_info(dev, &blocks, &blksz)) != 0) {
367 373 tc_log(1, "could not get disk info\n");
@@ -490,11 +496,12 @@ create_volume(const char *dev, int hidden, const char *keyfiles[], int nkeyfiles
490 496 /* get rid of trailing newline */
491 497 buf[strlen(buf)-1] = '\0';
492 498 if ((error = dehumanize_number(buf,
493   - (int64_t *)&hidden_blocks)) != 0) {
  499 + &tmp)) != 0) {
494 500 tc_log(1, "Could not interpret input: %s\n", buf);
495 501 return -1;
496 502 }
497 503
  504 + hidden_blocks = (size_t)tmp;
498 505 hidden_blocks /= blksz;
499 506 if (hidden_blocks >= blocks - MIN_VOL_BLOCKS) {
500 507 tc_log(1, "Hidden volume needs to be "
@@ -546,8 +553,8 @@ create_volume(const char *dev, int hidden, const char *keyfiles[], int nkeyfiles
546 553
547 554 if (hidden) {
548 555 hehdr = create_hdr(h_pass,
549   - (n_hkeyfiles > 0)?MAX_PASSSZ:strlen(h_pass), prf_algo,
550   - cipher_chain,
  556 + (n_hkeyfiles > 0)?MAX_PASSSZ:strlen(h_pass), h_prf_algo,
  557 + h_cipher_chain,
551 558 blksz, blocks, blocks - hidden_blocks, hidden_blocks, 1);
552 559 if (hehdr == NULL) {
553 560 tc_log(1, "Could not create hidden volume header\n");
1  tcplay.h
@@ -171,6 +171,7 @@ int process_hdr(const char *dev, unsigned char *pass, int passlen,
171 171 int create_volume(const char *dev, int hidden, const char *keyfiles[],
172 172 int nkeyfiles, const char *h_keyfiles[], int n_hkeyfiles,
173 173 struct pbkdf_prf_algo *prf_algo, struct tc_cipher_chain *cipher_chain,
  174 + struct pbkdf_prf_algo *h_prf_algo, struct tc_cipher_chain *h_cipher_chain,
174 175 char *passphrase, char *h_passphrase, size_t hidden_blocks_in,
175 176 int interactive);
176 177 int info_volume(const char *device, int sflag, const char *sys_dev,
2  tcplay_api.c
@@ -111,6 +111,8 @@ tc_api_create_volume(tc_api_opts *api_opts)
111 111 api_opts->tc_keyfiles_hidden, n_hkeyfiles,
112 112 check_prf_algo(api_opts->tc_prf_hash, 1),
113 113 check_cipher_chain(api_opts->tc_cipher, 1),
  114 + check_prf_algo(api_opts->tc_prf_hash_hidden, 1),
  115 + check_cipher_chain(api_opts->tc_cipher_hidden, 1),
114 116 api_opts->tc_passphrase, api_opts->tc_passphrase_hidden,
115 117 api_opts->tc_size_hidden_in_blocks, 0 /* non-interactive */);
116 118
2  tcplay_api.h
@@ -44,6 +44,8 @@ typedef struct tc_api_opts {
44 44 /* Fields for creation */
45 45 char *tc_cipher;
46 46 char *tc_prf_hash;
  47 + char *tc_cipher_hidden;
  48 + char *tc_prf_hash_hidden;
47 49 size_t tc_size_hidden_in_blocks;
48 50 char *tc_passphrase_hidden;
49 51 const char **tc_keyfiles_hidden;
7 tcplay_api_test.c
@@ -19,10 +19,12 @@ main(void)
19 19 api_opts.tc_passphrase = "apitest2";
20 20 api_opts.tc_keyfiles = NULL;
21 21 api_opts.tc_keyfiles_hidden = NULL;
22   - api_opts.tc_size_hidden_in_blocks = 0;
23   - api_opts.tc_passphrase_hidden = NULL;
  22 + api_opts.tc_size_hidden_in_blocks = 12000;
  23 + api_opts.tc_passphrase_hidden = "apihidden";
24 24 api_opts.tc_cipher = "AES-256-XTS,TWOFISH-256-XTS,SERPENT-256-XTS";
  25 + api_opts.tc_cipher_hidden = "SERPENT-256-XTS,TWOFISH-256-XTS";
25 26 api_opts.tc_prf_hash = "whirlpool";
  27 + api_opts.tc_prf_hash_hidden = "RIPEMD160";
26 28
27 29 error = tc_api_create_volume(&api_opts);
28 30 if (error)
@@ -35,6 +37,7 @@ main(void)
35 37 error = tc_api_init(/*verbose */ 1);
36 38 assert(error == 0);
37 39
  40 + api_opts.tc_passphrase = NULL;
38 41 api_opts.tc_map_name = "dragonfly-test";
39 42 api_opts.tc_password_retries = 5;
40 43 api_opts.tc_interactive_prompt = 1;

0 comments on commit c4608da

Please sign in to comment.
Something went wrong with that request. Please try again.