zkey: Add common passphrase options for cryptsetup command

When generating 'cryptsetup luksFormat' or 'zkey-cryptsetup setvp'
commands for LUKS2 volumes, allow to specify common passphrase options
like --key-file, --keyfile-offset, --keyfile-size and --tries and
pass those to the generated commands.

Closes: https://github.com/ibm-s390-tools/s390-tools/pull/59
Fixes: https://github.com/ibm-s390-tools/s390-tools/issues/58

Suggested-by: Dimitri John Ledkov <xnox@ubuntu.com>
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Ingo Franzki
2019-03-07 11:16:11 +01:00
committed by Jan Höppner
parent cdb23f8d22
commit b0c7965234
4 changed files with 209 additions and 7 deletions

View File

@@ -3242,6 +3242,10 @@ static int _keystore_execute_cmd(const char *cmd,
struct crypt_info {
bool execute;
const char *keyfile;
size_t keyfile_offset;
size_t keyfile_size;
size_t tries;
char **volume_filter;
int (*process_func)(struct keystore *keystore,
const char *volume,
@@ -3280,12 +3284,38 @@ static int _keystore_process_cryptsetup(struct keystore *keystore,
const char *volume_type,
struct crypt_info *info)
{
char *keyfile_opt = NULL, *offset_opt = NULL;
char *size_opt = NULL, *tries_opt = NULL;
char *common_passphrase_options;
size_t common_len;
char temp[100];
int rc = 0;
char *cmd;
sprintf(temp, "--sector-size %lu ", sector_size);
if (info->keyfile) {
util_asprintf(&keyfile_opt, "--key-file '%s' ", info->keyfile);
if (info->keyfile_offset > 0)
util_asprintf(&offset_opt, "--keyfile-offset %lu ",
info->keyfile_offset);
if (info->keyfile_size > 0)
util_asprintf(&size_opt, "--keyfile-size %lu ",
info->keyfile_size);
}
if (info->tries > 0)
util_asprintf(&tries_opt, "--tries %lu ", info->tries);
util_asprintf(&common_passphrase_options, "%s%s%s%s",
keyfile_opt != NULL ? keyfile_opt : "",
offset_opt != NULL ? offset_opt : "",
size_opt != NULL ? size_opt : "",
tries_opt != NULL ? tries_opt : "");
common_len = strlen(common_passphrase_options);
free(keyfile_opt);
free(offset_opt);
free(size_opt);
free(tries_opt);
if (strcasecmp(volume_type, VOLUME_TYPE_PLAIN) == 0) {
util_asprintf(&cmd,
"cryptsetup plainOpen %s--key-file '%s' "
@@ -3310,9 +3340,10 @@ static int _keystore_process_cryptsetup(struct keystore *keystore,
util_asprintf(&cmd,
"cryptsetup luksFormat %s--type luks2 "
"--master-key-file '%s' --key-size %lu "
"--cipher %s --pbkdf pbkdf2 %s%s",
"--cipher %s --pbkdf pbkdf2 %s%s%s",
keystore->verbose ? "-v " : "", key_file_name,
key_file_size * 8, cipher_spec,
common_len > 0 ? common_passphrase_options : "",
sector_size > 0 ? temp : "", volume);
if (info->execute) {
@@ -3327,8 +3358,9 @@ static int _keystore_process_cryptsetup(struct keystore *keystore,
return rc;
util_asprintf(&cmd,
"zkey-cryptsetup setvp %s%s", volume,
keystore->verbose ? " -V " : "");
"zkey-cryptsetup setvp %s %s%s", volume,
common_len > 0 ? common_passphrase_options : "",
keystore->verbose ? "-V" : "");
if (info->execute) {
printf("Executing: %s\n", cmd);
@@ -3340,6 +3372,7 @@ static int _keystore_process_cryptsetup(struct keystore *keystore,
return -EINVAL;
}
free(common_passphrase_options);
free(cmd);
return rc;
}
@@ -3577,11 +3610,17 @@ out:
* @param[in] execute If TRUE the cryptsetup command is executed,
* otherwise it is printed to stdout
* @param[in] volume_type the type of volume to generate cryptsetup cmds for
* *
* @param[in] keyfile If non-NULL, specifies the name of the file to
* read the passphrase from.
* @param[in] keyfile_offset the offset in bytes for reading from keyfile
* @param[in] keyfile_size the size in bytes for reading from keyfile
* @param[in] tries the number of tries for passphrase entry
* @returns 0 for success or a negative errno in case of an error
*/
int keystore_cryptsetup(struct keystore *keystore, const char *volume_filter,
bool execute, const char *volume_type)
bool execute, const char *volume_type,
const char *keyfile, size_t keyfile_offset,
size_t keyfile_size, size_t tries)
{
struct crypt_info info = { 0 };
int rc;
@@ -3598,6 +3637,10 @@ int keystore_cryptsetup(struct keystore *keystore, const char *volume_filter,
}
info.execute = execute;
info.keyfile = keyfile;
info.keyfile_offset = keyfile_offset;
info.keyfile_size = keyfile_size;
info.tries = tries;
info.volume_filter = str_list_split(volume_filter);
info.process_func = _keystore_process_cryptsetup;

View File

@@ -68,7 +68,9 @@ int keystore_list_keys(struct keystore *keystore, const char *name_filter,
const char *volume_type);
int keystore_cryptsetup(struct keystore *keystore, const char *volume_filter,
bool execute, const char *volume_type);
bool execute, const char *volume_type,
const char *keyfile, size_t keyfile_offset,
size_t keyfile_size, size_t tries);
int keystore_crypttab(struct keystore *keystore, const char *volume_filter,
const char *volume_type);

View File

@@ -547,6 +547,14 @@ option to generate crypttab entries for the specified volume type only.
.RB [ \-\-volume-type | \-t
.IR type ]
.RB [ \-\-run | \-r ]
.RB [ \-\-key\-file
.IR file-name ]
.RB [ \-\-keyfile\-offset
.IR bytes ]
.RB [ \-\-keyfile\-size
.IR bytes ]
.RB [ \-\-tries
.IR number ]
.RB [ \-\-verbose | \-V ]
.
.PP
@@ -576,6 +584,24 @@ errors when multiple encrypted volumes are unlocked automatically at boot
through /etc/crypttab. Because PAES uses secure AES keys as volume keys, the
security of the key derivation function used to encrypt the volume key in the
LUKS key slots is of less relevance.
.P
For LUKS2 volumes, a passphrase is required. You are prompted for the
passphrase when running the generated commands, unless option
.B \-\-key\-file
is specified. Option
.B \-\-tries
specifies how often a passphrase can be re-entered. When option
.B \-\-key\-file
is specified, the passphrase is read from the specified file. You can specify
options
.B \-\-keyfile\-offset
and
.B \-\-keyfile\-size
to control which part of the key file is used as passphrase. These options are
only available if
.B zkey
has been compiled with LUKS2 support enabled. These options are passed to the
generated command(s) and behave in the same way as with \fBcryptsetup\fP.
.
.
.
@@ -956,6 +982,42 @@ This option is only used for secure keys contained in the secure key repository.
Runs the generated cryptsetup commands. When one of the cryptsetup command fail,
no further cryptsetup commands are run, and zkey ends with an error.
This option is only used for secure keys contained in the secure key repository.
.TP
.BR \-\-key\-file\~\fIfile\-name\fP
Reads the passphrase from the specified file. If this option is omitted,
or if the file\-name is \fI-\fP (a dash), then you are prompted to enter the
passphrase interactively. This option is passed to the generated command(s)
for LUKS2 volumes, and is only available if
.B zkey
has been compiled with LUKS2 support enabled.
.TP
.BR \-\-keyfile\-offset\~\fIbytes\fP
Specifies the number of bytes to skip before starting to read in the file
specified with option \fB\-\-key\-file\fP. If omitted, the file is read
from the beginning. When option \fB\-\-key\-file\fP is not specified, this
option is ignored. This option is passed to the generated command(s)
for LUKS2 volumes, and is only available if
.B zkey
has been compiled with LUKS2 support enabled.
.TP
.BR \-\-keyfile\-size\~\fIbytes\fP
Specifies the number of bytes to be read from the beginning of the file
specified with option \fB\-\-key\-file\fP. If omitted, the file is read
until the end. When \fB\-\-keyfile\-offset\fP is also specified, reading starts
at the offset. When option \fB\-\-key\-file\fP is not specified, this option is
ignored. This option is passed to the generated command(s) for LUKS2 volumes,
and is only available if
.B zkey
has been compiled with LUKS2 support enabled.
.TP
.BR \-\-tries\~\fInumber\fP
Specifies how often the interactive input of the passphrase can be re-entered.
The default is 3 times. When option \fB\-\-key\-file\fP is specified, this
option is ignored, and the passphrase is read only once from the file.
This option is passed to the generated command(s) for LUKS2 volumes, and is
only available if
.B zkey
has been compiled with LUKS2 support enabled.
.
.
.

View File

@@ -71,6 +71,10 @@ static struct zkey_globals {
char *volume_type;
char *newname;
bool run;
char *keyfile;
long long keyfile_offset;
long long keyfile_size;
long long tries;
bool force;
void *lib_csulcca;
t_CSNBKTC dll_CSNBKTC;
@@ -102,6 +106,11 @@ static struct zkey_globals {
#define ENVVAR_ZKEY_REPOSITORY "ZKEY_REPOSITORY"
#define DEFAULT_KEYSTORE "/etc/zkey/repository"
#define OPT_CRYPTSETUP_KEYFILE 256
#define OPT_CRYPTSETUP_KEYFILE_OFFSET 257
#define OPT_CRYPTSETUP_KEYFILE_SIZE 258
#define OPT_CRYPTSETUP_TRIES 259
/*
* Configuration of command line options
*/
@@ -582,6 +591,51 @@ static struct util_opt opt_vec[] = {
.desc = "Runs the generated cryptsetup command",
.command = COMMAND_CRYPTSETUP,
},
#ifdef HAVE_LUKS2_SUPPORT
{
.option = {"key-file", required_argument, NULL,
OPT_CRYPTSETUP_KEYFILE},
.argument = "FILE-NAME",
.desc = "Read the passphrase from the specified file. "
"This option is passed to the generated command(s) for "
"LUKS2 volumes",
.command = COMMAND_CRYPTSETUP,
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = {"keyfile-offset", required_argument, NULL,
OPT_CRYPTSETUP_KEYFILE_OFFSET},
.argument = "BYTES",
.desc = "Specifies the number of bytes to skip in the file "
"specified with option '--key-file'. "
"This option is passed to the generated command(s) for "
"LUKS2 volumes",
.command = COMMAND_CRYPTSETUP,
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = {"keyfile-size", required_argument, NULL,
OPT_CRYPTSETUP_KEYFILE_SIZE},
.argument = "BYTES",
.desc = "Specifies the number of bytes to read from the file "
"specified with option '--key-file'. "
"This option is passed to the generated command(s) for "
"LUKS2 volumes",
.command = COMMAND_CRYPTSETUP,
.flags = UTIL_OPT_FLAG_NOSHORT,
},
{
.option = {"tries", required_argument, NULL,
OPT_CRYPTSETUP_TRIES},
.argument = "NUMBER",
.desc = "Specifies how often the interactive input of the "
"passphrase can be retried. "
"This option is passed to the generated command(s) for "
"LUKS2 volumes",
.command = COMMAND_CRYPTSETUP,
.flags = UTIL_OPT_FLAG_NOSHORT,
},
#endif
/***********************************************************/
{
.flags = UTIL_OPT_FLAG_SECTION,
@@ -1380,7 +1434,9 @@ static int command_cryptsetup(void)
{
int rc;
rc = keystore_cryptsetup(g.keystore, g.volumes, g.run, g.volume_type);
rc = keystore_cryptsetup(g.keystore, g.volumes, g.run, g.volume_type,
g.keyfile, g.keyfile_offset, g.keyfile_size,
g.tries);
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
@@ -1574,6 +1630,45 @@ int main(int argc, char *argv[])
case 'V':
g.verbose = 1;
break;
#ifdef HAVE_LUKS2_SUPPORT
case OPT_CRYPTSETUP_KEYFILE:
g.keyfile = optarg;
break;
case OPT_CRYPTSETUP_KEYFILE_OFFSET:
g.keyfile_offset = strtoll(optarg, &endp, 0);
if (*optarg == '\0' || *endp != '\0' ||
g.keyfile_offset < 0 ||
(g.keyfile_offset == LLONG_MAX &&
errno == ERANGE)) {
warnx("Invalid value for '--keyfile-offset': "
"'%s'", optarg);
util_prg_print_parse_error();
return EXIT_FAILURE;
}
break;
case OPT_CRYPTSETUP_KEYFILE_SIZE:
g.keyfile_size = strtoll(optarg, &endp, 0);
if (*optarg == '\0' || *endp != '\0' ||
g.keyfile_size <= 0 ||
(g.keyfile_size == LLONG_MAX && errno == ERANGE)) {
warnx("Invalid value for '--keyfile-size': "
"'%s'", optarg);
util_prg_print_parse_error();
return EXIT_FAILURE;
}
break;
case OPT_CRYPTSETUP_TRIES:
g.tries = strtoll(optarg, &endp, 0);
if (*optarg == '\0' || *endp != '\0' ||
g.tries <= 0 ||
(g.tries == LLONG_MAX && errno == ERANGE)) {
warnx("Invalid value for '--tries': '%s'",
optarg);
util_prg_print_parse_error();
return EXIT_FAILURE;
}
break;
#endif
case 'h':
print_help(command);
return EXIT_SUCCESS;