diff --git a/zkey/keystore.c b/zkey/keystore.c index 70f7137f..e2f43ca1 100644 --- a/zkey/keystore.c +++ b/zkey/keystore.c @@ -2266,11 +2266,14 @@ int keystore_change_key(struct keystore *keystore, const char *name, .nomsg = 0 }; struct key_filenames file_names = { NULL, NULL, NULL }; struct properties *key_props = NULL; + char *upd_volume_type = NULL; char *apqns_prop, *key_type; + char *upd_volumes = NULL; size_t secure_key_size; u8 mkvp[MKVP_LENGTH]; + char sect_size[30]; u8 *secure_key; - char temp[30]; + bool kms_bound; int rc; util_assert(keystore != NULL, "Internal error: keystore is NULL"); @@ -2291,6 +2294,8 @@ int keystore_change_key(struct keystore *keystore, const char *name, goto out; } + kms_bound = _keystore_is_kms_bound_key(key_props, NULL); + if (description != NULL) { rc = properties_set(key_props, PROP_NAME_DESCRIPTION, description); @@ -2307,9 +2312,18 @@ int keystore_change_key(struct keystore *keystore, const char *name, &vol_check); if (rc != 0) goto out; + + upd_volumes = properties_get(key_props, PROP_NAME_VOLUMES); } if (apqns != NULL) { + if (kms_bound) { + rc = -EINVAL; + warnx("The APQN association of a KMS-bound key can not " + "be changed"); + goto out; + } + rc = _keystore_change_association(key_props, PROP_NAME_APQNS, apqns, "APQN", _keystore_apqn_check, @@ -2357,9 +2371,9 @@ int keystore_change_key(struct keystore *keystore, const char *name, goto out; } - sprintf(temp, "%lu", sector_size); + sprintf(sect_size, "%lu", sector_size); rc = properties_set(key_props, PROP_NAME_SECTOR_SIZE, - temp); + sect_size); if (rc != 0) { warnx("Invalid characters in sector-size"); goto out; @@ -2379,6 +2393,29 @@ int keystore_change_key(struct keystore *keystore, const char *name, warnx("Invalid characters in volume-type"); goto out; } + + upd_volume_type = properties_get(key_props, + PROP_NAME_VOLUME_TYPE); + } + + if (kms_bound) { + rc = perform_kms_login(keystore->kms_info, keystore->verbose); + if (rc != 0) + goto out; + + rc = set_kms_key_properties(keystore->kms_info, key_props, NULL, + description, upd_volumes, + upd_volume_type, sector_size >= 0 ? + sect_size : NULL, + keystore->verbose); + if (rc != 0) { + warnx("KMS plugin '%s' failed to set key properties " + "for key '%s': %s", + keystore->kms_info->plugin_name, name, + strerror(-rc)); + print_last_kms_error(keystore->kms_info); + goto out; + } } rc = _keystore_ensure_vp_exists(keystore, &file_names, key_props); @@ -2402,6 +2439,10 @@ out: _keystore_free_key_filenames(&file_names); if (key_props != NULL) properties_free(key_props); + if (upd_volumes != NULL) + free(upd_volumes); + if (upd_volume_type != NULL) + free(upd_volume_type); if (rc != 0) pr_verbose(keystore, "Failed to change key '%s': %s", @@ -2424,6 +2465,7 @@ int keystore_rename_key(struct keystore *keystore, const char *name, struct key_filenames file_names = { NULL, NULL, NULL }; struct key_filenames new_names = { NULL, NULL, NULL }; struct properties *key_props = NULL; + bool reenc_exists = false; char *msg; int rc; @@ -2457,18 +2499,16 @@ int keystore_rename_key(struct keystore *keystore, const char *name, rc = -errno; pr_verbose(keystore, "Failed to rename '%s': %s", file_names.info_filename, strerror(-rc)); - rename(new_names.skey_filename, file_names.skey_filename); + goto out_rename_skey; } if (_keystore_reencipher_key_exists(&file_names)) { + reenc_exists = true; if (rename(file_names.renc_filename, new_names.renc_filename) != 0) { rc = -errno; pr_verbose(keystore, "Failed to rename '%s': %s", file_names.renc_filename, strerror(-rc)); - rename(new_names.skey_filename, - file_names.skey_filename); - rename(new_names.info_filename, - file_names.info_filename); + goto out_rename_info; } } @@ -2476,7 +2516,25 @@ int keystore_rename_key(struct keystore *keystore, const char *name, rc = properties_load(key_props, new_names.info_filename, 1); if (rc != 0) { warnx("Key '%s' does not exist or is invalid", newname); - goto out; + goto out_rename_info; + } + + if (_keystore_is_kms_bound_key(key_props, NULL)) { + rc = perform_kms_login(keystore->kms_info, keystore->verbose); + if (rc != 0) + goto out_rename_info; + + rc = set_kms_key_properties(keystore->kms_info, key_props, + newname, NULL, NULL, NULL, NULL, + keystore->verbose); + if (rc != 0) { + warnx("KMS plugin '%s' failed to set key properties " + "for key '%s': %s", + keystore->kms_info->plugin_name, name, + strerror(-rc)); + print_last_kms_error(keystore->kms_info); + goto out_rename_info; + } } util_asprintf(&msg, "The following volumes are associated with the " @@ -2489,6 +2547,16 @@ int keystore_rename_key(struct keystore *keystore, const char *name, pr_verbose(keystore, "Successfully renamed key '%s' to '%s'", name, newname); + goto out; + +out_rename_info: + if (reenc_exists) + rename(file_names.renc_filename, new_names.renc_filename); + rename(new_names.info_filename, file_names.info_filename); + +out_rename_skey: + rename(new_names.skey_filename, file_names.skey_filename); + out: _keystore_free_key_filenames(&file_names); _keystore_free_key_filenames(&new_names); diff --git a/zkey/kms.c b/zkey/kms.c index 8f522125..6edeef06 100644 --- a/zkey/kms.c +++ b/zkey/kms.c @@ -2309,3 +2309,120 @@ out: return rc; } +/** + * Sets (adds/replaces) properties of a key. Already existing properties + * with the same property name are replaced, non-existing properties are added. + * + * @param[in] kms_info information of the currently bound plugin. + * @param[in] key_props a properties object of the key + * @param[in] name the name of the key in zkey (can be NULL) + * @param[in] description the description of the key (can be NULL) + * @param[in] volumes the volumes of the key (can be NULL) + * @param[in] vol_type the volume type of the key (can be NULL) + * @param[in] sector_size the sector_size of the key (can be NULL) + * + * @returns 0 for success or a negative errno in case of an error. + */ + +int set_kms_key_properties(struct kms_info *kms_info, + struct properties *key_props, + const char *name, const char *description, + const char *volumes, const char *vol_type, + const char *sector_size, bool verbose) +{ + char *key1_id = NULL, *key2_id = NULL; + struct kms_property kms_props[10]; + size_t num_kms_props = 0; + char *sys_volumes = NULL; + char *sys_name = 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_set_key_properties == NULL) { + pr_verbose(verbose, "The KMS plugin does not support to " + "set properties"); + 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; + } + + if (name != NULL) { + sys_name = _get_system_specific_prop_name(KMS_KEY_PROP_NAME); + if (sys_name == NULL) + return -ENOMEM; + ADD_KMS_PROPS(kms_props, num_kms_props, sys_name, name); + } + if (description != NULL) + ADD_KMS_PROPS(kms_props, num_kms_props, + KMS_KEY_PROP_DESCRIPTION, description); + if (volumes != NULL) { + sys_volumes = + _get_system_specific_prop_name(KMS_KEY_PROP_VOLUMES); + if (sys_volumes == NULL) + return -ENOMEM; + ADD_KMS_PROPS(kms_props, num_kms_props, sys_volumes, + volumes); + } + if (vol_type != NULL) + ADD_KMS_PROPS(kms_props, num_kms_props, + KMS_KEY_PROP_VOLUME_TYPE, vol_type); + if (sector_size != NULL) + ADD_KMS_PROPS(kms_props, num_kms_props, + KMS_KEY_PROP_SECTOR_SIZE, sector_size); + + if (num_kms_props == 0) + goto out; + + rc = kms_info->funcs->kms_set_key_properties(kms_info->handle, key1_id, + kms_props, num_kms_props); + if (rc != 0) { + pr_verbose(verbose, "KMS plugin failed to set properties of " + "key '%s': %s", key1_id, strerror(-rc)); + goto out; + } + + if (xts) { + rc = kms_info->funcs->kms_set_key_properties(kms_info->handle, + key2_id, + kms_props, + num_kms_props); + if (rc != 0) { + pr_verbose(verbose, "KMS plugin failed to set " + "properties of key '%s': %s", key2_id, + strerror(-rc)); + goto out; + } + } + +out: + if (sys_name != NULL) + free(sys_name); + if (sys_volumes != NULL) + free(sys_volumes); + 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 51dfb8a5..91113a19 100644 --- a/zkey/kms.h +++ b/zkey/kms.h @@ -77,4 +77,10 @@ int generate_kms_key(struct kms_info *kms_info, const char *name, struct kms_option *kms_options, size_t num_kms_options, bool verbose); +int set_kms_key_properties(struct kms_info *kms_info, + struct properties *key_props, + const char *name, const char *description, + const char *volumes, const char *vol_type, + const char *sector_size, bool verbose); + #endif diff --git a/zkey/zkey.1 b/zkey/zkey.1 index 7712897d..56106371 100644 --- a/zkey/zkey.1 +++ b/zkey/zkey.1 @@ -536,6 +536,12 @@ options. You cannot mix \fI+\fP and \fI-\fP in one specification. You can either add or remove (or set) the associations with one command. .PP +For secure AES keys that are bound to a key management system (KMS) you can not +change the APQN association. KMS-bound secure AES keys are always bound to the +APQNs that are associated with the key management system plugin. +Other associated information is also changed in the key management system when +changed using the change command. +.PP .B Note: The secure key itself cannot be changed, only information about the secure key is changed. To rename a secure key, use the \fBrename\fP command. diff --git a/zkey/zkey.c b/zkey/zkey.c index 09468499..d82a19ce 100644 --- a/zkey/zkey.c +++ b/zkey/zkey.c @@ -1189,6 +1189,7 @@ static struct zkey_command zkey_commands[] = { "the repository", .has_options = 1, .need_keystore = 1, + .use_kms_plugin = 1, }, { .command = COMMAND_RENAME, @@ -1198,6 +1199,7 @@ static struct zkey_command zkey_commands[] = { .long_desc = "Rename a secure AES key in the repository", .has_options = 1, .need_keystore = 1, + .use_kms_plugin = 1, }, { .command = COMMAND_COPY,