mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zkey: Add 'zkey kms list' command to list keys in a KMS
Allow to list the keys managed by a key management system. The keys are displayed together with the key properties stored in the KMS. Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
f832428109
commit
bcce1e8d18
485
zkey/kms.c
485
zkey/kms.c
@@ -7,11 +7,13 @@
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <argz.h>
|
||||
#include <ctype.h>
|
||||
#include <dlfcn.h>
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <regex.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
@@ -60,6 +62,17 @@
|
||||
#define KMS_KEY_PROP_XTS_KEY1_LABEL "xts-key1-label"
|
||||
#define KMS_KEY_PROP_XTS_KEY2_LABEL "xts-key2-label"
|
||||
|
||||
#define KMS_REC_LABEL "Key label"
|
||||
#define KMS_REC_NAME "Name"
|
||||
#define KMS_REC_KEY_TYPE "Key type"
|
||||
#define KMS_REC_KEY_SIZE "Key size"
|
||||
#define KMS_REC_DESCRIPTION "Description"
|
||||
#define KMS_REC_XTS "XTS type key"
|
||||
#define KMS_REC_VOLUMES "Volumes"
|
||||
#define KMS_REC_VOLUME_TYPE "Volume type"
|
||||
#define KMS_REC_SECTOR_SIZE "Sector size"
|
||||
#define KMS_REC_ADDL_INFOS "Addl. infos"
|
||||
|
||||
static const char * const key_types[] = {
|
||||
KEY_TYPE_CCA_AESDATA,
|
||||
KEY_TYPE_CCA_AESCIPHER,
|
||||
@@ -2502,3 +2515,475 @@ out:
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct process_keys_data {
|
||||
struct kms_info *kms_info;
|
||||
bool verbose;
|
||||
const char *label_filter;
|
||||
const char *name_filter;
|
||||
char **volume_filter;
|
||||
char *volume_type;
|
||||
char *zkey_name_system;
|
||||
char *volume_system;
|
||||
kms_process_callback callback;
|
||||
void *private_data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Finds a KMS property in the property array and returns its value or NULL if
|
||||
* it has not been found.
|
||||
*
|
||||
* @param properties a list of properties of the key
|
||||
* @param num_properties the number of properties in above array
|
||||
* @param prop_name the name of the property to get
|
||||
*
|
||||
* @returns the properties value, or NULL if not found.
|
||||
* Note: The returned string is the value field from the array element.
|
||||
*/
|
||||
static const char *_find_property(const struct kms_property *properties,
|
||||
size_t num_properties, const char *prop_name)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < num_properties; i++) {
|
||||
if (strcmp(properties[i].name, prop_name) == 0)
|
||||
return properties[i].value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the value matches the filter list. The value is a comma
|
||||
* separated string.
|
||||
*
|
||||
* If the filter values contain a second part separated by a colon (':'), then
|
||||
* the filter matches only if both parts match. If the filter values do not
|
||||
* contain a second part,then only the first part is checked, and the second
|
||||
* parts of the values are ignored.
|
||||
*
|
||||
* @param[in] value the value to check
|
||||
* @param[in] filter_list a list of filter strings to match the value with
|
||||
* @param[in] match_func the filter match function. If NULL fnmatch() is used.
|
||||
*
|
||||
* @returns 1 for a match, 0 for not matched
|
||||
*/
|
||||
static int _match_volumes_filter(const char *volumes, char **volumes_filter)
|
||||
{
|
||||
char **value_list;
|
||||
int i, k, rc = 0;
|
||||
char *ch;
|
||||
|
||||
if (volumes_filter == NULL)
|
||||
return 1;
|
||||
|
||||
value_list = str_list_split(volumes);
|
||||
for (i = 0; volumes_filter[i] != NULL && rc == 0; i++) {
|
||||
for (k = 0; value_list[k] != NULL; k++) {
|
||||
/*
|
||||
* Ignore part after ':' of value if filter does
|
||||
* not also contain a ':' part.
|
||||
*/
|
||||
if (strchr(volumes_filter[i], ':') == NULL) {
|
||||
ch = strchr(value_list[k], ':');
|
||||
if (ch != NULL)
|
||||
*ch = '\0';
|
||||
}
|
||||
|
||||
if (fnmatch(volumes_filter[i], value_list[k], 0) == 0) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
str_list_free_string_array(value_list);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used with the process_kms_keys() function. Called for each key.
|
||||
*
|
||||
* @param key_id the key-ID of the key
|
||||
* @param key_label the label of the key.
|
||||
* @param key_type the type of the key (CCA-AESDATA, etc)
|
||||
* @param key_bits the key size in bits
|
||||
* @param properties a list of properties of the key
|
||||
* @param num_properties the number of properties in above array
|
||||
* @param addl_info_argz an argz string containing additional KMS plugin
|
||||
* specific infos to be displayed, or NULL if none.
|
||||
* @param addl_info_len length of the argz string in addl_info_argz
|
||||
* @param private_data the private data pointer
|
||||
*
|
||||
* @returns 0 on success, or a negative errno in case of an error.
|
||||
*/
|
||||
static int _process_kms_keys_cb(const char *key_id, const char *key_label,
|
||||
const char *key_type, size_t key_bits,
|
||||
const struct kms_property *properties,
|
||||
size_t num_properties,
|
||||
const char *addl_info_argz,
|
||||
size_t addl_info_len, void *private_data)
|
||||
{
|
||||
struct process_keys_data *process_data = private_data;
|
||||
const char *name, *volumes, *cipher, *iv_mode, *description;
|
||||
const char *xts_key2_id = NULL, *xts_key2_label = NULL;
|
||||
const char *xts_key, *volume_type, *temp;
|
||||
size_t sector_size = 0;
|
||||
bool xts = false;
|
||||
|
||||
pr_verbose(process_data->verbose, "processing key_id: %s", key_id);
|
||||
|
||||
xts_key = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_XTS_KEY);
|
||||
if (xts_key != NULL) {
|
||||
if (strcasecmp(xts_key, "XTS-KEY-1") != 0) {
|
||||
pr_verbose(process_data->verbose,
|
||||
"skipping '%s' due to %s=%s", key_id,
|
||||
KMS_KEY_PROP_XTS_KEY, xts_key);
|
||||
return 0;
|
||||
}
|
||||
xts = true;
|
||||
|
||||
xts_key2_id = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_XTS_KEY2_ID);
|
||||
xts_key2_label = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_XTS_KEY2_LABEL);
|
||||
if (xts_key2_id == NULL || xts_key2_label == NULL) {
|
||||
pr_verbose(process_data->verbose, "skipping '%s' due "
|
||||
"to missing XTS cross refs", key_id);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
name = _find_property(properties, num_properties,
|
||||
process_data->zkey_name_system);
|
||||
if (name == NULL)
|
||||
name = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_NAME);
|
||||
if (name == NULL) {
|
||||
pr_verbose(process_data->verbose, "skipping '%s' due "
|
||||
"to missing %s", key_id, KMS_KEY_PROP_NAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cipher = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_CIPHER);
|
||||
iv_mode = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_IV_MODE);
|
||||
description = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_DESCRIPTION);
|
||||
volumes = _find_property(properties, num_properties,
|
||||
process_data->volume_system);
|
||||
if (volumes == NULL)
|
||||
volumes = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_VOLUMES);
|
||||
volume_type = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_VOLUME_TYPE);
|
||||
temp = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_SECTOR_SIZE);
|
||||
if (temp != NULL)
|
||||
sscanf(temp, "%lu", §or_size);
|
||||
|
||||
if (process_data->label_filter != NULL) {
|
||||
if (fnmatch(process_data->label_filter, key_label,
|
||||
FNM_PATHNAME) != 0)
|
||||
return 0;
|
||||
|
||||
if (xts && fnmatch(process_data->label_filter, xts_key2_label,
|
||||
FNM_PATHNAME) != 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (process_data->name_filter != NULL &&
|
||||
fnmatch(process_data->name_filter, name, FNM_PATHNAME) != 0)
|
||||
return 0;
|
||||
|
||||
if (process_data->volume_filter != NULL) {
|
||||
if (volumes == NULL)
|
||||
return 0;
|
||||
|
||||
if (!_match_volumes_filter(volumes,
|
||||
process_data->volume_filter))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (process_data->volume_type != NULL &&
|
||||
strcasecmp(process_data->volume_type, volume_type) != 0)
|
||||
return 0;
|
||||
|
||||
return process_data->callback(key_id, key_label, xts_key2_id,
|
||||
xts_key2_label, xts, name, key_type,
|
||||
xts ? key_bits * 2 : key_bits,
|
||||
description, cipher, iv_mode,
|
||||
volumes, volume_type, sector_size,
|
||||
addl_info_argz, addl_info_len,
|
||||
process_data->private_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes KMS managed keys. The keys can be filtered by label, name, volume,
|
||||
* and volume type.
|
||||
*
|
||||
* @param[in] kms_info information of the currently bound plugin.
|
||||
* @param[in] label_filter the KMS label filter. Can contain wild cards.
|
||||
* NULL means no name filter.
|
||||
* @param[in] name_filter the name filter. Can contain wild cards.
|
||||
* NULL means no name filter.
|
||||
* @param[in] volume_filter the volume filter. Can contain wild cards, and
|
||||
* mutliple volume filters separated by commas.
|
||||
* If the filter does not contain the ':dm-name'
|
||||
* part, then the volumes are matched without the
|
||||
* dm-name part. If the filter contains the
|
||||
* ':dm-name' part, then the filter is matched
|
||||
* including the dm-name part.
|
||||
* NULL means no volume filter.
|
||||
* @param[in] volume_type If not NULL, specifies the volume type.
|
||||
* @param[in] callback the callback that is called for each matching key
|
||||
* @param[in] private_data the private data of the callback
|
||||
* @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 process_kms_keys(struct kms_info *kms_info,
|
||||
const char *label_filter, const char *name_filter,
|
||||
const char *volume_filter, const char *volume_type,
|
||||
struct kms_option *kms_options, size_t num_kms_options,
|
||||
kms_process_callback callback, void *private_data,
|
||||
bool verbose)
|
||||
{
|
||||
struct process_keys_data process_data = { 0 };
|
||||
struct kms_property kms_props;
|
||||
size_t num_kms_props = 0;
|
||||
int rc = 0;
|
||||
|
||||
util_assert(kms_info != NULL, "Internal error: kms_info is NULL");
|
||||
util_assert(callback != NULL, "Internal error: callback is NULL");
|
||||
|
||||
if (kms_info->funcs->kms_list_keys == NULL) {
|
||||
pr_verbose(verbose, "The KMS plugin does not support to "
|
||||
"list keys");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
process_data.kms_info = kms_info;
|
||||
process_data.verbose = verbose;
|
||||
process_data.label_filter = label_filter;
|
||||
process_data.name_filter = name_filter;
|
||||
if (volume_filter != NULL)
|
||||
process_data.volume_filter = str_list_split(volume_filter);
|
||||
if (volume_type != NULL) {
|
||||
process_data.volume_type = util_strdup(volume_type);
|
||||
util_str_toupper(process_data.volume_type);
|
||||
}
|
||||
process_data.callback = callback;
|
||||
process_data.private_data = private_data;
|
||||
process_data.zkey_name_system =
|
||||
_get_system_specific_prop_name(KMS_KEY_PROP_NAME);
|
||||
process_data.volume_system =
|
||||
_get_system_specific_prop_name(KMS_KEY_PROP_VOLUMES);
|
||||
|
||||
if (process_data.volume_type != NULL) {
|
||||
kms_props.name = KMS_KEY_PROP_VOLUME_TYPE;
|
||||
kms_props.value = process_data.volume_type;
|
||||
num_kms_props = 1;
|
||||
}
|
||||
|
||||
rc = kms_info->funcs->kms_list_keys(kms_info->handle, label_filter,
|
||||
num_kms_props > 0 ?
|
||||
&kms_props : NULL,
|
||||
num_kms_props, kms_options,
|
||||
num_kms_options,
|
||||
_process_kms_keys_cb,
|
||||
&process_data);
|
||||
|
||||
if (rc != 0) {
|
||||
warnx("KMS plugin '%s' failed to list keys: %s",
|
||||
kms_info->plugin_name, strerror(-rc));
|
||||
print_last_kms_error(kms_info);
|
||||
}
|
||||
|
||||
free(process_data.zkey_name_system);
|
||||
free(process_data.volume_system);
|
||||
if (process_data.volume_filter != NULL)
|
||||
str_list_free_string_array(process_data.volume_filter);
|
||||
if (process_data.volume_type != NULL)
|
||||
free(process_data.volume_type);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct list_keys_data {
|
||||
struct util_rec *rec;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback used with the list_kms_keys() function. Called for each key.
|
||||
*
|
||||
* @param key1_id the key-ID of the key (1st key of an XTS key)
|
||||
* @param key1_label the label of the key (1st key of an XTS key)
|
||||
* @param key2_id the key-ID of the 2nd XTS key, NULL if not XTS
|
||||
* @param key2_label the label of the 2nd XTS key, NULL if not XTS
|
||||
* @param xts if true, this is an XTS key pair
|
||||
* @param name the zkey name of the key
|
||||
* @param key_type the type of the key (CCA-AESDATA, etc)
|
||||
* @param key_bits the key size in bits
|
||||
* @param description the description of the key (can be NULL)
|
||||
* @param cipher the cipher of the key (can be NULL)
|
||||
* @param iv_mode the IV-mode of the key (can be NULL)
|
||||
* @param volumes the associated volumes of the key (can be NULL)
|
||||
* @param volume_type the volume type of the volume (can be NULL)
|
||||
* @param sector_size the sector size of the volume (0 means default)
|
||||
* @param addl_info_argz an argz string containing additional KMS plugin
|
||||
* specific infos to be displayed, or NULL if none.
|
||||
* @param addl_info_len length of the argz string in addl_info_argz
|
||||
* @param private_data the private data pointer
|
||||
*
|
||||
* @returns 0 on success, or a negative errno in case of an error.
|
||||
*/
|
||||
static int _list_kms_keys_cb(const char *UNUSED(key1_id),
|
||||
const char *key1_label,
|
||||
const char *UNUSED(key2_id),
|
||||
const char *key2_label,
|
||||
bool xts, const char *name,
|
||||
const char *key_type, size_t key_bits,
|
||||
const char *description,
|
||||
const char *UNUSED(cipher),
|
||||
const char *UNUSED(iv_mode), const char *volumes,
|
||||
const char *volume_type, size_t sector_size,
|
||||
const char *addl_info_argz, size_t addl_info_len,
|
||||
void *private_data)
|
||||
{
|
||||
struct list_keys_data *list_data = private_data;
|
||||
size_t volumes_argz_len, label_argz_len;
|
||||
char *volumes_argz = NULL;
|
||||
char *label_argz = NULL;
|
||||
|
||||
if (xts)
|
||||
label_argz_len = util_asprintf(&label_argz, "%s%c%s",
|
||||
key1_label, '\0', key2_label);
|
||||
else
|
||||
label_argz_len = util_asprintf(&label_argz, "%s", key1_label);
|
||||
label_argz_len += 1;
|
||||
|
||||
if (volumes != NULL)
|
||||
util_assert(argz_create_sep(volumes, ',',
|
||||
&volumes_argz,
|
||||
&volumes_argz_len) == 0,
|
||||
"Internal error: argz_create_sep failed");
|
||||
|
||||
util_rec_set(list_data->rec, KMS_REC_NAME, name);
|
||||
util_rec_set_argz(list_data->rec, KMS_REC_LABEL, label_argz,
|
||||
label_argz_len);
|
||||
util_rec_set(list_data->rec, KMS_REC_DESCRIPTION,
|
||||
description != NULL ? description : "");
|
||||
util_rec_set(list_data->rec, KMS_REC_XTS, xts ? "Yes" : "No");
|
||||
util_rec_set(list_data->rec, KMS_REC_KEY_TYPE, key_type);
|
||||
util_rec_set(list_data->rec, KMS_REC_KEY_SIZE, "%lu bits", key_bits);
|
||||
if (volumes_argz != NULL)
|
||||
util_rec_set_argz(list_data->rec, KMS_REC_VOLUMES, volumes_argz,
|
||||
volumes_argz_len);
|
||||
else
|
||||
util_rec_set(list_data->rec, KMS_REC_VOLUMES, "(none)");
|
||||
util_rec_set(list_data->rec, KMS_REC_VOLUME_TYPE,
|
||||
volume_type != NULL ? volume_type : "");
|
||||
if (sector_size == 0)
|
||||
util_rec_set(list_data->rec, KMS_REC_SECTOR_SIZE,
|
||||
"(system default)");
|
||||
else
|
||||
util_rec_set(list_data->rec, KMS_REC_SECTOR_SIZE, "%lu bytes",
|
||||
sector_size);
|
||||
if (addl_info_argz != NULL)
|
||||
util_rec_set_argz(list_data->rec, KMS_REC_ADDL_INFOS,
|
||||
addl_info_argz, addl_info_len);
|
||||
else
|
||||
util_rec_set(list_data->rec, KMS_REC_ADDL_INFOS, "(none)");
|
||||
|
||||
util_rec_print(list_data->rec);
|
||||
|
||||
if (volumes_argz != NULL)
|
||||
free(volumes_argz);
|
||||
if (label_argz != NULL)
|
||||
free(label_argz);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists KMS managed keys. The list can be filtered by label, name, volume,
|
||||
* and volume type.
|
||||
*
|
||||
* @param[in] kms_info information of the currently bound plugin.
|
||||
* @param[in] label_filter the KMS label filter. Can contain wild cards.
|
||||
* NULL means no name filter.
|
||||
* @param[in] name_filter the name filter. Can contain wild cards.
|
||||
* NULL means no name filter.
|
||||
* @param[in] volume_filter the volume filter. Can contain wild cards, and
|
||||
* mutliple volume filters separated by commas.
|
||||
* If the filter does not contain the ':dm-name'
|
||||
* part, then the volumes are matched without the
|
||||
* dm-name part. If the filter contains the
|
||||
* ':dm-name' part, then the filter is matched
|
||||
* including the dm-name part.
|
||||
* NULL means no volume filter.
|
||||
* @param[in] volume_type If not NULL, specifies the volume type.
|
||||
* @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 list_kms_keys(struct kms_info *kms_info, const char *label_filter,
|
||||
const char *name_filter, const char *volume_filter,
|
||||
const char *volume_type, struct kms_option *kms_options,
|
||||
size_t num_kms_options, bool verbose)
|
||||
{
|
||||
struct list_keys_data list_data = { 0 };
|
||||
int rc;
|
||||
|
||||
util_assert(kms_info != NULL, "Internal error: kms_info 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_list_keys == NULL) {
|
||||
pr_verbose(verbose, "The KMS plugin does not support to "
|
||||
"list keys");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
list_data.rec = util_rec_new_long("-", ":", KMS_REC_NAME, 28, 54);
|
||||
util_rec_def(list_data.rec, KMS_REC_NAME, UTIL_REC_ALIGN_LEFT, 54,
|
||||
KMS_REC_NAME);
|
||||
util_rec_def(list_data.rec, KMS_REC_LABEL, UTIL_REC_ALIGN_LEFT, 54,
|
||||
KMS_REC_LABEL);
|
||||
util_rec_def(list_data.rec, KMS_REC_DESCRIPTION, UTIL_REC_ALIGN_LEFT,
|
||||
54, KMS_REC_DESCRIPTION);
|
||||
util_rec_def(list_data.rec, KMS_REC_KEY_SIZE, UTIL_REC_ALIGN_LEFT, 20,
|
||||
KMS_REC_KEY_SIZE);
|
||||
util_rec_def(list_data.rec, KMS_REC_XTS, UTIL_REC_ALIGN_LEFT, 20,
|
||||
KMS_REC_XTS);
|
||||
util_rec_def(list_data.rec, KMS_REC_KEY_TYPE, UTIL_REC_ALIGN_LEFT, 54,
|
||||
KMS_REC_KEY_TYPE);
|
||||
util_rec_def(list_data.rec, KMS_REC_VOLUMES, UTIL_REC_ALIGN_LEFT, 54,
|
||||
KMS_REC_VOLUMES);
|
||||
util_rec_def(list_data.rec, KMS_REC_VOLUME_TYPE, UTIL_REC_ALIGN_LEFT,
|
||||
54, KMS_REC_VOLUME_TYPE);
|
||||
util_rec_def(list_data.rec, KMS_REC_SECTOR_SIZE, UTIL_REC_ALIGN_LEFT,
|
||||
20, KMS_REC_SECTOR_SIZE);
|
||||
util_rec_def(list_data.rec, KMS_REC_ADDL_INFOS, UTIL_REC_ALIGN_LEFT,
|
||||
54, KMS_REC_ADDL_INFOS);
|
||||
|
||||
rc = process_kms_keys(kms_info, label_filter, name_filter,
|
||||
volume_filter, volume_type, kms_options,
|
||||
num_kms_options, _list_kms_keys_cb,
|
||||
&list_data, verbose);
|
||||
|
||||
util_rec_free(list_data.rec);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
23
zkey/kms.h
23
zkey/kms.h
@@ -87,4 +87,27 @@ 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);
|
||||
|
||||
typedef int (*kms_process_callback)(const char *key1_id, const char *key1_label,
|
||||
const char *key2_id, const char *key2_label,
|
||||
bool xts, const char *name,
|
||||
const char *key_type, size_t key_bits,
|
||||
const char *description, const char *cipher,
|
||||
const char *iv_mode, const char *volumes,
|
||||
const char *volume_type, size_t sector_size,
|
||||
const char *addl_info_argz,
|
||||
size_t addl_info_len,
|
||||
void *private_data);
|
||||
|
||||
int process_kms_keys(struct kms_info *kms_info,
|
||||
const char *label_filter, const char *name_filter,
|
||||
const char *volume_filter, const char *volume_type,
|
||||
struct kms_option *kms_options, size_t num_kms_options,
|
||||
kms_process_callback callback, void *private_data,
|
||||
bool verbose);
|
||||
|
||||
int list_kms_keys(struct kms_info *kms_info, const char *label_filter,
|
||||
const char *name_filter, const char *volume_filter,
|
||||
const char *volume_type, struct kms_option *kms_options,
|
||||
size_t num_kms_options, bool verbose);
|
||||
|
||||
#endif
|
||||
|
||||
71
zkey/zkey.1
71
zkey/zkey.1
@@ -1030,6 +1030,41 @@ re-enciphering. Re-enciphering from \fBCURRENT\fP to \fBNEW\fP is performed in
|
||||
staged mode per default. You can use option \fB\-\-staged\fP to force a staged
|
||||
re-enciphering for the \fBOLD\fP to \fBCURRENT\fP case.
|
||||
.
|
||||
.SS "List secure keys managed by a key management system"
|
||||
.
|
||||
.B zkey kms
|
||||
.BR list | li
|
||||
.RB [ \-\-label | \-B
|
||||
.IR key-label ]
|
||||
.RB [ \-\-name | \-N
|
||||
.IR key-name ]
|
||||
.RB [ \-\-volumes | \-l
|
||||
.IR volume1[:dmname1][,volume2[:dmname2][,...]] ]
|
||||
.RB [ \-\-volume-type | \-t
|
||||
.IR type ]
|
||||
.RB [ KMS\-plugin\ specific\ options ]
|
||||
.RB [ \-\-verbose | \-V ]
|
||||
.
|
||||
.PP
|
||||
Use the
|
||||
.B kms list
|
||||
command to display secure keys managed by a key management system (KMS).
|
||||
You can filter the displayed list by key label, key name, associated volumes,
|
||||
and volume type. You can use wildcards for the key label, key name, and
|
||||
associated volumes. The device-mapper name of an associated volume can be
|
||||
omitted. If specified, then only those keys are listed that are associated
|
||||
with the specified volume and device-mapper name.
|
||||
.PP
|
||||
A key management system plugin may offer plugin specific options that can be
|
||||
specified with the \fBkms list\fP command. Use \fBkms list \-\-help\fP
|
||||
to display the plugin specific options and their meaning.
|
||||
.PP
|
||||
The
|
||||
.B kms list
|
||||
command displays the attributes of the secure keys, such as key label, key name,
|
||||
whether it is a secure key that can be used for the XTS cipher mode, the textual
|
||||
description, associated volumes, the volume type, and sector size.
|
||||
.
|
||||
.
|
||||
.
|
||||
.SH OPTIONS
|
||||
@@ -1685,6 +1720,42 @@ display the plugin specific options and their meaning.
|
||||
.
|
||||
.
|
||||
.
|
||||
.SS "Options for the kms list command"
|
||||
.TP
|
||||
.BR \-B ", " \-\-label\~\fIkey-label\fP
|
||||
Specifies the label of the secure key in the key management system (KMS).
|
||||
You can use wildcards to select multiple secure keys.
|
||||
When wildcards are used you must quote the value.
|
||||
Only keys with labels that match the pattern are listed.
|
||||
.TP
|
||||
.BR \-N ", " \-\-name\~\fIkey-name\fP
|
||||
Specifies the name of the secure key in the key management system (KMS).
|
||||
You can use wildcards to select multiple secure keys.
|
||||
When wildcards are used you must quote the value.
|
||||
Only keys with names that match the pattern are listed.
|
||||
This option is only used for secure keys contained in the secure key repository.
|
||||
.TP
|
||||
.BR \-l ", " \-\-volumes\~\fIvolume1[:dmname1][,volume2[:dmname2][,...]]\fP
|
||||
Specifies a comma-separated list of volumes (block devices) which are
|
||||
associated with the secure AES key in the key management system (KMS). Only
|
||||
those keys are listed, which are associated with the specified volumes.
|
||||
The volume association also contains the device-mapper name, separated by a
|
||||
colon, used with dm-crypt. You can omit the device-mapper name; if it is
|
||||
specified then only those keys are listed that are associated with the
|
||||
specified volume and device-mapper name. You can use wildcards to specify
|
||||
the volumes and device-mapper names.
|
||||
When wildcards are used you must quote the value.
|
||||
.TP
|
||||
.BR \-t ", " \-\-volume-type\~\fItype\fP
|
||||
Specifies the volume type of the associated volumes used with dm-crypt. Possible
|
||||
values are \fBplain\fP and \fBluks2\fP. Only keys with the specified volume
|
||||
type are listed.
|
||||
This option is only available if
|
||||
.B zkey
|
||||
has been compiled with LUKS2 support enabled.
|
||||
.
|
||||
.
|
||||
.
|
||||
|
||||
.SS "General options"
|
||||
.TP
|
||||
|
||||
86
zkey/zkey.c
86
zkey/zkey.c
@@ -76,6 +76,7 @@ static struct zkey_globals {
|
||||
char *volume_type;
|
||||
char *newname;
|
||||
char *key_type;
|
||||
char *label;
|
||||
bool local;
|
||||
bool kms_bound;
|
||||
bool run;
|
||||
@@ -126,6 +127,7 @@ static struct zkey_globals {
|
||||
#define COMMAND_KMS_INFO "info"
|
||||
#define COMMAND_KMS_CONFIGURE "configure"
|
||||
#define COMMAND_KMS_REENCIPHER "reencipher"
|
||||
#define COMMAND_KMS_LIST "list"
|
||||
|
||||
#define OPT_COMMAND_PLACEHOLDER "PLACEHOLDER"
|
||||
|
||||
@@ -915,6 +917,50 @@ static struct util_opt opt_vec[] = {
|
||||
"staged mode per default.",
|
||||
.command = COMMAND_KMS " " COMMAND_KMS_REENCIPHER,
|
||||
},
|
||||
/***********************************************************/
|
||||
{
|
||||
.flags = UTIL_OPT_FLAG_SECTION,
|
||||
.desc = "OPTIONS",
|
||||
.command = COMMAND_KMS " " COMMAND_KMS_LIST,
|
||||
},
|
||||
{
|
||||
.option = { "label", required_argument, NULL, 'B'},
|
||||
.argument = "LABEL",
|
||||
.desc = "Label of the secure AES keys as known by the KMS that "
|
||||
"are to be listed. You can use wildcards to select "
|
||||
"the keys to be listed.",
|
||||
.command = COMMAND_KMS " " COMMAND_KMS_LIST,
|
||||
},
|
||||
{
|
||||
.option = { "name", required_argument, NULL, 'N'},
|
||||
.argument = "NAME",
|
||||
.desc = "Name of the secure AES keys as known by zkey that "
|
||||
"are to be listed. You can use wildcards to select "
|
||||
"the keys to be listed.",
|
||||
.command = COMMAND_KMS " " COMMAND_KMS_LIST,
|
||||
},
|
||||
{
|
||||
.option = { "volumes", required_argument, NULL, 'l'},
|
||||
.argument = "VOLUME[:DMNAME][,...]",
|
||||
.desc = "Comma-separated pairs of volume and device-mapper "
|
||||
"names that are associated with the secure AES key in "
|
||||
"the KMS. Use this option to list all keys "
|
||||
"associated with specific volumes. The device-mapper "
|
||||
"name (DMNAME) is optional. If specified, only those "
|
||||
"keys are listed where both, the volume and the device-"
|
||||
"mapper name matches.",
|
||||
.command = COMMAND_KMS " " COMMAND_KMS_LIST,
|
||||
},
|
||||
#ifdef HAVE_LUKS2_SUPPORT
|
||||
{
|
||||
.option = { "volume-type", required_argument, NULL, 't'},
|
||||
.argument = "type",
|
||||
.desc = "The type of the associated volume(s). Possible values "
|
||||
"are 'plain' and 'luks2'. Use this option to list all "
|
||||
"keys with the specified volumes type.",
|
||||
.command = COMMAND_KMS " " COMMAND_KMS_LIST,
|
||||
},
|
||||
#endif
|
||||
/***********************************************************/
|
||||
OPT_PLACEHOLDER,
|
||||
OPT_PLACEHOLDER,
|
||||
@@ -1016,6 +1062,7 @@ static int command_kms_unbind(void);
|
||||
static int command_kms_info(void);
|
||||
static int command_kms_configure(void);
|
||||
static int command_kms_reencipher(void);
|
||||
static int command_kms_list(void);
|
||||
|
||||
static struct zkey_command zkey_kms_commands[] = {
|
||||
{
|
||||
@@ -1089,6 +1136,20 @@ static struct zkey_command zkey_kms_commands[] = {
|
||||
.use_kms_plugin = 1,
|
||||
.kms_plugin_opts_cmd = KMS_COMMAND_REENCIPHER,
|
||||
},
|
||||
{
|
||||
.command = COMMAND_KMS_LIST,
|
||||
.abbrev_len = 2,
|
||||
.function = command_kms_list,
|
||||
.short_desc = "Lists secure keys managed by a key management "
|
||||
"system",
|
||||
.long_desc = "Lists secure keys managed by a key management "
|
||||
"system (KMS)",
|
||||
.need_keystore = 1,
|
||||
.has_options = 1,
|
||||
.use_kms_plugin = 1,
|
||||
.need_kms_login = 1,
|
||||
.kms_plugin_opts_cmd = KMS_COMMAND_LIST,
|
||||
},
|
||||
{ .command = NULL }
|
||||
};
|
||||
|
||||
@@ -2448,6 +2509,28 @@ static int command_kms_reencipher(void)
|
||||
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Command handler for 'kms list'.
|
||||
*
|
||||
* List secure keys managed by a KMS
|
||||
*/
|
||||
static int command_kms_list(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 = list_kms_keys(&g.kms_info, g.label, g.name, g.volumes,
|
||||
g.volume_type, g.kms_options, g.num_kms_options,
|
||||
g.verbose);
|
||||
|
||||
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
|
||||
@@ -2765,6 +2848,9 @@ int main(int argc, char *argv[])
|
||||
case 'M':
|
||||
g.kms_bound = 1;
|
||||
break;
|
||||
case 'B':
|
||||
g.label = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
print_help(command, sub_command);
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
Reference in New Issue
Block a user