zkey: Update properties in the KMS for change and rename commands

When key properties are changed with the 'change' command, also update
the key properties in the KMS, if the key is bound to a KMS. Do not
allow to change the associated APQNs for KMS bound keys. KMS bound keys
inherit the APQNs from the KMS plugin.

When a key is renamed in the repository, also update the key name
property in the KMS if the key is KMS bound.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Ingo Franzki
2020-06-15 15:11:04 +02:00
committed by Jan Höppner
parent a2f14fcfd7
commit 1d7bb283fd
5 changed files with 208 additions and 9 deletions

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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.

View File

@@ -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,