mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zkey: Add support to store LUKS2 dummy passphrase in key repository
Extend zkey to allow to store a (dummy) LUKS2 passphrase together with a secure key, for use with LUKS2 volumes. That way, when the repository is backed up, or archived, also the passphrases of the associated LUKS2 volumes are backed up, or archived, and thus can not be forgotten. This passphrase is then used in generated commands to format and open the LUKS2 volumes. Because of the use of secure keys to encrypt the volumes, the LUKS2 passphrase is of no or less relevance for security. It is therefore OK to store the passphrase in clear text in the key repository, and also use them in /etc/crypttab. Therefore, the passphrase could actually be a trivial passphrase, or a dummy passphrase. Note: Such a dummy passphrase is NOT considered a secret that needs to be protected. If for a certain usage the passphrase is of relevance for security, then the zkey dummy passphrase option must not be used to store the passphrase. Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com> Reviewed-by: Juergen Christ <jchrist@linux.ibm.com> Reviewed-by: Harald Freudenberger <freude@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
c239d99379
commit
7c47ea8e09
413
zkey/keystore.c
413
zkey/keystore.c
@@ -40,12 +40,16 @@ struct key_filenames {
|
||||
char *skey_filename;
|
||||
char *info_filename;
|
||||
char *renc_filename;
|
||||
char *pass_filename;
|
||||
};
|
||||
|
||||
#define FILE_EXTENSION_LEN 5
|
||||
#define SKEY_FILE_EXTENSION ".skey"
|
||||
#define INFO_FILE_EXTENSION ".info"
|
||||
#define RENC_FILE_EXTENSION ".renc"
|
||||
#define PASS_FILE_EXTENSION ".pass"
|
||||
|
||||
#define DUMMY_PASSPHRASE_LEN 16
|
||||
|
||||
#define LOCK_FILE_NAME ".lock"
|
||||
|
||||
@@ -76,6 +80,7 @@ struct key_filenames {
|
||||
#define REC_VOLUME_TYPE "Volume type"
|
||||
#define REC_KMS "KMS"
|
||||
#define REC_KMS_KEY_LABEL "KMS key label"
|
||||
#define REC_PASSPHRASE_FILE "Dummy passphrase"
|
||||
|
||||
#define pr_verbose(keystore, fmt...) do { \
|
||||
if (keystore->verbose) \
|
||||
@@ -110,6 +115,8 @@ static int _keystore_get_key_filenames(struct keystore *keystore,
|
||||
name, INFO_FILE_EXTENSION);
|
||||
util_asprintf(&names->renc_filename, "%s/%s%s", keystore->directory,
|
||||
name, RENC_FILE_EXTENSION);
|
||||
util_asprintf(&names->pass_filename, "%s/%s%s", keystore->directory,
|
||||
name, PASS_FILE_EXTENSION);
|
||||
|
||||
pr_verbose(keystore, "File names for key '%s': '%s' and '%s'", name,
|
||||
names->skey_filename, names->info_filename);
|
||||
@@ -128,6 +135,18 @@ static int _keystore_reencipher_key_exists(struct key_filenames *file_names)
|
||||
return util_path_is_reg_file("%s", file_names->renc_filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the .pass file exists.
|
||||
*
|
||||
* @param[in] file_names names of the files
|
||||
*
|
||||
* @returns 1 if the file exist, 0 if the file do not exist
|
||||
*/
|
||||
static int _keystore_passphrase_file_exists(struct key_filenames *file_names)
|
||||
{
|
||||
return util_path_is_reg_file("%s", file_names->pass_filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if both, the .skey and the .info (and .renc) files exist.
|
||||
*
|
||||
@@ -146,7 +165,8 @@ static int _keystore_exists_keyfiles(struct key_filenames *file_names)
|
||||
if (rc_skey && rc_info)
|
||||
return 1;
|
||||
if (!rc_skey && !rc_info &&
|
||||
_keystore_reencipher_key_exists(file_names) == 0)
|
||||
_keystore_reencipher_key_exists(file_names) == 0 &&
|
||||
_keystore_passphrase_file_exists(file_names) == 0)
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
@@ -220,6 +240,8 @@ static void _keystore_free_key_filenames(struct key_filenames *names)
|
||||
free(names->info_filename);
|
||||
if (names->renc_filename)
|
||||
free(names->renc_filename);
|
||||
if (names->pass_filename)
|
||||
free(names->pass_filename);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -985,7 +1007,7 @@ static int _keystore_process_filtered(struct keystore *keystore,
|
||||
process_key_t process_func,
|
||||
void *process_private)
|
||||
{
|
||||
struct key_filenames file_names = { NULL, NULL, NULL };
|
||||
struct key_filenames file_names = { 0 };
|
||||
char **apqn_filter_list = NULL;
|
||||
char **vol_filter_list = NULL;
|
||||
struct properties *key_props;
|
||||
@@ -1593,6 +1615,129 @@ static int _keystore_set_default_properties(struct properties *key_props)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate, Set or remove a dummy LUKS2 passphrase of a key.
|
||||
*
|
||||
* @param[in] keystore the key store
|
||||
* @param[in] name the name of the key
|
||||
* @param[in] file_names the file names of the key
|
||||
* @param[in] properties the properties of the key
|
||||
* @param[in] prompt if true, prompt for removal (if passphrase exists)
|
||||
*
|
||||
* @returns 0 on success, or a negative errno value on error
|
||||
*/
|
||||
static int _keystore_remove_passphrase(struct keystore *keystore,
|
||||
const char *name,
|
||||
const struct key_filenames *filenames,
|
||||
struct properties *properties,
|
||||
bool prompt)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (_keystore_passphrase_file_exists((struct key_filenames *)filenames)
|
||||
&& prompt) {
|
||||
util_print_indented("ATTENTION: When you remove the LUKS2 "
|
||||
"dummy passphrase of a key, you might no "
|
||||
"longer be able to open the LUKS2 volumes "
|
||||
"associated with the key, unless you still "
|
||||
"know a passphrase of one of the key slots "
|
||||
"of these volumes!", 0);
|
||||
_keystore_msg_for_volumes("The following volumes are encrypted "
|
||||
"with this key:", properties, NULL);
|
||||
printf("%s: Remove passphrase for key '%s' [y/N]? ",
|
||||
program_invocation_short_name, name);
|
||||
if (!prompt_for_yes(keystore->verbose)) {
|
||||
warnx("Operation aborted");
|
||||
return -ECANCELED;
|
||||
}
|
||||
}
|
||||
|
||||
rc = remove(filenames->pass_filename);
|
||||
if (rc != 0 && errno != ENOENT) {
|
||||
rc = -errno;
|
||||
warnx("Failed to remove file '%s': %s",
|
||||
filenames->pass_filename, strerror(-rc));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate, Set or remove a dummy LUKS2 passphrase of a key.
|
||||
*
|
||||
* @param[in] keystore the key store
|
||||
* @param[in] name the name of the key
|
||||
* @param[in] passphrase_file the file name of a file containing a passphrase
|
||||
* for LUKS2. If NULKL, the passphrase is generated by
|
||||
* random.
|
||||
* @param[in] file_names the file names of the key
|
||||
* @param[in] properties the properties of the key
|
||||
* @param[in] prompt if true, prompt for change, if passphrase exists
|
||||
* already
|
||||
*
|
||||
* @returns 0 on success, or a negative errno value on error
|
||||
*/
|
||||
static int _keystore_set_passphrase(struct keystore *keystore,
|
||||
const char *name,
|
||||
const char *passphrase_file,
|
||||
const struct key_filenames *filenames,
|
||||
struct properties *properties,
|
||||
bool prompt)
|
||||
{
|
||||
char *volume_type;
|
||||
int rc;
|
||||
|
||||
if (_keystore_passphrase_file_exists((struct key_filenames *)filenames)
|
||||
&& prompt) {
|
||||
warnx("There is already a LUKS2 dummy passphrase associated "
|
||||
"with key '%s'.", name);
|
||||
util_print_indented("To change a dummy passphrase of a key, "
|
||||
"first remove the currently associated "
|
||||
"passphrase with command 'zkey change "
|
||||
"--name <key> --remove-dummy-passphrase' "
|
||||
"and then set the new dummy passphrase for "
|
||||
"the key.", 0);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
volume_type = _keystore_get_volume_type(properties);
|
||||
if (volume_type == NULL) {
|
||||
pr_verbose(keystore, "No volume type available");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (strcasecmp(volume_type, VOLUME_TYPE_LUKS2) != 0) {
|
||||
warnx("The LUKS2 dummy passphrase can only be set for keys "
|
||||
"with a volume type of LUKS2.");
|
||||
free(volume_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
free(volume_type);
|
||||
|
||||
if (passphrase_file != NULL) {
|
||||
rc = copy_file(passphrase_file, filenames->pass_filename, 0);
|
||||
if (rc != 0) {
|
||||
warnx("Failed to copy the passphrase phase '%s': %s",
|
||||
passphrase_file, strerror(-rc));
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
rc = copy_file("/dev/urandom", filenames->pass_filename,
|
||||
DUMMY_PASSPHRASE_LEN);
|
||||
if (rc != 0) {
|
||||
warnx("Failed to generate the dummy passphrase: %s",
|
||||
strerror(-rc));
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
rc = _keystore_set_file_permission(keystore, filenames->pass_filename);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the key properties for a key
|
||||
*
|
||||
@@ -1615,6 +1760,8 @@ static int _keystore_set_default_properties(struct properties *key_props)
|
||||
* @param[in] key_type the type of the key
|
||||
* @param[in] kms the name of the KMS plugin, or NULL if no KMS is bound
|
||||
* @param[out] props the properties object is allocated and returned
|
||||
*
|
||||
* @returns 0 on success, or a negative errno value on error
|
||||
*/
|
||||
static int _keystore_create_info_props(struct keystore *keystore,
|
||||
const char *name,
|
||||
@@ -1721,7 +1868,7 @@ out:
|
||||
*
|
||||
* @param[in] keystore the key store
|
||||
* @param[in] name the name of the key
|
||||
* @param[in] info_filename the file name of the key info file
|
||||
* @param[in] filenames the file names of the key files
|
||||
* @param[in] description textual description of the key (optional, can be NULL)
|
||||
* @param[in] volumes a comma separated list of volumes associated with this
|
||||
* key (optional, can be NULL)
|
||||
@@ -1735,7 +1882,12 @@ out:
|
||||
* default is used.
|
||||
* @param[in] volume_type the type of volume
|
||||
* @param[in] key_type the type of the key
|
||||
* @param[in] gen_passphrase if true, generate a (dummy) passphrase for LUKS2
|
||||
* @param[in] passphrase_file the file name of a file containing a passphrase
|
||||
* for LUKS2 (optional, can be NULL)
|
||||
* @param[in] kms the name of the KMS plugin, or NULL if no KMS is bound
|
||||
*
|
||||
* @returns 0 on success, or a negative errno value on error
|
||||
*/
|
||||
static int _keystore_create_info_file(struct keystore *keystore,
|
||||
const char *name,
|
||||
@@ -1746,6 +1898,8 @@ static int _keystore_create_info_file(struct keystore *keystore,
|
||||
size_t sector_size,
|
||||
const char *volume_type,
|
||||
const char *key_type,
|
||||
bool gen_passphrase,
|
||||
const char *passphrase_file,
|
||||
const char *kms)
|
||||
{
|
||||
struct properties *key_props = NULL;
|
||||
@@ -1758,12 +1912,24 @@ static int _keystore_create_info_file(struct keystore *keystore,
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
if (gen_passphrase || passphrase_file != NULL) {
|
||||
rc = _keystore_set_passphrase(keystore, name, gen_passphrase ?
|
||||
NULL : passphrase_file,
|
||||
filenames, key_props, true);
|
||||
if (rc != 0) {
|
||||
pr_verbose(keystore, "Failed to set the passphrase: %s",
|
||||
strerror(-rc));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
remove(filenames->pass_filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1772,12 +1938,14 @@ static int _keystore_create_info_file(struct keystore *keystore,
|
||||
pr_verbose(keystore,
|
||||
"Key info file '%s' could not be written: %s",
|
||||
filenames->info_filename, strerror(-rc));
|
||||
remove(filenames->pass_filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = _keystore_set_file_permission(keystore, filenames->info_filename);
|
||||
if (rc != 0) {
|
||||
remove(filenames->info_filename);
|
||||
remove(filenames->pass_filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1809,6 +1977,9 @@ out:
|
||||
* if NULL, the secure key is generated by random.
|
||||
* @param[in] volume_type the type of volume
|
||||
* @param[in] key_type the type of the key
|
||||
* @param[in] gen_passphrase if true, generate a (dummy) passphrase for LUKS2
|
||||
* @param[in] passphrase_file the file name of a file containing a passphrase
|
||||
* for LUKS2 (optional, can be NULL)
|
||||
* @param[in] pkey_fd the file descriptor of /dev/pkey
|
||||
*
|
||||
* @returns 0 for success or a negative errno in case of an error
|
||||
@@ -1818,9 +1989,10 @@ int keystore_generate_key(struct keystore *keystore, const char *name,
|
||||
const char *apqns, bool noapqncheck,
|
||||
size_t sector_size, size_t keybits, bool xts,
|
||||
const char *clear_key_file, const char *volume_type,
|
||||
const char *key_type, int pkey_fd)
|
||||
const char *key_type, bool gen_passphrase,
|
||||
const char *passphrase_file, int pkey_fd)
|
||||
{
|
||||
struct key_filenames file_names = { NULL, NULL, NULL };
|
||||
struct key_filenames file_names = { 0 };
|
||||
struct properties *key_props = NULL;
|
||||
char **apqn_list = NULL;
|
||||
int rc;
|
||||
@@ -1880,7 +2052,8 @@ int keystore_generate_key(struct keystore *keystore, const char *name,
|
||||
rc = _keystore_create_info_file(keystore, name, &file_names,
|
||||
description, volumes, apqns,
|
||||
noapqncheck, sector_size, volume_type,
|
||||
key_type, NULL);
|
||||
key_type, gen_passphrase,
|
||||
passphrase_file, NULL);
|
||||
if (rc != 0)
|
||||
goto out_free_props;
|
||||
|
||||
@@ -1921,6 +2094,9 @@ out_free_key_filenames:
|
||||
* @param[in] xts if true, an XTS key is generated
|
||||
* @param[in] volume_type the type of volume
|
||||
* @param[in] key_type the type of the key (can be NULL)
|
||||
* @param[in] gen_passphrase if true, generate a (dummy) passphrase for LUKS2
|
||||
* @param[in] passphrase_file the file name of a file containing a passphrase
|
||||
* for LUKS2 (optional, can be NULL)
|
||||
* @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
|
||||
@@ -1931,10 +2107,11 @@ int keystore_generate_key_kms(struct keystore *keystore, const char *name,
|
||||
const char *description, const char *volumes,
|
||||
size_t sector_size, size_t keybits, bool xts,
|
||||
const char *volume_type, const char *key_type,
|
||||
bool gen_passphrase, const char *passphrase_file,
|
||||
struct kms_option *kms_options,
|
||||
size_t num_kms_options)
|
||||
{
|
||||
struct key_filenames file_names = { NULL, NULL, NULL };
|
||||
struct key_filenames file_names = { 0 };
|
||||
struct properties *key_props = NULL;
|
||||
struct kms_info *kms_info;
|
||||
char *apqns = NULL;
|
||||
@@ -2000,8 +2177,21 @@ int keystore_generate_key_kms(struct keystore *keystore, const char *name,
|
||||
if (rc != 0)
|
||||
goto out_free_key_filenames;
|
||||
|
||||
if (gen_passphrase || passphrase_file != NULL) {
|
||||
rc = _keystore_set_passphrase(keystore, name, gen_passphrase ?
|
||||
NULL : passphrase_file,
|
||||
&file_names, key_props, true);
|
||||
if (rc != 0) {
|
||||
pr_verbose(keystore, "Failed to set the passphrase: %s",
|
||||
strerror(-rc));
|
||||
goto out_free_key_filenames;
|
||||
}
|
||||
}
|
||||
|
||||
rc = generate_kms_key(kms_info, name, key_type, key_props, xts,
|
||||
keybits, file_names.skey_filename,
|
||||
_keystore_passphrase_file_exists(&file_names) ?
|
||||
file_names.pass_filename : NULL,
|
||||
kms_options, num_kms_options, keystore->verbose);
|
||||
if (rc != 0) {
|
||||
warnx("KMS plugin '%s' failed to generate key '%s': %s",
|
||||
@@ -2048,8 +2238,10 @@ out_del_info_file:
|
||||
out_free_props:
|
||||
if (key_props != NULL)
|
||||
properties_free(key_props);
|
||||
if (rc != 0)
|
||||
if (rc != 0) {
|
||||
remove(file_names.skey_filename);
|
||||
remove(file_names.pass_filename);
|
||||
}
|
||||
out_free_key_filenames:
|
||||
_keystore_free_key_filenames(&file_names);
|
||||
if (apqns != NULL)
|
||||
@@ -2081,6 +2273,9 @@ out_free_key_filenames:
|
||||
* default is used.
|
||||
* @param[in] import_file The name of a secure key containing the key to import
|
||||
* @param[in] volume_type the type of volume
|
||||
* @param[in] gen_passphrase if true, generate a (dummy) passphrase for LUKS2
|
||||
* @param[in] passphrase_file the file name of a file containing a passphrase
|
||||
* for LUKS2 (optional, can be NULL)
|
||||
* @param[in] lib the external library struct
|
||||
*
|
||||
* @returns 0 for success or a negative errno in case of an error
|
||||
@@ -2089,9 +2284,10 @@ int keystore_import_key(struct keystore *keystore, const char *name,
|
||||
const char *description, const char *volumes,
|
||||
const char *apqns, bool noapqncheck, size_t sector_size,
|
||||
const char *import_file, const char *volume_type,
|
||||
bool gen_passphrase, const char *passphrase_file,
|
||||
struct ext_lib *lib)
|
||||
{
|
||||
struct key_filenames file_names = { NULL, NULL, NULL };
|
||||
struct key_filenames file_names = { 0 };
|
||||
struct properties *key_props = NULL;
|
||||
size_t secure_key_size;
|
||||
const char *key_type;
|
||||
@@ -2206,7 +2402,8 @@ int keystore_import_key(struct keystore *keystore, const char *name,
|
||||
rc = _keystore_create_info_file(keystore, name, &file_names,
|
||||
description, volumes, apqns,
|
||||
noapqncheck, sector_size, volume_type,
|
||||
key_type, NULL);
|
||||
key_type, gen_passphrase,
|
||||
passphrase_file, NULL);
|
||||
if (rc != 0)
|
||||
goto out_free_props;
|
||||
|
||||
@@ -2256,23 +2453,33 @@ out_free_key_filenames:
|
||||
* not be changed.
|
||||
* @param[in] volume_type the type of volume. If NULL then the volume type is
|
||||
* not changed.
|
||||
* *
|
||||
* @param[in] gen_passphrase if true, generate a (dummy) passphrase for LUKS2
|
||||
* @param[in] passphrase_file the file name of a file containing a passphrase
|
||||
* for LUKS2 (optional, can be NULL)
|
||||
* @param[in] remove_passphrase if true, remove the (dummy) passphrase
|
||||
* @param[in] quiet if true no confirmation prompt is shown when removing
|
||||
* a (dummy) passphrase
|
||||
*
|
||||
* @returns 0 for success or a negative errno in case of an error
|
||||
*
|
||||
*/
|
||||
int keystore_change_key(struct keystore *keystore, const char *name,
|
||||
const char *description, const char *volumes,
|
||||
const char *apqns, bool noapqncheck,
|
||||
long int sector_size, const char *volume_type)
|
||||
long int sector_size, const char *volume_type,
|
||||
bool gen_passphrase, const char *passphrase_file,
|
||||
bool remove_passphrase, bool quiet)
|
||||
{
|
||||
struct volume_check vol_check = { .keystore = keystore, .name = name,
|
||||
.set = 0, .nocheck = 0 };
|
||||
struct apqn_check apqn_check = { .noonlinecheck = noapqncheck,
|
||||
.nomsg = 0 };
|
||||
struct key_filenames file_names = { NULL, NULL, NULL };
|
||||
struct key_filenames file_names = { 0 };
|
||||
struct properties *key_props = NULL;
|
||||
const char **passphrase_upd = NULL;
|
||||
char *upd_volume_type = NULL;
|
||||
char *apqns_prop, *key_type;
|
||||
const char *null_ptr = NULL;
|
||||
char *upd_volumes = NULL;
|
||||
size_t secure_key_size;
|
||||
u8 mkvp[MKVP_LENGTH];
|
||||
@@ -2401,6 +2608,38 @@ int keystore_change_key(struct keystore *keystore, const char *name,
|
||||
|
||||
upd_volume_type = properties_get(key_props,
|
||||
PROP_NAME_VOLUME_TYPE);
|
||||
|
||||
/* Remove dummy passphrase if change to PLAIN volume type */
|
||||
if (strcasecmp(volume_type, VOLUME_TYPE_LUKS2) != 0 &&
|
||||
_keystore_passphrase_file_exists(&file_names)) {
|
||||
rc = _keystore_remove_passphrase(keystore, name,
|
||||
&file_names, key_props,
|
||||
false);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
|
||||
passphrase_upd = &null_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (gen_passphrase || passphrase_file != NULL) {
|
||||
rc = _keystore_set_passphrase(keystore, name, gen_passphrase ?
|
||||
NULL : passphrase_file,
|
||||
&file_names, key_props, true);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
|
||||
passphrase_upd = (const char **)&file_names.pass_filename;
|
||||
}
|
||||
|
||||
if (remove_passphrase) {
|
||||
if (_keystore_passphrase_file_exists(&file_names))
|
||||
passphrase_upd = &null_ptr;
|
||||
|
||||
rc = _keystore_remove_passphrase(keystore, name, &file_names,
|
||||
key_props, !quiet);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (kms_bound) {
|
||||
@@ -2412,7 +2651,7 @@ int keystore_change_key(struct keystore *keystore, const char *name,
|
||||
description, upd_volumes,
|
||||
upd_volume_type, sector_size >= 0 ?
|
||||
sect_size : NULL,
|
||||
keystore->verbose);
|
||||
passphrase_upd, keystore->verbose);
|
||||
if (rc != 0) {
|
||||
warnx("KMS plugin '%s' failed to set key properties "
|
||||
"for key '%s': %s",
|
||||
@@ -2441,6 +2680,8 @@ int keystore_change_key(struct keystore *keystore, const char *name,
|
||||
pr_verbose(keystore, "Successfully changed key '%s'", name);
|
||||
|
||||
out:
|
||||
if (rc != 0 && passphrase_upd != NULL && *passphrase_upd != NULL)
|
||||
remove(*passphrase_upd);
|
||||
_keystore_free_key_filenames(&file_names);
|
||||
if (key_props != NULL)
|
||||
properties_free(key_props);
|
||||
@@ -2467,10 +2708,11 @@ out:
|
||||
int keystore_rename_key(struct keystore *keystore, const char *name,
|
||||
const char *newname)
|
||||
{
|
||||
struct key_filenames file_names = { NULL, NULL, NULL };
|
||||
struct key_filenames new_names = { NULL, NULL, NULL };
|
||||
struct key_filenames file_names = { 0 };
|
||||
struct key_filenames new_names = { 0 };
|
||||
struct properties *key_props = NULL;
|
||||
bool reenc_exists = false;
|
||||
bool pass_exists = false;
|
||||
char *msg;
|
||||
int rc;
|
||||
|
||||
@@ -2516,6 +2758,16 @@ int keystore_rename_key(struct keystore *keystore, const char *name,
|
||||
goto out_rename_info;
|
||||
}
|
||||
}
|
||||
if (_keystore_passphrase_file_exists(&file_names)) {
|
||||
pass_exists = true;
|
||||
if (rename(file_names.pass_filename,
|
||||
new_names.pass_filename) != 0) {
|
||||
rc = -errno;
|
||||
pr_verbose(keystore, "Failed to rename '%s': %s",
|
||||
file_names.pass_filename, strerror(-rc));
|
||||
goto out_rename_info;
|
||||
}
|
||||
}
|
||||
|
||||
key_props = properties_new();
|
||||
rc = properties_load(key_props, new_names.info_filename, 1);
|
||||
@@ -2531,7 +2783,7 @@ int keystore_rename_key(struct keystore *keystore, const char *name,
|
||||
|
||||
rc = set_kms_key_properties(keystore->kms_info, key_props,
|
||||
newname, NULL, NULL, NULL, NULL,
|
||||
keystore->verbose);
|
||||
NULL, keystore->verbose);
|
||||
if (rc != 0) {
|
||||
warnx("KMS plugin '%s' failed to set key properties "
|
||||
"for key '%s': %s",
|
||||
@@ -2549,6 +2801,16 @@ int keystore_rename_key(struct keystore *keystore, const char *name,
|
||||
_keystore_msg_for_volumes(msg, key_props, VOLUME_TYPE_PLAIN);
|
||||
free(msg);
|
||||
|
||||
if (_keystore_passphrase_file_exists(&new_names)) {
|
||||
util_asprintf(&msg, "The following volumes are associated with "
|
||||
"the renamed key '%s'. You should adjust the "
|
||||
"corresponding crypttab entries to use the new "
|
||||
"dummy passphrase file name '%s'.", newname,
|
||||
new_names.pass_filename);
|
||||
_keystore_msg_for_volumes(msg, key_props, VOLUME_TYPE_LUKS2);
|
||||
free(msg);
|
||||
}
|
||||
|
||||
pr_verbose(keystore, "Successfully renamed key '%s' to '%s'", name,
|
||||
newname);
|
||||
|
||||
@@ -2557,6 +2819,8 @@ int keystore_rename_key(struct keystore *keystore, const char *name,
|
||||
out_rename_info:
|
||||
if (reenc_exists)
|
||||
rename(file_names.renc_filename, new_names.renc_filename);
|
||||
if (pass_exists)
|
||||
rename(file_names.pass_filename, new_names.pass_filename);
|
||||
rename(new_names.info_filename, file_names.info_filename);
|
||||
|
||||
out_rename_skey:
|
||||
@@ -2613,6 +2877,8 @@ static struct util_rec *_keystore_setup_record(bool validation)
|
||||
util_rec_def(rec, REC_KMS, UTIL_REC_ALIGN_LEFT, 54, REC_KMS);
|
||||
util_rec_def(rec, REC_KMS_KEY_LABEL, UTIL_REC_ALIGN_LEFT, 54,
|
||||
REC_KMS_KEY_LABEL);
|
||||
util_rec_def(rec, REC_PASSPHRASE_FILE, UTIL_REC_ALIGN_LEFT, 54,
|
||||
REC_PASSPHRASE_FILE);
|
||||
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,
|
||||
@@ -2629,7 +2895,8 @@ static void _keystore_print_record(struct util_rec *rec,
|
||||
bool validation, const char *skey_filename,
|
||||
size_t secure_key_size, bool is_xts,
|
||||
size_t clear_key_bitsize, bool valid,
|
||||
bool is_old_mk, bool reenc_pending, u8 *mkvp)
|
||||
bool is_old_mk, bool reenc_pending, u8 *mkvp,
|
||||
const char *pass_filename)
|
||||
{
|
||||
char temp_vp[VERIFICATION_PATTERN_LEN + 2];
|
||||
char *kms_xts_key1_label = NULL;
|
||||
@@ -2767,6 +3034,10 @@ static void _keystore_print_record(struct util_rec *rec,
|
||||
label_argz_len);
|
||||
else
|
||||
util_rec_set(rec, REC_KMS_KEY_LABEL, "(local)");
|
||||
if (pass_filename != NULL)
|
||||
util_rec_set(rec, REC_PASSPHRASE_FILE, pass_filename);
|
||||
else
|
||||
util_rec_set(rec, REC_PASSPHRASE_FILE, "(none)");
|
||||
util_rec_set(rec, REC_CREATION_TIME, creation);
|
||||
util_rec_set(rec, REC_CHANGE_TIME,
|
||||
change != NULL ? change : "(never)");
|
||||
@@ -2966,7 +3237,9 @@ static int _keystore_process_validate(struct keystore *keystore,
|
||||
is_xts_key(secure_key, secure_key_size),
|
||||
clear_key_bitsize, valid, is_old_mk,
|
||||
_keystore_reencipher_key_exists(file_names),
|
||||
mkvp);
|
||||
mkvp,
|
||||
_keystore_passphrase_file_exists(file_names) ?
|
||||
file_names->pass_filename : NULL);
|
||||
|
||||
if (valid && is_old_mk) {
|
||||
util_print_indented("WARNING: The secure key is currently "
|
||||
@@ -3434,8 +3707,8 @@ int keystore_copy_key(struct keystore *keystore, const char *name,
|
||||
{
|
||||
struct volume_check vol_check = { .keystore = keystore, .name = newname,
|
||||
.set = 0, .nocheck = 0 };
|
||||
struct key_filenames file_names = { NULL, NULL, NULL };
|
||||
struct key_filenames new_names = { NULL, NULL, NULL };
|
||||
struct key_filenames file_names = { 0 };
|
||||
struct key_filenames new_names = { 0 };
|
||||
struct properties *key_prop = NULL;
|
||||
size_t secure_key_size;
|
||||
bool kms_bound = false;
|
||||
@@ -3536,7 +3809,6 @@ int keystore_copy_key(struct keystore *keystore, const char *name,
|
||||
pr_verbose(keystore,
|
||||
"Key info file '%s' could not be written: %s",
|
||||
new_names.info_filename, strerror(-rc));
|
||||
remove(new_names.skey_filename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -3544,6 +3816,23 @@ int keystore_copy_key(struct keystore *keystore, const char *name,
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
|
||||
if (_keystore_passphrase_file_exists(&file_names)) {
|
||||
rc = copy_file(file_names.skey_filename,
|
||||
new_names.pass_filename, 0);
|
||||
if (rc != 0) {
|
||||
pr_verbose(keystore,
|
||||
"Passphrase file '%s' could not be copied: "
|
||||
"%s", new_names.pass_filename,
|
||||
strerror(-rc));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = _keystore_set_file_permission(keystore,
|
||||
file_names.pass_filename);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
pr_verbose(keystore, "Successfully copied key '%s' to '%s'", name,
|
||||
newname);
|
||||
|
||||
@@ -3551,6 +3840,7 @@ out:
|
||||
if (rc != 0) {
|
||||
remove(new_names.skey_filename);
|
||||
remove(new_names.info_filename);
|
||||
remove(new_names.pass_filename);
|
||||
}
|
||||
|
||||
_keystore_free_key_filenames(&file_names);
|
||||
@@ -3576,7 +3866,7 @@ out:
|
||||
int keystore_export_key(struct keystore *keystore, const char *name,
|
||||
const char *export_file)
|
||||
{
|
||||
struct key_filenames file_names = { NULL, NULL, NULL };
|
||||
struct key_filenames file_names = { 0 };
|
||||
size_t secure_key_size;
|
||||
u8 *secure_key;
|
||||
int rc;
|
||||
@@ -3675,7 +3965,7 @@ int keystore_remove_key(struct keystore *keystore, const char *name,
|
||||
bool quiet, struct kms_option *kms_options,
|
||||
size_t num_kms_options)
|
||||
{
|
||||
struct key_filenames file_names = { NULL, NULL, NULL };
|
||||
struct key_filenames file_names = { 0 };
|
||||
struct properties *key_props = NULL;
|
||||
int rc;
|
||||
|
||||
@@ -3739,6 +4029,13 @@ int keystore_remove_key(struct keystore *keystore, const char *name,
|
||||
file_names.renc_filename, strerror(-rc));
|
||||
}
|
||||
}
|
||||
if (_keystore_passphrase_file_exists(&file_names)) {
|
||||
if (remove(file_names.pass_filename) != 0) {
|
||||
rc = -errno;
|
||||
pr_verbose(keystore, "Failed to remove '%s': %s",
|
||||
file_names.pass_filename, strerror(-rc));
|
||||
}
|
||||
}
|
||||
pr_verbose(keystore, "Successfully removed key '%s'", name);
|
||||
|
||||
out:
|
||||
@@ -3794,7 +4091,9 @@ static int _keystore_display_key(struct keystore *keystore,
|
||||
is_xts_key(secure_key, secure_key_size),
|
||||
clear_key_bitsize, 0, 0,
|
||||
_keystore_reencipher_key_exists(file_names),
|
||||
NULL);
|
||||
NULL,
|
||||
_keystore_passphrase_file_exists(file_names) ?
|
||||
file_names->pass_filename : NULL);
|
||||
|
||||
out:
|
||||
free(secure_key);
|
||||
@@ -3910,6 +4209,7 @@ struct crypt_info {
|
||||
size_t key_file_size,
|
||||
size_t sector_size,
|
||||
const char *volume_type,
|
||||
const char *passphrase_file,
|
||||
struct crypt_info *info);
|
||||
};
|
||||
|
||||
@@ -3925,6 +4225,7 @@ struct crypt_info {
|
||||
* @param[in] key_file_size the size of the key file in bytes
|
||||
* @param[in] sector_size the sector size in bytes or 0 if not specified
|
||||
* @param[in] volume_type the volume type
|
||||
* @param[in] passphrase_file the passphrase file name (can be NULL)
|
||||
* @param[in] info processing info
|
||||
*
|
||||
* @returns 0 if successful, a negative errno value otherwise
|
||||
@@ -3937,6 +4238,7 @@ static int _keystore_process_cryptsetup(struct keystore *keystore,
|
||||
size_t key_file_size,
|
||||
size_t sector_size,
|
||||
const char *volume_type,
|
||||
const char *passphrase_file,
|
||||
struct crypt_info *info)
|
||||
{
|
||||
char *keyfile_opt = NULL, *offset_opt = NULL;
|
||||
@@ -3957,6 +4259,9 @@ static int _keystore_process_cryptsetup(struct keystore *keystore,
|
||||
if (info->keyfile_size > 0)
|
||||
util_asprintf(&size_opt, "--keyfile-size %lu ",
|
||||
info->keyfile_size);
|
||||
} else if (passphrase_file != NULL) {
|
||||
util_asprintf(&keyfile_opt, "--key-file '%s' ",
|
||||
passphrase_file);
|
||||
}
|
||||
if (info->tries > 0)
|
||||
util_asprintf(&tries_opt, "--tries %lu ", info->tries);
|
||||
@@ -4069,6 +4374,7 @@ static int _keystore_process_cryptsetup(struct keystore *keystore,
|
||||
* @param[in] key_file_size the size of the key file in bytes
|
||||
* @param[in] sector_size the sector size in bytes or 0 if not specified
|
||||
* @param[in] volume_type the volume type
|
||||
* @param[in] passphrase_file the passphrase file name (can be NULL)
|
||||
* @param[in] info processing info (not used here)
|
||||
*
|
||||
* @returns 0 if successful, a negative errno value otherwise
|
||||
@@ -4082,6 +4388,7 @@ static int _keystore_process_crypttab(struct keystore *UNUSED(keystore),
|
||||
size_t key_file_size,
|
||||
size_t sector_size,
|
||||
const char *volume_type,
|
||||
const char *passphrase_file,
|
||||
struct crypt_info *info)
|
||||
{
|
||||
char temp[1000];
|
||||
@@ -4105,14 +4412,19 @@ static int _keystore_process_crypttab(struct keystore *UNUSED(keystore),
|
||||
dmname, volume, key_file_name, cipher_spec,
|
||||
key_file_size * 8, sector_size > 0 ? temp : "");
|
||||
} else if (strcasecmp(volume_type, VOLUME_TYPE_LUKS2) == 0) {
|
||||
printf("%s\t%s\t%s\tluks", dmname, volume,
|
||||
info->keyfile != NULL ? info->keyfile : "none");
|
||||
if (info->keyfile != NULL) {
|
||||
printf("%s\t%s\t%s\tluks", dmname, volume,
|
||||
info->keyfile);
|
||||
if (info->keyfile_offset > 0)
|
||||
printf(",keyfile-offset=%lu",
|
||||
info->keyfile_offset);
|
||||
if (info->keyfile_size > 0)
|
||||
printf(",keyfile-size=%lu", info->keyfile_size);
|
||||
} else if (passphrase_file != NULL) {
|
||||
printf("%s\t%s\t%s\tluks", dmname, volume,
|
||||
passphrase_file);
|
||||
} else {
|
||||
printf("%s\t%s\tnone\tluks", dmname, volume);
|
||||
}
|
||||
if (info->tries > 0)
|
||||
printf(",tries=%lu", info->tries);
|
||||
@@ -4237,7 +4549,10 @@ static int _keystore_process_crypt(struct keystore *keystore,
|
||||
rc = info->process_func(keystore, vol, dmname,
|
||||
cipher_spec, file_names->skey_filename,
|
||||
secure_key_size, sector_size,
|
||||
volume_type, info);
|
||||
volume_type,
|
||||
_keystore_passphrase_file_exists(file_names) ?
|
||||
file_names->pass_filename : NULL,
|
||||
info);
|
||||
if (rc != 0)
|
||||
break;
|
||||
}
|
||||
@@ -4403,7 +4718,7 @@ int keystore_convert_key(struct keystore *keystore, const char *name,
|
||||
const char *key_type, bool noapqncheck, bool quiet,
|
||||
int pkey_fd, struct ext_lib *lib)
|
||||
{
|
||||
struct key_filenames file_names = { NULL, NULL, NULL };
|
||||
struct key_filenames file_names = { 0 };
|
||||
u8 output_key[2 * MAX_SECURE_KEY_SIZE];
|
||||
struct properties *properties = NULL;
|
||||
int rc, min_level, selected = 1;
|
||||
@@ -4920,6 +5235,7 @@ struct kms_import {
|
||||
* @param[in] volumes the associated volumes of the key (can be NULL)
|
||||
* @param[in] volume_type the volume type of the volume (can be NULL)
|
||||
* @param[in] sector_size the sector size of the volume (0 means default)
|
||||
* @param[in] passphrase the passphrase of the key (can be NULL)
|
||||
* @param[in] addl_info_argz an argz string containing additional KMS plugin
|
||||
* specific infos to be displayed, or NULL if none.
|
||||
* @param[in] addl_info_len length of the argz string in addl_info_argz
|
||||
@@ -4940,12 +5256,13 @@ static int _keystore_process_kms_import(const char *key1_id,
|
||||
const char *volumes,
|
||||
const char *volume_type,
|
||||
size_t sector_size,
|
||||
const char *passphrase,
|
||||
const char *UNUSED(addl_info_argz),
|
||||
size_t UNUSED(addl_info_len),
|
||||
void *private_data)
|
||||
{
|
||||
struct key_filenames file_names = { NULL, NULL, NULL };
|
||||
struct kms_import *import_data = private_data;
|
||||
struct key_filenames file_names = { 0 };
|
||||
u8 secure_key[2 * MAX_SECURE_KEY_SIZE];
|
||||
struct properties *key_props = NULL;
|
||||
char vp[VERIFICATION_PATTERN_LEN];
|
||||
@@ -5042,6 +5359,23 @@ prompt_alt_name:
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
|
||||
if (passphrase != NULL && volume_type != NULL &&
|
||||
strcasecmp(volume_type, VOLUME_TYPE_LUKS2) == 0) {
|
||||
rc = store_passphrase_from_base64(passphrase,
|
||||
file_names.pass_filename,
|
||||
keystore->verbose);
|
||||
if (rc != 0) {
|
||||
pr_verbose(keystore, "Failed to parse passphrase: %s",
|
||||
strerror(-rc));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = _keystore_set_file_permission(keystore,
|
||||
file_names.pass_filename);
|
||||
if (rc != 0)
|
||||
goto out_remove;
|
||||
}
|
||||
|
||||
rc = properties_set(key_props, xts ? PROP_NAME_KMS_XTS_KEY1_ID :
|
||||
PROP_NAME_KMS_KEY_ID, key1_id);
|
||||
if (rc != 0) {
|
||||
@@ -5267,7 +5601,9 @@ static int _keystore_refresh_kms_key(struct keystore *keystore,
|
||||
rc = refresh_kms_key(keystore->kms_info, properties,
|
||||
&description, &cipher, &iv_mode, &volumes,
|
||||
&volume_type, §or_size,
|
||||
file_names->skey_filename, keystore->verbose);
|
||||
file_names->skey_filename,
|
||||
file_names->pass_filename,
|
||||
keystore->verbose);
|
||||
if (rc != 0) {
|
||||
warnx("KMS plugin '%s' failed to refresh key '%s': %s",
|
||||
keystore->kms_info->plugin_name, name, strerror(-rc));
|
||||
@@ -5277,6 +5613,17 @@ static int _keystore_refresh_kms_key(struct keystore *keystore,
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = _keystore_set_file_permission(keystore, file_names->skey_filename);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
|
||||
if (_keystore_passphrase_file_exists(file_names)) {
|
||||
rc = _keystore_set_file_permission(keystore,
|
||||
file_names->pass_filename);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!refresh_data->refresh_properties)
|
||||
goto save_props;
|
||||
|
||||
@@ -5345,6 +5692,10 @@ save_props:
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = _keystore_set_file_permission(keystore, file_names->info_filename);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
|
||||
out:
|
||||
if (rc == 0) {
|
||||
printf("Successfully refreshed key '%s'\n", name);
|
||||
|
||||
Reference in New Issue
Block a user