forked from pool/s390-tools
a7f8ed0265
Lots of features implemented for SLES15 SP1. OBS-URL: https://build.opensuse.org/request/show/648783 OBS-URL: https://build.opensuse.org/package/show/Base:System/s390-tools?expand=0&rev=57
1419 lines
39 KiB
Diff
1419 lines
39 KiB
Diff
Subject: zkey: Add keystore related commands
|
|
From: Philipp Rudo <prudo@linux.ibm.com>
|
|
|
|
Summary: zkey: Add support of protected key crypto for dm-crypt.
|
|
Description: Support the usage of protected key crypto for dm-crypt disks in
|
|
plain format by providing a tool to manage a key repository
|
|
allowing to associate secure keys with disk partitions or logical
|
|
volumes.
|
|
Upstream-ID: e2f92e4079eb3588574e3346a56472fb26128a7d
|
|
Problem-ID: SEC1800
|
|
|
|
Upstream-Description:
|
|
|
|
zkey: Add keystore related commands
|
|
|
|
Add new commands to the zkey utility to store secure AES keys in
|
|
the secure key repository provided by the keystore implementation
|
|
introduced in the previous commit.
|
|
|
|
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
|
|
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
|
|
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
|
|
|
|
|
|
Signed-off-by: Philipp Rudo <prudo@linux.ibm.com>
|
|
---
|
|
zkey/misc.h | 19 -
|
|
zkey/zkey.c | 1072 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
|
|
2 files changed, 1024 insertions(+), 67 deletions(-)
|
|
|
|
--- a/zkey/misc.h
|
|
+++ b/zkey/misc.h
|
|
@@ -3,7 +3,7 @@
|
|
*
|
|
* Local helper functions
|
|
*
|
|
- * Copyright 2017 IBM Corp.
|
|
+ * Copyright IBM Corp. 2017, 2018
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
@@ -37,7 +37,7 @@ void misc_print_invalid_command(const ch
|
|
/**
|
|
* An required parameter has not been specified
|
|
*
|
|
- * @param[in] option Parameter string
|
|
+ * @param[in] parm_name Parameter string
|
|
*/
|
|
void misc_print_required_parm(const char *parm_name)
|
|
{
|
|
@@ -45,4 +45,17 @@ void misc_print_required_parm(const char
|
|
util_prg_print_parse_error();
|
|
}
|
|
|
|
-#endif
|
|
\ No newline at end of file
|
|
+/**
|
|
+ * An required parameter has not been specified
|
|
+ *
|
|
+ * @param[in] parm_name1 Parameter string 1
|
|
+ * @param[in] parm_name2 Parameter string 2
|
|
+ */
|
|
+static void misc_print_required_parms(const char *parm_name1,
|
|
+ const char *parm_name2)
|
|
+{
|
|
+ warnx("Parameter '%s' or '%s' is required", parm_name1, parm_name2);
|
|
+ util_prg_print_parse_error();
|
|
+}
|
|
+
|
|
+#endif
|
|
--- a/zkey/zkey.c
|
|
+++ b/zkey/zkey.c
|
|
@@ -1,7 +1,7 @@
|
|
/*
|
|
* zkey - Generate, re-encipher, and validate secure keys
|
|
*
|
|
- * Copyright 2017 IBM Corp.
|
|
+ * Copyright IBM Corp. 2017, 2018
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
@@ -27,6 +27,7 @@
|
|
#include "lib/util_prg.h"
|
|
#include "lib/zt_common.h"
|
|
|
|
+#include "keystore.h"
|
|
#include "misc.h"
|
|
#include "pkey.h"
|
|
|
|
@@ -34,30 +35,77 @@
|
|
* Program configuration
|
|
*/
|
|
const struct util_prg prg = {
|
|
- .desc = "Generate, re-encipher, and validate secure AES keys",
|
|
- .command_args = "COMMAND SECURE-KEY-FILE",
|
|
+ .desc = "Manage secure AES keys",
|
|
+ .command_args = "COMMAND [SECURE-KEY-FILE]",
|
|
.args = "",
|
|
.copyright_vec = {
|
|
{
|
|
.owner = "IBM Corp.",
|
|
.pub_first = 2017,
|
|
- .pub_last = 2017,
|
|
+ .pub_last = 2018,
|
|
},
|
|
UTIL_PRG_COPYRIGHT_END
|
|
}
|
|
};
|
|
|
|
/*
|
|
+ * Global variables for program options
|
|
+ */
|
|
+static struct zkey_globals {
|
|
+ char *pos_arg;
|
|
+ char *clearkeyfile;
|
|
+ char *outputfile;
|
|
+ bool xts;
|
|
+ bool verbose;
|
|
+ long int keybits;
|
|
+ bool tonew;
|
|
+ bool fromold;
|
|
+ bool complete;
|
|
+ bool inplace;
|
|
+ bool staged;
|
|
+ char *name;
|
|
+ char *description;
|
|
+ char *volumes;
|
|
+ char *apqns;
|
|
+ long int sector_size;
|
|
+ char *newname;
|
|
+ bool run;
|
|
+ bool force;
|
|
+ void *lib_csulcca;
|
|
+ t_CSNBKTC dll_CSNBKTC;
|
|
+ int pkey_fd;
|
|
+ struct keystore *keystore;
|
|
+} g = {
|
|
+ .pkey_fd = -1,
|
|
+ .sector_size = -1,
|
|
+};
|
|
+
|
|
+/*
|
|
* Available commands
|
|
*/
|
|
#define COMMAND_GENERATE "generate"
|
|
#define COMMAND_REENCIPHER "reencipher"
|
|
#define COMMAND_VALIDATE "validate"
|
|
+#define COMMAND_IMPORT "import"
|
|
+#define COMMAND_EXPORT "export"
|
|
+#define COMMAND_LIST "list "
|
|
+#define COMMAND_REMOVE "remove"
|
|
+#define COMMAND_CHANGE "change"
|
|
+#define COMMAND_RENAME "rename"
|
|
+#define COMMAND_COPY "copy "
|
|
+#define COMMAND_CRYPTTAB "crypttab"
|
|
+#define COMMAND_CRYPTSETUP "cryptsetup"
|
|
+
|
|
+#define ZKEY_COMMAND_MAX_LEN 10
|
|
+
|
|
+#define ENVVAR_ZKEY_REPOSITORY "ZKEY_REPOSITORY"
|
|
+#define DEFAULT_KEYSTORE "/etc/zkey/repository"
|
|
|
|
/*
|
|
* Configuration of command line options
|
|
*/
|
|
static struct util_opt opt_vec[] = {
|
|
+ /***********************************************************/
|
|
{
|
|
.flags = UTIL_OPT_FLAG_SECTION,
|
|
.desc = "OPTIONS",
|
|
@@ -91,6 +139,49 @@ static struct util_opt opt_vec[] = {
|
|
.command = COMMAND_GENERATE,
|
|
},
|
|
{
|
|
+ .option = { "name", required_argument, NULL, 'N'},
|
|
+ .argument = "NAME",
|
|
+ .desc = "Name of the secure AES key in the repository. If "
|
|
+ "option --name/-N is specified, then the generated "
|
|
+ "secure AES key is stored in the repository. Parameter "
|
|
+ "SECURE-KEY-FILE is not used when option --name/-M is "
|
|
+ "specified",
|
|
+ .command = COMMAND_GENERATE,
|
|
+ },
|
|
+ {
|
|
+ .option = { "description", required_argument, NULL, 'd'},
|
|
+ .argument = "DESCRIPTION",
|
|
+ .desc = "Textual description of the secure AES key in the "
|
|
+ "repository",
|
|
+ .command = COMMAND_GENERATE,
|
|
+ },
|
|
+ {
|
|
+ .option = { "volumes", required_argument, NULL, 'l'},
|
|
+ .argument = "VOLUME:DMNAME[,...]",
|
|
+ .desc = "Comma-separated pairs of volume and device-mapper "
|
|
+ "names that are associated with the secure AES key in "
|
|
+ "the repository",
|
|
+ .command = COMMAND_GENERATE,
|
|
+ },
|
|
+ {
|
|
+ .option = { "apqns", required_argument, NULL, 'a'},
|
|
+ .argument = "CARD.DOMAIN[,...]",
|
|
+ .desc = "Comma-separated pairs of crypto cards and domains "
|
|
+ "that are associated with the secure AES key in the "
|
|
+ "repository",
|
|
+ .command = COMMAND_GENERATE,
|
|
+ },
|
|
+ {
|
|
+ .option = { "sector-size", required_argument, NULL, 'S'},
|
|
+ .argument = "bytes",
|
|
+ .desc = "The sector size used with dm-crypt. It must be a power "
|
|
+ "of two and in range 512 - 4096 bytes. If this option "
|
|
+ "is omitted, the system default sector size (512) is "
|
|
+ "used",
|
|
+ .command = COMMAND_GENERATE,
|
|
+ },
|
|
+ /***********************************************************/
|
|
+ {
|
|
.flags = UTIL_OPT_FLAG_SECTION,
|
|
.desc = "OPTIONS",
|
|
.command = COMMAND_REENCIPHER,
|
|
@@ -119,12 +210,322 @@ static struct util_opt opt_vec[] = {
|
|
.command = COMMAND_REENCIPHER,
|
|
},
|
|
{
|
|
+ .option = {"complete", 0, NULL, 'p'},
|
|
+ .desc = "Completes a pending re-enciphering of a secure AES "
|
|
+ "key that was re-enciphered with the master key in the "
|
|
+ "NEW register",
|
|
+ .command = COMMAND_REENCIPHER,
|
|
+ },
|
|
+ {
|
|
+ .option = {"in-place", 0, NULL, 'i'},
|
|
+ .desc = "Forces an in-place re-enchipering of a secure AES key",
|
|
+ .command = COMMAND_REENCIPHER,
|
|
+ },
|
|
+ {
|
|
+ .option = {"staged", 0, NULL, 's'},
|
|
+ .desc = "Forces a staged re-enchipering of a secure AES key",
|
|
+ .command = COMMAND_REENCIPHER,
|
|
+ },
|
|
+ {
|
|
+ .option = { "name", required_argument, NULL, 'N'},
|
|
+ .argument = "NAME",
|
|
+ .desc = "Name of the secure AES keys in the repository that "
|
|
+ "are to be re-enciphered. You can use wild-cards to "
|
|
+ "select the keys to re-encipher.",
|
|
+ .command = COMMAND_REENCIPHER,
|
|
+ },
|
|
+ {
|
|
+ .option = { "apqns", required_argument, NULL, 'a'},
|
|
+ .argument = "CARD.DOMAIN[,...]",
|
|
+ .desc = "Comma-separated pairs of crypto cards and domains "
|
|
+ "that are associated with the secure AES key in the "
|
|
+ "repository. Use this option to re-encipher all keys "
|
|
+ "associated with specific crypto cards",
|
|
+ .command = COMMAND_REENCIPHER,
|
|
+ },
|
|
+ /***********************************************************/
|
|
+ {
|
|
+ .flags = UTIL_OPT_FLAG_SECTION,
|
|
+ .desc = "OPTIONS",
|
|
+ .command = COMMAND_VALIDATE,
|
|
+ },
|
|
+ {
|
|
+ .option = { "name", required_argument, NULL, 'N'},
|
|
+ .argument = "NAME",
|
|
+ .desc = "Name of the secure AES keys in the repository that "
|
|
+ "are to be validated. You can use wild-cards to select "
|
|
+ "the keys to validate.",
|
|
+ .command = COMMAND_VALIDATE,
|
|
+ },
|
|
+ {
|
|
+ .option = { "apqns", required_argument, NULL, 'a'},
|
|
+ .argument = "CARD.DOMAIN[,...]",
|
|
+ .desc = "Comma-separated pairs of crypto cards and domains "
|
|
+ "that are associated with the secure AES key in the "
|
|
+ "repository. Use this option to validate all keys "
|
|
+ "associated with specific crypto cards",
|
|
+ .command = COMMAND_VALIDATE,
|
|
+ },
|
|
+ /***********************************************************/
|
|
+ {
|
|
+ .flags = UTIL_OPT_FLAG_SECTION,
|
|
+ .desc = "OPTIONS",
|
|
+ .command = COMMAND_IMPORT,
|
|
+ },
|
|
+ {
|
|
+ .option = { "name", required_argument, NULL, 'N'},
|
|
+ .argument = "NAME",
|
|
+ .desc = "Name of the imported secure AES key in the repository",
|
|
+ .command = COMMAND_IMPORT,
|
|
+ },
|
|
+ {
|
|
+ .option = { "description", required_argument, NULL, 'd'},
|
|
+ .argument = "DESCRIPTION",
|
|
+ .desc = "Textual description of the secure AES key in the "
|
|
+ "repository",
|
|
+ .command = COMMAND_IMPORT,
|
|
+ },
|
|
+ {
|
|
+ .option = { "volumes", required_argument, NULL, 'l'},
|
|
+ .argument = "VOLUME:DMNAME[,...]",
|
|
+ .desc = "Comma-separated pairs of volume and device-mapper "
|
|
+ "names that are associated with the secure AES key in "
|
|
+ "the repository",
|
|
+ .command = COMMAND_IMPORT,
|
|
+ },
|
|
+ {
|
|
+ .option = { "apqns", required_argument, NULL, 'a'},
|
|
+ .argument = "CARD.DOMAIN[,...]",
|
|
+ .desc = "Comma-separated pairs of crypto cards and domains "
|
|
+ "that are associated with the secure AES key in the "
|
|
+ "repository",
|
|
+ .command = COMMAND_IMPORT,
|
|
+ },
|
|
+ {
|
|
+ .option = { "sector-size", required_argument, NULL, 'S'},
|
|
+ .argument = "512|4096",
|
|
+ .desc = "The sector size used with dm-crypt. It must be power "
|
|
+ "of two and in range 512 - 4096 bytes. If this option "
|
|
+ "is omitted, the system default sector size (512) is "
|
|
+ "used",
|
|
+ .command = COMMAND_IMPORT,
|
|
+ },
|
|
+ /***********************************************************/
|
|
+ {
|
|
+ .flags = UTIL_OPT_FLAG_SECTION,
|
|
+ .desc = "OPTIONS",
|
|
+ .command = COMMAND_EXPORT,
|
|
+ },
|
|
+ {
|
|
+ .option = { "name", required_argument, NULL, 'N'},
|
|
+ .argument = "NAME",
|
|
+ .desc = "Name of the secure AES key in the repository that is "
|
|
+ "to be exported",
|
|
+ .command = COMMAND_EXPORT,
|
|
+ },
|
|
+ /***********************************************************/
|
|
+ {
|
|
+ .flags = UTIL_OPT_FLAG_SECTION,
|
|
+ .desc = "OPTIONS",
|
|
+ .command = COMMAND_LIST,
|
|
+ },
|
|
+ {
|
|
+ .option = { "name", required_argument, NULL, 'N'},
|
|
+ .argument = "NAME",
|
|
+ .desc = "Name of the secure AES keys in the repository that "
|
|
+ "are to be listed. You can use wild-cards to select "
|
|
+ "the keys to list.",
|
|
+ .command = COMMAND_LIST,
|
|
+ },
|
|
+ {
|
|
+ .option = { "volumes", required_argument, NULL, 'l'},
|
|
+ .argument = "VOLUME[:DMNAME][,...]",
|
|
+ .desc = "Comma-separated pairs of volume and device-mapper "
|
|
+ "names that are associated with the secure AES key in "
|
|
+ "the repository. Use this option to list all keys "
|
|
+ "associated with specific volumes. The device-mapper "
|
|
+ "name (DMNAME) is optional. If specified, only those "
|
|
+ "keys are listed where both, the volume and the device-"
|
|
+ "mapper name matches",
|
|
+ .command = COMMAND_LIST,
|
|
+ },
|
|
+ {
|
|
+ .option = { "apqns", required_argument, NULL, 'a'},
|
|
+ .argument = "CARD.DOMAIN[,...]",
|
|
+ .desc = "Comma-separated pairs of crypto cards and domains "
|
|
+ "that are associated with the secure AES key in the "
|
|
+ "repository. Use this option to list all keys "
|
|
+ "associated with specific crypto cards",
|
|
+ .command = COMMAND_LIST,
|
|
+ },
|
|
+ /***********************************************************/
|
|
+ {
|
|
+ .flags = UTIL_OPT_FLAG_SECTION,
|
|
+ .desc = "OPTIONS",
|
|
+ .command = COMMAND_REMOVE,
|
|
+ },
|
|
+ {
|
|
+ .option = { "name", required_argument, NULL, 'N'},
|
|
+ .argument = "NAME",
|
|
+ .desc = "Name of the secure AES key in the repository that is "
|
|
+ "to be removed",
|
|
+ .command = COMMAND_REMOVE,
|
|
+ },
|
|
+ {
|
|
+ .option = {"force", 0, NULL, 'F'},
|
|
+ .desc = "Do not prompt for a confirmation when removing a key",
|
|
+ .command = COMMAND_REMOVE,
|
|
+ },
|
|
+ /***********************************************************/
|
|
+ {
|
|
+ .flags = UTIL_OPT_FLAG_SECTION,
|
|
+ .desc = "OPTIONS",
|
|
+ .command = COMMAND_CHANGE,
|
|
+ },
|
|
+ {
|
|
+ .option = { "name", required_argument, NULL, 'N'},
|
|
+ .argument = "NAME",
|
|
+ .desc = "Name of the secure AES key in the repository that is "
|
|
+ "to be changed",
|
|
+ .command = COMMAND_CHANGE,
|
|
+ },
|
|
+ {
|
|
+ .option = { "description", required_argument, NULL, 'd'},
|
|
+ .argument = "DESCRIPTION",
|
|
+ .desc = "Textual description of the secure AES key in the "
|
|
+ "repository",
|
|
+ .command = COMMAND_CHANGE,
|
|
+ },
|
|
+ {
|
|
+ .option = { "volumes", required_argument, NULL, 'l'},
|
|
+ .argument = "[+|-]VOLUME:DMNAME[,...]",
|
|
+ .desc = "Comma-separated pairs of volume and device-mapper "
|
|
+ "names that are associated with the secure AES key in "
|
|
+ "the repository. To add pairs of volume and device-"
|
|
+ "mapper names to the key specify '+VOLUME:DMNAME[,...]'. "
|
|
+ "To remove pairs of volume and device-mapper names "
|
|
+ "from the key specify '-VOLUME:DMNAME[,...]'",
|
|
+ .command = COMMAND_CHANGE,
|
|
+ },
|
|
+ {
|
|
+ .option = { "apqns", required_argument, NULL, 'a'},
|
|
+ .argument = "[+|-]CARD.DOMAIN[,...]",
|
|
+ .desc = "Comma-separated pairs of crypto cards and domains "
|
|
+ "that are associated with the secure AES key in the "
|
|
+ "repository. To add pairs of crypto cards and domains "
|
|
+ "to the key specify '+CARD.DOMAIN[,...]'. To remove "
|
|
+ "pairs of crypto cards and domains from the key "
|
|
+ "specify '-CARD.DOMAIN[,...]'",
|
|
+ .command = COMMAND_CHANGE,
|
|
+ },
|
|
+ {
|
|
+ .option = { "sector-size", required_argument, NULL, 'S'},
|
|
+ .argument = "0|512|4096",
|
|
+ .desc = "The sector size used with dm-crypt. It must be power "
|
|
+ "of two and in range 512 - 4096 bytes. If this option "
|
|
+ "is omitted, the system default sector size (512) is "
|
|
+ "used",
|
|
+ .command = COMMAND_CHANGE,
|
|
+ },
|
|
+ /***********************************************************/
|
|
+ {
|
|
+ .flags = UTIL_OPT_FLAG_SECTION,
|
|
+ .desc = "OPTIONS",
|
|
+ .command = COMMAND_RENAME,
|
|
+ },
|
|
+ {
|
|
+ .option = { "name", required_argument, NULL, 'N'},
|
|
+ .argument = "NAME",
|
|
+ .desc = "Name of the secure AES key in the repository that is "
|
|
+ "to be renamed",
|
|
+ .command = COMMAND_RENAME,
|
|
+ },
|
|
+ {
|
|
+ .option = { "new-name", required_argument, NULL, 'w'},
|
|
+ .argument = "NEW-NAME",
|
|
+ .desc = "New name of the secure AES key in the repository",
|
|
+ .command = COMMAND_RENAME,
|
|
+ },
|
|
+ /***********************************************************/
|
|
+ {
|
|
+ .flags = UTIL_OPT_FLAG_SECTION,
|
|
+ .desc = "OPTIONS",
|
|
+ .command = COMMAND_COPY,
|
|
+ },
|
|
+ {
|
|
+ .option = { "name", required_argument, NULL, 'N'},
|
|
+ .argument = "NAME",
|
|
+ .desc = "Name of the secure AES key in the repository that is "
|
|
+ "to be copied",
|
|
+ .command = COMMAND_COPY,
|
|
+ },
|
|
+ {
|
|
+ .option = { "new-name", required_argument, NULL, 'w'},
|
|
+ .argument = "NEW-NAME",
|
|
+ .desc = "New name of the secure AES key in the repository",
|
|
+ .command = COMMAND_COPY,
|
|
+ },
|
|
+ {
|
|
+ .option = { "volumes", required_argument, NULL, 'l'},
|
|
+ .argument = "VOLUME:DMNAME[,...]",
|
|
+ .desc = "Comma-separated pairs of volume and device-mapper "
|
|
+ "names that are associated with the copied secure AES "
|
|
+ "key in the repository. If option '--volumes/-l' is "
|
|
+ "omitted, no volumes are associated with the copied "
|
|
+ "key, because only one key can be associated to a "
|
|
+ "specific volume.",
|
|
+ .command = COMMAND_COPY,
|
|
+ },
|
|
+ /***********************************************************/
|
|
+ {
|
|
+ .flags = UTIL_OPT_FLAG_SECTION,
|
|
+ .desc = "OPTIONS",
|
|
+ .command = COMMAND_CRYPTTAB,
|
|
+ },
|
|
+ {
|
|
+ .option = { "volumes", required_argument, NULL, 'l'},
|
|
+ .argument = "VOLUME[:DMNAME][,...]",
|
|
+ .desc = "Comma-separated pairs of volume and device-mapper "
|
|
+ "names that are associated with the secure AES key in "
|
|
+ "the repository. Use this option to select the volumes "
|
|
+ "for which a crypttab entry is to be generated. The "
|
|
+ "device-mapper name (DMNAME) is optional. If specified, "
|
|
+ "only those volumes are selected where both, the "
|
|
+ "volume and the device-mapper name matches",
|
|
+ .command = COMMAND_CRYPTTAB,
|
|
+ },
|
|
+ /***********************************************************/
|
|
+ {
|
|
+ .flags = UTIL_OPT_FLAG_SECTION,
|
|
+ .desc = "OPTIONS",
|
|
+ .command = COMMAND_CRYPTSETUP,
|
|
+ },
|
|
+ {
|
|
+ .option = { "volumes", required_argument, NULL, 'l'},
|
|
+ .argument = "VOLUME[:DMNAME][,...]",
|
|
+ .desc = "Comma-separated pairs of volume and device-mapper "
|
|
+ "names that are associated with the secure AES key in "
|
|
+ "the repository. Use this option to select the volumes "
|
|
+ "for which a cryptsetup command is to be generated or "
|
|
+ "run. The device-mapper name (DMNAME) is optional."
|
|
+ " If specified, only those volumes are selected where "
|
|
+ "both, the volume and the device-mapper name matches",
|
|
+ .command = COMMAND_CRYPTSETUP,
|
|
+ },
|
|
+ {
|
|
+ .option = {"run", 0, NULL, 'r'},
|
|
+ .desc = "Runs the generated cryptsetup command",
|
|
+ .command = COMMAND_CRYPTSETUP,
|
|
+ },
|
|
+ /***********************************************************/
|
|
+ {
|
|
.flags = UTIL_OPT_FLAG_SECTION,
|
|
.desc = "COMMON OPTIONS"
|
|
},
|
|
{
|
|
.option = {"verbose", 0, NULL, 'V'},
|
|
- .desc = "Print additional information messages during processing",
|
|
+ .desc = "Print additional information messages during "
|
|
+ "processing",
|
|
},
|
|
UTIL_OPT_HELP,
|
|
UTIL_OPT_VERSION,
|
|
@@ -139,17 +540,31 @@ static struct util_opt opt_vec[] = {
|
|
struct zkey_command {
|
|
char *command;
|
|
unsigned int abbrev_len;
|
|
- int (*function)(const char *keyfile);
|
|
+ int (*function)(void);
|
|
int need_cca_library;
|
|
int need_pkey_device;
|
|
char *short_desc;
|
|
char *long_desc;
|
|
int has_options;
|
|
+ char *pos_arg;
|
|
+ int pos_arg_optional;
|
|
+ char *pos_arg_alternate;
|
|
+ char **arg_alternate_value;
|
|
+ int need_keystore;
|
|
};
|
|
|
|
-static int command_generate(const char *keyfile);
|
|
-static int command_reencipher(const char *keyfile);
|
|
-static int command_validate(const char *keyfile);
|
|
+static int command_generate(void);
|
|
+static int command_reencipher(void);
|
|
+static int command_validate(void);
|
|
+static int command_import(void);
|
|
+static int command_export(void);
|
|
+static int command_list(void);
|
|
+static int command_remove(void);
|
|
+static int command_change(void);
|
|
+static int command_rename(void);
|
|
+static int command_copy(void);
|
|
+static int command_crypttab(void);
|
|
+static int command_cryptsetup(void);
|
|
|
|
static struct zkey_command zkey_commands[] = {
|
|
{
|
|
@@ -159,8 +574,14 @@ static struct zkey_command zkey_commands
|
|
.need_pkey_device = 1,
|
|
.short_desc = "Generate a secure AES key",
|
|
.long_desc = "Generate a secure AES key either by "
|
|
- "random or from a specified clear key",
|
|
+ "random or from a specified clear key and store "
|
|
+ "it either into SECURE-KEY-FILE or into the "
|
|
+ "repository",
|
|
.has_options = 1,
|
|
+ .pos_arg = "[SECURE-KEY-FILE]",
|
|
+ .pos_arg_optional = 1,
|
|
+ .pos_arg_alternate = "--name/-N",
|
|
+ .arg_alternate_value = &g.name,
|
|
},
|
|
{
|
|
.command = COMMAND_REENCIPHER,
|
|
@@ -170,8 +591,12 @@ static struct zkey_command zkey_commands
|
|
.need_pkey_device = 1,
|
|
.short_desc = "Re-encipher an existing secure AES key",
|
|
.long_desc = "Re-encipher an existing secure AES "
|
|
- "key with another CCA master key",
|
|
+ "key that is either contained in SECURE-KEY-FILE "
|
|
+ "or is stored in the repository with another "
|
|
+ "CCA master key",
|
|
.has_options = 1,
|
|
+ .pos_arg = "[SECURE-KEY-FILE]",
|
|
+ .pos_arg_optional = 1,
|
|
},
|
|
{
|
|
.command = COMMAND_VALIDATE,
|
|
@@ -179,8 +604,100 @@ static struct zkey_command zkey_commands
|
|
.function = command_validate,
|
|
.need_pkey_device = 1,
|
|
.short_desc = "Validate an existing secure AES key",
|
|
- .long_desc = "Validate an existing secure AES key and print "
|
|
- "information about the key",
|
|
+ .long_desc = "Validate an existing secure AES key that is "
|
|
+ "either contained in SECURE-KEY-FILE or is stored"
|
|
+ "in the repository and print information about "
|
|
+ "the key",
|
|
+ .has_options = 1,
|
|
+ .pos_arg = "[SECURE-KEY-FILE]",
|
|
+ .pos_arg_optional = 1,
|
|
+ },
|
|
+ {
|
|
+ .command = COMMAND_IMPORT,
|
|
+ .abbrev_len = 2,
|
|
+ .function = command_import,
|
|
+ .short_desc = "Import a secure AES key",
|
|
+ .long_desc = "Import a secure AES key from a file into the "
|
|
+ "repository",
|
|
+ .has_options = 1,
|
|
+ .pos_arg = "SECURE-KEY-FILE",
|
|
+ .need_keystore = 1,
|
|
+ },
|
|
+ {
|
|
+ .command = COMMAND_EXPORT,
|
|
+ .abbrev_len = 2,
|
|
+ .function = command_export,
|
|
+ .short_desc = "Export a secure AES key",
|
|
+ .long_desc = "Export a secure AES key from the repository to "
|
|
+ "a file",
|
|
+ .has_options = 1,
|
|
+ .pos_arg = "SECURE-KEY-FILE",
|
|
+ .need_keystore = 1,
|
|
+ },
|
|
+ {
|
|
+ .command = COMMAND_LIST,
|
|
+ .abbrev_len = 2,
|
|
+ .function = command_list,
|
|
+ .short_desc = "List keys in the repository",
|
|
+ .long_desc = "List secure AES key in the repository",
|
|
+ .has_options = 1,
|
|
+ .need_keystore = 1,
|
|
+ },
|
|
+ {
|
|
+ .command = COMMAND_REMOVE,
|
|
+ .abbrev_len = 3,
|
|
+ .function = command_remove,
|
|
+ .short_desc = "Remove a secure AES key",
|
|
+ .long_desc = "Remove a secure AES key from the repository",
|
|
+ .has_options = 1,
|
|
+ .need_keystore = 1,
|
|
+ },
|
|
+ {
|
|
+ .command = COMMAND_CHANGE,
|
|
+ .abbrev_len = 2,
|
|
+ .function = command_change,
|
|
+ .short_desc = "Change a secure AES key",
|
|
+ .long_desc = "Change the properties of a secure AES key in "
|
|
+ "the repository",
|
|
+ .has_options = 1,
|
|
+ .need_keystore = 1,
|
|
+ },
|
|
+ {
|
|
+ .command = COMMAND_RENAME,
|
|
+ .abbrev_len = 3,
|
|
+ .function = command_rename,
|
|
+ .short_desc = "Rename a secure AES key",
|
|
+ .long_desc = "Rename a secure AES key in the repository",
|
|
+ .has_options = 1,
|
|
+ .need_keystore = 1,
|
|
+ },
|
|
+ {
|
|
+ .command = COMMAND_COPY,
|
|
+ .abbrev_len = 2,
|
|
+ .function = command_copy,
|
|
+ .short_desc = "Copy a secure AES key",
|
|
+ .long_desc = "Copy a secure AES key in the repository",
|
|
+ .has_options = 1,
|
|
+ .need_keystore = 1,
|
|
+ },
|
|
+ {
|
|
+ .command = COMMAND_CRYPTTAB,
|
|
+ .abbrev_len = 6,
|
|
+ .function = command_crypttab,
|
|
+ .short_desc = "Generate crypttab entries",
|
|
+ .long_desc = "Generate crypttab entries for selected volumes",
|
|
+ .has_options = 1,
|
|
+ .need_keystore = 1,
|
|
+ },
|
|
+ {
|
|
+ .command = COMMAND_CRYPTSETUP,
|
|
+ .abbrev_len = 6,
|
|
+ .function = command_cryptsetup,
|
|
+ .short_desc = "Generate or run cryptsetup commands",
|
|
+ .long_desc = "Generate or run cryptsetup commands for "
|
|
+ "selected volumes",
|
|
+ .has_options = 1,
|
|
+ .need_keystore = 1,
|
|
},
|
|
{ .command = NULL }
|
|
};
|
|
@@ -197,9 +714,12 @@ static void print_usage_command(const st
|
|
for (i = 0; i < command->abbrev_len; i++)
|
|
command_str[i] = toupper(command_str[i]);
|
|
|
|
- printf("Usage: %s %s SECURE-KEY-FILE",
|
|
+ printf("Usage: %s %s",
|
|
program_invocation_short_name, command_str);
|
|
- printf(" [OPTIONS]");
|
|
+ if (command->pos_arg != NULL)
|
|
+ printf(" %s", command->pos_arg);
|
|
+ if (command->has_options)
|
|
+ printf(" [OPTIONS]");
|
|
if (prg.args)
|
|
printf(" %s", prg.args);
|
|
printf("\n\n");
|
|
@@ -222,7 +742,8 @@ static void print_usage_command_list(voi
|
|
strcpy(command_str, cmd->command);
|
|
for (i = 0; i < cmd->abbrev_len; i++)
|
|
command_str[i] = toupper(command_str[i]);
|
|
- printf(" %s\t%s\n", command_str, cmd->short_desc);
|
|
+ printf(" %-*s %s\n", ZKEY_COMMAND_MAX_LEN, command_str,
|
|
+ cmd->short_desc);
|
|
cmd++;
|
|
}
|
|
printf("\n");
|
|
@@ -250,40 +771,21 @@ static void print_help(const struct zkey
|
|
}
|
|
|
|
/*
|
|
- * Global variables for program options
|
|
- */
|
|
-static struct zkey_globals {
|
|
- char *clearkeyfile;
|
|
- char *outputfile;
|
|
- int xts;
|
|
- int verbose;
|
|
- long int keybits;
|
|
- int tonew;
|
|
- int fromold;
|
|
- void *lib_csulcca;
|
|
- t_CSNBKTC dll_CSNBKTC;
|
|
- int pkey_fd;
|
|
-} g = {
|
|
- .pkey_fd = -1,
|
|
-};
|
|
-
|
|
-/*
|
|
* Command handler for 'generate with clear key'
|
|
*
|
|
* Generate a secure key from the specified clear key.
|
|
*/
|
|
-static int command_generate_clear(const char *keyfile)
|
|
+static int command_generate_clear(void)
|
|
{
|
|
int rc;
|
|
|
|
- rc = generate_secure_key_clear(g.pkey_fd, keyfile,
|
|
+ rc = generate_secure_key_clear(g.pkey_fd, g.pos_arg,
|
|
g.keybits, g.xts,
|
|
g.clearkeyfile,
|
|
AUTOSELECT, AUTOSELECT,
|
|
g.verbose);
|
|
- if (rc != 0)
|
|
- rc = EXIT_FAILURE;
|
|
- return rc;
|
|
+
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
@@ -291,29 +793,78 @@ static int command_generate_clear(const
|
|
*
|
|
* Generate a secure key by random using the pkey kernel module.
|
|
*/
|
|
-static int command_generate_random(const char *keyfile)
|
|
+static int command_generate_random(void)
|
|
{
|
|
int rc;
|
|
|
|
- rc = generate_secure_key_random(g.pkey_fd, keyfile,
|
|
+ rc = generate_secure_key_random(g.pkey_fd, g.pos_arg,
|
|
g.keybits, g.xts,
|
|
AUTOSELECT, AUTOSELECT,
|
|
g.verbose);
|
|
- if (rc != 0)
|
|
- rc = EXIT_FAILURE;
|
|
|
|
- return rc;
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
+ * Command handler for 'generate in repository'.
|
|
+ *
|
|
+ * Generate a secure key and store it in the repository.
|
|
+ */
|
|
+static int command_generate_repository(void)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ if (g.sector_size < 0)
|
|
+ g.sector_size = 0;
|
|
+
|
|
+ rc = keystore_generate_key(g.keystore, g.name, g.description, g.volumes,
|
|
+ g.apqns, g.sector_size, g.keybits, g.xts,
|
|
+ g.clearkeyfile, g.pkey_fd);
|
|
+
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
* Command handler for 'generate'.
|
|
*
|
|
* Generate a new secure key either by random or from the specified clear key.
|
|
*/
|
|
-static int command_generate(const char *keyfile)
|
|
+static int command_generate(void)
|
|
{
|
|
- return g.clearkeyfile ? command_generate_clear(keyfile)
|
|
- : command_generate_random(keyfile);
|
|
+ if (g.pos_arg != NULL && g.name != NULL) {
|
|
+ warnx(" Option '--name|-N' is not valid for generating a key "
|
|
+ "outside of the repository");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ if (g.name != NULL)
|
|
+ return command_generate_repository();
|
|
+ if (g.pos_arg != NULL) {
|
|
+ if (g.volumes != NULL) {
|
|
+ warnx("Option '--volumes|-l' is not valid for "
|
|
+ "generating a key outside of the repository");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ if (g.apqns != NULL) {
|
|
+ warnx("Option '--apqns|-a' is not valid for "
|
|
+ "generating a key outside of the repository");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ if (g.description != NULL) {
|
|
+ warnx("Option '--description|-d' is not valid for "
|
|
+ "generating a key outside of the repository");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
+ return g.clearkeyfile ? command_generate_clear()
|
|
+ : command_generate_random();
|
|
+ }
|
|
+
|
|
+ return EXIT_FAILURE;
|
|
}
|
|
|
|
|
|
@@ -322,21 +873,52 @@ static int command_generate(const char *
|
|
*
|
|
* Re-encipher the specified secure key with the NEW or CURRENT CCA master key.
|
|
*/
|
|
-static int command_reencipher(const char *keyfile)
|
|
+static int command_reencipher_file(void)
|
|
{
|
|
size_t secure_key_size;
|
|
int rc, is_old_mk;
|
|
u8 *secure_key;
|
|
|
|
+ if (g.name != NULL) {
|
|
+ warnx("Option '--name|-N' is not valid for "
|
|
+ "re-enciphering a key outside of the repository");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ if (g.apqns != NULL) {
|
|
+ warnx("Option '--apqns|-a' is not valid for "
|
|
+ "re-enciphering a key outside of the repository");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ if (g.inplace) {
|
|
+ warnx("Option '--in-place|-i' is not valid for "
|
|
+ "re-enciphering a key outside of the repository");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ if (g.staged) {
|
|
+ warnx("Option '--staged|-s' is not valid for "
|
|
+ "re-enciphering a key outside of the repository");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ if (g.complete) {
|
|
+ warnx("Option '--complete|-p' is not valid for "
|
|
+ "re-enciphering a key outside of the repository");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
/* Read the secure key to be re-enciphered */
|
|
- secure_key = read_secure_key(keyfile, &secure_key_size, g.verbose);
|
|
+ secure_key = read_secure_key(g.pos_arg, &secure_key_size, g.verbose);
|
|
if (secure_key == NULL)
|
|
return EXIT_FAILURE;
|
|
|
|
rc = validate_secure_key(g.pkey_fd, secure_key, secure_key_size, NULL,
|
|
&is_old_mk, g.verbose);
|
|
if (rc != 0) {
|
|
- warnx("The secure key in file '%s' is not valid", keyfile);
|
|
+ warnx("The secure key in file '%s' is not valid", g.pos_arg);
|
|
rc = EXIT_FAILURE;
|
|
goto out;
|
|
}
|
|
@@ -401,7 +983,7 @@ static int command_reencipher(const char
|
|
pr_verbose("Secure key was re-enciphered successfully");
|
|
|
|
/* Write the migrated secure key */
|
|
- rc = write_secure_key(g.outputfile ? g.outputfile : keyfile,
|
|
+ rc = write_secure_key(g.outputfile ? g.outputfile : g.pos_arg,
|
|
secure_key, secure_key_size, g.verbose);
|
|
if (rc != 0)
|
|
rc = EXIT_FAILURE;
|
|
@@ -411,11 +993,69 @@ out:
|
|
}
|
|
|
|
/*
|
|
+ * Command handler for 'reencipher in repository'.
|
|
+ *
|
|
+ * Re-encipher the specified secure key with the NEW or CURRENT CCA master key.
|
|
+ */
|
|
+static int command_reencipher_repository(void)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ if (g.outputfile) {
|
|
+ warnx("Option '--output|-o' is not valid for "
|
|
+ "re-enciphering a key in the repository");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ if (g.inplace && g.staged) {
|
|
+ warnx("Either '--in-place|-i' or '--staged|-s' can be "
|
|
+ "specified, but not both");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ if (g.complete) {
|
|
+ if (g.inplace) {
|
|
+ warnx("Option '--in-place|-i' is not valid together "
|
|
+ "with '--complete|-p'");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ if (g.staged) {
|
|
+ warnx("Option '--staged|-s' is not valid together "
|
|
+ "with '--complete|-p'");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ rc = keystore_reencipher_key(g.keystore, g.name, g.apqns, g.fromold,
|
|
+ g.tonew, g.inplace, g.staged, g.complete,
|
|
+ g.pkey_fd, g.dll_CSNBKTC);
|
|
+
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Command handler for 'reencipher'.
|
|
+ *
|
|
+ * Re-encipher the specified secure key with the NEW or CURRENT CCA master key.
|
|
+ */
|
|
+static int command_reencipher(void)
|
|
+{
|
|
+ if (g.pos_arg != NULL)
|
|
+ return command_reencipher_file();
|
|
+ else
|
|
+ return command_reencipher_repository();
|
|
+
|
|
+ return EXIT_FAILURE;
|
|
+}
|
|
+
|
|
+/*
|
|
* Command handler for 'validate'.
|
|
*
|
|
* Validates the specified secure key and prints out information about it.
|
|
*/
|
|
-static int command_validate(const char *keyfile)
|
|
+static int command_validate_file(void)
|
|
{
|
|
size_t secure_key_size;
|
|
size_t clear_key_size;
|
|
@@ -423,20 +1063,33 @@ static int command_validate(const char *
|
|
int is_old_mk;
|
|
int rc;
|
|
|
|
+ if (g.name != NULL) {
|
|
+ warnx("Option '--name|-N' is not valid for "
|
|
+ "validating a key outside of the repository");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ if (g.apqns != NULL) {
|
|
+ warnx("Option '--apqns|-a' is not valid for "
|
|
+ "validating a key outside of the repository");
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
/* Read the secure key to be re-enciphered */
|
|
- secure_key = read_secure_key(keyfile, &secure_key_size, g.verbose);
|
|
+ secure_key = read_secure_key(g.pos_arg, &secure_key_size, g.verbose);
|
|
if (secure_key == NULL)
|
|
return EXIT_FAILURE;
|
|
|
|
rc = validate_secure_key(g.pkey_fd, secure_key, secure_key_size,
|
|
&clear_key_size, &is_old_mk, g.verbose);
|
|
if (rc != 0) {
|
|
- warnx("The secure key in file '%s' is not valid", keyfile);
|
|
+ warnx("The secure key in file '%s' is not valid", g.pos_arg);
|
|
rc = EXIT_FAILURE;
|
|
goto out;
|
|
}
|
|
|
|
- printf("Validation of secure key in file '%s':\n", keyfile);
|
|
+ printf("Validation of secure key in file '%s':\n", g.pos_arg);
|
|
printf(" Status: Valid\n");
|
|
printf(" Secure key size: %lu bytes\n", secure_key_size);
|
|
printf(" Clear key size: %lu bits\n", clear_key_size);
|
|
@@ -450,6 +1103,222 @@ out:
|
|
return rc;
|
|
}
|
|
|
|
+/*
|
|
+ * Command handler for 'validate in repository'.
|
|
+ *
|
|
+ * Validates the specified secure key and prints out information about it.
|
|
+ */
|
|
+static int command_validate_repository(void)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ rc = keystore_validate_key(g.keystore, g.name, g.apqns, g.pkey_fd);
|
|
+
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Command handler for 'validate'.
|
|
+ *
|
|
+ * Validates the specified secure key and prints out information about it.
|
|
+ */
|
|
+static int command_validate(void)
|
|
+{
|
|
+ if (g.pos_arg != NULL)
|
|
+ return command_validate_file();
|
|
+ else
|
|
+ return command_validate_repository();
|
|
+
|
|
+ return EXIT_FAILURE;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Command handler for 'import'.
|
|
+ *
|
|
+ * Imports a secure key from a file into the key repository.
|
|
+ */
|
|
+static int command_import(void)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ if (g.name == NULL) {
|
|
+ misc_print_required_parm("--name/-N");
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
+ if (g.sector_size < 0)
|
|
+ g.sector_size = 0;
|
|
+
|
|
+ rc = keystore_import_key(g.keystore, g.name, g.description, g.volumes,
|
|
+ g.apqns, g.sector_size, g.pos_arg);
|
|
+
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Command handler for 'export'.
|
|
+ *
|
|
+ * Exports a secure key from the repository to a file
|
|
+ */
|
|
+static int command_export(void)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ if (g.name == NULL) {
|
|
+ misc_print_required_parm("--name/-N");
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
+ rc = keystore_export_key(g.keystore, g.name, g.pos_arg);
|
|
+
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Command handler for 'list'.
|
|
+ *
|
|
+ * Lists keys stored in the repository
|
|
+ */
|
|
+static int command_list(void)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ rc = keystore_list_keys(g.keystore, g.name, g.volumes, g.apqns);
|
|
+
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Command handler for 'remove'.
|
|
+ *
|
|
+ * Remove a key from the repository
|
|
+ */
|
|
+static int command_remove(void)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ if (g.name == NULL) {
|
|
+ misc_print_required_parm("--name/-N");
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
+ rc = keystore_remove_key(g.keystore, g.name, g.force);
|
|
+
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Command handler for 'change'.
|
|
+ *
|
|
+ * Changes the properties of a key in the repository
|
|
+ */
|
|
+static int command_change(void)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ if (g.name == NULL) {
|
|
+ misc_print_required_parm("--name/-N");
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
+ rc = keystore_change_key(g.keystore, g.name, g.description, g.volumes,
|
|
+ g.apqns, g.sector_size);
|
|
+
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Command handler for 'rname'.
|
|
+ *
|
|
+ * renames a key in the repository
|
|
+ */
|
|
+static int command_rename(void)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ if (g.name == NULL) {
|
|
+ misc_print_required_parm("--name/-N");
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ if (g.newname == NULL) {
|
|
+ misc_print_required_parm("--new-name/-w");
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
+ rc = keystore_rename_key(g.keystore, g.name, g.newname);
|
|
+
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Command handler for 'copy'.
|
|
+ *
|
|
+ * Copies a key in the repository
|
|
+ */
|
|
+static int command_copy(void)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ if (g.name == NULL) {
|
|
+ misc_print_required_parm("--name/-N");
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ if (g.newname == NULL) {
|
|
+ misc_print_required_parm("--new-name/-w");
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
+ rc = keystore_copy_key(g.keystore, g.name, g.newname, g.volumes);
|
|
+
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Command handler for 'crypttab'.
|
|
+ *
|
|
+ * Generates crypttab entries for selected volumes
|
|
+ */
|
|
+static int command_crypttab(void)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ rc = keystore_crypttab(g.keystore, g.volumes);
|
|
+
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * Command handler for 'cryptsetup'.
|
|
+ *
|
|
+ * Generates and runs cryptsetup commands for selected volumes
|
|
+ */
|
|
+static int command_cryptsetup(void)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ rc = keystore_cryptsetup(g.keystore, g.volumes, g.run);
|
|
+
|
|
+ return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * Opens the keystore. The keystore directory is either the
|
|
+ * default directory or as specified in an environment variable
|
|
+ */
|
|
+static int open_keystore(void)
|
|
+{
|
|
+ char *directory;
|
|
+
|
|
+ directory = getenv(ENVVAR_ZKEY_REPOSITORY);
|
|
+ if (directory == NULL)
|
|
+ directory = DEFAULT_KEYSTORE;
|
|
+
|
|
+ g.keystore = keystore_new(directory, g.verbose);
|
|
+
|
|
+ return g.keystore == NULL ? EXIT_FAILURE : EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+
|
|
static bool is_command(struct zkey_command *command, const char *str)
|
|
{
|
|
char command_str[ZKEY_COMMAND_STR_LEN];
|
|
@@ -484,12 +1353,34 @@ struct zkey_command *find_command(const
|
|
}
|
|
|
|
/*
|
|
+ * Check if positional arguments are specified as needed by the command
|
|
+ */
|
|
+static int check_positional_arg(struct zkey_command *command)
|
|
+{
|
|
+ if (command->pos_arg_optional) {
|
|
+ if (g.pos_arg == NULL &&
|
|
+ command->arg_alternate_value != NULL &&
|
|
+ *command->arg_alternate_value == NULL) {
|
|
+ misc_print_required_parms(command->pos_arg,
|
|
+ command->pos_arg_alternate);
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ } else {
|
|
+ if (g.pos_arg == NULL) {
|
|
+ misc_print_required_parm(command->pos_arg);
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return EXIT_SUCCESS;
|
|
+}
|
|
+
|
|
+/*
|
|
* Entry point
|
|
*/
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct zkey_command *command = NULL;
|
|
- char *keyfile = NULL;
|
|
int arg_count = argc;
|
|
char **args = argv;
|
|
char *endp;
|
|
@@ -498,7 +1389,7 @@ int main(int argc, char *argv[])
|
|
util_prg_init(&prg);
|
|
util_opt_init(opt_vec, NULL);
|
|
|
|
- /* Get command if one is pspecified */
|
|
+ /* Get command if one is specified */
|
|
if (argc >= 2 && strncmp(argv[1], "-", 1) != 0) {
|
|
command = find_command(argv[1]);
|
|
if (command == NULL) {
|
|
@@ -510,7 +1401,7 @@ int main(int argc, char *argv[])
|
|
args = &argv[1];
|
|
|
|
if (argc >= 3 && strncmp(argv[2], "-", 1) != 0) {
|
|
- keyfile = argv[2];
|
|
+ g.pos_arg = argv[2];
|
|
arg_count = argc - 2;
|
|
args = &argv[2];
|
|
}
|
|
@@ -550,6 +1441,47 @@ int main(int argc, char *argv[])
|
|
case 'o':
|
|
g.fromold = 1;
|
|
break;
|
|
+ case 'p':
|
|
+ g.complete = 1;
|
|
+ break;
|
|
+ case 'i':
|
|
+ g.inplace = 1;
|
|
+ break;
|
|
+ case 's':
|
|
+ g.staged = 1;
|
|
+ break;
|
|
+ case 'N':
|
|
+ g.name = optarg;
|
|
+ break;
|
|
+ case 'd':
|
|
+ g.description = optarg;
|
|
+ break;
|
|
+ case 'l':
|
|
+ g.volumes = optarg;
|
|
+ break;
|
|
+ case 'a':
|
|
+ g.apqns = optarg;
|
|
+ break;
|
|
+ case 'S':
|
|
+ g.sector_size = strtol(optarg, &endp, 0);
|
|
+ if (*optarg == '\0' || *endp != '\0' ||
|
|
+ g.sector_size < 0 ||
|
|
+ (g.sector_size == LONG_MAX && errno == ERANGE)) {
|
|
+ warnx("Invalid value for '--sector-size'|'-S': "
|
|
+ "'%s'", optarg);
|
|
+ util_prg_print_parse_error();
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+ break;
|
|
+ case 'w':
|
|
+ g.newname = optarg;
|
|
+ break;
|
|
+ case 'r':
|
|
+ g.run = 1;
|
|
+ break;
|
|
+ case 'F':
|
|
+ g.force = 1;
|
|
+ break;
|
|
case 'V':
|
|
g.verbose = 1;
|
|
break;
|
|
@@ -575,31 +1507,43 @@ int main(int argc, char *argv[])
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
- if (keyfile == NULL) {
|
|
- misc_print_required_parm("SECURE-KEY-FILE");
|
|
- return EXIT_FAILURE;
|
|
+ if (command->pos_arg != NULL) {
|
|
+ if (check_positional_arg(command) != EXIT_SUCCESS)
|
|
+ return EXIT_FAILURE;
|
|
+ }
|
|
+
|
|
+ if (command->need_keystore || g.pos_arg == NULL) {
|
|
+ rc = open_keystore();
|
|
+ if (rc != EXIT_SUCCESS)
|
|
+ goto out;
|
|
}
|
|
|
|
if (command->need_cca_library) {
|
|
rc = load_cca_library(&g.lib_csulcca, &g.dll_CSNBKTC,
|
|
g.verbose);
|
|
- if (rc != 0)
|
|
+ if (rc != 0) {
|
|
+ rc = EXIT_FAILURE;
|
|
goto out;
|
|
+ }
|
|
}
|
|
if (command->need_pkey_device) {
|
|
g.pkey_fd = open_pkey_device(g.verbose);
|
|
- if (g.pkey_fd == -1)
|
|
+ if (g.pkey_fd == -1) {
|
|
+ rc = EXIT_FAILURE;
|
|
goto out;
|
|
+ }
|
|
}
|
|
|
|
umask(0077);
|
|
|
|
- rc = command->function(keyfile);
|
|
+ rc = command->function();
|
|
|
|
out:
|
|
if (g.lib_csulcca)
|
|
dlclose(g.lib_csulcca);
|
|
if (g.pkey_fd >= 0)
|
|
close(g.pkey_fd);
|
|
+ if (g.keystore)
|
|
+ keystore_free(g.keystore);
|
|
return rc;
|
|
}
|