File s390-tools-sles15sp2-27-zkey-Add-support-for-re-enciphering-AES-CIPHER-keys.patch of Package s390-tools.18357

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;
openSUSE Build Service is sponsored by