Skip to content
Browse files

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...
1 parent 6b3d19e commit c4608da1644886503d60506377f57e6fb086acef @bwalex committed Jul 10, 2011
Showing with 104 additions and 20 deletions.
  1. +47 −6 main.c
  2. +14 −1 tcplay.3
  3. +21 −6 tcplay.8
  4. +12 −5 tcplay.c
  5. +1 −0 tcplay.h
  6. +2 −0 tcplay_api.c
  7. +2 −0 tcplay_api.h
  8. +5 −2 tcplay_api_test.c
View
53 main.c
@@ -62,22 +62,34 @@ usage(void)
" -m <mapping name>, --map=<mapping name>\n"
"\t Creates a dm-crypt mapping with the given name for the device\n"
"\t specified by -d or --device\n"
- "\nValid options and its arguments for 'create' are:\n"
+ "\n"
+ "Valid options and its arguments for 'create' are:\n"
" -a <pbkdf prf algorithm>, --pbkdf-prf=<pbkdf prf algorithm>\n"
"\t specifies which hashing function to use for the PBKDF password\n"
"\t derivation when creating a new volume\n"
"\t To see valid options, specify -a help\n"
" -b <cipher>, --cipher=<cipher>\n"
"\t specifies which cipher to use when creating a new TC volume\n"
"\t To see valid options, specify -b help\n"
+ " -x <pbkdf prf algorithm>, --pbkdf-prf=<pbkdf prf algorithm>\n"
+ "\t specifies which hashing function to use for the PBKDF password\n"
+ "\t derivation when creating a new hidden volume. By default, the\n"
+ "\t same as for the outer volume will be used\n"
+ "\t To see valid options, specify -a help\n"
+ " -y <cipher>, --cipher=<cipher>\n"
+ "\t specifies which cipher to use when creating a new hidden volume.\n"
+ "\t By default, the same as for the outer volume will be used\n"
+ "\t To see valid options, specify -b help\n"
" -g, --hidden\n"
"\t specifies that the newly created volume will contain a hidden volume\n"
- "\nValid options and its arguments for 'info' and 'map' are:\n"
+ "\n"
+ "Valid options and its arguments for 'info' and 'map' are:\n"
" -e, --protect-hidden\n"
"\t protect a hidden volume when mounting the outer volume\n"
" -s <disk path>, --system-encryption=<disk path>\n"
"\t specifies that the disk (e.g. /dev/da0) is using system encryption\n"
- "\nValid options and its arguments common to all commands are:\n"
+ "\n"
+ "Valid options and its arguments common to all commands are:\n"
" -d <device path>, --device=<device path>\n"
"\t specifies the path to the volume to operate on (e.g. /dev/da0s1)\n"
" -k <key file>, --keyfile=<key file>\n"
@@ -95,8 +107,10 @@ usage(void)
static struct option longopts[] = {
{ "create", no_argument, NULL, 'c' },
{ "cipher", required_argument, NULL, 'b' },
+ { "cipher-hidden", required_argument, NULL, 'y' },
{ "hidden", no_argument, NULL, 'g' },
{ "pbkdf-prf", required_argument, NULL, 'a' },
+ { "pbkdf-prf-hidden", required_argument, NULL, 'x' },
{ "info", no_argument, NULL, 'i' },
{ "map", required_argument, NULL, 'm' },
{ "keyfile", required_argument, NULL, 'k' },
@@ -122,6 +136,8 @@ main(int argc, char *argv[])
create_vol = 0, contain_hidden = 0;
struct pbkdf_prf_algo *prf = NULL;
struct tc_cipher_chain *cipher_chain = NULL;
+ struct pbkdf_prf_algo *h_prf = NULL;
+ struct tc_cipher_chain *h_cipher_chain = NULL;
if ((error = tc_play_init()) != 0) {
fprintf(stderr, "Initialization failed, exiting.");
@@ -135,8 +151,8 @@ main(int argc, char *argv[])
nkeyfiles = 0;
n_hkeyfiles = 0;
- while ((ch = getopt_long(argc, argv, "a:b:cd:efgh:ik:m:s:v", longopts,
- NULL)) != -1) {
+ while ((ch = getopt_long(argc, argv, "a:b:cd:efgh:ik:m:s:vx:y:",
+ longopts, NULL)) != -1) {
switch(ch) {
case 'a':
if (prf != NULL)
@@ -146,6 +162,7 @@ main(int argc, char *argv[])
exit(0);
else
usage();
+ /* NOT REACHED */
}
break;
case 'b':
@@ -156,6 +173,7 @@ main(int argc, char *argv[])
exit(0);
else
usage();
+ /* NOT REACHED */
}
break;
case 'c':
@@ -191,6 +209,28 @@ main(int argc, char *argv[])
printf("tcplay v%d.%d\n", MAJ_VER, MIN_VER);
exit(0);
/* NOT REACHED */
+ case 'x':
+ if (h_prf != NULL)
+ usage();
+ if ((h_prf = check_prf_algo(optarg, 0)) == NULL) {
+ if (strcmp(optarg, "help") == 0)
+ exit(0);
+ else
+ usage();
+ /* NOT REACHED */
+ }
+ break;
+ case 'y':
+ if (h_cipher_chain != NULL)
+ usage();
+ if ((h_cipher_chain = check_cipher_chain(optarg, 0)) == NULL) {
+ if (strcmp(optarg, "help") == 0)
+ exit(0);
+ else
+ usage();
+ /* NOT REACHED */
+ }
+ break;
case 'h':
case '?':
default:
@@ -218,7 +258,8 @@ main(int argc, char *argv[])
/* Create a new volume */
if (create_vol) {
error = create_volume(dev, contain_hidden, keyfiles, nkeyfiles,
- h_keyfiles, n_hkeyfiles, prf, cipher_chain, NULL, NULL,
+ h_keyfiles, n_hkeyfiles, prf, cipher_chain, h_prf,
+ h_cipher_chain, NULL, NULL,
0, 1 /* interactive */);
if (error) {
tc_log(1, "could not create new volume on %s\n", dev);
View
15 tcplay.3
@@ -92,6 +92,8 @@ typedef struct tc_api_opts {
/* Fields for creation */
char *tc_cipher;
char *tc_prf_hash;
+ char *tc_cipher_hidden;
+ char *tc_prf_hash_hidden;
size_t tc_size_hidden_in_blocks;
char *tc_passphrase_hidden;
const char **tc_keyfiles_hidden;
@@ -140,7 +142,18 @@ respectively.
If
.Fa tc_size_hidden_in_blocks
is not zero, a hidden volume of the given size will be created, using
-the passphrase and keyfiles specified by
+the cipher specified by
+.Fa tc_cipher_hidden
+and the pbkdf2 prf hash algorithm specified by
+.Fa tc_prf_hash_hidden .
+If
+.Fa tc_cipher_hidden
+or
+.Fa tc_prf_hash_hidden
+are
+.Dv NULL ,
+the same algorithm as for the outer volume will be used.
+The passphrase and keyfiles used are specified by
.Fa tc_passphrase_hidden
and
.Fa tc_keyfiles_hidden
View
27 tcplay.8
@@ -20,14 +20,11 @@
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
.\" FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-INDIRECT,
+.\" COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED
-.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-LIABILITY,
+.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
@@ -121,6 +118,24 @@ Specifies with cipher algorithm or cascade of ciphers to use
to encrypt the new volume.
To see which algorithms are supported, specify
.Fl -cipher Ns = Ns Ar help .
+.It Fl x Ar pbkdf_hash , Fl -pbkdf-prf-hidden Ns = Ns Ar pbkdf_hash
+Specifies with hash algorithm to use for the PBKDF2 password
+derivation for the hidden volume.
+Only valid in conjunction with
+.Fl -hidden .
+If no algorithm is specified, the same as for the outer volume
+will be used.
+To see which algorithms are supported, specify
+.Fl -pbkdf-prf-hidden Ns = Ns Ar help .
+.It Fl y Ar cipher , Fl -cipher-hidden Ns = Ns Ar cipher
+Specifies with cipher algorithm or cascade of ciphers to use
+to encrypt the hidden volume on the new TrueCrypt volume.
+Only valid in conjunction with
+.Fl -hidden .
+If no cipher is specified, the same as for the outer volume
+will be used.
+To see which algorithms are supported, specify
+.Fl -cipher-hidden Ns = Ns Ar help .
.It Fl g, Fl -hidden
Specifies that the newly created volume will contain a hidden
volume.
View
17 tcplay.c
@@ -348,20 +348,26 @@ process_hdr(const char *dev, unsigned char *pass, int passlen,
int
create_volume(const char *dev, int hidden, const char *keyfiles[], int nkeyfiles,
const char *h_keyfiles[], int n_hkeyfiles, struct pbkdf_prf_algo *prf_algo,
- struct tc_cipher_chain *cipher_chain, char *passphrase, char *h_passphrase,
- size_t hidden_blocks_in, int interactive)
+ struct tc_cipher_chain *cipher_chain, struct pbkdf_prf_algo *h_prf_algo,
+ struct tc_cipher_chain *h_cipher_chain, char *passphrase,
+ char *h_passphrase, size_t hidden_blocks_in, int interactive)
{
char *pass, *pass_again;
char *h_pass = NULL;
char buf[1024];
size_t blocks, blksz, hidden_blocks;
struct tchdr_enc *ehdr, *hehdr;
+ int64_t tmp;
int error, r;
if (cipher_chain == NULL)
cipher_chain = tc_cipher_chains[0];
if (prf_algo == NULL)
prf_algo = &pbkdf_prf_algos[0];
+ if (h_cipher_chain == NULL)
+ h_cipher_chain = cipher_chain;
+ if (h_prf_algo == NULL)
+ h_prf_algo = prf_algo;
if ((error = get_disk_info(dev, &blocks, &blksz)) != 0) {
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
/* get rid of trailing newline */
buf[strlen(buf)-1] = '\0';
if ((error = dehumanize_number(buf,
- (int64_t *)&hidden_blocks)) != 0) {
+ &tmp)) != 0) {
tc_log(1, "Could not interpret input: %s\n", buf);
return -1;
}
+ hidden_blocks = (size_t)tmp;
hidden_blocks /= blksz;
if (hidden_blocks >= blocks - MIN_VOL_BLOCKS) {
tc_log(1, "Hidden volume needs to be "
@@ -546,8 +553,8 @@ create_volume(const char *dev, int hidden, const char *keyfiles[], int nkeyfiles
if (hidden) {
hehdr = create_hdr(h_pass,
- (n_hkeyfiles > 0)?MAX_PASSSZ:strlen(h_pass), prf_algo,
- cipher_chain,
+ (n_hkeyfiles > 0)?MAX_PASSSZ:strlen(h_pass), h_prf_algo,
+ h_cipher_chain,
blksz, blocks, blocks - hidden_blocks, hidden_blocks, 1);
if (hehdr == NULL) {
tc_log(1, "Could not create hidden volume header\n");
View
1 tcplay.h
@@ -171,6 +171,7 @@ int process_hdr(const char *dev, unsigned char *pass, int passlen,
int create_volume(const char *dev, int hidden, const char *keyfiles[],
int nkeyfiles, const char *h_keyfiles[], int n_hkeyfiles,
struct pbkdf_prf_algo *prf_algo, struct tc_cipher_chain *cipher_chain,
+ struct pbkdf_prf_algo *h_prf_algo, struct tc_cipher_chain *h_cipher_chain,
char *passphrase, char *h_passphrase, size_t hidden_blocks_in,
int interactive);
int info_volume(const char *device, int sflag, const char *sys_dev,
View
2 tcplay_api.c
@@ -111,6 +111,8 @@ tc_api_create_volume(tc_api_opts *api_opts)
api_opts->tc_keyfiles_hidden, n_hkeyfiles,
check_prf_algo(api_opts->tc_prf_hash, 1),
check_cipher_chain(api_opts->tc_cipher, 1),
+ check_prf_algo(api_opts->tc_prf_hash_hidden, 1),
+ check_cipher_chain(api_opts->tc_cipher_hidden, 1),
api_opts->tc_passphrase, api_opts->tc_passphrase_hidden,
api_opts->tc_size_hidden_in_blocks, 0 /* non-interactive */);
View
2 tcplay_api.h
@@ -44,6 +44,8 @@ typedef struct tc_api_opts {
/* Fields for creation */
char *tc_cipher;
char *tc_prf_hash;
+ char *tc_cipher_hidden;
+ char *tc_prf_hash_hidden;
size_t tc_size_hidden_in_blocks;
char *tc_passphrase_hidden;
const char **tc_keyfiles_hidden;
View
7 tcplay_api_test.c
@@ -19,10 +19,12 @@ main(void)
api_opts.tc_passphrase = "apitest2";
api_opts.tc_keyfiles = NULL;
api_opts.tc_keyfiles_hidden = NULL;
- api_opts.tc_size_hidden_in_blocks = 0;
- api_opts.tc_passphrase_hidden = NULL;
+ api_opts.tc_size_hidden_in_blocks = 12000;
+ api_opts.tc_passphrase_hidden = "apihidden";
api_opts.tc_cipher = "AES-256-XTS,TWOFISH-256-XTS,SERPENT-256-XTS";
+ api_opts.tc_cipher_hidden = "SERPENT-256-XTS,TWOFISH-256-XTS";
api_opts.tc_prf_hash = "whirlpool";
+ api_opts.tc_prf_hash_hidden = "RIPEMD160";
error = tc_api_create_volume(&api_opts);
if (error)
@@ -35,6 +37,7 @@ main(void)
error = tc_api_init(/*verbose */ 1);
assert(error == 0);
+ api_opts.tc_passphrase = NULL;
api_opts.tc_map_name = "dragonfly-test";
api_opts.tc_password_retries = 5;
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.