From f83242810968e40aeae68b304ed309d21634a2ec Mon Sep 17 00:00:00 2001 From: Ingo Franzki Date: Tue, 16 Jun 2020 16:37:29 +0200 Subject: [PATCH] zkey: Add KMS support for the 'zkey remove' command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When removing a KMS-bound key from the local repository, call the KMS plugin and let it perform an action in the KMS. Usually keys are not removed from key management systems, instead the key state is changed to non-active or similar. Signed-off-by: Ingo Franzki Signed-off-by: Jan Höppner --- zkey/keystore.c | 34 +++++++++++++++++++++- zkey/keystore.h | 3 +- zkey/kms.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ zkey/kms.h | 4 +++ zkey/zkey.1 | 17 +++++++++++ zkey/zkey.c | 5 +++- 6 files changed, 136 insertions(+), 3 deletions(-) diff --git a/zkey/keystore.c b/zkey/keystore.c index e2f43ca1..f0e3fe69 100644 --- a/zkey/keystore.c +++ b/zkey/keystore.c @@ -3660,13 +3660,18 @@ out: * @param[in] keystore the key store * @param[in] name the name of the key * @param[in] quiet if true no confirmation prompt is shown + * @param[in] kms_options an array of KMS options specified, or NULL if no + * KMS options have been specified + * @param[in] num_kms_options the number of options in above array * * @returns 0 for success or a negative errno in case of an error */ int keystore_remove_key(struct keystore *keystore, const char *name, - bool quiet) + bool quiet, struct kms_option *kms_options, + size_t num_kms_options) { struct key_filenames file_names = { NULL, NULL, NULL }; + struct properties *key_props = NULL; int rc; util_assert(keystore != NULL, "Internal error: keystore is NULL"); @@ -3686,6 +3691,31 @@ int keystore_remove_key(struct keystore *keystore, const char *name, goto out; } + key_props = properties_new(); + rc = properties_load(key_props, file_names.info_filename, 1); + if (rc != 0) { + warnx("Key '%s' does not exist or is invalid", name); + goto out; + } + + if (_keystore_is_kms_bound_key(key_props, NULL)) { + rc = perform_kms_login(keystore->kms_info, keystore->verbose); + if (rc != 0) + goto out; + + rc = remove_kms_key(keystore->kms_info, key_props, + kms_options, num_kms_options, + keystore->verbose); + + if (rc != 0) { + warnx("KMS plugin '%s' failed to remove key '%s': %s", + keystore->kms_info->plugin_name, name, + strerror(-rc)); + print_last_kms_error(keystore->kms_info); + goto out; + } + } + if (remove(file_names.skey_filename) != 0) { rc = -errno; pr_verbose(keystore, "Failed to remove '%s': %s", @@ -3708,6 +3738,8 @@ int keystore_remove_key(struct keystore *keystore, const char *name, out: _keystore_free_key_filenames(&file_names); + if (key_props != NULL) + properties_free(key_props); if (rc != 0) pr_verbose(keystore, "Failed to remove key '%s': %s", diff --git a/zkey/keystore.h b/zkey/keystore.h index 08a85571..141522d4 100644 --- a/zkey/keystore.h +++ b/zkey/keystore.h @@ -94,7 +94,8 @@ int keystore_export_key(struct keystore *keystore, const char *name, const char *export_file); int keystore_remove_key(struct keystore *keystore, const char *name, - bool quiet); + bool quiet, struct kms_option *kms_options, + size_t num_kms_options); int keystore_list_keys(struct keystore *keystore, const char *name_filter, const char *volume_filter, const char *apqn_filter, diff --git a/zkey/kms.c b/zkey/kms.c index 6edeef06..5abc2d09 100644 --- a/zkey/kms.c +++ b/zkey/kms.c @@ -2426,3 +2426,79 @@ out: return rc; } +/** + * Requests the KMS plugin to remove a KMS managed key. Removing a key mean + * to change its state, but not remove it. + * * + * @param[in] kms_info information of the currently bound plugin. + * @param[in] key_props a properties object + * @param[in] kms_options an array of KMS options specified, or NULL if no + * KMS options have been specified + * @param[in] num_kms_options the number of options in above array + * @param[in] verbose if true, verbose messages are printed + * + * @returns 0 for success or a negative errno in case of an error. + */ +int remove_kms_key(struct kms_info *kms_info, struct properties *key_props, + struct kms_option *kms_options, size_t num_kms_options, + bool verbose) +{ + char *key1_id = NULL, *key2_id = NULL; + bool xts = false; + + int rc = 0; + + util_assert(kms_info != NULL, "Internal error: kms_info is NULL"); + util_assert(key_props != NULL, "Internal error: key_props is NULL"); + + if (kms_info->plugin_lib == NULL) { + warnx("The repository is not bound to a KMS plugin"); + return -ENOENT; + } + + if (kms_info->funcs->kms_remove_key == NULL) { + pr_verbose(verbose, "The KMS plugin does not support to " + "remove keys"); + return -ENOTSUP; + } + + key1_id = properties_get(key_props, PROP_NAME_KMS_KEY_ID); + if (key1_id == NULL) { + key1_id = properties_get(key_props, PROP_NAME_KMS_XTS_KEY1_ID); + key2_id = properties_get(key_props, PROP_NAME_KMS_XTS_KEY2_ID); + if (key1_id == NULL || key2_id == NULL) { + pr_verbose(verbose, "Failed to get key-id(s)"); + rc = -ENOENT; + goto out; + } + xts = true; + } + + rc = kms_info->funcs->kms_remove_key(kms_info->handle, key1_id, + kms_options, num_kms_options); + if (rc != 0) { + pr_verbose(verbose, "KMS plugin failed to remove key '%s': %s", + key1_id, strerror(-rc)); + goto out; + } + + if (xts) { + rc = kms_info->funcs->kms_remove_key(kms_info->handle, + key2_id, + kms_options, + num_kms_options); + if (rc != 0) { + pr_verbose(verbose, "KMS plugin failed to remove key " + "'%s': %s", key2_id, strerror(-rc)); + goto out; + } + } + +out: + if (key1_id != NULL) + free(key1_id); + if (key2_id != NULL) + free(key2_id); + + return rc; +} diff --git a/zkey/kms.h b/zkey/kms.h index 91113a19..36ea0dc0 100644 --- a/zkey/kms.h +++ b/zkey/kms.h @@ -83,4 +83,8 @@ int set_kms_key_properties(struct kms_info *kms_info, const char *volumes, const char *vol_type, const char *sector_size, bool verbose); +int remove_kms_key(struct kms_info *kms_info, struct properties *key_props, + struct kms_option *kms_options, size_t num_kms_options, + bool verbose); + #endif diff --git a/zkey/zkey.1 b/zkey/zkey.1 index 56106371..cb512dc8 100644 --- a/zkey/zkey.1 +++ b/zkey/zkey.1 @@ -466,6 +466,7 @@ bound to a key management systen (KMS). .B \-\-name | \-N .IR key-name .RB [ \-\-force | \-F ] +.RB [ KMS\-plugin\ specific\ options ] .RB [ \-\-verbose | \-V ] . .PP @@ -479,6 +480,16 @@ a confirmation, unless you specify the .B \-\-force option. .PP +When the secure key that is to be removed is bound to a key management system, +then the key management system plugin might also take an action in the key +management system. It may for example change the state of the key in the key +management system, instead of removing the key. Nevertheless, the secure key +is removed from the local repository. +.PP +A key management system plugin may offer plugin specific options that can be +specified with the \fBremove\fP command. Use \fBremove \-\-help\fP +to display the plugin specific options and their meaning. +.PP .B Note: When removing a secure key that is associated with one or multiple volumes, and the key's volume type is \fBplain\fP, @@ -1329,6 +1340,12 @@ The user is prompted to confirm the removal of a secure key from the secure key repository. Use this option to remove a secure key without prompting for a confirmation. This option is only used for secure keys contained in the secure key repository. +.TP +.B KMS-plugin specific options +A key management system plugin may offer and even require plugin specific +options that can be specified with the remove command when the secure key +repository is bound to a key management system plugin. Use \fBremove +\-\-help\fP to display the plugin specific options and their meaning. . . . diff --git a/zkey/zkey.c b/zkey/zkey.c index d82a19ce..29dfd909 100644 --- a/zkey/zkey.c +++ b/zkey/zkey.c @@ -1179,6 +1179,8 @@ static struct zkey_command zkey_commands[] = { .long_desc = "Remove a secure AES key from the repository", .has_options = 1, .need_keystore = 1, + .use_kms_plugin = 1, + .kms_plugin_opts_cmd = KMS_COMMAND_REMOVE, }, { .command = COMMAND_CHANGE, @@ -1958,7 +1960,8 @@ static int command_remove(void) return EXIT_FAILURE; } - rc = keystore_remove_key(g.keystore, g.name, g.force); + rc = keystore_remove_key(g.keystore, g.name, g.force, g.kms_options, + g.num_kms_options); return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS; }