195 lines
6.7 KiB
Diff
195 lines
6.7 KiB
Diff
|
Subject: zkey: Add support for re-enciphering AES CIPHER keys
|
||
|
From: Ingo Franzki <ifranzki@linux.ibm.com>
|
||
|
|
||
|
Summary: zkey: Add support for CCA AES CIPHER keys
|
||
|
Description: With CCA 5 there is a new secure key type, the so called
|
||
|
variable length symmetric cipher key token. This token format
|
||
|
can hold AES keys with size 128, 192 and 256 bits together
|
||
|
with additional attributes cryptographic bound to the key
|
||
|
token. The attributes may limit the usage of the key, for
|
||
|
example restrict export or usability scope. So this key type
|
||
|
is considered to be even more secure than the traditional
|
||
|
secure key token. This key token type is also called "CCA
|
||
|
AES CIPHER key", where the formerly used key token is called
|
||
|
"CCA AES DATA key".
|
||
|
The zkey as well as the zkey-cryptsetup tools are enhanced
|
||
|
to support AES CIPHER keys. That is, zkey can manage AES DATA
|
||
|
keys, as well as AES CIPHER keys. The key type must be specified
|
||
|
at key generation time, the default is to generate AED DATA
|
||
|
keys.
|
||
|
Upstream-ID: 560b672bfad3c7bb6631ed4e1676a8b2c836e030
|
||
|
Problem-ID: SEC1717
|
||
|
|
||
|
Upstream-Description:
|
||
|
|
||
|
zkey: Add support for re-enciphering AES CIPHER keys
|
||
|
|
||
|
For secure keys of type CCA-AESCIPHER the CCA verb CSNBKTC2
|
||
|
(Key Token Change2) is used. CCA-AESDATA keys will continue
|
||
|
to use CCA verb CSNBKTC (Key Token Change).
|
||
|
|
||
|
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
|
||
|
Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
|
||
|
Signed-off-by: Jan Hoeppner <hoeppner@linux.ibm.com>
|
||
|
|
||
|
|
||
|
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
|
||
|
---
|
||
|
zkey/cca.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++------------
|
||
|
zkey/cca.h | 10 +++++++
|
||
|
2 files changed, 76 insertions(+), 15 deletions(-)
|
||
|
|
||
|
--- a/zkey/cca.c
|
||
|
+++ b/zkey/cca.c
|
||
|
@@ -142,6 +142,9 @@ int load_cca_library(struct cca_lib *cca
|
||
|
/* Get the Key Token Change function */
|
||
|
cca->dll_CSNBKTC = (t_CSNBKTC)dlsym(cca->lib_csulcca, "CSNBKTC");
|
||
|
|
||
|
+ /* Get the Key Token Change 2 function */
|
||
|
+ cca->dll_CSNBKTC2 = (t_CSNBKTC2)dlsym(cca->lib_csulcca, "CSNBKTC2");
|
||
|
+
|
||
|
/* Get the Cryptographic Facility Query function */
|
||
|
cca->dll_CSUACFQ = (t_CSUACFQ)dlsym(cca->lib_csulcca, "CSUACFQ");
|
||
|
|
||
|
@@ -153,6 +156,7 @@ int load_cca_library(struct cca_lib *cca
|
||
|
|
||
|
if (cca->dll_CSUACFV == NULL ||
|
||
|
cca->dll_CSNBKTC == NULL ||
|
||
|
+ cca->dll_CSNBKTC2 == NULL ||
|
||
|
cca->dll_CSUACFQ == NULL ||
|
||
|
cca->dll_CSUACRA == NULL ||
|
||
|
cca->dll_CSUACRD == NULL) {
|
||
|
@@ -187,10 +191,13 @@ int key_token_change(struct cca_lib *cca
|
||
|
u8 *secure_key, unsigned int secure_key_size,
|
||
|
char *method, bool verbose)
|
||
|
{
|
||
|
+ struct aescipherkeytoken *cipherkey =
|
||
|
+ (struct aescipherkeytoken *)secure_key;
|
||
|
long exit_data_len = 0, rule_array_count;
|
||
|
unsigned char rule_array[2 * 8] = { 0, };
|
||
|
unsigned char exit_data[4] = { 0, };
|
||
|
long return_code, reason_code;
|
||
|
+ long key_token_length;
|
||
|
|
||
|
util_assert(cca != NULL, "Internal error: cca is NULL");
|
||
|
util_assert(secure_key != NULL, "Internal error: secure_key is NULL");
|
||
|
@@ -202,33 +209,77 @@ int key_token_change(struct cca_lib *cca
|
||
|
memcpy(rule_array + 8, "AES ", 8);
|
||
|
rule_array_count = 2;
|
||
|
|
||
|
- cca->dll_CSNBKTC(&return_code, &reason_code,
|
||
|
- &exit_data_len, exit_data,
|
||
|
- &rule_array_count, rule_array,
|
||
|
- secure_key);
|
||
|
-
|
||
|
- pr_verbose(verbose, "CSNBKTC (Key Token Change) with '%s' returned: "
|
||
|
- "return_code: %ld, reason_code: %ld", method, return_code,
|
||
|
- reason_code);
|
||
|
- if (return_code != 0) {
|
||
|
- print_CCA_error(return_code, reason_code);
|
||
|
- return -EIO;
|
||
|
- }
|
||
|
-
|
||
|
- if (secure_key_size == 2 * AESDATA_KEY_SIZE) {
|
||
|
+ if (is_cca_aes_data_key(secure_key, secure_key_size)) {
|
||
|
cca->dll_CSNBKTC(&return_code, &reason_code,
|
||
|
&exit_data_len, exit_data,
|
||
|
&rule_array_count, rule_array,
|
||
|
- secure_key + AESDATA_KEY_SIZE);
|
||
|
+ secure_key);
|
||
|
|
||
|
pr_verbose(verbose, "CSNBKTC (Key Token Change) with '%s' "
|
||
|
"returned: return_code: %ld, reason_code: %ld",
|
||
|
method, return_code, reason_code);
|
||
|
+ } else if (is_cca_aes_cipher_key(secure_key, secure_key_size)) {
|
||
|
+ key_token_length = cipherkey->length;
|
||
|
+ cca->dll_CSNBKTC2(&return_code, &reason_code,
|
||
|
+ &exit_data_len, exit_data,
|
||
|
+ &rule_array_count, rule_array,
|
||
|
+ &key_token_length,
|
||
|
+ (unsigned char *)cipherkey);
|
||
|
+
|
||
|
+ pr_verbose(verbose, "CSNBKTC2 (Key Token Change2) with '%s' "
|
||
|
+ "returned: return_code: %ld, reason_code: %ld",
|
||
|
+ method, return_code, reason_code);
|
||
|
+
|
||
|
+ pr_verbose(verbose, "key_token_length: %lu", key_token_length);
|
||
|
+ } else {
|
||
|
+ warnx("Invalid key type specified");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (return_code != 0) {
|
||
|
+ print_CCA_error(return_code, reason_code);
|
||
|
+ return -EIO;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (is_xts_key(secure_key, secure_key_size)) {
|
||
|
+ if (is_cca_aes_data_key(secure_key, secure_key_size)) {
|
||
|
+ cca->dll_CSNBKTC(&return_code, &reason_code,
|
||
|
+ &exit_data_len, exit_data,
|
||
|
+ &rule_array_count, rule_array,
|
||
|
+ secure_key + AESDATA_KEY_SIZE);
|
||
|
+
|
||
|
+ pr_verbose(verbose, "CSNBKTC (Key Token Change) with "
|
||
|
+ "'%s' returned: return_code: %ld, "
|
||
|
+ "reason_code: %ld", method, return_code,
|
||
|
+ reason_code);
|
||
|
+ } else if (is_cca_aes_cipher_key(secure_key, secure_key_size)) {
|
||
|
+ cipherkey = (struct aescipherkeytoken *)(secure_key +
|
||
|
+ AESCIPHER_KEY_SIZE);
|
||
|
+ key_token_length = cipherkey->length;
|
||
|
+ cca->dll_CSNBKTC2(&return_code, &reason_code,
|
||
|
+ &exit_data_len, exit_data,
|
||
|
+ &rule_array_count, rule_array,
|
||
|
+ &key_token_length,
|
||
|
+ (unsigned char *)cipherkey);
|
||
|
+
|
||
|
+ pr_verbose(verbose, "CSNBKTC2 (Key Token Change2) with "
|
||
|
+ "'%s' returned: return_code: %ld, "
|
||
|
+ "reason_code: %ld", method, return_code,
|
||
|
+ reason_code);
|
||
|
+
|
||
|
+ pr_verbose(verbose, "key_token_length: %lu",
|
||
|
+ key_token_length);
|
||
|
+ } else {
|
||
|
+ warnx("Invalid key type specified");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
if (return_code != 0) {
|
||
|
print_CCA_error(return_code, reason_code);
|
||
|
return -EIO;
|
||
|
}
|
||
|
}
|
||
|
+
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
--- a/zkey/cca.h
|
||
|
+++ b/zkey/cca.h
|
||
|
@@ -25,6 +25,15 @@ typedef void (*t_CSNBKTC)(long *return_c
|
||
|
unsigned char *rule_array,
|
||
|
unsigned char *key_identifier);
|
||
|
|
||
|
+typedef void (*t_CSNBKTC2)(long *return_code,
|
||
|
+ long *reason_code,
|
||
|
+ long *exit_data_length,
|
||
|
+ unsigned char *exit_data,
|
||
|
+ long *rule_array_count,
|
||
|
+ unsigned char *rule_array,
|
||
|
+ long *key_identifier_length,
|
||
|
+ unsigned char *key_identifier);
|
||
|
+
|
||
|
typedef void (*t_CSUACFV)(long *return_code,
|
||
|
long *reason_code,
|
||
|
long *exit_data_length,
|
||
|
@@ -68,6 +77,7 @@ struct cca_version {
|
||
|
struct cca_lib {
|
||
|
void *lib_csulcca;
|
||
|
t_CSNBKTC dll_CSNBKTC;
|
||
|
+ t_CSNBKTC2 dll_CSNBKTC2;
|
||
|
t_CSUACFV dll_CSUACFV;
|
||
|
t_CSUACFQ dll_CSUACFQ;
|
||
|
t_CSUACRA dll_CSUACRA;
|