mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
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:
committed by
Jan Höppner
parent
cdb23f8d22
commit
b0c7965234
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
62
zkey/zkey.1
62
zkey/zkey.1
@@ -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.
|
||||
.
|
||||
.
|
||||
.
|
||||
|
||||
97
zkey/zkey.c
97
zkey/zkey.c
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user