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:
Ingo Franzki
2020-06-17 17:28:32 +02:00
committed by Jan Höppner
parent f832428109
commit bcce1e8d18
4 changed files with 665 additions and 0 deletions

View File

@@ -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", &sector_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;
}

View File

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

View File

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

View File

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