diff --git a/zkey/kms.c b/zkey/kms.c index e2b5e21a..f54a3365 100644 --- a/zkey/kms.c +++ b/zkey/kms.c @@ -39,6 +39,13 @@ #define KMS_CONFIG_PROP_APQNS "apqns" #define KMS_CONFIG_LOCAL "local" +static const char * const key_types[] = { + KEY_TYPE_CCA_AESDATA, + KEY_TYPE_CCA_AESCIPHER, + KEY_TYPE_EP11_AES, + NULL +}; + typedef const struct kms_functions *(*kms_get_functions_t)(void); #define pr_verbose(verbose, fmt...) do { \ @@ -739,3 +746,69 @@ out: free(filename); return rc; } + +/** + * Displays information about the KMS plugin and its configuration + * + * @param[in] kms_info information of the currently bound plugin. + * + * @returns 0 for success or a negative errno in case of an error. + */ +int print_kms_info(struct kms_info *kms_info) +{ + bool first; + int rc = 0; + size_t i; + + util_assert(kms_info != NULL, "Internal error: kms_info is NULL"); + + if (kms_info->plugin_lib == NULL) { + rc = -ENOENT; + warnx("The repository is not bound to a KMS plugin"); + goto out; + } + + printf("KMS-Plugin: %s\n", kms_info->plugin_name); + + if (kms_info->funcs->kms_supports_key_type != NULL) { + for (i = 0, first = true; key_types[i] != NULL; i++) { + if (kms_info->funcs->kms_supports_key_type( + kms_info->handle, key_types[i])) { + printf(" %s %s\n", first ? + "Supported key types:" : + " ", key_types[i]); + first = false; + } + } + if (first) + printf(" Supported key types: (none)\n"); + } else { + printf(" Supported key types: (unknown)\n"); + } + + if (kms_info->apqns == NULL || kms_info->num_apqns == 0) { + printf(" APQNs: (configuration required)\n"); + goto kms_info; + } + + for (i = 0; i < kms_info->num_apqns; i++) + printf(" %s %02x.%04x\n", + i == 0 ? "APQNs:" : " ", + kms_info->apqns[i].card, + kms_info->apqns[i].domain); + +kms_info: + if (kms_info->funcs->kms_display_info == NULL) + goto out; + + rc = kms_info->funcs->kms_display_info(kms_info->handle); + if (rc != 0) { + warnx("Failed to display information about the plugin: %s", + strerror(-rc)); + print_last_kms_error(kms_info); + goto out; + } + +out: + return rc; +} diff --git a/zkey/kms.h b/zkey/kms.h index 59bed625..467c73ea 100644 --- a/zkey/kms.h +++ b/zkey/kms.h @@ -45,4 +45,6 @@ int bind_kms_plugin(struct keystore *keystore, const char *plugin, int unbind_kms_plugin(struct kms_info *kms_info, struct keystore *keystore, bool verbose); +int print_kms_info(struct kms_info *kms_info); + #endif diff --git a/zkey/zkey.1 b/zkey/zkey.1 index 48dfec11..d96a4070 100644 --- a/zkey/zkey.1 +++ b/zkey/zkey.1 @@ -15,6 +15,12 @@ zkey \- Manage secure AES keys . .PP .B zkey +.I command sub-command +.RB [ OPTIONS ] +. +. +.PP +.B zkey .BR \-\-help | \-h .br .B zkey @@ -775,6 +781,85 @@ is 6.3.27 or later. For the supported environments and downloads, see: \fIhttp://www.ibm.com/security/cryptocards\fP . . +.SH COMMANDS FOR KEY MANAGEMENT SYSTEM INTEGRATION +. +Use the \fBkms\fP command to control the integration into key management +systems. The \fBkms\fP command offers several subcommands for key management +specific operations. Use \fBzkey kms \-\-help\fP to show the available +subcommands. +. +.SS "List key management system plugins" +. +.B zkey kms +.BR plugins | pl +.RB [ \-\-verbose | \-V ] +. +.PP +Use the +.B kms plugins +command to display a list of configured key management system plugins (KMS +plugins). It displays the key management system plugin name, and the shared +library that implements the plugin. +. +.P +Key management system plugins are configured in configuration file +\fB/etc/zkey/kms-plugins.conf\fP. This file contains the KMS plugin name and +its shared library. Set environment variable \fBZKEY_KMS_PLUGINS\fP to point to +a different file to use a different KMS plugin configuration file. +. +.SS "Bind the repository to a key management system" +. +.B zkey kms +.BR bind | bi +.I KMS\-plugin\-name +.RB [ \-\-verbose | \-V ] +. +.PP +Use the +.B kms bind +command to bind the repository to a key management system (KMS). +The \fBkms plugins\fP command displays a list of configured key management +system plugins that can be used. +. +.PP +After binding a repository to a key management system, the KMS plugin must +first be configured. Use the \fBkms configure\fP command to +configure the plugin. As a minimum, you must associate APQNs with the key +management system plugin. The plugin may require additional configuration +before it is fully functioning. Use the \fBkms info\fP command to display +information about the key management system plugin and its configuration. +. +.PP +When a key repository is bound to a key management system, then all keys are +generated by this key management system per default, and are thus also bound to +the key management system. Any additional information associated with the keys +in the repository is also stored in the key management system. +. +.SS "Unbind the repository from a key management system" +. +.B zkey kms +.BR unbind | unb +.RB [ \-\-verbose | \-V ] +. +.PP +Use the +.B kms unbind +command to unbind the repository from a key management system (KMS). All keys +that are currently bound to the key management system, are unbound and become +local keys. You are prompted to confirm the unbinding. +. +.SS "Display information about a key management system plugin" +. +.B zkey kms +.BR info | in +.RB [ \-\-verbose | \-V ] +. +.PP +Use the +.B kms info +command to display information about the currently bound key management system +plugin (KMS plugin) and its configuration. +. . . .SH OPTIONS @@ -1440,4 +1525,11 @@ If .B $ZKEY_REPOSITORY is set, it specifies the location of the secure key repository. If it is not set, then the the default location of the secure key -repository is \fB/etc/zkey/repository\fP. \ No newline at end of file +repository is \fB/etc/zkey/repository\fP. +.TP +.BR ZKEY_KMS_PLUGINS +If +.B $ZKEY_KMS_PLUGINS +is set, it specifies the name of the KMS plugin configuration file. +If it is not set, then the default KMS plugin configuration file +\fB/etc/zkey/kms-plugins.conf\fP is used. \ No newline at end of file diff --git a/zkey/zkey.c b/zkey/zkey.c index 2add12f4..19cc0e75 100644 --- a/zkey/zkey.c +++ b/zkey/zkey.c @@ -33,6 +33,7 @@ #include "misc.h" #include "pkey.h" #include "utils.h" +#include "kms.h" /* * Program configuration @@ -115,6 +116,11 @@ static struct zkey_globals { #define COMMAND_CRYPTTAB "crypttab" #define COMMAND_CRYPTSETUP "cryptsetup" #define COMMAND_CONVERT "convert" +#define COMMAND_KMS "kms" +#define COMMAND_KMS_PLUGINS "plugins" +#define COMMAND_KMS_BIND "bind" +#define COMMAND_KMS_UNBIND "unbind" +#define COMMAND_KMS_INFO "info" #define ZKEY_COMMAND_MAX_LEN 10 @@ -852,6 +858,7 @@ struct zkey_command { char *pos_arg_alternate; char **arg_alternate_value; int need_keystore; + int use_kms_plugin; struct zkey_command *sub_commands; }; @@ -868,6 +875,60 @@ static int command_copy(void); static int command_crypttab(void); static int command_cryptsetup(void); static int command_convert(void); +static int command_kms_plugins(void); +static int command_kms_bind(void); +static int command_kms_unbind(void); +static int command_kms_info(void); + +static struct zkey_command zkey_kms_commands[] = { + { + .command = COMMAND_KMS_PLUGINS, + .abbrev_len = 2, + .function = command_kms_plugins, + .short_desc = "Lists key management system plugins", + .long_desc = "Lists available key management system (KMS) " + "plugins.", + .has_options = 1, + }, + { + .command = COMMAND_KMS_BIND, + .abbrev_len = 2, + .function = command_kms_bind, + .short_desc = "Binds the repository to a key management system " + "plugin", + .long_desc = "Binds the repository to the specified key " + "management system (KMS) plugin.", + .need_keystore = 1, + .has_options = 1, + .pos_arg = "[KMS-PLUGIN]", + }, + { + .command = COMMAND_KMS_UNBIND, + .abbrev_len = 3, + .function = command_kms_unbind, + .short_desc = "Unbinds the repository from a key management " + "system plugin", + .long_desc = "Unbinds the repository from the current key " + "management system (KMS) plugin, and turns all " + "KMS-bound keys into local keys", + .need_keystore = 1, + .has_options = 1, + .use_kms_plugin = 1, + }, + { + .command = COMMAND_KMS_INFO, + .abbrev_len = 2, + .function = command_kms_info, + .short_desc = "Displays information about a key management " + "system plugin", + .long_desc = "Displays information about the current key " + "management system (KMS) plugin", + .need_keystore = 1, + .has_options = 1, + .use_kms_plugin = 1, + }, + { .command = NULL } +}; static struct zkey_command zkey_commands[] = { { @@ -1017,6 +1078,15 @@ static struct zkey_command zkey_commands[] = { .pos_arg = "[SECURE-KEY-FILE]", .pos_arg_optional = 1, }, + { + .command = COMMAND_KMS, + .abbrev_len = 2, + .short_desc = "key management system (KMS) support", + .long_desc = "Provides subcommands for key management system " + "(KMS) support.", + .has_options = 1, + .sub_commands = zkey_kms_commands, + }, { .command = NULL } }; @@ -2002,6 +2072,97 @@ static int command_convert(void) return EXIT_SUCCESS; } +/* + * Command handler for 'kms plugins'. + * + * List KMS plugins + */ +static int command_kms_plugins(void) +{ + int rc; + + rc = list_kms_plugins(g.verbose); + + return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} + +/* + * Command handler for 'kms bind'. + * + * Bind repository to a KMS plugin + */ +static int command_kms_bind(void) +{ + int rc; + + rc = bind_kms_plugin(g.keystore, g.pos_arg, g.verbose); + + if (rc == 0) + util_print_indented("The KMS plugin requires configuration, " + "run 'zkey kms configure [OPTIONS]' to " + "complete the KMS binding process", 0); + + return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} + +/* + * Command handler for 'kms unbind'. + * + * Unbind repository from a KMS plugin + */ +static int command_kms_unbind(void) +{ + char *msg; + int rc; + + if (g.kms_info.plugin_lib == NULL) { + rc = -ENOENT; + warnx("The repository is not bound to a KMS plugin"); + return EXIT_FAILURE; + } + + util_asprintf(&msg, "%s: Unbind this repository from KMS plugin '%s' " + "and turn all KMS-bound keys into local keys [y/N]? ", + program_invocation_short_name, g.kms_info.plugin_name); + util_print_indented(msg, 0); + free(msg); + if (!prompt_for_yes(g.verbose)) { + warnx("Operation aborted"); + return EXIT_FAILURE; + } + + rc = keystore_kms_keys_unbind(g.keystore); + if (rc != 0) { + warnx("Failed to turn KMS-bound keys into local keys: %s", + strerror(-rc)); + return EXIT_FAILURE; + } + + rc = unbind_kms_plugin(&g.kms_info, g.keystore, g.verbose); + + return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} + +/* + * Command handler for 'kms info'. + * + * Prints information about a KMS plugin + */ +static int command_kms_info(void) +{ + int rc; + + if (g.kms_info.plugin_lib == NULL) { + rc = -ENOENT; + warnx("The repository is not bound to a KMS plugin"); + return EXIT_FAILURE; + } + + rc = print_kms_info(&g.kms_info); + + 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 @@ -2140,6 +2301,12 @@ int main(int argc, char *argv[]) else cmd = command; + if (cmd != NULL && cmd->use_kms_plugin) { + rc = check_for_kms_plugin(&g.kms_info, g.verbose); + if (rc != 0) + return EXIT_FAILURE; + } + while (1) { c = util_opt_getopt_long(arg_count, args); if (c == -1) @@ -2314,7 +2481,8 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - if (cmd->need_keystore || g.pos_arg == NULL) { + if (cmd->need_keystore || + (cmd->pos_arg_optional && g.pos_arg == NULL)) { rc = open_keystore(); if (rc != EXIT_SUCCESS) goto out; @@ -2342,11 +2510,20 @@ int main(int argc, char *argv[]) } } + if (g.kms_info.plugin_lib != NULL) { + rc = init_kms_plugin(&g.kms_info, g.verbose); + if (rc != 0) { + rc = EXIT_FAILURE; + goto out; + } + } + umask(0077); rc = cmd->function(); out: + free_kms_plugin(&g.kms_info); if (g.cca.lib_csulcca) dlclose(g.cca.lib_csulcca); if (g.ep11.lib_ep11)