From a2f14fcfd7ed8029f4809bceac1b870a3797ee5a Mon Sep 17 00:00:00 2001 From: Ingo Franzki Date: Mon, 15 Jun 2020 15:20:45 +0200 Subject: [PATCH] zkey: Add KMS restrictions for the convert and copy commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not allow to convert a KMS bound key. The key type of a KMS bound key is determined by what the KMS plugin supports, thus it can not be converted. Do only allow to copy a KMS bound key, if the '--local' option is specified. The result of the copy is a local key, that is not bound to a KMS. Signed-off-by: Ingo Franzki Signed-off-by: Jan Höppner --- zkey/keystore.c | 42 +++++++++++++++++++++++++++++++++--------- zkey/keystore.h | 2 +- zkey/zkey.1 | 12 ++++++++++++ zkey/zkey.c | 12 +++++++++++- 4 files changed, 57 insertions(+), 11 deletions(-) diff --git a/zkey/keystore.c b/zkey/keystore.c index d8ebe2cd..70f7137f 100644 --- a/zkey/keystore.c +++ b/zkey/keystore.c @@ -82,6 +82,9 @@ struct key_filenames { warnx(fmt); \ } while (0) +static int _keystore_kms_key_unbind(struct keystore *keystore, + struct properties *properties); + /** * Gets the file names of the .skey and .info and .renc files for a named * key in the key strore's directory @@ -3349,11 +3352,12 @@ int keystore_reencipher_key(struct keystore *keystore, const char *name_filter, * @param[in] newname the new name of the key * @param[in] volumes a comma separated list of volumes associated with this * key (optional, can be NULL) + * @param[in] local if true copy a KMS-bound key to a local one * * @returns 0 for success or a negative errno in case of an error */ int keystore_copy_key(struct keystore *keystore, const char *name, - const char *newname, const char *volumes) + const char *newname, const char *volumes, bool local) { struct volume_check vol_check = { .keystore = keystore, .name = newname, .set = 0 }; @@ -3361,6 +3365,7 @@ int keystore_copy_key(struct keystore *keystore, const char *name, struct key_filenames new_names = { NULL, NULL, NULL }; struct properties *key_prop = NULL; size_t secure_key_size; + bool kms_bound = false; u8 *secure_key; int rc; @@ -3384,6 +3389,21 @@ int keystore_copy_key(struct keystore *keystore, const char *name, if (rc != 0) goto out; + key_prop = properties_new(); + rc = properties_load(key_prop, file_names.info_filename, 1); + if (rc != 0) { + warnx("Key '%s' does not exist or is invalid", name); + goto out; + } + + kms_bound = _keystore_is_kms_bound_key(key_prop, NULL); + if (kms_bound && !local) { + rc = -EINVAL; + warnx("Copying a KMS-bound key requires the " + "'--local|-L' option"); + goto out; + } + secure_key = read_secure_key(file_names.skey_filename, &secure_key_size, keystore->verbose); if (secure_key == NULL) { @@ -3401,14 +3421,6 @@ int keystore_copy_key(struct keystore *keystore, const char *name, if (rc != 0) goto out; - key_prop = properties_new(); - rc = properties_load(key_prop, file_names.info_filename, 1); - if (rc != 0) { - warnx("Key '%s' does not exist or is invalid", name); - remove(file_names.skey_filename); - goto out; - } - /* * Remove any volume association, since a volume can only be associated * with one key @@ -3440,6 +3452,12 @@ int keystore_copy_key(struct keystore *keystore, const char *name, if (rc != 0) goto out; + if (kms_bound) { + rc = _keystore_kms_key_unbind(keystore, key_prop); + if (rc != 0) + goto out; + } + rc = properties_save(key_prop, new_names.info_filename, 1); if (rc != 0) { pr_verbose(keystore, @@ -4310,6 +4328,12 @@ int keystore_convert_key(struct keystore *keystore, const char *name, goto out; } + if (_keystore_is_kms_bound_key(properties, NULL)) { + rc = -EINVAL; + warnx("A KMS-bound key can not be converted"); + goto out; + } + cur_key_type = _keystore_get_key_type(properties); if (strcasecmp(cur_key_type, key_type) == 0) { warnx("The secure key '%s' is already of type %s", name, diff --git a/zkey/keystore.h b/zkey/keystore.h index 8c9ca7cf..08a85571 100644 --- a/zkey/keystore.h +++ b/zkey/keystore.h @@ -88,7 +88,7 @@ int keystore_reencipher_key(struct keystore *keystore, const char *name_filter, struct ext_lib *lib); int keystore_copy_key(struct keystore *keystore, const char *name, - const char *newname, const char *volumes); + const char *newname, const char *volumes, bool local); int keystore_export_key(struct keystore *keystore, const char *name, const char *export_file); diff --git a/zkey/zkey.1 b/zkey/zkey.1 index 0d9e957f..7712897d 100644 --- a/zkey/zkey.1 +++ b/zkey/zkey.1 @@ -581,6 +581,7 @@ secure key is contained in the LUKS2 header. .IR new-key-name .RB [ \-\-volumes | \-l .IR volume1:dmname1[,volume2:dmname2[,...]] ] +.RB [ \-\-local | \-L ] .RB [ \-\-verbose | \-V ] . .PP @@ -600,6 +601,10 @@ a specific volume can only be associated with a single secure key. Specify the option to associate different volumes with the copied secure key, or use the \fBchange\fP command to associate volumes afterwards. +.PP +You can not copy secure keys that are bound to a key management system (KMS), +except when the \fB\-\-local\fP option is specified. The copied secure key is +then created as a local key. . .SS "Generate crypttab entries for volumes associated with secure AES keys" . @@ -757,6 +762,7 @@ Use the .B convert command to convert an existing secure key from one key type to another type. You can convert secure keys of type CCA-AESDATA to type CCA-AESCIPHER only. +You can not convert keys that are bound to a key management system (KMS). .B Note: Secure keys converted to type \fBCCA-AESCIPHER\fP require an IBM cryptographic @@ -1411,6 +1417,12 @@ These volumes are to be encrypted using dm-crypt with the secure AES key. The volume association also contains the device-mapper name, separated by a colon, used with dm-crypt. This option is only used for secure keys contained in the secure key repository. +.TP +.BR \-L ", "\-\-local +Copy the secure key to a local key. This is the default when no key management +system plugin (KMS plugin) is bound to the secure key repository. If the +repository is bound to a key management system plugin, then the keys are bound +to the KMS per default, and KMS-bound keys can only be copied to local keys. . . . diff --git a/zkey/zkey.c b/zkey/zkey.c index ca3f218d..09468499 100644 --- a/zkey/zkey.c +++ b/zkey/zkey.c @@ -634,6 +634,15 @@ static struct util_opt opt_vec[] = { "specific volume.", .command = COMMAND_COPY, }, + { + .option = { "local", 0, NULL, 'L'}, + .desc = "Copy the key to a local key. This is the default when " + "no KMS plugin is bound to the repository. If the " + "repository is bound to a KMS plugin, then keys are " + "bound to the KMS per default, and KMS-bound key can " + "only be copied to local keys.", + .command = COMMAND_COPY, + }, /***********************************************************/ { .flags = UTIL_OPT_FLAG_SECTION, @@ -2020,7 +2029,8 @@ static int command_copy(void) return EXIT_FAILURE; } - rc = keystore_copy_key(g.keystore, g.name, g.newname, g.volumes); + rc = keystore_copy_key(g.keystore, g.name, g.newname, g.volumes, + g.local); return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS; }