Merge branch 'vendor/LIBARCHIVE'
[dragonfly.git] / lib / libtcplay / tcplay.c
1 /*
2  * Copyright (c) 2011 Alex Hornung <alex@alexhornung.com>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
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
14  *    distribution.
15  *
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
27  * SUCH DAMAGE.
28  */
29
30 #define _BSD_SOURCE
31 #include <sys/types.h>
32 #include <sys/stat.h>
33
34 #if defined(__DragonFly__)
35 #include <sys/param.h>
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <stdarg.h>
41 #include <inttypes.h>
42 #include <unistd.h>
43 #include <errno.h>
44 #include <string.h>
45 #include <err.h>
46 #include <time.h>
47 #if defined(__linux__)
48 #include <libdevmapper.h>
49 #include <uuid/uuid.h>
50 #elif defined(__DragonFly__)
51 #include <libdm.h>
52 #include <uuid.h>
53 #endif
54
55 #include <dirent.h>
56
57 #include "crc32.h"
58 #include "tcplay.h"
59 #include "humanize.h"
60
61
62 /* XXX TODO:
63  *  - LRW-benbi support? needs further work in dm-crypt and even opencrypto
64  *  - secure buffer review (i.e: is everything that needs it using secure mem?)
65  *  - mlockall? (at least MCL_FUTURE, which is the only one we support)
66  */
67
68 summary_fn_t summary_fn = NULL;
69 int tc_internal_verbose = 1;
70 char tc_internal_log_buffer[LOG_BUFFER_SZ];
71 int tc_internal_state = STATE_UNKNOWN;
72
73 void
74 tc_log(int is_err, const char *fmt, ...)
75 {
76         va_list ap;
77         FILE *fp;
78
79         if (is_err)
80                 fp = stderr;
81         else
82                 fp = stdout;
83
84         va_start(ap, fmt);
85
86         vsnprintf(tc_internal_log_buffer, LOG_BUFFER_SZ, fmt, ap);
87
88         va_end(ap);
89
90         if (tc_internal_verbose)
91             fprintf(fp, "%s", tc_internal_log_buffer);
92 }
93
94 /* Supported algorithms */
95 struct pbkdf_prf_algo pbkdf_prf_algos[] = {
96         { "RIPEMD160",  2000 }, /* needs to come before the other RIPEMD160 */
97         { "RIPEMD160",  1000 },
98         { "SHA512",     1000 },
99         { "whirlpool",  1000 },
100         { NULL,         0    }
101 };
102
103 struct tc_crypto_algo tc_crypto_algos[] = {
104 #if 0
105         /* XXX: turns out TC doesn't support AES-128-XTS */
106         { "AES-128-XTS",        "aes-xts-plain",        32,     8 },
107         { "TWOFISH-128-XTS",    "twofish-xts-plain",    32,     8 },
108         { "SERPENT-128-XTS",    "serpent-xts-plain",    32,     8 },
109 #endif
110         { "AES-256-XTS",        "aes-xts-plain64",      64,     8 },
111         { "TWOFISH-256-XTS",    "twofish-xts-plain64",  64,     8 },
112         { "SERPENT-256-XTS",    "serpent-xts-plain64",  64,     8 },
113         { NULL,                 NULL,                   0,      0 }
114 };
115
116 const char *valid_cipher_chains[][MAX_CIPHER_CHAINS] = {
117         { "AES-256-XTS", NULL },
118         { "TWOFISH-256-XTS", NULL },
119         { "SERPENT-256-XTS", NULL },
120         { "AES-256-XTS", "TWOFISH-256-XTS", "SERPENT-256-XTS", NULL },
121         { "SERPENT-256-XTS", "TWOFISH-256-XTS", "AES-256-XTS", NULL },
122 #if 0
123         /* It seems that all the two-way cascades are the other way round... */
124         { "AES-256-XTS", "TWOFISH-256-XTS", NULL },
125         { "SERPENT-256-XTS", "AES-256-XTS", NULL },
126         { "TWOFISH-256-XTS", "SERPENT-256-XTS", NULL },
127
128 #endif
129         { "TWOFISH-256-XTS", "AES-256-XTS", NULL },
130         { "AES-256-XTS", "SERPENT-256-XTS", NULL },
131         { "SERPENT-256-XTS", "TWOFISH-256-XTS", NULL },
132         { NULL }
133 };
134
135 struct tc_cipher_chain *tc_cipher_chains[MAX_CIPHER_CHAINS];
136
137 static
138 int
139 tc_build_cipher_chains(void)
140 {
141         struct tc_cipher_chain *chain, *elem, *prev;
142         int i = 0;
143         int k;
144
145         while (valid_cipher_chains[i][0] != NULL) {
146                 chain = NULL;
147                 prev = NULL;
148                 k = 0;
149
150                 while (valid_cipher_chains[i][k] != NULL) {
151                         if ((elem = alloc_safe_mem(sizeof(*elem))) == NULL) {
152                                 tc_log(1, "Error allocating memory for "
153                                    "cipher chain\n");
154                                 return -1;
155                         }
156
157                         /* Initialize first element of chain */
158                         if (chain == NULL) {
159                                 chain = elem;
160                                 elem->prev = NULL;
161                         }
162
163                         /* Populate previous element */
164                         if (prev != NULL) {
165                                 prev->next = elem;
166                                 elem->prev = prev;
167                         }
168
169                         /* Assume we are the last element in the chain */
170                         elem->next = NULL;
171
172                         /* Initialize other fields */
173                         elem->cipher = check_cipher(valid_cipher_chains[i][k], 0);
174                         if (elem->cipher == NULL)
175                                 return -1;
176
177                         elem->key = NULL;
178
179                         prev = elem;
180                         ++k;
181                 }
182
183                 /* Store cipher chain */
184                 tc_cipher_chains[i++] = chain;
185
186                 /* Integrity check */
187                 if (i >= MAX_CIPHER_CHAINS) {
188                         tc_log(1, "FATAL: tc_cipher_chains is full!!\n");
189                         return -1;
190                 }
191
192                 /* Make sure array is NULL terminated */
193                 tc_cipher_chains[i] = NULL;
194         }
195
196         return 0;
197 }
198
199 static
200 struct tc_cipher_chain *
201 tc_dup_cipher_chain(struct tc_cipher_chain *src)
202 {
203         struct tc_cipher_chain *first = NULL, *prev = NULL, *elem;
204
205         for (; src != NULL; src = src->next) {
206                 if ((elem = alloc_safe_mem(sizeof(*elem))) == NULL) {
207                         tc_log(1, "Error allocating memory for "
208                             "duplicate cipher chain\n");
209                         return NULL;
210                 }
211
212                 memcpy(elem, src, sizeof(*elem));
213
214                 if (src->key != NULL) {
215                         if ((elem->key = alloc_safe_mem(src->cipher->klen)) == NULL) {
216                                 tc_log(1, "Error allocating memory for "
217                                     "duplicate key in cipher chain\n");
218                                 return NULL;
219                         }
220
221                         memcpy(elem->key, src->key, src->cipher->klen);
222                 }
223
224                 if (first == NULL)
225                         first = elem;
226
227                 elem->next = NULL;
228                 elem->prev = prev;
229
230                 if (prev != NULL)
231                         prev->next = elem;
232
233                 prev = elem;
234         }
235
236         return first;
237 }
238
239 static
240 int
241 tc_free_cipher_chain(struct tc_cipher_chain *chain)
242 {
243         struct tc_cipher_chain *next = chain;
244
245         while ((chain = next) != NULL) {
246                 next = chain->next;
247
248                 if (chain->key != NULL)
249                         free_safe_mem(chain->key);
250                 free_safe_mem(chain);
251         }
252
253         return 0;
254 }
255
256 int
257 tc_cipher_chain_length(struct tc_cipher_chain *chain)
258 {
259         int len = 0;
260
261         for (; chain != NULL; chain = chain->next)
262                 ++len;
263
264         return len;
265 }
266
267 int
268 tc_cipher_chain_klen(struct tc_cipher_chain *chain)
269 {
270         int klen_bytes = 0;
271
272         for (; chain != NULL; chain = chain->next) {
273                 klen_bytes += chain->cipher->klen;
274         }
275
276         return klen_bytes;
277 }
278
279 char *
280 tc_cipher_chain_sprint(char *buf, size_t bufsz, struct tc_cipher_chain *chain)
281 {
282         static char sbuf[256];
283         int n = 0;
284
285         if (buf == NULL) {
286                 buf = sbuf;
287                 bufsz = sizeof(sbuf);
288         }
289
290         for (; chain != NULL; chain = chain->next) {
291                 n += snprintf(buf+n, bufsz-n, "%s%s", chain->cipher->name,
292                     (chain->next != NULL) ? "," : "\0");
293         }
294
295         return buf;
296 }
297
298 #ifdef DEBUG
299 static void
300 print_hex(unsigned char *buf, off_t start, size_t len)
301 {
302         size_t i;
303
304         for (i = start; i < start+len; i++)
305                 printf("%02x", buf[i]);
306
307         printf("\n");
308 }
309 #endif
310
311 void
312 print_info(struct tcplay_info *info)
313 {
314         printf("Device:\t\t\t%s\n", info->dev);
315
316         if (info->pbkdf_prf != NULL) {
317                 printf("PBKDF2 PRF:\t\t%s\n", info->pbkdf_prf->name);
318                 printf("PBKDF2 iterations:\t%d\n",
319                     info->pbkdf_prf->iteration_count);
320         }
321
322         printf("Cipher:\t\t\t%s\n",
323             tc_cipher_chain_sprint(NULL, 0, info->cipher_chain));
324
325         printf("Key Length:\t\t%d bits\n",
326             8*tc_cipher_chain_klen(info->cipher_chain));
327
328         if (info->hdr != NULL) {
329                 printf("CRC Key Data:\t\t%#x\n", info->hdr->crc_keys);
330                 printf("Sector size:\t\t%d\n", info->hdr->sec_sz);
331         } else {
332                 printf("Sector size:\t\t512\n");
333         }
334         printf("Volume size:\t\t%"DISKSZ_FMT" sectors\n", info->size);
335 #if 0
336         /* Don't print this; it's always 0 and is rather confusing */
337         printf("Volume offset:\t\t%"PRIu64"\n", (uint64_t)info->start);
338 #endif
339
340 #ifdef DEBUG
341         printf("Vol Flags:\t\t%d\n", info->volflags);
342 #endif
343
344         printf("IV offset:\t\t%"PRIu64" sectors\n",
345             (uint64_t)info->skip);
346         printf("Block offset:\t\t%"PRIu64" sectors\n",
347             (uint64_t)info->offset);
348 }
349
350 static
351 struct tcplay_info *
352 new_info(const char *dev, int flags, struct tc_cipher_chain *cipher_chain,
353     struct pbkdf_prf_algo *prf, struct tchdr_dec *hdr, off_t start)
354 {
355         struct tc_cipher_chain *chain_start;
356         struct tcplay_info *info;
357         int i;
358         int error;
359
360         chain_start = cipher_chain;
361
362         if ((info = (struct tcplay_info *)alloc_safe_mem(sizeof(*info))) == NULL) {
363                 tc_log(1, "could not allocate safe info memory\n");
364                 return NULL;
365         }
366
367         strncpy(info->dev, dev, sizeof(info->dev));
368         info->cipher_chain = cipher_chain;
369         info->pbkdf_prf = prf;
370         info->start = start;
371         info->hdr = hdr;
372         info->blk_sz = hdr->sec_sz;
373         info->size = hdr->sz_mk_scope / hdr->sec_sz;    /* volume size */
374         info->skip = hdr->off_mk_scope / hdr->sec_sz;   /* iv skip */
375
376         info->volflags = hdr->flags;
377         info->flags = flags;
378
379         if (TC_FLAG_SET(flags, SYS))
380                 info->offset = 0; /* offset is 0 for system volumes */
381         else
382                 info->offset = hdr->off_mk_scope / hdr->sec_sz; /* block offset */
383
384         /* Associate a key out of the key pool with each cipher in the chain */
385         error = tc_cipher_chain_populate_keys(cipher_chain, hdr->keys);
386         if (error) {
387                 tc_log(1, "could not populate keys in cipher chain\n");
388                 return NULL;
389         }
390
391         for (; cipher_chain != NULL; cipher_chain = cipher_chain->next) {
392                 for (i = 0; i < cipher_chain->cipher->klen; i++)
393                         sprintf(&cipher_chain->dm_key[i*2], "%02x",
394                             cipher_chain->key[i]);
395         }
396
397         tc_cipher_chain_free_keys(chain_start);
398
399         return info;
400 }
401
402 int
403 free_info(struct tcplay_info *info)
404 {
405         if (info->cipher_chain)
406                 tc_free_cipher_chain(info->cipher_chain);
407         if (info->hdr)
408                 free_safe_mem(info->hdr);
409
410         free_safe_mem(info);
411
412         return 0;
413 }
414
415 int
416 adjust_info(struct tcplay_info *info, struct tcplay_info *hinfo)
417 {
418         if (hinfo->hdr->sz_hidvol == 0)
419                 return 1;
420
421         info->size -= hinfo->hdr->sz_hidvol / hinfo->hdr->sec_sz;
422         return 0;
423 }
424
425 int
426 process_hdr(const char *dev, int flags, unsigned char *pass, int passlen,
427     struct tchdr_enc *ehdr, struct tcplay_info **pinfo)
428 {
429         struct tchdr_dec *dhdr;
430         struct tcplay_info *info;
431         struct tc_cipher_chain *cipher_chain = NULL;
432         unsigned char *key;
433         int i, j, found, error;
434
435         *pinfo = NULL;
436
437         if ((key = alloc_safe_mem(MAX_KEYSZ)) == NULL) {
438                 tc_log(1, "could not allocate safe key memory\n");
439                 return ENOMEM;
440         }
441
442         /* Start search for correct algorithm combination */
443         found = 0;
444         for (i = 0; !found && pbkdf_prf_algos[i].name != NULL; i++) {
445 #ifdef DEBUG
446                 printf("\nTrying PRF algo %s (%d)\n", pbkdf_prf_algos[i].name,
447                     pbkdf_prf_algos[i].iteration_count);
448                 printf("Salt: ");
449                 print_hex(ehdr->salt, 0, sizeof(ehdr->salt));
450 #endif
451                 error = pbkdf2(&pbkdf_prf_algos[i], (char *)pass, passlen,
452                     ehdr->salt, sizeof(ehdr->salt),
453                     MAX_KEYSZ, key);
454
455                 if (error) {
456                         tc_log(1, "pbkdf failed for algorithm %s\n",
457                             pbkdf_prf_algos[i].name);
458                         free_safe_mem(key);
459                         return EINVAL;
460                 }
461
462 #if 0
463                 printf("Derived Key: ");
464                 print_hex(key, 0, MAX_KEYSZ);
465 #endif
466
467                 for (j = 0; !found && tc_cipher_chains[j] != NULL; j++) {
468                         cipher_chain = tc_dup_cipher_chain(tc_cipher_chains[j]);
469 #ifdef DEBUG
470                         printf("\nTrying cipher chain %d\n", j);
471 #endif
472
473                         dhdr = decrypt_hdr(ehdr, cipher_chain, key);
474                         if (dhdr == NULL) {
475                                 tc_log(1, "hdr decryption failed for cipher "
476                                     "chain %d\n", j);
477                                 free_safe_mem(key);
478                                 return EINVAL;
479                         }
480
481                         if (verify_hdr(dhdr)) {
482 #ifdef DEBUG
483                                 printf("tc_str: %.4s, tc_ver: %d, tc_min_ver: %d, "
484                                     "crc_keys: %d, sz_vol: %"PRIu64", "
485                                     "off_mk_scope: %"PRIu64", sz_mk_scope: %"PRIu64", "
486                                     "flags: %d, sec_sz: %d crc_dhdr: %d\n",
487                                     dhdr->tc_str, dhdr->tc_ver, dhdr->tc_min_ver,
488                                     dhdr->crc_keys, dhdr->sz_vol, dhdr->off_mk_scope,
489                                     dhdr->sz_mk_scope, dhdr->flags, dhdr->sec_sz,
490                                     dhdr->crc_dhdr);
491 #endif
492                                 found = 1;
493                         } else {
494                                 free_safe_mem(dhdr);
495                                 tc_free_cipher_chain(cipher_chain);
496                         }
497                 }
498         }
499
500         free_safe_mem(key);
501
502         if (!found)
503                 return EINVAL;
504
505         if ((info = new_info(dev, flags, cipher_chain,
506             &pbkdf_prf_algos[i-1], dhdr, 0)) == NULL) {
507                 free_safe_mem(dhdr);
508                 return ENOMEM;
509         }
510
511         *pinfo = info;
512
513         return 0;
514 }
515
516 int
517 create_volume(struct tcplay_opts *opts)
518 {
519         char *pass, *pass_again;
520         char *h_pass = NULL;
521         char buf[1024];
522         disksz_t blocks, hidden_blocks = 0;
523         size_t blksz;
524         struct tchdr_enc *ehdr, *hehdr;
525         struct tchdr_enc *ehdr_backup, *hehdr_backup;
526         uint64_t tmp;
527         int error, r, ret;
528
529         pass = h_pass = pass_again = NULL;
530         ehdr = hehdr = NULL;
531         ehdr_backup = hehdr_backup = NULL;
532         ret = -1; /* Default to returning error */
533
534         if (opts->cipher_chain == NULL)
535                 opts->cipher_chain = tc_cipher_chains[0];
536         if (opts->prf_algo == NULL)
537                 opts->prf_algo = &pbkdf_prf_algos[0];
538         if (opts->h_cipher_chain == NULL)
539                 opts->h_cipher_chain = opts->cipher_chain;
540         if (opts->h_prf_algo == NULL)
541                 opts->h_prf_algo = opts->prf_algo;
542
543         if ((error = get_disk_info(opts->dev, &blocks, &blksz)) != 0) {
544                 tc_log(1, "could not get disk info\n");
545                 return -1;
546         }
547
548         if ((blocks*blksz) <= MIN_VOL_BYTES) {
549                 tc_log(1, "Cannot create volumes on devices with less "
550                     "than %d bytes\n", MIN_VOL_BYTES);
551                 return -1;
552         }
553
554         if (opts->interactive) {
555                 if (((pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) ||
556                    ((pass_again = alloc_safe_mem(PASS_BUFSZ)) == NULL)) {
557                         tc_log(1, "could not allocate safe passphrase memory\n");
558                         goto out;
559                 }
560
561                 if ((error = read_passphrase("Passphrase: ", pass, MAX_PASSSZ,
562                     PASS_BUFSZ, 0) ||
563                     (read_passphrase("Repeat passphrase: ", pass_again,
564                     MAX_PASSSZ, PASS_BUFSZ, 0)))) {
565                         tc_log(1, "could not read passphrase\n");
566                         goto out;
567                 }
568
569                 if (strcmp(pass, pass_again) != 0) {
570                         tc_log(1, "Passphrases don't match\n");
571                         goto out;
572                 }
573
574                 free_safe_mem(pass_again);
575                 pass_again = NULL;
576         } else {
577                 /* In batch mode, use provided passphrase */
578                 if ((pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) {
579                         tc_log(1, "could not allocate safe "
580                             "passphrase memory");
581                         goto out;
582                 }
583
584                 if (opts->passphrase != NULL) {
585                         strncpy(pass, opts->passphrase, MAX_PASSSZ);
586                         pass[MAX_PASSSZ] = '\0';
587                 }
588         }
589
590         if (opts->nkeyfiles > 0) {
591                 /* Apply keyfiles to 'pass' */
592                 if ((error = apply_keyfiles((unsigned char *)pass, PASS_BUFSZ,
593                     opts->keyfiles, opts->nkeyfiles))) {
594                         tc_log(1, "could not apply keyfiles\n");
595                         goto out;
596                 }
597         }
598
599         if (opts->hidden) {
600                 if (opts->interactive) {
601                         if (((h_pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) ||
602                            ((pass_again = alloc_safe_mem(PASS_BUFSZ)) == NULL)) {
603                                 tc_log(1, "could not allocate safe "
604                                     "passphrase memory\n");
605                                 goto out;
606                         }
607
608                         if ((error = read_passphrase("Passphrase for hidden volume: ",
609                            h_pass, MAX_PASSSZ, PASS_BUFSZ, 0) ||
610                            (read_passphrase("Repeat passphrase: ", pass_again,
611                            MAX_PASSSZ, PASS_BUFSZ, 0)))) {
612                                 tc_log(1, "could not read passphrase\n");
613                                 goto out;
614                         }
615
616                         if (strcmp(h_pass, pass_again) != 0) {
617                                 tc_log(1, "Passphrases for hidden volume don't "
618                                     "match\n");
619                                 goto out;
620                         }
621
622                         free_safe_mem(pass_again);
623                         pass_again = NULL;
624                 } else {
625                         /* In batch mode, use provided passphrase */
626                         if ((h_pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) {
627                                 tc_log(1, "could not allocate safe "
628                                     "passphrase memory");
629                                 goto out;
630                         }
631
632                         if (opts->h_passphrase != NULL) {
633                                 strncpy(h_pass, opts->h_passphrase, MAX_PASSSZ);
634                                 h_pass[MAX_PASSSZ] = '\0';
635                         }
636                 }
637
638                 if (opts->n_hkeyfiles > 0) {
639                         /* Apply keyfiles to 'h_pass' */
640                         if ((error = apply_keyfiles((unsigned char *)h_pass,
641                             PASS_BUFSZ, opts->h_keyfiles, opts->n_hkeyfiles))) {
642                                 tc_log(1, "could not apply keyfiles\n");
643                                 goto out;
644                         }
645                 }
646
647                 if (opts->interactive) {
648                         hidden_blocks = 0;
649                 } else {
650                         hidden_blocks = opts->hidden_size_bytes/blksz;
651                         if (hidden_blocks == 0) {
652                                 tc_log(1, "hidden_blocks to create volume "
653                                     "cannot be zero!\n");
654                                 goto out;
655                         }
656
657                         if (opts->hidden_size_bytes >=
658                             (blocks*blksz) - MIN_VOL_BYTES) {
659                                 tc_log(1, "Hidden volume needs to be "
660                                     "smaller than the outer volume\n");
661                                 goto out;
662                         }
663                 }
664
665                 /* This only happens in interactive mode */
666                 while (hidden_blocks == 0) {
667                         if ((r = _humanize_number(buf, sizeof(buf),
668                             (uint64_t)(blocks * blksz))) < 0) {
669                                 sprintf(buf, "%"DISKSZ_FMT" bytes", (blocks * blksz));
670                         }
671
672                         printf("The total volume size of %s is %s (bytes)\n", opts->dev, buf);
673                         memset(buf, 0, sizeof(buf));
674                         printf("Size of hidden volume (e.g. 127M):  ");
675                         fflush(stdout);
676
677                         if ((fgets(buf, sizeof(buf), stdin)) == NULL) {
678                                 tc_log(1, "Could not read from stdin\n");
679                                 goto out;
680                         }
681
682                         /* get rid of trailing newline */
683                         buf[strlen(buf)-1] = '\0';
684                         if ((error = _dehumanize_number(buf,
685                             &tmp)) != 0) {
686                                 tc_log(1, "Could not interpret input: %s\n", buf);
687                                 continue;
688                         }
689
690                         if (tmp >= (blocks*blksz) - MIN_VOL_BYTES) {
691                                 tc_log(1, "Hidden volume needs to be "
692                                     "smaller than the outer volume\n");
693                                 hidden_blocks = 0;
694                                 continue;
695                         }
696
697                         hidden_blocks = (size_t)tmp;
698                         hidden_blocks /= blksz;
699                 }
700         }
701
702         if (opts->interactive) {
703                 /* Show summary and ask for confirmation */
704                 printf("Summary of actions:\n");
705                 if (opts->secure_erase)
706                         printf(" - Completely erase *EVERYTHING* on %s\n", opts->dev);
707                 printf(" - Create %svolume on %s\n", opts->hidden?("outer "):"", opts->dev);
708                 if (opts->hidden) {
709                         printf(" - Create hidden volume of %"DISKSZ_FMT" bytes at end of "
710                             "outer volume\n",
711                             hidden_blocks * blksz);
712                 }
713
714                 printf("\n Are you sure you want to proceed? (y/n) ");
715                 fflush(stdout);
716                 if ((fgets(buf, sizeof(buf), stdin)) == NULL) {
717                         tc_log(1, "Could not read from stdin\n");
718                         goto out;
719                 }
720
721                 if ((buf[0] != 'y') && (buf[0] != 'Y')) {
722                         tc_log(1, "User cancelled action(s)\n");
723                         goto out;
724                 }
725         }
726
727         /* erase volume */
728         if (opts->secure_erase) {
729                 tc_log(0, "Securely erasing the volume...\nThis process may take "
730                     "some time depending on the size of the volume\n");
731
732                 if (opts->state_change_fn)
733                         opts->state_change_fn(opts->api_ctx, "secure_erase", 1);
734
735                 if ((error = secure_erase(opts->dev, blocks * blksz, blksz)) != 0) {
736                         tc_log(1, "could not securely erase device %s\n", opts->dev);
737                         goto out;
738                 }
739
740                 if (opts->state_change_fn)
741                         opts->state_change_fn(opts->api_ctx, "secure_erase", 0);
742         }
743
744         tc_log(0, "Creating volume headers...\nDepending on your system, this "
745             "process may take a few minutes as it uses true random data which "
746             "might take a while to refill\n");
747
748         if (opts->weak_keys_and_salt) {
749                 tc_log(0, "WARNING: Using a weak random generator to get "
750                     "entropy for the key material. Odds are this is NOT "
751                     "what you want.\n");
752         }
753
754         if (opts->state_change_fn)
755                 opts->state_change_fn(opts->api_ctx, "create_header", 1);
756
757         /* create encrypted headers */
758         ehdr = create_hdr((unsigned char *)pass,
759             (opts->nkeyfiles > 0)?MAX_PASSSZ:strlen(pass),
760             opts->prf_algo, opts->cipher_chain, blksz, blocks, VOL_RSVD_BYTES_START/blksz,
761             blocks - (MIN_VOL_BYTES/blksz), 0, opts->weak_keys_and_salt, &ehdr_backup);
762         if (ehdr == NULL) {
763                 tc_log(1, "Could not create header\n");
764                 goto out;
765         }
766
767         if (opts->hidden) {
768                 hehdr = create_hdr((unsigned char *)h_pass,
769                     (opts->n_hkeyfiles > 0)?MAX_PASSSZ:strlen(h_pass), opts->h_prf_algo,
770                     opts->h_cipher_chain,
771                     blksz, blocks,
772                     blocks - (VOL_RSVD_BYTES_END/blksz) - hidden_blocks,
773                     hidden_blocks, 1, opts->weak_keys_and_salt, &hehdr_backup);
774                 if (hehdr == NULL) {
775                         tc_log(1, "Could not create hidden volume header\n");
776                         goto out;
777                 }
778         }
779
780         if (opts->state_change_fn)
781                 opts->state_change_fn(opts->api_ctx, "create_header", 0);
782
783         tc_log(0, "Writing volume headers to disk...\n");
784
785         if ((error = write_to_disk(opts->dev, 0, blksz, ehdr, sizeof(*ehdr))) != 0) {
786                 tc_log(1, "Could not write volume header to device\n");
787                 goto out;
788         }
789
790         /* Write backup header; it's offset is relative to the end */
791         if ((error = write_to_disk(opts->dev, (blocks*blksz - BACKUP_HDR_OFFSET_END),
792             blksz, ehdr_backup, sizeof(*ehdr_backup))) != 0) {
793                 tc_log(1, "Could not write backup volume header to device\n");
794                 goto out;
795         }
796
797         if (opts->hidden) {
798                 if ((error = write_to_disk(opts->dev, HDR_OFFSET_HIDDEN, blksz, hehdr,
799                     sizeof(*hehdr))) != 0) {
800                         tc_log(1, "Could not write hidden volume header to "
801                             "device\n");
802                         goto out;
803                 }
804
805                 /* Write backup hidden header; offset is relative to end */
806                 if ((error = write_to_disk(opts->dev,
807                     (blocks*blksz - BACKUP_HDR_HIDDEN_OFFSET_END), blksz,
808                     hehdr_backup, sizeof(*hehdr_backup))) != 0) {
809                         tc_log(1, "Could not write backup hidden volume "
810                             "header to device\n");
811                         goto out;
812                 }
813         }
814
815         /* Everything went ok */
816         tc_log(0, "All done!\n");
817
818         ret = 0;
819
820 out:
821         if (pass)
822                 free_safe_mem(pass);
823         if (h_pass)
824                 free_safe_mem(h_pass);
825         if (pass_again)
826                 free_safe_mem(pass_again);
827         if (ehdr)
828                 free_safe_mem(ehdr);
829         if (hehdr)
830                 free_safe_mem(hehdr);
831         if (ehdr_backup)
832                 free_safe_mem(ehdr_backup);
833         if (hehdr_backup)
834                 free_safe_mem(hehdr_backup);
835
836         return ret;
837 }
838
839 struct tcplay_info *
840 info_map_common(struct tcplay_opts *opts, char *passphrase_out)
841 {
842         struct tchdr_enc *ehdr, *hehdr = NULL;
843         struct tcplay_info *info, *hinfo = NULL;
844         char *pass;
845         char *h_pass;
846         int error, error2 = 0;
847         size_t sz;
848         size_t blksz;
849         disksz_t blocks;
850         int is_hidden = 0;
851         int try_empty = 0;
852         int retries;
853
854         if ((error = get_disk_info(opts->dev, &blocks, &blksz)) != 0) {
855                 tc_log(1, "could not get disk information\n");
856                 return NULL;
857         }
858
859         if (opts->retries < 1)
860                 retries = 1;
861         else
862                 retries = opts->retries;
863
864         /*
865          * Add one retry so we can do a first try without asking for
866          * a password if keyfiles are passed in.
867          */
868         if (opts->interactive && (opts->nkeyfiles > 0)) {
869                 try_empty = 1;
870                 ++retries;
871         }
872
873         info = NULL;
874
875         ehdr = NULL;
876         pass = h_pass = NULL;
877
878         while ((info == NULL) && retries-- > 0)
879         {
880                 pass = h_pass = NULL;
881                 ehdr = hehdr = NULL;
882                 info = hinfo = NULL;
883
884                 if ((pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) {
885                         tc_log(1, "could not allocate safe passphrase memory\n");
886                         goto out;
887                 }
888
889                 if (try_empty) {
890                         pass[0] = '\0';
891                 } else if (opts->interactive) {
892                         if ((error = read_passphrase("Passphrase: ", pass,
893                             MAX_PASSSZ, PASS_BUFSZ, opts->timeout))) {
894                                 tc_log(1, "could not read passphrase\n");
895                                 /* XXX: handle timeout differently? */
896                                 goto out;
897                         }
898                         pass[MAX_PASSSZ] = '\0';
899                 } else {
900                         /* In batch mode, use provided passphrase */
901                         if (opts->passphrase != NULL) {
902                                 strncpy(pass, opts->passphrase, MAX_PASSSZ);
903                                 pass[MAX_PASSSZ] = '\0';
904                         }
905                 }
906
907                 if (passphrase_out != NULL) {
908                         strcpy(passphrase_out, pass);
909                 }
910
911                 if (opts->nkeyfiles > 0) {
912                         /* Apply keyfiles to 'pass' */
913                         if ((error = apply_keyfiles((unsigned char *)pass, PASS_BUFSZ,
914                             opts->keyfiles, opts->nkeyfiles))) {
915                                 tc_log(1, "could not apply keyfiles");
916                                 goto out;
917                         }
918                 }
919
920                 if (opts->protect_hidden) {
921                         if ((h_pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) {
922                                 tc_log(1, "could not allocate safe passphrase memory\n");
923                                 goto out;
924                         }
925
926                         if (opts->interactive) {
927                                 if ((error = read_passphrase(
928                                     "Passphrase for hidden volume: ", h_pass,
929                                     MAX_PASSSZ, PASS_BUFSZ, opts->timeout))) {
930                                         tc_log(1, "could not read passphrase\n");
931                                         goto out;
932                                 }
933                                 h_pass[MAX_PASSSZ] = '\0';
934                         } else {
935                                 /* In batch mode, use provided passphrase */
936                                 if (opts->h_passphrase != NULL) {
937                                         strncpy(h_pass, opts->h_passphrase, MAX_PASSSZ);
938                                         h_pass[MAX_PASSSZ] = '\0';
939                                 }
940                         }
941
942                         if (opts->n_hkeyfiles > 0) {
943                                 /* Apply keyfiles to 'pass' */
944                                 if ((error = apply_keyfiles((unsigned char *)h_pass, PASS_BUFSZ,
945                                     opts->h_keyfiles, opts->n_hkeyfiles))) {
946                                         tc_log(1, "could not apply keyfiles");
947                                         goto out;
948                                 }
949                         }
950                 }
951
952                 /* Always read blksz-sized chunks */
953                 sz = blksz;
954
955                 if (TC_FLAG_SET(opts->flags, HDR_FROM_FILE)) {
956                         ehdr = (struct tchdr_enc *)read_to_safe_mem(
957                             opts->hdr_file_in, 0, &sz);
958                         if (ehdr == NULL) {
959                                 tc_log(1, "error read hdr_enc: %s", opts->hdr_file_in);
960                                 goto out;
961                         }
962                 } else {
963                         ehdr = (struct tchdr_enc *)read_to_safe_mem(
964                             (TC_FLAG_SET(opts->flags, SYS)) ? opts->sys_dev : opts->dev,
965                             (TC_FLAG_SET(opts->flags, SYS) || TC_FLAG_SET(opts->flags, FDE)) ?
966                             HDR_OFFSET_SYS :
967                             (!TC_FLAG_SET(opts->flags, BACKUP)) ? 0 : -BACKUP_HDR_OFFSET_END,
968                             &sz);
969                         if (ehdr == NULL) {
970                                 tc_log(1, "error read hdr_enc: %s", opts->dev);
971                                 goto out;
972                         }
973                 }
974
975                 if (!TC_FLAG_SET(opts->flags, SYS)) {
976                         /* Always read blksz-sized chunks */
977                         sz = blksz;
978
979                         if (TC_FLAG_SET(opts->flags, H_HDR_FROM_FILE)) {
980                                 hehdr = (struct tchdr_enc *)read_to_safe_mem(
981                                     opts->h_hdr_file_in, 0, &sz);
982                                 if (hehdr == NULL) {
983                                         tc_log(1, "error read hdr_enc: %s", opts->h_hdr_file_in);
984                                         goto out;
985                                 }
986                         } else {
987                                 hehdr = (struct tchdr_enc *)read_to_safe_mem(opts->dev,
988                                     (!TC_FLAG_SET(opts->flags, BACKUP)) ? HDR_OFFSET_HIDDEN :
989                                     -BACKUP_HDR_HIDDEN_OFFSET_END, &sz);
990                                 if (hehdr == NULL) {
991                                         tc_log(1, "error read hdr_enc: %s", opts->dev);
992                                         goto out;
993                                 }
994                         }
995                 } else {
996                         hehdr = NULL;
997                 }
998
999                 error = process_hdr(opts->dev, opts->flags, (unsigned char *)pass,
1000                     (opts->nkeyfiles > 0)?MAX_PASSSZ:strlen(pass),
1001                     ehdr, &info);
1002
1003                 /*
1004                  * Try to process hidden header if we have to protect the hidden
1005                  * volume, or the decryption/verification of the main header
1006                  * failed.
1007                  */
1008                 if (hehdr && (error || opts->protect_hidden)) {
1009                         if (error) {
1010                                 error2 = process_hdr(opts->dev, opts->flags, (unsigned char *)pass,
1011                                     (opts->nkeyfiles > 0)?MAX_PASSSZ:strlen(pass), hehdr,
1012                                     &info);
1013                                 is_hidden = !error2;
1014                         } else if (opts->protect_hidden) {
1015                                 error2 = process_hdr(opts->dev, opts->flags, (unsigned char *)h_pass,
1016                                     (opts->n_hkeyfiles > 0)?MAX_PASSSZ:strlen(h_pass), hehdr,
1017                                     &hinfo);
1018                         }
1019                 }
1020
1021                 /* We need both to protect a hidden volume */
1022                 if ((opts->protect_hidden && (error || error2)) ||
1023                     (error && error2)) {
1024                         if (!try_empty)
1025                                 tc_log(1, "Incorrect password or not a TrueCrypt volume\n");
1026
1027                         if (info) {
1028                                 free_info(info);
1029                                 info = NULL;
1030                         }
1031                         if (hinfo) {
1032                                 free_info(hinfo);
1033                                 hinfo = NULL;
1034                         }
1035
1036                         /* Try again (or finish) */
1037                         free_safe_mem(pass);
1038                         pass = NULL;
1039
1040                         if (h_pass) {
1041                                 free_safe_mem(h_pass);
1042                                 h_pass = NULL;
1043                         }
1044                         if (ehdr) {
1045                                 free_safe_mem(ehdr);
1046                                 ehdr = NULL;
1047                         }
1048                         if (hehdr) {
1049                                 free_safe_mem(hehdr);
1050                                 hehdr = NULL;
1051                         }
1052
1053                         try_empty = 0;
1054                         continue;
1055                 }
1056
1057                 if (opts->protect_hidden) {
1058                         if (adjust_info(info, hinfo) != 0) {
1059                                 tc_log(1, "Could not protect hidden volume\n");
1060                                 if (info)
1061                                         free_info(info);
1062                                 info = NULL;
1063
1064                                 if (hinfo)
1065                                         free_info(hinfo);
1066                                 hinfo = NULL;
1067
1068                                 goto out;
1069                         }
1070
1071                         if (hinfo) {
1072                                 free_info(hinfo);
1073                                 hinfo = NULL;
1074                         }
1075                 }
1076                 try_empty = 0;
1077         }
1078
1079 out:
1080         if (hinfo)
1081                 free_info(hinfo);
1082         if (pass)
1083                 free_safe_mem(pass);
1084         if (h_pass)
1085                 free_safe_mem(h_pass);
1086         if (ehdr)
1087                 free_safe_mem(ehdr);
1088         if (hehdr)
1089                 free_safe_mem(hehdr);
1090
1091         if (info != NULL)
1092                 info->hidden = is_hidden;
1093
1094         return info;
1095 }
1096
1097 int
1098 info_mapped_volume(struct tcplay_opts *opts)
1099 {
1100         struct tcplay_info *info;
1101
1102         info = dm_info_map(opts->map_name);
1103         if (info != NULL) {
1104                 if (opts->interactive)
1105                         print_info(info);
1106
1107                 free_info(info);
1108
1109                 return 0;
1110                 /* NOT REACHED */
1111         } else if (opts->interactive) {
1112                 tc_log(1, "Could not retrieve information about mapped "
1113                     "volume %s. Does it exist?\n", opts->map_name);
1114         }
1115
1116         return -1;
1117 }
1118
1119 int
1120 info_volume(struct tcplay_opts *opts)
1121 {
1122         struct tcplay_info *info;
1123
1124         info = info_map_common(opts, NULL);
1125
1126         if (info != NULL) {
1127                 if (opts->interactive)
1128                         print_info(info);
1129
1130                 free_info(info);
1131
1132                 return 0;
1133                 /* NOT REACHED */
1134         }
1135
1136         return -1;
1137 }
1138
1139 int
1140 map_volume(struct tcplay_opts *opts)
1141 {
1142         struct tcplay_info *info;
1143         int error;
1144
1145         info = info_map_common(opts, NULL);
1146
1147         if (info == NULL)
1148                 return -1;
1149
1150         if ((error = dm_setup(opts->map_name, info)) != 0) {
1151                 tc_log(1, "Could not set up mapping %s\n", opts->map_name);
1152                 free_info(info);
1153                 return -1;
1154         }
1155
1156         if (opts->interactive)
1157                 printf("All ok!\n");
1158
1159         free_info(info);
1160
1161         return 0;
1162 }
1163
1164 int
1165 modify_volume(struct tcplay_opts *opts)
1166 {
1167         struct tcplay_info *info;
1168         struct tchdr_enc *ehdr, *ehdr_backup;
1169         const char *new_passphrase = opts->new_passphrase;
1170         const char **new_keyfiles = opts->new_keyfiles;
1171         struct pbkdf_prf_algo *new_prf_algo = opts->new_prf_algo;
1172         int n_newkeyfiles = opts->n_newkeyfiles;
1173         char *pass, *pass_again;
1174         int ret = -1;
1175         off_t offset, offset_backup = 0;
1176         const char *dev;
1177         size_t blksz;
1178         disksz_t blocks;
1179         int error;
1180
1181         ehdr = ehdr_backup = NULL;
1182         pass = pass_again = NULL;
1183         info = NULL;
1184
1185         if (TC_FLAG_SET(opts->flags, ONLY_RESTORE)) {
1186                 if (opts->interactive) {
1187                         if ((pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) {
1188                                 tc_log(1, "could not allocate safe "
1189                                     "passphrase memory");
1190                                 goto out;
1191                         }
1192                 } else {
1193                         new_passphrase = opts->passphrase;
1194                 }
1195                 new_keyfiles = opts->keyfiles;
1196                 n_newkeyfiles = opts->nkeyfiles;
1197                 new_prf_algo = NULL;
1198         }
1199
1200         info = info_map_common(opts, pass);
1201         if (info == NULL)
1202                 goto out;
1203
1204         if (opts->interactive && !TC_FLAG_SET(opts->flags, ONLY_RESTORE)) {
1205                 if (((pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) ||
1206                    ((pass_again = alloc_safe_mem(PASS_BUFSZ)) == NULL)) {
1207                         tc_log(1, "could not allocate safe passphrase memory\n");
1208                         goto out;
1209                 }
1210
1211                 if ((error = read_passphrase("New passphrase: ", pass, MAX_PASSSZ,
1212                     PASS_BUFSZ, 0) ||
1213                     (read_passphrase("Repeat passphrase: ", pass_again,
1214                     MAX_PASSSZ, PASS_BUFSZ, 0)))) {
1215                         tc_log(1, "could not read passphrase\n");
1216                         goto out;
1217                 }
1218
1219                 if (strcmp(pass, pass_again) != 0) {
1220                         tc_log(1, "Passphrases don't match\n");
1221                         goto out;
1222                 }
1223
1224                 free_safe_mem(pass_again);
1225                 pass_again = NULL;
1226         } else if (!opts->interactive) {
1227                 /* In batch mode, use provided passphrase */
1228                 if ((pass = alloc_safe_mem(PASS_BUFSZ)) == NULL) {
1229                         tc_log(1, "could not allocate safe "
1230                             "passphrase memory");
1231                         goto out;
1232                 }
1233
1234                 if (new_passphrase != NULL) {
1235                         strncpy(pass, new_passphrase, MAX_PASSSZ);
1236                         pass[MAX_PASSSZ] = '\0';
1237                 }
1238         }
1239
1240         if (n_newkeyfiles > 0) {
1241                 /* Apply keyfiles to 'pass' */
1242                 if ((error = apply_keyfiles((unsigned char *)pass, PASS_BUFSZ,
1243                     new_keyfiles, n_newkeyfiles))) {
1244                         tc_log(1, "could not apply keyfiles\n");
1245                         goto out;
1246                 }
1247         }
1248
1249         ehdr = copy_reencrypt_hdr((unsigned char *)pass,
1250             (opts->n_newkeyfiles > 0)?MAX_PASSSZ:strlen(pass),
1251             new_prf_algo, opts->weak_keys_and_salt, info, &ehdr_backup);
1252         if (ehdr == NULL) {
1253                 tc_log(1, "Could not create header\n");
1254                 goto out;
1255         }
1256
1257         dev = (TC_FLAG_SET(opts->flags, SYS)) ? opts->sys_dev : opts->dev;
1258         if (TC_FLAG_SET(opts->flags, SYS) || TC_FLAG_SET(opts->flags, FDE)) {
1259                 /* SYS and FDE don't have backup headers (as far as I understand) */
1260                 if (info->hidden) {
1261                         offset = HDR_OFFSET_HIDDEN;
1262                 } else {
1263                         offset = HDR_OFFSET_SYS;
1264                 }
1265         } else {
1266                 if (info->hidden) {
1267                         offset = HDR_OFFSET_HIDDEN;
1268                         offset_backup = -BACKUP_HDR_HIDDEN_OFFSET_END;
1269                 } else {
1270                         offset = 0;
1271                         offset_backup = -BACKUP_HDR_OFFSET_END;
1272                 }
1273         }
1274
1275         if ((error = get_disk_info(dev, &blocks, &blksz)) != 0) {
1276                 tc_log(1, "could not get disk information\n");
1277                 goto out;
1278         }
1279
1280         tc_log(0, "Writing new volume headers to disk/file...\n");
1281
1282         if (TC_FLAG_SET(opts->flags, SAVE_TO_FILE)) {
1283                 if ((error = write_to_file(opts->hdr_file_out, ehdr, sizeof(*ehdr))) != 0) {
1284                         tc_log(1, "Could not write volume header to file\n");
1285                         goto out;
1286                 }
1287         } else {
1288                 if ((error = write_to_disk(dev, offset, blksz, ehdr,
1289                     sizeof(*ehdr))) != 0) {
1290                         tc_log(1, "Could not write volume header to device\n");
1291                         goto out;
1292                 }
1293
1294                 if (!TC_FLAG_SET(opts->flags, SYS) && !TC_FLAG_SET(opts->flags, FDE)) {
1295                         if ((error = write_to_disk(dev, offset_backup, blksz,
1296                             ehdr_backup, sizeof(*ehdr_backup))) != 0) {
1297                                 tc_log(1, "Could not write backup volume header to device\n");
1298                                 goto out;
1299                         }
1300                 }
1301         }
1302
1303         /* Everything went ok */
1304         tc_log(0, "All done!\n");
1305
1306         ret = 0;
1307
1308 out:
1309         if (pass)
1310                 free_safe_mem(pass);
1311         if (pass_again)
1312                 free_safe_mem(pass_again);
1313         if (ehdr)
1314                 free_safe_mem(ehdr);
1315         if (ehdr_backup)
1316                 free_safe_mem(ehdr_backup);
1317         if (info)
1318                 free_safe_mem(info);
1319
1320         return ret;
1321 }
1322
1323 static
1324 int
1325 dm_get_info(const char *name, struct dm_info *dmi)
1326 {
1327         struct dm_task *dmt = NULL;
1328         int error = -1;
1329
1330         if ((dmt = dm_task_create(DM_DEVICE_INFO)) == NULL)
1331                 goto out;
1332
1333         if ((dm_task_set_name(dmt, name)) == 0)
1334                 goto out;
1335
1336         if ((dm_task_run(dmt)) == 0)
1337                 goto out;
1338
1339         if ((dm_task_get_info(dmt, dmi)) == 0)
1340                 goto out;
1341
1342         error = 0;
1343
1344 out:
1345         if (dmt)
1346                 dm_task_destroy(dmt);
1347
1348         return error;
1349 }
1350
1351 #if defined(__DragonFly__)
1352 static
1353 int
1354 xlate_maj_min(const char *start_path __unused, int max_depth __unused,
1355     char *buf, size_t bufsz, uint32_t maj, uint32_t min)
1356 {
1357         dev_t dev = makedev(maj, min);
1358
1359         snprintf(buf, bufsz, "/dev/%s", devname(dev, S_IFCHR));
1360         return 1;
1361 }
1362 #else
1363 static
1364 int
1365 xlate_maj_min(const char *start_path, int max_depth, char *buf, size_t bufsz,
1366     uint32_t maj, uint32_t min)
1367 {
1368         dev_t dev = makedev(maj, min);
1369         char path[PATH_MAX];
1370         struct stat sb;
1371         struct dirent *ent;
1372         DIR *dirp;
1373         int found = 0;
1374
1375         if (max_depth <= 0)
1376                 return -1;
1377
1378         if ((dirp = opendir(start_path)) == NULL)
1379                 return -1;
1380
1381         while ((ent = readdir(dirp)) != NULL) {
1382                 /* d_name, d_type, DT_BLK, DT_CHR, DT_DIR, DT_LNK */
1383                 if (ent->d_name[0] == '.')
1384                         continue;
1385
1386                 /* Linux' /dev is littered with junk, so skip over it */
1387                 /*
1388                  * The dm-<number> devices seem to be the raw DM devices
1389                  * things in mapper/ link to.
1390                  */
1391                 if (((strcmp(ent->d_name, "block")) == 0) ||
1392                     ((strcmp(ent->d_name, "fd")) == 0) ||
1393                     (((strncmp(ent->d_name, "dm-", 3) == 0) && strlen(ent->d_name) <= 5)))
1394                         continue;
1395
1396                 snprintf(path, PATH_MAX, "%s/%s", start_path, ent->d_name);
1397
1398                 if ((stat(path, &sb)) < 0)
1399                         continue;
1400
1401                 if (S_ISDIR(sb.st_mode)) {
1402                         found = !xlate_maj_min(path, max_depth-1, buf, bufsz, maj, min);
1403                         if (found)
1404                                 break;
1405                 }
1406
1407                 if (!S_ISBLK(sb.st_mode))
1408                         continue;
1409
1410                 if (sb.st_rdev != dev)
1411                         continue;
1412
1413                 snprintf(buf, bufsz, "%s", path);
1414                 found = 1;
1415                 break;
1416         }
1417
1418         if (dirp)
1419                 closedir(dirp);
1420
1421         return found ? 0 : -ENOENT;
1422 }
1423 #endif
1424
1425 static
1426 struct tcplay_dm_table *
1427 dm_get_table(const char *name)
1428 {
1429         struct tcplay_dm_table *tc_table;
1430         struct dm_task *dmt = NULL;
1431         void *next = NULL;
1432         uint64_t start, length;
1433         char *target_type;
1434         char *params;
1435         char *p1;
1436         int c = 0;
1437         uint32_t maj, min;
1438
1439         if ((tc_table = (struct tcplay_dm_table *)alloc_safe_mem(sizeof(*tc_table))) == NULL) {
1440                 tc_log(1, "could not allocate safe tc_table memory\n");
1441                 return NULL;
1442         }
1443
1444         if ((dmt = dm_task_create(DM_DEVICE_TABLE)) == NULL)
1445                 goto error;
1446
1447         if ((dm_task_set_name(dmt, name)) == 0)
1448                 goto error;
1449
1450         if ((dm_task_run(dmt)) == 0)
1451                 goto error;
1452
1453         tc_table->start = (off_t)0;
1454         tc_table->size = (size_t)0;
1455
1456         do {
1457                 next = dm_get_next_target(dmt, next, &start, &length,
1458                     &target_type, &params);
1459
1460                 tc_table->size += (size_t)length;
1461                 strncpy(tc_table->target, target_type,
1462                     sizeof(tc_table->target));
1463
1464                 /* Skip any leading whitespace */
1465                 while (params && *params == ' ')
1466                         params++;
1467
1468                 if (strcmp(target_type, "crypt") == 0) {
1469                         while ((p1 = strsep(&params, " ")) != NULL) {
1470                                 /* Skip any whitespace before the next strsep */
1471                                 while (params && *params == ' ')
1472                                         params++;
1473
1474                                 /* Process p1 */
1475                                 if (c == 0) {
1476                                         /* cipher */
1477                                         strncpy(tc_table->cipher, p1,
1478                                             sizeof(tc_table->cipher));
1479                                 } else if (c == 2) {
1480                                         /* iv offset */
1481                                         tc_table->skip = (off_t)strtoll(p1, NULL, 10);
1482                                 } else if (c == 3) {
1483                                         /* major:minor */
1484                                         maj = strtoul(p1, NULL, 10);
1485                                         while (*p1 != ':' && *p1 != '\0')
1486                                                 p1++;
1487                                         min = strtoul(++p1, NULL, 10);
1488                                         if ((xlate_maj_min("/dev", 2, tc_table->device,
1489                                             sizeof(tc_table->device), maj, min)) != 0)
1490                                                 snprintf(tc_table->device,
1491                                                     sizeof(tc_table->device),
1492                                                     "%u:%u", maj, min);
1493                                 } else if (c == 4) {
1494                                         /* block offset */
1495                                         tc_table->offset = (off_t)strtoll(p1,
1496                                             NULL, 10);
1497                                 }
1498                                 ++c;
1499                         }
1500
1501                         if (c < 5) {
1502                                 tc_log(1, "could not get all the info required from "
1503                                     "the table\n");
1504                                 goto error;
1505                         }
1506                 }
1507         } while (next != NULL);
1508
1509         if (dmt)
1510                 dm_task_destroy(dmt);
1511
1512 #ifdef DEBUG
1513         printf("device: %s\n", tc_table->device);
1514         printf("target: %s\n", tc_table->target);
1515         printf("cipher: %s\n", tc_table->cipher);
1516         printf("size:   %ju\n", tc_table->size);
1517         printf("offset: %"PRId64"\n", tc_table->offset);
1518         printf("skip:   %"PRId64"\n", tc_table->skip);
1519 #endif
1520
1521         return tc_table;
1522
1523 error:
1524         if (dmt)
1525                 dm_task_destroy(dmt);
1526         if (tc_table)
1527                 free_safe_mem(tc_table);
1528
1529         return NULL;
1530 }
1531
1532 struct tcplay_info *
1533 dm_info_map(const char *map_name)
1534 {
1535         struct dm_task *dmt = NULL;
1536         struct dm_info dmi[3];
1537         struct tcplay_dm_table *dm_table[3];
1538         struct tc_crypto_algo *crypto_algo;
1539         struct tcplay_info *info;
1540         char map[PATH_MAX];
1541         char ciphers[512];
1542         int i, outermost = -1;
1543
1544         memset(dm_table, 0, sizeof(dm_table));
1545
1546         if ((info = (struct tcplay_info *)alloc_safe_mem(sizeof(*info))) == NULL) {
1547                 tc_log(1, "could not allocate safe info memory\n");
1548                 return NULL;
1549         }
1550
1551         strncpy(map, map_name, PATH_MAX);
1552         for (i = 0; i < 3; i++) {
1553                 if ((dm_get_info(map, &dmi[i])) != 0)
1554                         goto error;
1555
1556                 if (dmi[i].exists)
1557                         dm_table[i] = dm_get_table(map);
1558
1559                 snprintf(map, PATH_MAX, "%s.%d", map_name, i);
1560         }
1561
1562         if (dmt)
1563                 dm_task_destroy(dmt);
1564
1565         if (dm_table[0] == NULL)
1566                 goto error;
1567
1568         /*
1569          * Process our dmi, dm_table fun into the info structure.
1570          */
1571         /* First find which cipher chain we are using */
1572         ciphers[0] = '\0';
1573         for (i = 0; i < 3; i++) {
1574                 if (dm_table[i] == NULL)
1575                         continue;
1576
1577                 if (outermost < i)
1578                         outermost = i;
1579
1580                 crypto_algo = &tc_crypto_algos[0];
1581                 while ((crypto_algo != NULL) &&
1582                     (strcmp(dm_table[i]->cipher, crypto_algo->dm_crypt_str) != 0))
1583                         ++crypto_algo;
1584                 if (crypto_algo == NULL) {
1585                         tc_log(1, "could not find corresponding cipher\n");
1586                         goto error;
1587                 }
1588                 strcat(ciphers, crypto_algo->name);
1589                 strcat(ciphers, ",");
1590         }
1591         ciphers[strlen(ciphers)-1] = '\0';
1592
1593         info->cipher_chain = check_cipher_chain(ciphers, 1);
1594         if (info->cipher_chain == NULL) {
1595                 tc_log(1, "could not find cipher chain\n");
1596                 goto error;
1597         }
1598
1599         /* Copy over the name */
1600         strncpy(info->dev, dm_table[outermost]->device, sizeof(info->dev));
1601
1602         /* Other fields */
1603         info->hdr = NULL;
1604         info->pbkdf_prf = NULL;
1605         info->start = dm_table[outermost]->start;
1606         info->size = dm_table[0]->size;
1607         info->skip = dm_table[outermost]->skip;
1608         info->offset = dm_table[outermost]->offset;
1609         info->blk_sz = 512;
1610
1611         return info;
1612
1613 error:
1614         if (dmt)
1615                 dm_task_destroy(dmt);
1616         if (info)
1617                 free_safe_mem(info);
1618         for (i = 0; i < 3; i++)
1619                 if (dm_table[i] != NULL)
1620                         free_safe_mem(dm_table[i]);
1621
1622         return NULL;
1623 }
1624
1625 static
1626 int
1627 dm_exists_device(const char *name)
1628 {
1629         struct dm_info dmi;
1630         int exists = 0;
1631
1632         if (dm_get_info(name, &dmi) != 0)
1633                 goto out;
1634
1635         exists = dmi.exists;
1636
1637 out:
1638         return exists;
1639 }
1640
1641 static
1642 int
1643 dm_remove_device(const char *name)
1644 {
1645         struct dm_task *dmt = NULL;
1646         int ret = EINVAL;
1647
1648         if ((dmt = dm_task_create(DM_DEVICE_REMOVE)) == NULL)
1649                 goto out;
1650
1651         if ((dm_task_set_name(dmt, name)) == 0)
1652                 goto out;
1653
1654         if ((dm_task_run(dmt)) == 0)
1655                 goto out;
1656
1657         ret = 0;
1658 out:
1659         if (dmt)
1660                 dm_task_destroy(dmt);
1661
1662         return ret;
1663 }
1664
1665 int
1666 dm_setup(const char *mapname, struct tcplay_info *info)
1667 {
1668         struct tc_cipher_chain *cipher_chain;
1669         struct dm_task *dmt = NULL;
1670         struct dm_info dmi;
1671         char *params = NULL;
1672         char *uu, *uu_temp;
1673         char *uu_stack[64];
1674         int uu_stack_idx;
1675 #if defined(__DragonFly__)
1676         uint32_t status;
1677 #endif
1678         int r, ret = 0;
1679         int j, len;
1680         off_t start, offset;
1681         char dev[PATH_MAX];
1682         char map[PATH_MAX];
1683         uint32_t cookie;
1684
1685         dm_udev_set_sync_support(1);
1686
1687         if ((params = alloc_safe_mem(512)) == NULL) {
1688                 tc_log(1, "could not allocate safe parameters memory");
1689                 return ENOMEM;
1690         }
1691
1692         strcpy(dev, info->dev);
1693
1694         /*
1695          * Device Mapper blocks are always 512-byte blocks, so convert
1696          * from the "native" block size to the dm block size here.
1697          */
1698         start = INFO_TO_DM_BLOCKS(info, start);
1699         offset = INFO_TO_DM_BLOCKS(info, offset);
1700         uu_stack_idx = 0;
1701
1702         /*
1703          * Find length of cipher chain. Could use the for below, but doesn't
1704          * really matter.
1705          */
1706         len = tc_cipher_chain_length(info->cipher_chain);
1707
1708         /* Get to the end of the chain */
1709         for (cipher_chain = info->cipher_chain; cipher_chain->next != NULL;
1710             cipher_chain = cipher_chain->next)
1711                 ;
1712
1713         /*
1714          * Start j at len-2, as we want to use .0, and the final one has no
1715          * suffix.
1716          */
1717         for (j = len-2; cipher_chain != NULL;
1718             cipher_chain = cipher_chain->prev, j--) {
1719
1720                 cookie = 0;
1721
1722                 if ((dmt = dm_task_create(DM_DEVICE_CREATE)) == NULL) {
1723                         tc_log(1, "dm_task_create failed\n");
1724                         ret = -1;
1725                         goto out;
1726                 }
1727
1728                 /*
1729                  * If this is the last element in the cipher chain, use the
1730                  * final map name. Otherwise pick a secondary name...
1731                  */
1732                 if (cipher_chain->prev == NULL)
1733                         strcpy(map, mapname);
1734                 else
1735                         sprintf(map, "%s.%d", mapname, j);
1736
1737                 if ((dm_task_set_name(dmt, map)) == 0) {
1738                         tc_log(1, "dm_task_set_name failed\n");
1739                         ret = -1;
1740                         goto out;
1741                 }
1742
1743 #if defined(__linux__)
1744                 uuid_generate(info->uuid);
1745                 if ((uu_temp = malloc(1024)) == NULL) {
1746                         tc_log(1, "uuid_unparse memory failed\n");
1747                         ret = -1;
1748                         goto out;
1749                 }
1750                 uuid_unparse(info->uuid, uu_temp);
1751 #elif defined(__DragonFly__)
1752                 uuid_create(&info->uuid, &status);
1753                 if (status != uuid_s_ok) {
1754                         tc_log(1, "uuid_create failed\n");
1755                         ret = -1;
1756                         goto out;
1757                 }
1758
1759                 uuid_to_string(&info->uuid, &uu_temp, &status);
1760                 if (uu_temp == NULL) {
1761                         tc_log(1, "uuid_to_string failed\n");
1762                         ret = -1;
1763                         goto out;
1764                 }
1765 #endif
1766
1767                 if ((uu = malloc(1024)) == NULL) {
1768                         free(uu_temp);
1769                         tc_log(1, "uuid second malloc failed\n");
1770                         ret = -1;
1771                         goto out;
1772                 }
1773
1774                 snprintf(uu, 1024, "CRYPT-TCPLAY-%s", uu_temp);
1775                 free(uu_temp);
1776
1777                 if ((dm_task_set_uuid(dmt, uu)) == 0) {
1778                         free(uu);
1779                         tc_log(1, "dm_task_set_uuid failed\n");
1780                         ret = -1;
1781                         goto out;
1782                 }
1783
1784                 free(uu);
1785
1786                 if (TC_FLAG_SET(info->flags, FDE)) {
1787                         /*
1788                          * When the full disk encryption (FDE) flag is set,
1789                          * we map the first N sectors using a linear target
1790                          * as they aren't encrypted.
1791                          */
1792
1793                         /*  /dev/ad0s0a              0 */
1794                         /* dev---^       block off --^ */
1795                         snprintf(params, 512, "%s 0", dev);
1796
1797                         if ((dm_task_add_target(dmt, 0,
1798                                 INFO_TO_DM_BLOCKS(info, offset),
1799                                 "linear", params)) == 0) {
1800                                 tc_log(1, "dm_task_add_target failed\n");
1801                                 ret = -1;
1802                                 goto out;
1803                         }
1804
1805                         start = INFO_TO_DM_BLOCKS(info, offset);
1806                 }
1807
1808                 /* aes-cbc-essiv:sha256 7997f8af... 0 /dev/ad0s0a 8 <opts> */
1809                 /*                         iv off---^  block off--^ <opts> */
1810                 snprintf(params, 512, "%s %s %"PRIu64 " %s %"PRIu64 " %s",
1811                     cipher_chain->cipher->dm_crypt_str, cipher_chain->dm_key,
1812                     (uint64_t)INFO_TO_DM_BLOCKS(info, skip), dev,
1813                     (uint64_t)offset,
1814                     TC_FLAG_SET(info->flags, ALLOW_TRIM) ? "1 allow_discards" : "");
1815 #ifdef DEBUG
1816                 printf("Params: %s\n", params);
1817 #endif
1818
1819                 if ((dm_task_add_target(dmt, start,
1820                     INFO_TO_DM_BLOCKS(info, size), "crypt", params)) == 0) {
1821                         tc_log(1, "dm_task_add_target failed\n");
1822                         ret = -1;
1823                         goto out;
1824                 }
1825
1826                 if ((dm_task_set_cookie(dmt, &cookie, 0)) == 0) {
1827                         tc_log(1, "dm_task_set_cookie failed\n");
1828                         ret = -1;
1829                         goto out;
1830                 }
1831
1832                 if ((dm_task_run(dmt)) == 0) {
1833                         dm_udev_wait(cookie);
1834                         tc_log(1, "dm_task_run failed\n");
1835                         ret = -1;
1836                         goto out;
1837                 }
1838
1839                 if ((dm_task_get_info(dmt, &dmi)) == 0) {
1840                         dm_udev_wait(cookie);
1841                         tc_log(1, "dm_task_get info failed\n");
1842                         ret = -1;
1843                         goto out;
1844                 }
1845
1846                 dm_udev_wait(cookie);
1847
1848                 if ((r = asprintf(&uu_stack[uu_stack_idx++], "%s", map)) < 0)
1849                         tc_log(1, "warning, asprintf failed. won't be able to "
1850                             "unroll changes\n");
1851
1852
1853                 offset = 0;
1854                 start = 0;
1855                 sprintf(dev, "/dev/mapper/%s.%d", mapname, j);
1856
1857                 dm_task_destroy(dmt);
1858                 dm_task_update_nodes();
1859         }
1860
1861 out:
1862         /*
1863          * If an error occured, try to unroll changes made before it
1864          * happened.
1865          */
1866         if (ret) {
1867                 j = uu_stack_idx;
1868                 while (j > 0) {
1869 #ifdef DEBUG
1870                         printf("Unrolling dm changes! j = %d (%s)\n", j-1,
1871                             uu_stack[j-1]);
1872 #endif
1873                         if ((uu_stack[j-1] == NULL) ||
1874                             ((r = dm_remove_device(uu_stack[--j])) != 0)) {
1875                                 tc_log(1, "Tried to unroll dm changes, "
1876                                     "giving up.\n");
1877                                 break;
1878                         }
1879                 }
1880         }
1881
1882         while (uu_stack_idx > 0)
1883                 free(uu_stack[--uu_stack_idx]);
1884
1885         free_safe_mem(params);
1886
1887         return ret;
1888 }
1889
1890 int
1891 dm_teardown(const char *mapname, const char *device __unused)
1892 {
1893 #if 0
1894         struct dm_task *dmt = NULL;
1895         struct dm_info dmi;
1896 #endif
1897         char map[PATH_MAX];
1898         int i, error;
1899
1900         if ((error = dm_remove_device(mapname)) != 0) {
1901                 tc_log(1, "Could not remove mapping %s\n", mapname);
1902                 return error;
1903         }
1904
1905         /* Try to remove other cascade devices */
1906         for (i = 0; i < 2; i++) {
1907                 sprintf(map, "%s.%d", mapname, i);
1908                 if (dm_exists_device(map))
1909                         dm_remove_device(map);
1910         }
1911
1912         return 0;
1913 }
1914
1915 struct tc_crypto_algo *
1916 check_cipher(const char *cipher, int quiet)
1917 {
1918         int i, found = 0;
1919
1920         for (i = 0; tc_crypto_algos[i].name != NULL; i++) {
1921                 if (strcmp(cipher, tc_crypto_algos[i].name) == 0) {
1922                         found = 1;
1923                         break;
1924                 }
1925         }
1926
1927         if (!found && !quiet) {
1928                 fprintf(stderr, "Valid ciphers are: ");
1929                 for (i = 0; tc_crypto_algos[i].name != NULL; i++)
1930                         fprintf(stderr, "%s ", tc_crypto_algos[i].name);
1931                 fprintf(stderr, "\n");
1932                 return NULL;
1933         }
1934
1935         return &tc_crypto_algos[i];
1936 }
1937
1938 struct tc_cipher_chain *
1939 check_cipher_chain(const char *cipher_chain, int quiet)
1940 {
1941         struct tc_cipher_chain *cipher = NULL;
1942         int i,k, nciphers = 0, mismatch = 0;
1943         char *ciphers[8];
1944         char *tmp_chain, *tmp_chain_free;
1945         char *token;
1946
1947         if ((tmp_chain = strdup(cipher_chain)) == NULL) {
1948                 tc_log(1, "Could not allocate strdup memory\n");
1949                 return NULL;
1950         }
1951
1952         tmp_chain_free = tmp_chain;
1953
1954         while ((token = strsep(&tmp_chain, ",")) != NULL)
1955                 ciphers[nciphers++] = token;
1956
1957         cipher = NULL;
1958
1959         for (i = 0; valid_cipher_chains[i][0] != NULL; i++) {
1960                 mismatch = 0;
1961
1962                 for (k = 0; (valid_cipher_chains[i][k] != NULL); k++) {
1963                         /*
1964                          * If there are more ciphers in the chain than in the
1965                          * ciphers[] variable this is not the right chain.
1966                          */
1967                         if (k == nciphers) {
1968                                 mismatch = 1;
1969                                 break;
1970                         }
1971
1972                         if (strcmp(ciphers[k], valid_cipher_chains[i][k]) != 0)
1973                                 mismatch = 1;
1974                 }
1975
1976                 /*
1977                  * If all ciphers matched and there are exactly nciphers,
1978                  * then we found the right cipher chain.
1979                  */
1980                 if ((k == nciphers) && !mismatch) {
1981                         cipher = tc_cipher_chains[i];
1982                         break;
1983                 }
1984         }
1985
1986         if (cipher == NULL) {
1987                 tc_log(1, "Invalid cipher: %s\n", cipher_chain);
1988                 if (!quiet) {
1989                         fprintf(stderr, "Valid cipher chains are:\n");
1990                         for (i = 0; valid_cipher_chains[i][0] != NULL; i++) {
1991                                 for (k = 0; valid_cipher_chains[i][k] != NULL;
1992                                     k++) {
1993                                         fprintf(stderr, "%s%c",
1994                                             valid_cipher_chains[i][k],
1995                                             (valid_cipher_chains[i][k+1] != NULL) ?
1996                                             ',' : '\0');
1997                                 }
1998                                 fprintf(stderr, "\n");
1999                         }
2000                 }
2001         }
2002
2003         free(tmp_chain_free);
2004         return cipher;
2005 }
2006
2007 struct pbkdf_prf_algo *
2008 check_prf_algo(const char *algo, int quiet)
2009 {
2010         int i, found = 0;
2011
2012         for (i = 0; pbkdf_prf_algos[i].name != NULL; i++) {
2013                 if (strcmp(algo, pbkdf_prf_algos[i].name) == 0) {
2014                         found = 1;
2015                         break;
2016                 }
2017         }
2018
2019         if (!found && !quiet) {
2020                 fprintf(stderr, "Valid PBKDF PRF algorithms are: ");
2021                 for (i = 0; pbkdf_prf_algos[i].name != NULL; i++)
2022                         fprintf(stderr, "%s ", pbkdf_prf_algos[i].name);
2023                 fprintf(stderr, "\n");
2024                 return NULL;
2025         }
2026
2027         return &pbkdf_prf_algos[i];
2028 }
2029
2030 int
2031 tc_play_init(void)
2032 {
2033         int error;
2034
2035         if ((error = tc_build_cipher_chains()) != 0)
2036                 return error;
2037
2038         if ((error = tc_crypto_init()) != 0)
2039                 return error;
2040
2041         return 0;
2042 }
2043
2044 struct tcplay_opts *opts_init(void)
2045 {
2046         struct tcplay_opts *opts;
2047
2048         if ((opts = (struct tcplay_opts *)alloc_safe_mem(sizeof(*opts))) == NULL) {
2049                 tc_log(1, "could not allocate safe opts memory\n");
2050                 return NULL;
2051         }
2052
2053         memset(opts, 0, sizeof(*opts));
2054
2055         opts->retries = DEFAULT_RETRIES;
2056         opts->secure_erase = 1;
2057
2058         return opts;
2059 }
2060
2061 int
2062 opts_add_keyfile(struct tcplay_opts *opts, const char *keyfile)
2063 {
2064         const char *keyf;
2065
2066         if (opts->nkeyfiles == MAX_KEYFILES)
2067                 return -1;
2068
2069         if ((keyf = strdup_safe_mem(keyfile)) == NULL) {
2070                 return -1;
2071         }
2072
2073         opts->keyfiles[opts->nkeyfiles++] = keyf;
2074
2075         return 0;
2076 }
2077
2078 int
2079 opts_add_keyfile_hidden(struct tcplay_opts *opts, const char *keyfile)
2080 {
2081         const char *keyf;
2082
2083         if (opts->n_hkeyfiles == MAX_KEYFILES)
2084                 return -1;
2085
2086         if ((keyf = strdup_safe_mem(keyfile)) == NULL) {
2087                 return -1;
2088         }
2089
2090         opts->h_keyfiles[opts->n_hkeyfiles++] = keyf;
2091
2092         return 0;
2093 }
2094
2095 int
2096 opts_add_keyfile_new(struct tcplay_opts *opts, const char *keyfile)
2097 {
2098         const char *keyf;
2099
2100         if (opts->n_newkeyfiles == MAX_KEYFILES)
2101                 return -1;
2102
2103         if ((keyf = strdup_safe_mem(keyfile)) == NULL) {
2104                 return -1;
2105         }
2106
2107         opts->new_keyfiles[opts->n_newkeyfiles++] = keyf;
2108
2109         return 0;
2110 }
2111
2112 void
2113 opts_clear_keyfile(struct tcplay_opts *opts)
2114 {
2115         int i;
2116
2117         for (i = 0; i < opts->nkeyfiles; i++) {
2118                 free_safe_mem(opts->keyfiles[i]);
2119         }
2120
2121         opts->nkeyfiles = 0;
2122 }
2123
2124 void
2125 opts_clear_keyfile_hidden(struct tcplay_opts *opts)
2126 {
2127         int i;
2128
2129         for (i = 0; i < opts->n_hkeyfiles; i++) {
2130                 free_safe_mem(opts->h_keyfiles[i]);
2131         }
2132
2133         opts->n_hkeyfiles = 0;
2134 }
2135
2136
2137 void
2138 opts_clear_keyfile_new(struct tcplay_opts *opts)
2139 {
2140         int i;
2141
2142         for (i = 0; i < opts->n_newkeyfiles; i++) {
2143                 free_safe_mem(opts->new_keyfiles[i]);
2144         }
2145
2146         opts->n_newkeyfiles = 0;
2147 }
2148
2149
2150 void
2151 opts_free(struct tcplay_opts *opts)
2152 {
2153         int i;
2154
2155         for (i = 0; i < opts->nkeyfiles; i++) {
2156                 free_safe_mem(opts->keyfiles[i]);
2157         }
2158
2159         for (i = 0; i < opts->n_hkeyfiles; i++) {
2160                 free_safe_mem(opts->h_keyfiles[i]);
2161         }
2162
2163         for (i = 0; i < opts->n_newkeyfiles; i++) {
2164                 free_safe_mem(opts->new_keyfiles[i]);
2165         }
2166
2167         if (opts->dev)
2168                 free_safe_mem(opts->dev);
2169         if (opts->passphrase)
2170                 free_safe_mem(opts->passphrase);
2171         if (opts->h_passphrase)
2172                 free_safe_mem(opts->h_passphrase);
2173         if (opts->new_passphrase)
2174                 free_safe_mem(opts->new_passphrase);
2175         if (opts->map_name)
2176                 free_safe_mem(opts->map_name);
2177         if (opts->sys_dev)
2178                 free_safe_mem(opts->sys_dev);
2179         if (opts->hdr_file_in)
2180                 free_safe_mem(opts->hdr_file_in);
2181         if (opts->h_hdr_file_in)
2182                 free_safe_mem(opts->h_hdr_file_in);
2183         if (opts->hdr_file_out)
2184                 free_safe_mem(opts->hdr_file_out);
2185
2186         free_safe_mem(opts);
2187 }