mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zkey: Add key verification pattern property
Store a verification pattern in the properties file along with the secure key. The verification pattern allows to identify the inner key even when the secure key is no longer valid. Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com> Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
818ffbc4b0
commit
512b47c004
132
zkey/keystore.c
132
zkey/keystore.c
@@ -58,6 +58,7 @@ struct key_filenames {
|
||||
#define PROP_NAME_CREATION_TIME "creation-time"
|
||||
#define PROP_NAME_CHANGE_TIME "update-time"
|
||||
#define PROP_NAME_REENC_TIME "reencipher-time"
|
||||
#define PROP_NAME_KEY_VP "verification-pattern"
|
||||
|
||||
#define IS_XTS(secure_key_size) (secure_key_size > SECURE_KEY_SIZE ? 1 : 0)
|
||||
|
||||
@@ -75,6 +76,7 @@ struct key_filenames {
|
||||
#define REC_CREATION_TIME "Created"
|
||||
#define REC_CHANGE_TIME "Changed"
|
||||
#define REC_REENC_TIME "Re-enciphered"
|
||||
#define REC_KEY_VP "Verification pattern"
|
||||
|
||||
#define pr_verbose(keystore, fmt...) do { \
|
||||
if (keystore->verbose) \
|
||||
@@ -1269,6 +1271,77 @@ struct keystore *keystore_new(const char *directory, bool verbose)
|
||||
return keystore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the key verification pattern from the specified secure key file
|
||||
*
|
||||
* @param[in] keystore the key store
|
||||
* @param[in} keyfile the key file
|
||||
* @param[in] vp buffer filled with the verification pattern
|
||||
* @param[in] vp_len length of the buffer. Must be at
|
||||
* least VERIFICATION_PATTERN_LEN bytes in size.
|
||||
*
|
||||
* @returns 0 for success or a negative errno in case of an error
|
||||
*/
|
||||
static int _keystore_generate_verification_pattern(struct keystore *keystore,
|
||||
const char *keyfile,
|
||||
char *vp, size_t vp_len)
|
||||
{
|
||||
size_t key_size;
|
||||
u8 *key;
|
||||
int rc;
|
||||
|
||||
util_assert(keystore != NULL, "Internal error: keystore is NULL");
|
||||
util_assert(keyfile != NULL, "Internal error: keyfile is NULL");
|
||||
util_assert(vp != NULL, "Internal error: vp is NULL");
|
||||
|
||||
key = read_secure_key(keyfile, &key_size, keystore->verbose);
|
||||
if (key == NULL)
|
||||
return -EIO;
|
||||
|
||||
rc = generate_key_verification_pattern((const char *)key, key_size,
|
||||
vp, vp_len, keystore->verbose);
|
||||
|
||||
free(key);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the key verification pattern property exists. If not, then it is
|
||||
* created from the secure key.
|
||||
*
|
||||
* @param[in] keystore the key store
|
||||
* @param[in] file_names the file names of the key
|
||||
* @param[in] key_props the properties of the key
|
||||
*
|
||||
* @returns 0 for success or a negative errno in case of an error
|
||||
*/
|
||||
static int _keystore_ensure_vp_exists(struct keystore *keystore,
|
||||
const struct key_filenames *file_names,
|
||||
struct properties *key_props)
|
||||
{
|
||||
char vp[VERIFICATION_PATTERN_LEN];
|
||||
char *temp;
|
||||
int rc;
|
||||
|
||||
temp = properties_get(key_props, PROP_NAME_KEY_VP);
|
||||
if (temp != NULL) {
|
||||
free(temp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = _keystore_generate_verification_pattern(keystore,
|
||||
file_names->skey_filename,
|
||||
vp, sizeof(vp));
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
rc = properties_set(key_props, PROP_NAME_KEY_VP, vp);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a timestamp to be used as creation/update/reencipher time into
|
||||
* the specified property
|
||||
@@ -1348,7 +1421,7 @@ static int _keystore_set_default_properties(struct properties *key_props)
|
||||
*/
|
||||
static int _keystore_create_info_file(struct keystore *keystore,
|
||||
const char *name,
|
||||
const char *info_filename,
|
||||
const struct key_filenames *filenames,
|
||||
const char *description,
|
||||
const char *volumes, const char *apqns,
|
||||
size_t sector_size)
|
||||
@@ -1396,17 +1469,26 @@ static int _keystore_create_info_file(struct keystore *keystore,
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = properties_save(key_props, info_filename, 1);
|
||||
rc = _keystore_ensure_vp_exists(keystore, filenames, key_props);
|
||||
if (rc != 0) {
|
||||
warnx("Failed to generate the key verification pattern: %s",
|
||||
strerror(-rc));
|
||||
warnx("Make sure that kernel module 'paes_s390' is loaded and "
|
||||
"that the 'paes' cipher is available");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = properties_save(key_props, filenames->info_filename, 1);
|
||||
if (rc != 0) {
|
||||
pr_verbose(keystore,
|
||||
"Key info file '%s' could not be written: %s",
|
||||
info_filename, strerror(-rc));
|
||||
filenames->info_filename, strerror(-rc));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = _keystore_set_file_permission(keystore, info_filename);
|
||||
rc = _keystore_set_file_permission(keystore, filenames->info_filename);
|
||||
if (rc != 0) {
|
||||
remove(info_filename);
|
||||
remove(filenames->info_filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1519,8 +1601,7 @@ int keystore_generate_key(struct keystore *keystore, const char *name,
|
||||
if (rc != 0)
|
||||
goto out_free_props;
|
||||
|
||||
rc = _keystore_create_info_file(keystore, name,
|
||||
file_names.info_filename,
|
||||
rc = _keystore_create_info_file(keystore, name, &file_names,
|
||||
description, volumes, apqns,
|
||||
sector_size);
|
||||
if (rc != 0)
|
||||
@@ -1603,8 +1684,7 @@ int keystore_import_key(struct keystore *keystore, const char *name,
|
||||
if (rc != 0)
|
||||
goto out_free_props;
|
||||
|
||||
rc = _keystore_create_info_file(keystore, name,
|
||||
file_names.info_filename,
|
||||
rc = _keystore_create_info_file(keystore, name, &file_names,
|
||||
description, volumes, apqns,
|
||||
sector_size);
|
||||
if (rc != 0)
|
||||
@@ -1723,6 +1803,9 @@ int keystore_change_key(struct keystore *keystore, const char *name,
|
||||
}
|
||||
}
|
||||
|
||||
rc = _keystore_ensure_vp_exists(keystore, &file_names, key_props);
|
||||
/* ignore return code, vp generation might fail if key is not valid */
|
||||
|
||||
rc = _keystore_set_timestamp_property(key_props, PROP_NAME_CHANGE_TIME);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
@@ -1838,7 +1921,7 @@ static struct util_rec *_keystore_setup_record(bool validation)
|
||||
{
|
||||
struct util_rec *rec;
|
||||
|
||||
rec = util_rec_new_long("-", ":", REC_KEY, 23, 54);
|
||||
rec = util_rec_new_long("-", ":", REC_KEY, 28, 54);
|
||||
util_rec_def(rec, REC_KEY, UTIL_REC_ALIGN_LEFT, 54, REC_KEY);
|
||||
if (validation)
|
||||
util_rec_def(rec, REC_STATUS, UTIL_REC_ALIGN_LEFT, 54,
|
||||
@@ -1858,6 +1941,7 @@ static struct util_rec *_keystore_setup_record(bool validation)
|
||||
util_rec_def(rec, REC_KEY_FILE, UTIL_REC_ALIGN_LEFT, 54, REC_KEY_FILE);
|
||||
util_rec_def(rec, REC_SECTOR_SIZE, UTIL_REC_ALIGN_LEFT, 54,
|
||||
REC_SECTOR_SIZE);
|
||||
util_rec_def(rec, REC_KEY_VP, UTIL_REC_ALIGN_LEFT, 54, REC_KEY_VP);
|
||||
util_rec_def(rec, REC_CREATION_TIME, UTIL_REC_ALIGN_LEFT, 54,
|
||||
REC_CREATION_TIME);
|
||||
util_rec_def(rec, REC_CHANGE_TIME, UTIL_REC_ALIGN_LEFT, 54,
|
||||
@@ -1876,6 +1960,7 @@ static void _keystore_print_record(struct util_rec *rec,
|
||||
size_t clear_key_bitsize, bool valid,
|
||||
bool is_old_mk, bool reenc_pending)
|
||||
{
|
||||
char temp_vp[VERIFICATION_PATTERN_LEN + 2];
|
||||
char *volumes_argz = NULL;
|
||||
size_t volumes_argz_len;
|
||||
char *apqns_argz = NULL;
|
||||
@@ -1888,6 +1973,8 @@ static void _keystore_print_record(struct util_rec *rec,
|
||||
char *change;
|
||||
char *apqns;
|
||||
char *temp;
|
||||
char *vp;
|
||||
int len;
|
||||
|
||||
description = properties_get(properties, PROP_NAME_DESCRIPTION);
|
||||
volumes = properties_get(properties, PROP_NAME_VOLUMES);
|
||||
@@ -1913,6 +2000,7 @@ static void _keystore_print_record(struct util_rec *rec,
|
||||
creation = properties_get(properties, PROP_NAME_CREATION_TIME);
|
||||
change = properties_get(properties, PROP_NAME_CHANGE_TIME);
|
||||
reencipher = properties_get(properties, PROP_NAME_REENC_TIME);
|
||||
vp = properties_get(properties, PROP_NAME_KEY_VP);
|
||||
|
||||
util_rec_set(rec, REC_KEY, name);
|
||||
if (validation)
|
||||
@@ -1951,6 +2039,15 @@ static void _keystore_print_record(struct util_rec *rec,
|
||||
else
|
||||
util_rec_set(rec, REC_SECTOR_SIZE, "%lu bytes",
|
||||
sector_size);
|
||||
if (vp != NULL) {
|
||||
len = sprintf(temp_vp, "%.*s%c%.*s",
|
||||
VERIFICATION_PATTERN_LEN / 2, vp,
|
||||
'\0', VERIFICATION_PATTERN_LEN / 2,
|
||||
&vp[VERIFICATION_PATTERN_LEN / 2]);
|
||||
util_rec_set_argz(rec, REC_KEY_VP, temp_vp, len + 1);
|
||||
} else {
|
||||
util_rec_set(rec, REC_KEY_VP, "(not available)");
|
||||
}
|
||||
util_rec_set(rec, REC_CREATION_TIME, creation);
|
||||
util_rec_set(rec, REC_CHANGE_TIME,
|
||||
change != NULL ? change : "(never)");
|
||||
@@ -1976,6 +2073,8 @@ static void _keystore_print_record(struct util_rec *rec,
|
||||
free(change);
|
||||
if (reencipher != NULL)
|
||||
free(reencipher);
|
||||
if (vp != NULL)
|
||||
free(vp);
|
||||
}
|
||||
|
||||
struct validate_info {
|
||||
@@ -2404,6 +2503,17 @@ static int _keystore_process_reencipher(struct keystore *keystore,
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
|
||||
rc = _keystore_ensure_vp_exists(keystore, file_names,
|
||||
properties);
|
||||
if (rc != 0) {
|
||||
warnx("Failed to generate the key verification pattern "
|
||||
"for key '%s': %s", file_names->skey_filename,
|
||||
strerror(-rc));
|
||||
warnx("Make sure that kernel module 'paes_s390' is loaded and "
|
||||
"that the 'paes' cipher is available");
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = properties_save(properties, file_names->info_filename, 1);
|
||||
if (rc != 0) {
|
||||
pr_verbose(keystore,
|
||||
@@ -3040,7 +3150,7 @@ static int _keystore_process_crypttab(struct keystore *UNUSED(keystore),
|
||||
"At the time this utility was developed, systemd's "
|
||||
"support of crypttab did not support to specify a "
|
||||
"sector size with plain dm-crypt devices. The generated "
|
||||
"crypttab entry may or may not work, and may need "
|
||||
"crypttab entry might or might not work, and might need "
|
||||
"manual adoptions.", volume, sector_size);
|
||||
util_print_indented(temp, 0);
|
||||
}
|
||||
|
||||
@@ -361,8 +361,8 @@ The
|
||||
command displays the attributes of the secure keys, such as key sizes,
|
||||
whether it is a secure key that can be used for the XTS cipher mode, the textual
|
||||
description, associated cryptographic adapters (APQNs) and volumes, the
|
||||
sector size, and timestamps for key creation, last modification and last
|
||||
re-encipherment.
|
||||
sector size, the key verification pattern, and timestamps for key creation, last
|
||||
modification and last re-encipherment.
|
||||
.
|
||||
.SS "Remove existing AES secure keys from the secure key repository"
|
||||
.
|
||||
|
||||
27
zkey/zkey.c
27
zkey/zkey.c
@@ -1057,6 +1057,7 @@ static int command_reencipher(void)
|
||||
*/
|
||||
static int command_validate_file(void)
|
||||
{
|
||||
char vp[VERIFICATION_PATTERN_LEN];
|
||||
size_t secure_key_size;
|
||||
size_t clear_key_size;
|
||||
u8 *secure_key;
|
||||
@@ -1089,14 +1090,30 @@ static int command_validate_file(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = generate_key_verification_pattern((char *)secure_key,
|
||||
secure_key_size, vp, sizeof(vp),
|
||||
g.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");
|
||||
rc = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
printf("Validation of secure key in file '%s':\n", g.pos_arg);
|
||||
printf(" Status: Valid\n");
|
||||
printf(" Secure key size: %lu bytes\n", secure_key_size);
|
||||
printf(" Clear key size: %lu bits\n", clear_key_size);
|
||||
printf(" XTS type key: %s\n",
|
||||
printf(" Status: Valid\n");
|
||||
printf(" Secure key size: %lu bytes\n", secure_key_size);
|
||||
printf(" Clear key size: %lu bits\n", clear_key_size);
|
||||
printf(" XTS type key: %s\n",
|
||||
secure_key_size > SECURE_KEY_SIZE ? "Yes" : "No");
|
||||
printf(" Encrypted with: %s CCA master key\n",
|
||||
printf(" Enciphered with: %s CCA master key\n",
|
||||
is_old_mk ? "OLD" : "CURRENT");
|
||||
printf(" Verification pattern: %.*s\n", VERIFICATION_PATTERN_LEN / 2,
|
||||
vp);
|
||||
printf(" %.*s\n", VERIFICATION_PATTERN_LEN / 2,
|
||||
&vp[VERIFICATION_PATTERN_LEN / 2]);
|
||||
|
||||
out:
|
||||
free(secure_key);
|
||||
|
||||
Reference in New Issue
Block a user