libekmfweb: Re-encipher the identity key

The identity key of the client is a secure key enciphered with the
master key of a cryptographic adapter (APQN). When the master key of
the used APQNs is changed, the identity key must be re-enciphered
under the new master key.

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-04-23 15:41:12 +02:00
committed by Jan Höppner
parent 5fb30f1e6f
commit 1cdfb4946e
5 changed files with 355 additions and 1 deletions
+86
View File
@@ -1209,6 +1209,92 @@ int ekmf_generate_identity_key(const struct ekmf_config *config,
return 0;
}
/**
* Re-encipher the secure identity key (form field identity_secure_key in
* config) used to identify the client to EKMFWeb.
* The secure key blob is encrypted using the HSM master key. Whenever the HSM
* master key is being changed, the secure identity key must be re-enciphered.
* You can either pro-actively re-encipher a secure key once the new master key
* has been prepared (but not yet made active): to_new = true; or you can
* re-encipher a secure key when the HSM master key has already been changed:
* to_new = false. This requires that the HSM still has the old master key.
* Not all HSMs support this.
*
* For pro-active re-encipherment it is suggested to store the re-enciphered
* secure key on a separate place, until the new HSM master key has been made
* active. Specify a file name in reenc_secure_key to do so. For an in-place
* re-encipherment, set reenc_secure_key = NULL.
*
* @param config the configuration structure. Only field
* identity_secure_key must be specified, all others
* are optional.
* @param to_new If true: the identity key is re-enciphered from the
* current to the new master key.
* If false: the identity key is re-enciphered from the
* old to the current master key.
* @param reenc_secure_key if not NULL, then the re-enciphered secure key is
* stored into the filename specified here. Otherwise
* the re-enciphered secure key replaces the original
* secure identity key.
* @param ext_lib External secure key crypto library to use
* @param verbose if true, verbose messages are printed
*
* @returns a negative errno in case of an error, 0 if success.
* A -ENODEV indicates that the master keys are not loaded.
*/
int ekmf_reencipher_identity_key(const struct ekmf_config *config,
bool to_new, const char *reenc_secure_key,
const struct ekmf_ext_lib *ext_lib,
bool verbose)
{
unsigned char key_blob[MAX_KEY_BLOB_SIZE];
size_t key_blob_size = sizeof(key_blob);
const char *out_file;
int rc;
if (config == NULL || ext_lib == NULL)
return -EINVAL;
if (config->identity_secure_key == NULL)
return -EINVAL;
rc = read_key_blob(config->identity_secure_key, key_blob,
&key_blob_size);
if (rc != 0) {
pr_verbose(verbose, "Failed to read identity key from file "
"'%s': %s", config->identity_secure_key,
strerror(-rc));
return rc;
}
switch (ext_lib->type) {
case EKMF_EXT_LIB_CCA:
rc = cca_reencipher_key(ext_lib->cca, key_blob, key_blob_size,
to_new, verbose);
break;
default:
pr_verbose(verbose, "Invalid ext lib type: %d", ext_lib->type);
return -EINVAL;
}
if (rc != 0) {
pr_verbose(verbose, "Failed to re-encipher the secure identity "
"key from file '%s': %s",
config->identity_secure_key, strerror(-rc));
return rc;
}
out_file = reenc_secure_key != NULL ? reenc_secure_key :
config->identity_secure_key;
rc = write_key_blob(out_file, key_blob, key_blob_size);
if (rc != 0) {
pr_verbose(verbose, "Failed to write identity key to file "
"'%s': %s", out_file, strerror(-rc));
return rc;
}
return 0;
}
/**
* Library constructor
*/