mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zkey: Add 'zkey kms refresh' command to update a KMS-bound key
Allow to refresh or update a KMS-bound key in the repository. The secure key is re-imported from the KMS, and optionally also its properties are updates from 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
cd8a733c82
commit
91b1692b16
+223
@@ -5225,6 +5225,229 @@ int keystore_import_kms_keys(struct keystore *keystore,
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct kms_refresh {
|
||||
bool refresh_properties;
|
||||
bool novolcheck;
|
||||
unsigned long num_refreshed;
|
||||
unsigned long num_failed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Processing function for the key refresh function.
|
||||
*
|
||||
* @param[in] keystore the keystore
|
||||
* @param[in] name the name of the key
|
||||
* @param[in] properties the properties object of the key
|
||||
* @param[in] file_names the file names used by this key
|
||||
* @param[in] private private data: struct reencipher_info
|
||||
*
|
||||
* @returns 0 if the display is successful, a negative errno value otherwise
|
||||
*/
|
||||
static int _keystore_refresh_kms_key(struct keystore *keystore,
|
||||
const char *name,
|
||||
struct properties *properties,
|
||||
struct key_filenames *file_names,
|
||||
void *private)
|
||||
{
|
||||
struct volume_check vol_check = { .keystore = keystore, .name = name,
|
||||
.set = 1, .nocheck = 0 };
|
||||
char *description = NULL, *cipher = NULL, *iv_mode = NULL;
|
||||
struct kms_refresh *refresh_data = private;
|
||||
char *volumes = NULL, *volume_type = NULL;
|
||||
ssize_t sector_size = -1;
|
||||
bool fatal_err = false;
|
||||
char sect_size[30];
|
||||
char *msg;
|
||||
int rc;
|
||||
|
||||
vol_check.nocheck = refresh_data->novolcheck;
|
||||
|
||||
rc = refresh_kms_key(keystore->kms_info, properties,
|
||||
&description, &cipher, &iv_mode, &volumes,
|
||||
&volume_type, §or_size,
|
||||
file_names->skey_filename, keystore->verbose);
|
||||
if (rc != 0) {
|
||||
warnx("KMS plugin '%s' failed to refresh key '%s': %s",
|
||||
keystore->kms_info->plugin_name, name, strerror(-rc));
|
||||
print_last_kms_error(keystore->kms_info);
|
||||
if (rc == -ENOTSUP)
|
||||
fatal_err = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!refresh_data->refresh_properties)
|
||||
goto save_props;
|
||||
|
||||
if (description != NULL) {
|
||||
rc = properties_set(properties, PROP_NAME_DESCRIPTION,
|
||||
description);
|
||||
if (rc != 0) {
|
||||
warnx("Invalid characters in description");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (volumes != NULL) {
|
||||
rc = _keystore_change_association(properties, PROP_NAME_VOLUMES,
|
||||
volumes, "volume",
|
||||
_keystore_volume_check,
|
||||
&vol_check);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sector_size >= 0) {
|
||||
if (!_keystore_valid_sector_size(sector_size)) {
|
||||
warnx("Invalid sector-size specified");
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sprintf(sect_size, "%lu", sector_size);
|
||||
rc = properties_set(properties, PROP_NAME_SECTOR_SIZE,
|
||||
sect_size);
|
||||
if (rc != 0) {
|
||||
warnx("Invalid characters in sector-size");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (volume_type != NULL) {
|
||||
if (!_keystore_valid_volume_type(volume_type)) {
|
||||
warnx("Invalid volume-type specified");
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = properties_set2(properties, PROP_NAME_VOLUME_TYPE,
|
||||
volume_type, true);
|
||||
if (rc != 0) {
|
||||
warnx("Invalid characters in volume-type");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
save_props:
|
||||
rc = _keystore_set_timestamp_property(properties,
|
||||
PROP_NAME_CHANGE_TIME);
|
||||
if (rc != 0) {
|
||||
warnx("Failed to set the update timestamp property");
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = properties_save(properties, file_names->info_filename, 1);
|
||||
if (rc != 0) {
|
||||
pr_verbose(keystore,
|
||||
"Key info file '%s' could not be written: %s",
|
||||
file_names->info_filename, strerror(-rc));
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (rc == 0) {
|
||||
printf("Successfully refreshed key '%s'\n", name);
|
||||
refresh_data->num_refreshed++;
|
||||
|
||||
util_asprintf(&msg, "The following LUKS2 volumes are "
|
||||
"encrypted with key '%s'. To update the secure "
|
||||
"AES volume key in the LUKS2 header, run command "
|
||||
"'zkey-cryptsetup setkey <device> "
|
||||
"--master-key-file %s':", name,
|
||||
file_names->skey_filename);
|
||||
_keystore_msg_for_volumes(msg, properties, VOLUME_TYPE_LUKS2);
|
||||
free(msg);
|
||||
} else {
|
||||
warnx("Failed to refresh key '%s': %s", name, strerror(-rc));
|
||||
refresh_data->num_failed++;
|
||||
}
|
||||
|
||||
if (description != NULL)
|
||||
free(description);
|
||||
if (cipher != NULL)
|
||||
free(cipher);
|
||||
if (iv_mode != NULL)
|
||||
free(iv_mode);
|
||||
if (volumes != NULL)
|
||||
free(volumes);
|
||||
if (volume_type != NULL)
|
||||
free(volume_type);
|
||||
|
||||
return fatal_err ? rc : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes secure KMS-bound secure key and updates them from the KMS
|
||||
*
|
||||
* @param[in] keystore the key store
|
||||
* @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] key_type The key type. NULL means no key type filter.
|
||||
* @param[in] refresh_properties if true, also refresh the key's properties
|
||||
* @param[in] novolcheck if true, do not check the associated volumes for
|
||||
* existence and duplicate use
|
||||
*
|
||||
* @returns 0 for success or a negative errno in case of an error
|
||||
*/
|
||||
int keystore_refresh_kms_keys(struct keystore *keystore,
|
||||
const char *name_filter,
|
||||
const char *volume_filter,
|
||||
const char *volume_type, const char *key_type,
|
||||
bool refresh_properties, bool novolcheck)
|
||||
{
|
||||
struct kms_refresh refresh_data = { 0 };
|
||||
int rc;
|
||||
|
||||
util_assert(keystore != NULL, "Internal error: keystore is NULL");
|
||||
|
||||
if (keystore->kms_info->plugin_lib == NULL) {
|
||||
warnx("The repository is not bound to a KMS plugin");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (volume_type != NULL &&
|
||||
!_keystore_valid_volume_type(volume_type)) {
|
||||
warnx("Invalid volume-type specified");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (key_type != NULL &&
|
||||
!_keystore_valid_key_type(key_type)) {
|
||||
warnx("Invalid key-type specified");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
refresh_data.refresh_properties = refresh_properties;
|
||||
refresh_data.novolcheck = novolcheck;
|
||||
refresh_data.num_refreshed = 0;
|
||||
refresh_data.num_failed = 0;
|
||||
|
||||
rc = _keystore_process_filtered(keystore, name_filter, volume_filter,
|
||||
NULL, volume_type, key_type, false,
|
||||
true, _keystore_refresh_kms_key,
|
||||
&refresh_data);
|
||||
|
||||
if (rc != 0) {
|
||||
pr_verbose(keystore, "Failed to refresh kms keys: %s",
|
||||
strerror(-rc));
|
||||
} else {
|
||||
printf("%lu keys refreshed, %lu keys failed to refresh\n",
|
||||
refresh_data.num_refreshed, refresh_data.num_failed);
|
||||
if (refresh_data.num_failed > 0)
|
||||
rc = -EIO;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees a keystore object
|
||||
*
|
||||
|
||||
@@ -135,6 +135,12 @@ int keystore_import_kms_keys(struct keystore *keystore,
|
||||
size_t num_kms_options,
|
||||
bool batch_mode, bool novolcheck);
|
||||
|
||||
int keystore_refresh_kms_keys(struct keystore *keystore,
|
||||
const char *name_filter,
|
||||
const char *volume_filter,
|
||||
const char *volume_type, const char *key_type,
|
||||
bool refres_properties, bool novolcheck);
|
||||
|
||||
void keystore_free(struct keystore *keystore);
|
||||
|
||||
|
||||
|
||||
+196
@@ -3113,3 +3113,199 @@ out:
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes KMS managed keys.
|
||||
*
|
||||
* @param[in] kms_info information of the currently bound plugin.
|
||||
* @param[in] key_props the key properties
|
||||
* @param[out] description on return: the description property
|
||||
* @param[out] cipher on return: the cipher property
|
||||
* @param[out] iv_mode on return: the iv_mode property
|
||||
* @param[out] volumes on return: the volumes property
|
||||
* @param[out] volume_type on return: the volume_type property
|
||||
* @param[out] sector_size on return: the sector_size property
|
||||
* @param[in] filename the file name to store the refreshed key blob in
|
||||
* @param[in] verbose if true, verbose messages are printed
|
||||
*
|
||||
* @returns 0 for success or a negative errno in case of an error.
|
||||
*/
|
||||
int refresh_kms_key(struct kms_info *kms_info, struct properties *key_props,
|
||||
char **description, char **cipher, char **iv_mode,
|
||||
char **volumes, char **volume_type, ssize_t *sector_size,
|
||||
const char *filename, bool verbose)
|
||||
{
|
||||
struct kms_property *properties = NULL;
|
||||
u8 key_blob[2 * MAX_SECURE_KEY_SIZE];
|
||||
char *key1_id = NULL, *key2_id = NULL;
|
||||
size_t key_blob_size, key_size = 0;
|
||||
char vp[VERIFICATION_PATTERN_LEN];
|
||||
size_t i, num_properties = 0;
|
||||
char *sys_volumes = NULL;
|
||||
char *orig_vp = NULL;
|
||||
bool xts = false;
|
||||
const char *str;
|
||||
int rc = 0;
|
||||
|
||||
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_import_key == NULL ||
|
||||
kms_info->funcs->kms_get_key_properties == NULL) {
|
||||
pr_verbose(verbose, "The KMS plugin does not support to "
|
||||
"import keys or get 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;
|
||||
}
|
||||
|
||||
rc = kms_info->funcs->kms_get_key_properties(kms_info->handle, key1_id,
|
||||
&properties,
|
||||
&num_properties);
|
||||
if (rc != 0) {
|
||||
pr_verbose(verbose, "KMS plugin failed to get attributes of "
|
||||
"key '%s': %s", key1_id, strerror(-rc));
|
||||
goto out;
|
||||
}
|
||||
|
||||
sys_volumes = _get_system_specific_prop_name(KMS_KEY_PROP_VOLUMES);
|
||||
if (sys_volumes == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (description != NULL) {
|
||||
str = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_DESCRIPTION);
|
||||
*description = (str != NULL) ? util_strdup(str) : NULL;
|
||||
}
|
||||
|
||||
if (cipher != NULL) {
|
||||
str = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_CIPHER);
|
||||
*cipher = (str != NULL) ? util_strdup(str) : NULL;
|
||||
}
|
||||
|
||||
if (iv_mode != NULL) {
|
||||
str = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_IV_MODE);
|
||||
*iv_mode = (str != NULL) ? util_strdup(str) : NULL;
|
||||
}
|
||||
|
||||
if (volumes != NULL) {
|
||||
str = _find_property(properties, num_properties,
|
||||
sys_volumes);
|
||||
if (str == NULL)
|
||||
str = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_VOLUMES);
|
||||
*volumes = (str != NULL) ? util_strdup(str) : NULL;
|
||||
}
|
||||
|
||||
if (volume_type != NULL) {
|
||||
str = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_VOLUME_TYPE);
|
||||
*volume_type = (str != NULL) ? util_strdup(str) : NULL;
|
||||
}
|
||||
|
||||
if (sector_size != NULL) {
|
||||
*sector_size = -1;
|
||||
str = _find_property(properties, num_properties,
|
||||
KMS_KEY_PROP_SECTOR_SIZE);
|
||||
if (str != NULL)
|
||||
sscanf(str, "%lu", sector_size);
|
||||
}
|
||||
|
||||
key_blob_size = sizeof(key_blob);
|
||||
memset(key_blob, 0, key_blob_size);
|
||||
|
||||
rc = kms_info->funcs->kms_import_key(kms_info->handle, key1_id,
|
||||
key_blob, &key_blob_size);
|
||||
if (rc != 0) {
|
||||
pr_verbose(verbose, "KMS plugin failed to import key '%s': %s",
|
||||
key1_id, strerror(-rc));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (is_cca_aes_data_key(key_blob, key_blob_size))
|
||||
key_size = AESDATA_KEY_SIZE;
|
||||
else if (is_cca_aes_cipher_key(key_blob, key_blob_size))
|
||||
key_size = AESCIPHER_KEY_SIZE;
|
||||
else if (is_ep11_aes_key(key_blob, key_blob_size))
|
||||
key_size = EP11_KEY_SIZE;
|
||||
|
||||
if (key_size == 0 || key_blob_size > key_size) {
|
||||
pr_verbose(verbose, "Key '%s' has an unknown or unsupported "
|
||||
"key type", key1_id);
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (xts) {
|
||||
key_blob_size = key_size;
|
||||
rc = kms_info->funcs->kms_import_key(kms_info->handle, key2_id,
|
||||
key_blob + key_size,
|
||||
&key_blob_size);
|
||||
if (rc != 0) {
|
||||
pr_verbose(verbose, "KMS plugin failed to import key #2"
|
||||
"'%s': %s", key2_id, strerror(-rc));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
key_blob_size = xts ? key_size * 2 : key_size;
|
||||
|
||||
orig_vp = properties_get(key_props, PROP_NAME_KEY_VP);
|
||||
if (orig_vp != NULL) {
|
||||
rc = generate_key_verification_pattern(key_blob, key_blob_size,
|
||||
vp, sizeof(vp), verbose);
|
||||
if (rc != 0) {
|
||||
warnx("Failed to generate the verification pattern: %s",
|
||||
strerror(-rc));
|
||||
warnx("Make sure that kernel module 'paes_s390' is "
|
||||
"loaded and that the 'paes' cipher is available");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp(vp, orig_vp) != 0) {
|
||||
warnx("The key verification pattern of the refreshed "
|
||||
"secure key does not match the current one.");
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
rc = write_secure_key(filename, key_blob, key_blob_size, verbose);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
if (key1_id != NULL)
|
||||
free(key1_id);
|
||||
if (key2_id != NULL)
|
||||
free(key2_id);
|
||||
if (sys_volumes != NULL)
|
||||
free(sys_volumes);
|
||||
if (orig_vp != NULL)
|
||||
free(orig_vp);
|
||||
if (properties != NULL) {
|
||||
for (i = 0; i < num_properties; i++) {
|
||||
free((void *)properties[i].name);
|
||||
free((void *)properties[i].value);
|
||||
}
|
||||
free(properties);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -115,4 +115,9 @@ int import_kms_key(struct kms_info *kms_info, const char *key1_id,
|
||||
unsigned char *key_blob, size_t *key_blob_length,
|
||||
bool verbose);
|
||||
|
||||
int refresh_kms_key(struct kms_info *kms_info, struct properties *key_props,
|
||||
char **description, char **cipher, char **iv_mode,
|
||||
char **volumes, char **volume_type, ssize_t *sector_size,
|
||||
const char *filename, bool verbose);
|
||||
|
||||
#endif
|
||||
|
||||
+84
@@ -1109,6 +1109,45 @@ not available, or are already associated with another secure key, the import
|
||||
fails. Use option \fB\-\-no\-volume\-check\fP to omit the volume check, and
|
||||
import the keys even if the associated volume(s) do not exist.
|
||||
.
|
||||
.SS "Refresh secure keys that are bound to a key management system"
|
||||
.
|
||||
.B zkey kms
|
||||
.BR refresh | ref
|
||||
.RB [ \-\-name | \-N
|
||||
.IR key-name ]
|
||||
.RB [ \-\-volumes | \-l
|
||||
.IR volume1[:dmname1][,volume2[:dmname2][,...]] ]
|
||||
.RB [ \-\-volume-type | \-t
|
||||
.IR type ]
|
||||
.RB [ \-\-key-type | \-K
|
||||
.IR type ]
|
||||
.RB [ \-\-refresh\-properties | \-P ]
|
||||
.RB [ \-\-no\-volume\-check ]
|
||||
.RB [ \-\-verbose | \-V ]
|
||||
.
|
||||
.PP
|
||||
Use the
|
||||
.B kms refresh
|
||||
command to refresh secure keys that are bound to a key management system (KMS).
|
||||
Refreshing a key updates the secure key by re-importing it from the key
|
||||
management system. Use option \fB\-\-refresh\-properties\fP to also update the
|
||||
associated information, such as the textual description, associated volumes,
|
||||
volume type, and sector size, with the information stored in the key management
|
||||
system.
|
||||
.PP
|
||||
You can filter the list of keys to be refreshed by key name, associated volumes,
|
||||
volume type, and key type. You can use wildcards for the key name, and
|
||||
associated volumes. The device-mapper name of an associated volume can be
|
||||
omitted; if it is specified then only those keys are listed that are associated
|
||||
with the specified volume and device-mapper name.
|
||||
.PP
|
||||
If a refreshed key is associated with one or multiple volumes, it is
|
||||
verified that the volumes are available, and are not already associated with
|
||||
another secure key in the repository. If one of the volumes or all of them are
|
||||
not available, or are already associated with another secure key, the refresh
|
||||
fails. Use option \fB\-\-no\-volume\-check\fP to omit the volume check, and
|
||||
refresh the keys even if the associated volume(s) do not exist.
|
||||
.
|
||||
.
|
||||
.
|
||||
.SH OPTIONS
|
||||
@@ -1846,6 +1885,51 @@ repository.
|
||||
.
|
||||
.
|
||||
.
|
||||
.SS "Options for the kms refresh command"
|
||||
.TP
|
||||
.BR \-N ", " \-\-name\~\fIkey-name\fP
|
||||
Specifies the name of the secure key in the secure key repository. You can
|
||||
use wildcards to select multiple secure keys in the secure key repository.
|
||||
When wildcards are used you must quote the value.
|
||||
Only keys with names that match the pattern are refreshed.
|
||||
.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 repository. Only those keys are
|
||||
refreshed, 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 refreshed.
|
||||
This option is only available if
|
||||
.B zkey
|
||||
has been compiled with LUKS2 support enabled.
|
||||
.TP
|
||||
.BR \-K ", " \-\-key-type\~\fItype\fP
|
||||
Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP,
|
||||
\fBCCA-AESCIPHER\fP, and \fBEP11-AES\fP. Only keys with the specified key type
|
||||
are refreshed.
|
||||
.TP
|
||||
.BR \-q ", " \-\-refresh\-properties
|
||||
Also update the associated information, such as the textual description,
|
||||
associated volumes, volume type, and sector size, with the information stored in
|
||||
the key management system.
|
||||
.TP
|
||||
.BR \-\-no\-volume\-check
|
||||
Do not check if the volume(s) associated with the secure key(s) to be refreshed
|
||||
are available, or are already associated with other secure keys in the
|
||||
repository. This option only has an effect when specified together with option
|
||||
\fB\-\-refresh\-properties\fP.
|
||||
.
|
||||
.
|
||||
.
|
||||
.SS "General options"
|
||||
.TP
|
||||
.BR \-V ", " \-\-verbose
|
||||
|
||||
+101
@@ -89,6 +89,7 @@ static struct zkey_globals {
|
||||
bool force;
|
||||
bool open;
|
||||
bool format;
|
||||
bool refresh_properties;
|
||||
struct ext_lib lib;
|
||||
struct cca_lib cca;
|
||||
struct ep11_lib ep11;
|
||||
@@ -130,6 +131,7 @@ static struct zkey_globals {
|
||||
#define COMMAND_KMS_REENCIPHER "reencipher"
|
||||
#define COMMAND_KMS_LIST "list"
|
||||
#define COMMAND_KMS_IMPORT "import"
|
||||
#define COMMAND_KMS_REFRESH "refresh"
|
||||
|
||||
#define OPT_COMMAND_PLACEHOLDER "PLACEHOLDER"
|
||||
|
||||
@@ -153,6 +155,7 @@ static struct zkey_globals {
|
||||
#define OPT_CRYPTSETUP_FORMAT 261
|
||||
#define OPT_NO_APQN_CHECK 262
|
||||
#define OPT_NO_VOLUME_CHECK 263
|
||||
#define OPT_REFRESH_PROPERTIES 264
|
||||
|
||||
/*
|
||||
* Configuration of command line options
|
||||
@@ -1025,6 +1028,65 @@ static struct util_opt opt_vec[] = {
|
||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||
},
|
||||
/***********************************************************/
|
||||
{
|
||||
.flags = UTIL_OPT_FLAG_SECTION,
|
||||
.desc = "OPTIONS",
|
||||
.command = COMMAND_KMS " " COMMAND_KMS_REFRESH,
|
||||
},
|
||||
{
|
||||
.option = { "name", required_argument, NULL, 'N'},
|
||||
.argument = "NAME",
|
||||
.desc = "Name of the secure AES keys in the repository that "
|
||||
"are to be refreshed. You can use wildcards to select "
|
||||
"the keys to be refreshed.",
|
||||
.command = COMMAND_KMS " " COMMAND_KMS_REFRESH,
|
||||
},
|
||||
{
|
||||
.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 repository. Use this option to refresh all keys "
|
||||
"associated with specific volumes. The device-mapper "
|
||||
"name (DMNAME) is optional. If specified, only those "
|
||||
"keys are refreshed where both, the volume and the "
|
||||
"device-mapper name matches",
|
||||
.command = COMMAND_KMS " " COMMAND_KMS_REFRESH,
|
||||
},
|
||||
#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 refresh "
|
||||
"all keys with the specified volumes type.",
|
||||
.command = COMMAND_KMS " " COMMAND_KMS_REFRESH,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.option = { "key-type", required_argument, NULL, 'K'},
|
||||
.argument = "type",
|
||||
.desc = "The type of the key. Possible values are '"
|
||||
KEY_TYPE_CCA_AESDATA"', '"KEY_TYPE_CCA_AESCIPHER"' "
|
||||
"and '"KEY_TYPE_EP11_AES"'. Use this option to refresh "
|
||||
"all keys with the specified key type.",
|
||||
.command = COMMAND_KMS " " COMMAND_KMS_REFRESH,
|
||||
},
|
||||
{
|
||||
.option = {"refresh-properties", 0, NULL, 'P'},
|
||||
.desc = "Also refresh the properties of the secure AES key "
|
||||
"and update them with the values from the KMS.",
|
||||
.command = COMMAND_KMS " " COMMAND_KMS_REFRESH,
|
||||
},
|
||||
{
|
||||
.option = {"no-volume-check", 0, NULL, OPT_NO_VOLUME_CHECK},
|
||||
.desc = "Do not check if the volume(s) associated with the "
|
||||
"secure key(s) to be refreshed are available, or are "
|
||||
"already associated with other secure keys.",
|
||||
.command = COMMAND_KMS " " COMMAND_KMS_REFRESH,
|
||||
.flags = UTIL_OPT_FLAG_NOSHORT,
|
||||
},
|
||||
/***********************************************************/
|
||||
OPT_PLACEHOLDER,
|
||||
OPT_PLACEHOLDER,
|
||||
OPT_PLACEHOLDER,
|
||||
@@ -1127,6 +1189,7 @@ static int command_kms_configure(void);
|
||||
static int command_kms_reencipher(void);
|
||||
static int command_kms_list(void);
|
||||
static int command_kms_import(void);
|
||||
static int command_kms_refresh(void);
|
||||
|
||||
static struct zkey_command zkey_kms_commands[] = {
|
||||
{
|
||||
@@ -1228,6 +1291,19 @@ static struct zkey_command zkey_kms_commands[] = {
|
||||
.need_kms_login = 1,
|
||||
.kms_plugin_opts_cmd = KMS_COMMAND_LIST_IMPORT,
|
||||
},
|
||||
{
|
||||
.command = COMMAND_KMS_REFRESH,
|
||||
.abbrev_len = 3,
|
||||
.function = command_kms_refresh,
|
||||
.short_desc = "Refreshes secure keys that are bound to a key "
|
||||
"management system",
|
||||
.long_desc = "Refreshes secure keys that are bound to a key "
|
||||
"management system (KMS)",
|
||||
.need_keystore = 1,
|
||||
.has_options = 1,
|
||||
.use_kms_plugin = 1,
|
||||
.need_kms_login = 1,
|
||||
},
|
||||
{ .command = NULL }
|
||||
};
|
||||
|
||||
@@ -2632,6 +2708,28 @@ static int command_kms_import(void)
|
||||
return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Command handler for 'kms refresh'.
|
||||
*
|
||||
* Refreshes secure keys managed by a KMS
|
||||
*/
|
||||
static int command_kms_refresh(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 = keystore_refresh_kms_keys(g.keystore, g.name, g.volumes,
|
||||
g.volume_type, g.key_type,
|
||||
g.refresh_properties, g.novolcheck);
|
||||
|
||||
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
|
||||
@@ -2955,6 +3053,9 @@ int main(int argc, char *argv[])
|
||||
case 'B':
|
||||
g.label = optarg;
|
||||
break;
|
||||
case 'P':
|
||||
g.refresh_properties = 1;
|
||||
break;
|
||||
case 'h':
|
||||
print_help(command, sub_command);
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
Reference in New Issue
Block a user