static const char *opt_cipher = NULL;
static const char *opt_hash = NULL;
static int opt_verify_passphrase = 0;
+
static const char *opt_key_file = NULL;
+static int opt_keyfiles_count = 0;
+static const char *opt_keyfiles[MAX_KEYFILES];
+
static const char *opt_master_key_file = NULL;
static const char *opt_header_backup_file = NULL;
static const char *opt_uuid = NULL;
static uint64_t opt_skip = 0;
static int opt_skip_valid = 0;
static int opt_readonly = 0;
-static int opt_iteration_time = 1000;
+static int opt_iteration_time = DEFAULT_LUKS1_ITER_TIME;
static int opt_version_mode = 0;
static int opt_timeout = 0;
static int opt_tries = 3;
static int opt_shared = 0;
static int opt_allow_discards = 0;
static int opt_test_passphrase = 0;
+static int opt_hidden = 0;
static const char **action_argv;
static int action_argc;
+static const char *null_action_argv[] = {NULL, NULL};
static int action_create(int arg);
static int action_remove(int arg);
static int action_resize(int arg);
static int action_status(int arg);
+static int action_benchmark(int arg);
static int action_luksFormat(int arg);
static int action_luksOpen(int arg);
static int action_luksAddKey(int arg);
static int action_luksRestore(int arg);
static int action_loopaesOpen(int arg);
static int action_luksRepair(int arg);
+static int action_tcryptOpen(int arg);
+static int action_tcryptDump(int arg);
static struct action_type {
const char *type;
{ "remove", action_remove, 0, 1, 1, N_("<name>"), N_("remove device") },
{ "resize", action_resize, 0, 1, 1, N_("<name>"), N_("resize active device") },
{ "status", action_status, 0, 1, 0, N_("<name>"), N_("show device status") },
+ { "benchmark", action_benchmark, 0, 0, 0, N_("<name>"), N_("benchmark cipher") },
{ "repair", action_luksRepair, 0, 1, 1, N_("<device>"), N_("try to repair on-disk metadata") },
{ "luksFormat", action_luksFormat, 0, 1, 1, N_("<device> [<new key file>]"), N_("formats a LUKS device") },
{ "luksOpen", action_luksOpen, 0, 2, 1, N_("<device> <name> "), N_("open LUKS device as mapping <name>") },
{ "luksHeaderRestore",action_luksRestore,0,1, 1, N_("<device>"), N_("Restore LUKS device header and keyslots") },
{ "loopaesOpen",action_loopaesOpen, 0, 2, 1, N_("<device> <name> "), N_("open loop-AES device as mapping <name>") },
{ "loopaesClose",action_remove, 0, 1, 1, N_("<name>"), N_("remove loop-AES mapping") },
+ { "tcryptOpen", action_tcryptOpen, 0, 2, 1, N_("<device> <name> "), N_("open TCRYPT device as mapping <name>") },
+ { "tcryptDump", action_tcryptDump, 0, 1, 1, N_("<device>"), N_("dump TCRYPT device information") },
{ NULL, NULL, 0, 0, 0, NULL, NULL }
};
return r;
}
+static int action_tcryptOpen(int arg __attribute__((unused)))
+{
+ struct crypt_device *cd = NULL;
+ struct crypt_params_tcrypt params = {
+ .keyfiles = opt_keyfiles,
+ .keyfiles_count = opt_keyfiles_count,
+ .flags = CRYPT_TCRYPT_LEGACY_MODES,
+ };
+ const char *activated_name;
+ uint32_t flags = 0;
+ int r;
+
+ activated_name = opt_test_passphrase ? NULL : action_argv[1];
+
+ if ((r = crypt_init(&cd, action_argv[0])))
+ goto out;
+
+ /* TCRYPT header is encrypted, get passphrase now */
+ r = crypt_get_key(_("Enter passphrase: "),
+ CONST_CAST(char**)¶ms.passphrase,
+ ¶ms.passphrase_size, 0, 0, NULL, opt_timeout,
+ _verify_passphrase(0), cd);
+ if (r < 0)
+ goto out;
+
+ if (opt_hidden)
+ params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
+
+ r = crypt_load(cd, CRYPT_TCRYPT, ¶ms);
+ if (r < 0)
+ goto out;
+
+ if (opt_readonly)
+ flags |= CRYPT_ACTIVATE_READONLY;
+
+ if (activated_name)
+ r = crypt_activate_by_volume_key(cd, activated_name, NULL, 0, flags);
+out:
+ crypt_free(cd);
+ crypt_safe_free(CONST_CAST(char*)params.passphrase);
+ return r;
+}
+
+static int action_tcryptDump(int arg __attribute__((unused)))
+{
+ struct crypt_device *cd = NULL;
+ struct crypt_params_tcrypt params = {
+ .keyfiles = opt_keyfiles,
+ .keyfiles_count = opt_keyfiles_count,
+ .flags = CRYPT_TCRYPT_LEGACY_MODES,
+ };
+ int r;
+
+ if ((r = crypt_init(&cd, action_argv[0])))
+ goto out;
+
+ /* TCRYPT header is encrypted, get passphrase now */
+ r = crypt_get_key(_("Enter passphrase: "),
+ CONST_CAST(char**)¶ms.passphrase,
+ ¶ms.passphrase_size, 0, 0, NULL, opt_timeout,
+ _verify_passphrase(0), cd);
+ if (r < 0)
+ goto out;
+
+ if (opt_hidden)
+ params.flags |= CRYPT_TCRYPT_HIDDEN_HEADER;
+
+ r = crypt_load(cd, CRYPT_TCRYPT, ¶ms);
+ if (r < 0)
+ goto out;
+
+ r = crypt_dump(cd);
+out:
+ crypt_free(cd);
+ crypt_safe_free(CONST_CAST(char*)params.passphrase);
+ return r;
+}
+
static int action_remove(int arg __attribute__((unused)))
{
struct crypt_device *cd = NULL;
return r;
}
+static int action_benchmark(int arg __attribute__((unused)))
+{
+ static struct {
+ char *cipher;
+ char *mode;
+ size_t key_size;
+ size_t iv_size;
+ } bciphers[] = {
+ { "aes", "cbc", 16, 16 },
+ { "serpent", "cbc", 16, 16 },
+ { "twofish", "cbc", 16, 16 },
+ { "aes", "cbc", 32, 16 },
+ { "serpent", "cbc", 32, 16 },
+ { "twofish", "cbc", 32, 16 },
+ { "aes", "xts", 32, 16 },
+ { "serpent", "xts", 32, 16 },
+ { "twofish", "xts", 32, 16 },
+ { "aes", "xts", 64, 16 },
+ { "serpent", "xts", 64, 16 },
+ { "twofish", "xts", 64, 16 },
+ { NULL, NULL, 0, 0 }
+ };
+ char *header = "# Tests are approximate using memory only (no storage IO).\n"
+ "# Algorithm | Key | Encryption | Decryption\n";
+ char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
+ double enc_mbr = 0, dec_mbr = 0;
+ int key_size = (opt_key_size ?: DEFAULT_PLAIN_KEYBITS);
+ int iv_size = 16;
+ int buffer_size = 1024 * 1024;
+ char *c;
+ int i, r;
+
+ if (opt_cipher) {
+ r = crypt_parse_name_and_mode(opt_cipher, cipher, NULL, cipher_mode);
+ if (r < 0) {
+ log_err(_("No known cipher specification pattern detected.\n"));
+ return r;
+ }
+ if ((c = strchr(cipher_mode, '-')))
+ *c = '\0';
+
+ /* FIXME: not really clever :) */
+ if (strstr(cipher, "des"))
+ iv_size = 8;
+
+ r = crypt_benchmark(NULL, cipher, cipher_mode,
+ key_size / 8, iv_size, buffer_size,
+ &enc_mbr, &dec_mbr);
+ if (!r) {
+ log_std("%s", header);
+ strncat(cipher, "-", MAX_CIPHER_LEN);
+ strncat(cipher, cipher_mode, MAX_CIPHER_LEN);
+ log_std("%11s %4db %5.1f MiB/s %5.1f MiB/s\n",
+ cipher, key_size, enc_mbr, dec_mbr);
+ } else if (r == -ENOTSUP)
+ log_err(_("Cipher %s is not available.\n"), opt_cipher);
+ } else {
+ for (i = 0; bciphers[i].cipher; i++) {
+ r = crypt_benchmark(NULL, bciphers[i].cipher, bciphers[i].mode,
+ bciphers[i].key_size, bciphers[i].iv_size,
+ buffer_size, &enc_mbr, &dec_mbr);
+ if (r == -ENOENT)
+ break;
+ if (i == 0)
+ log_std("%s", header);
+
+ snprintf(cipher, MAX_CIPHER_LEN, "%s-%s",
+ bciphers[i].cipher, bciphers[i].mode);
+ if (!r)
+ log_std("%11s %4db %5.1f MiB/s %5.1f MiB/s\n",
+ cipher, bciphers[i].key_size*8, enc_mbr, dec_mbr);
+ else
+ log_std("%11s %4db %12s %12s\n", cipher,
+ bciphers[i].key_size*8, _("N/A"), _("N/A"));
+ }
+ }
+
+ if (r == -ENOENT)
+ log_err( _("Required kernel crypto interface is not available.\n"
+ "Ensure you have af_skcipher kernel module loaded.\n"));
+ return r;
+}
+
static int _read_mk(const char *file, char **key, int keysize)
{
int fd;
"<key file> optional key file for the new key for luksAddKey action\n"),
crypt_get_dir());
- log_std(_("\nDefault compiled-in keyfile parameters:\n"
+ log_std(_("\nDefault compiled-in key and passphrase parameters:\n"
"\tMaximum keyfile size: %dkB, "
- "Maximum interactive passphrase length %d (characters)\n"),
- DEFAULT_KEYFILE_SIZE_MAXKB, DEFAULT_PASSPHRASE_SIZE_MAX);
+ "Maximum interactive passphrase length %d (characters)\n"
+ "Default PBKDF2 iteration time for LUKS: %d (ms)\n"),
+ DEFAULT_KEYFILE_SIZE_MAXKB, DEFAULT_PASSPHRASE_SIZE_MAX,
+ DEFAULT_LUKS1_ITER_TIME);
log_std(_("\nDefault compiled-in device cipher parameters:\n"
"\tloop-AES: %s, Key %d bits\n"
{ "cipher", 'c', POPT_ARG_STRING, &opt_cipher, 0, N_("The cipher used to encrypt the disk (see /proc/crypto)"), NULL },
{ "hash", 'h', POPT_ARG_STRING, &opt_hash, 0, N_("The hash used to create the encryption key from the passphrase"), NULL },
{ "verify-passphrase", 'y', POPT_ARG_NONE, &opt_verify_passphrase, 0, N_("Verifies the passphrase by asking for it twice"), NULL },
- { "key-file", 'd', POPT_ARG_STRING, &opt_key_file, 0, N_("Read the key from a file."), NULL },
+ { "key-file", 'd', POPT_ARG_STRING, &opt_key_file, 5, N_("Read the key from a file."), NULL },
{ "master-key-file", '\0', POPT_ARG_STRING, &opt_master_key_file, 0, N_("Read the volume (master) key from file."), NULL },
{ "dump-master-key", '\0', POPT_ARG_NONE, &opt_dump_master_key, 0, N_("Dump volume (master) key instead of keyslots info."), NULL },
{ "key-size", 's', POPT_ARG_INT, &opt_key_size, 0, N_("The size of the encryption key"), N_("BITS") },
{ "allow-discards", '\0', POPT_ARG_NONE, &opt_allow_discards, 0, N_("Allow discards (aka TRIM) requests for device."), NULL },
{ "header", '\0', POPT_ARG_STRING, &opt_header_device, 0, N_("Device or file with separated LUKS header."), NULL },
{ "test-passphrase", '\0', POPT_ARG_NONE, &opt_test_passphrase, 0, N_("Do not activate device, just check passphrase."), NULL },
+ { "hidden", '\0', POPT_ARG_NONE, &opt_hidden, 0, N_("Use hidden header (hiden TCRYPT device) ."), NULL },
POPT_TABLEEND
};
poptContext popt_context;
struct action_type *action;
const char *aname;
int r;
- const char *null_action_argv[] = {NULL};
crypt_set_log_callback(NULL, tool_log, NULL);
unsigned long long ull_value;
char *endp;
+ if (r == 5) {
+ if (opt_keyfiles_count < MAX_KEYFILES)
+ opt_keyfiles[opt_keyfiles_count++] = poptGetOptArg(popt_context);
+ continue;
+ }
+
errno = 0;
ull_value = strtoull(popt_tmp, &endp, 0);
if (*endp || !*popt_tmp ||
if (opt_key_size &&
strcmp(aname, "luksFormat") &&
strcmp(aname, "create") &&
- strcmp(aname, "loopaesOpen"))
+ strcmp(aname, "loopaesOpen") &&
+ strcmp(aname, "benchmark"))
usage(popt_context, EXIT_FAILURE,
- _("Option --key-size is allowed only for luksFormat, create and loopaesOpen.\n"
+ _("Option --key-size is allowed only for luksFormat, create, loopaesOpen and benchmark.\n"
"To limit read from keyfile use --keyfile-size=(bytes)."),
poptGetInvocationName(popt_context));
if (opt_test_passphrase &&
- strcmp(aname, "luksOpen"))
+ strcmp(aname, "luksOpen") &&
+ strcmp(aname, "tcryptOpen"))
usage(popt_context, EXIT_FAILURE,
- _("Option --test-passphrase is allowed only for luksOpen.\n"),
+ _("Option --test-passphrase is allowed only for luksOpen and tcryptOpen.\n"),
poptGetInvocationName(popt_context));
if (opt_key_size % 8)
_("Option --offset is supported only for create and loopaesOpen commands.\n"),
poptGetInvocationName(popt_context));
+ if (opt_hidden && strcmp(aname, "tcryptOpen") && strcmp(aname, "tcryptDump"))
+ usage(popt_context, EXIT_FAILURE,
+ _("Option --hidden is supported only for TCRYPT commands.\n"),
+ poptGetInvocationName(popt_context));
+
if (opt_debug) {
opt_verbose = 1;
crypt_set_debug_level(-1);