File s390-tools-sles15sp2-20-zkey-Allow-to-specify-the-key-type-with-the-generate.patch of Package s390-tools.16701

Subject: zkey: Allow to specify the key type with the generate command
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: b47007b8ac8b446eb94b06e7ed3050b3df3e80e8
Problem-ID:  SEC1717

Upstream-Description:

             zkey: Allow to specify the key type with the generate command

             The zkey generate command allows to specify the --key-type|-K
             option to specify the key type. If not specified, then the
             default is CCA-AESDATA.

             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/keystore.c |   35 ++++++++++++++++++++++++-----------
 zkey/keystore.h |    2 +-
 zkey/pkey.c     |   20 +++++++++++++++++---
 zkey/pkey.h     |    6 +++---
 zkey/zkey.1     |   14 ++++++++++++++
 zkey/zkey.c     |   17 ++++++++++++++---
 6 files changed, 73 insertions(+), 21 deletions(-)

--- a/zkey/keystore.c
+++ b/zkey/keystore.c
@@ -1525,11 +1525,6 @@ static int _keystore_set_default_propert
 {
 	int rc;
 
-	rc = properties_set(key_props, PROP_NAME_KEY_TYPE,
-			    KEY_TYPE_CCA_AESDATA);
-	if (rc != 0)
-		return rc;
-
 	rc = properties_set(key_props, PROP_NAME_CIPHER, "paes");
 	if (rc != 0)
 		return rc;
@@ -1564,6 +1559,7 @@ static int _keystore_set_default_propert
  *                        the sector size is not specified and the system
  *                        default is used.
  * @param[in] volume_type the type of volume
+ * @param[in] key_type    the type of the key
  */
 static int _keystore_create_info_file(struct keystore *keystore,
 				      const char *name,
@@ -1572,7 +1568,8 @@ static int _keystore_create_info_file(st
 				      const char *volumes, const char *apqns,
 				      bool noapqncheck,
 				      size_t sector_size,
-				      const char *volume_type)
+				      const char *volume_type,
+				      const char *key_type)
 {
 	struct volume_check vol_check = { .keystore = keystore, .name = name,
 					  .set = 0 };
@@ -1594,6 +1591,12 @@ static int _keystore_create_info_file(st
 		goto out;
 	}
 
+	rc = properties_set2(key_props, PROP_NAME_KEY_TYPE, key_type, true);
+	if (rc != 0) {
+		warnx("Invalid characters in key-type");
+		goto out;
+	}
+
 	rc = _keystore_change_association(key_props, PROP_NAME_VOLUMES,
 					  volumes != NULL ? volumes : "",
 					  "volume", _keystore_volume_check,
@@ -1731,6 +1734,7 @@ out:
  *                        clear key contained in the file denoted here.
  *                        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] pkey_fd     the file descriptor of /dev/pkey
  *
  * @returns 0 for success or a negative errno in case of an error
@@ -1740,7 +1744,7 @@ int keystore_generate_key(struct keystor
 			  const char *apqns, bool noapqncheck,
 			  size_t sector_size, size_t keybits, bool xts,
 			  const char *clear_key_file, const char *volume_type,
-			  int pkey_fd)
+			  const char *key_type, int pkey_fd)
 {
 	struct key_filenames file_names = { NULL, NULL, NULL };
 	struct properties *key_props = NULL;
@@ -1749,6 +1753,12 @@ int keystore_generate_key(struct keystor
 
 	util_assert(keystore != NULL, "Internal error: keystore is NULL");
 	util_assert(name != NULL, "Internal error: name is NULL");
+	util_assert(key_type != NULL, "Internal error: key_type is NULL");
+
+	if (!_keystore_valid_key_type(key_type)) {
+		warnx("Invalid key-type specified");
+		return -EINVAL;
+	}
 
 	rc = _keystore_get_key_filenames(keystore, name, &file_names);
 	if (rc != 0)
@@ -1773,13 +1783,14 @@ int keystore_generate_key(struct keystor
 	if (clear_key_file == NULL)
 		rc = generate_secure_key_random(pkey_fd,
 						file_names.skey_filename,
-						keybits, xts, card, domain,
+						keybits, xts, key_type,
+						card, domain,
 						keystore->verbose);
 	else
 		rc = generate_secure_key_clear(pkey_fd,
 					       file_names.skey_filename,
 					       keybits, xts, clear_key_file,
-					       card, domain,
+					       key_type, card, domain,
 					       keystore->verbose);
 	if (rc != 0)
 		goto out_free_props;
@@ -1790,7 +1801,8 @@ int keystore_generate_key(struct keystor
 
 	rc = _keystore_create_info_file(keystore, name, &file_names,
 					description, volumes, apqns,
-					noapqncheck, sector_size, volume_type);
+					noapqncheck, sector_size, volume_type,
+					key_type);
 	if (rc != 0)
 		goto out_free_props;
 
@@ -1894,7 +1906,8 @@ int keystore_import_key(struct keystore
 
 	rc = _keystore_create_info_file(keystore, name, &file_names,
 					description, volumes, apqns,
-					noapqncheck, sector_size, volume_type);
+					noapqncheck, sector_size, volume_type,
+					KEY_TYPE_CCA_AESDATA);
 	if (rc != 0)
 		goto out_free_props;
 
--- a/zkey/keystore.h
+++ b/zkey/keystore.h
@@ -32,7 +32,7 @@ int keystore_generate_key(struct keystor
 			  const char *apqns, bool noapqncheck,
 			  size_t sector_size, size_t keybits, bool xts,
 			  const char *clear_key_file, const char *volume_type,
-			  int pkey_fd);
+			  const char *key_type, int pkey_fd);
 
 int keystore_import_key(struct keystore *keystore, const char *name,
 			const char *description, const char *volumes,
--- a/zkey/pkey.c
+++ b/zkey/pkey.c
@@ -278,6 +278,7 @@ out:
  * @param[in] keyfile       the file name of the secure key to generate
  * @param[in] keybits       the cryptographic size of the key in bits
  * @param[in] xts           if true an XTS key is generated
+ * @param[in] key_type      the type of the key
  * @param[in] card          the card number to use (or AUTOSELECT)
  * @param[in] domain        the domain number to use (or AUTOSELECT)
  * @param[in] verbose       if true, verbose messages are printed
@@ -285,8 +286,8 @@ out:
  * @returns 0 on success, a negative errno in case of an error
  */
 int generate_secure_key_random(int pkey_fd, const char *keyfile,
-			       size_t keybits, bool xts, u16 card, u16 domain,
-			       bool verbose)
+			       size_t keybits, bool xts, const char *key_type,
+			       u16 card, u16 domain, bool verbose)
 {
 	struct pkey_genseck gensec;
 	size_t secure_key_size;
@@ -295,6 +296,12 @@ int generate_secure_key_random(int pkey_
 
 	util_assert(pkey_fd != -1, "Internal error: pkey_fd is -1");
 	util_assert(keyfile != NULL, "Internal error: keyfile is NULL");
+	util_assert(key_type != NULL, "Internal error: key_type is NULL");
+
+	if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) != 0) {
+		warnx("Invalid key-type: %s", key_type);
+		return -EINVAL;
+	}
 
 	if (keybits == 0)
 		keybits = DEFAULT_KEYBITS;
@@ -374,6 +381,7 @@ out:
  *                          determines the keybits.
  * @param[in] xts           if true an XTS key is generated
  * @param[in] clearkeyfile  the file name of the clear key to read
+ * @param[in] key_type      the type of the key
  * @param[in] card          the card number to use (or AUTOSELECT)
  * @param[in] domain        the domain number to use (or AUTOSELECT)
  * @param[in] verbose       if true, verbose messages are printed
@@ -382,7 +390,7 @@ out:
  */
 int generate_secure_key_clear(int pkey_fd, const char *keyfile,
 			      size_t keybits, bool xts,
-			      const char *clearkeyfile,
+			      const char *clearkeyfile, const char *key_type,
 			      u16 card, u16 domain,
 			      bool verbose)
 {
@@ -397,6 +405,12 @@ int generate_secure_key_clear(int pkey_f
 	util_assert(keyfile != NULL, "Internal error: keyfile is NULL");
 	util_assert(clearkeyfile != NULL,
 		    "Internal error: clearkeyfile is NULL");
+	util_assert(key_type != NULL, "Internal error: key_type is NULL");
+
+	if (strcasecmp(key_type, KEY_TYPE_CCA_AESDATA) != 0) {
+		warnx("Invalid key-type: %s", key_type);
+		return -EINVAL;
+	}
 
 	secure_key_size = DOUBLE_KEYSIZE_FOR_XTS(SECURE_KEY_SIZE, xts);
 	secure_key = util_malloc(secure_key_size);
--- a/zkey/pkey.h
+++ b/zkey/pkey.h
@@ -103,12 +103,12 @@ struct pkey_verifykey {
 int open_pkey_device(bool verbose);
 
 int generate_secure_key_random(int pkey_fd, const char *keyfile,
-			       size_t keybits, bool xts, u16 card, u16 domain,
-			       bool verbose);
+			       size_t keybits, bool xts, const char *key_type,
+			       u16 card, u16 domain, bool verbose);
 
 int generate_secure_key_clear(int pkey_fd, const char *keyfile,
 			      size_t keybits, bool xts,
-			      const char *clearkeyfile,
+			      const char *clearkeyfile, const char *key_type,
 			      u16 card, u16 domain,
 			      bool verbose);
 
--- a/zkey/zkey.1
+++ b/zkey/zkey.1
@@ -79,6 +79,8 @@ key repository.
 .RB [ \-\-xts | \-x ]
 .RB [ \-\-clearkey | \-c
 .IR clear\-key\-file ]
+.RB [ \-\-key-type | \-K
+.IR type ]
 .RB [ \-\-verbose | \-V ]
 .
 .PP
@@ -102,6 +104,8 @@ key repository.
 .RB [ \-\-xts | \-x ]
 .RB [ \-\-clearkey | \-c
 .IR clear\-key\-file ]
+.RB [ \-\-key-type | \-K
+.IR type ]
 .RB [ \-\-verbose | \-V ]
 .PP
 Use the
@@ -129,6 +133,11 @@ additional information can be associated
 , or the
 .B \-\-sector-size
 options.
+.PP
+You can generate different types of secure keys: \fBCCA-AESDATA\fP keys.
+Specify the type of the secure key using the
+.B \-\-key\-type
+option. The default key type is CCA-AESDATA.
 .
 .SS "Validating secure AES keys"
 .
@@ -730,6 +739,11 @@ This option is only available if
 has been compiled with LUKS2 support enabled. If LUKS2 support is not enabled,
 the default volume type is \fBplain\fP.
 This option is only used for secure keys contained in the secure key repository.
+.TP
+.BR \-K ", " \-\-key-type\~\fItype\fP
+Specifies the key type of the secure key. Possible values are \fBCCA-AESDATA\fP.
+If this option is omitted, then a secure key of type
+CCA-AESDATA is generated.
 .
 .
 .
--- a/zkey/zkey.c
+++ b/zkey/zkey.c
@@ -217,6 +217,15 @@ static struct util_opt opt_vec[] = {
 		.command = COMMAND_GENERATE,
 	},
 #endif
+	{
+		.option = { "key-type", required_argument, NULL, 'K'},
+		.argument = "type",
+		.desc = "The type of the key. Possible values are '"
+			KEY_TYPE_CCA_AESDATA"'. "
+			"When this option is omitted, the default is '"
+			KEY_TYPE_CCA_AESDATA"'",
+		.command = COMMAND_GENERATE,
+	},
 	/***********************************************************/
 	{
 		.flags = UTIL_OPT_FLAG_SECTION,
@@ -1019,7 +1028,7 @@ static int command_generate_clear(void)
 
 	rc = generate_secure_key_clear(g.pkey_fd, g.pos_arg,
 				       g.keybits, g.xts,
-				       g.clearkeyfile,
+				       g.clearkeyfile, g.key_type,
 				       AUTOSELECT, AUTOSELECT,
 				       g.verbose);
 
@@ -1036,7 +1045,7 @@ static int command_generate_random(void)
 	int rc;
 
 	rc = generate_secure_key_random(g.pkey_fd, g.pos_arg,
-					g.keybits, g.xts,
+					g.keybits, g.xts, g.key_type,
 					AUTOSELECT, AUTOSELECT,
 					g.verbose);
 
@@ -1058,7 +1067,7 @@ static int command_generate_repository(v
 	rc = keystore_generate_key(g.keystore, g.name, g.description, g.volumes,
 				   g.apqns, g.noapqncheck, g.sector_size,
 				   g.keybits, g.xts, g.clearkeyfile,
-				   g.volume_type, g.pkey_fd);
+				   g.volume_type, g.key_type, g.pkey_fd);
 
 	return rc != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 }
@@ -1085,6 +1094,8 @@ static int command_generate(void)
 		util_prg_print_parse_error();
 		return EXIT_FAILURE;
 	}
+	if (g.key_type == NULL)
+		g.key_type = KEY_TYPE_CCA_AESDATA;
 	if (g.name != NULL)
 		return command_generate_repository();
 	if (g.pos_arg != NULL) {
openSUSE Build Service is sponsored by