File s390-tools-sles15sp2-04-zkey-Add-utility-function-to-get-the-mkvp-of-a-crypt.patch of Package s390-tools.15932

Subject: zkey: Add utility function to get the mkvp of a crypto card
From: Ingo Franzki <ifranzki@linux.ibm.com>

Summary:     zkey: check master key consistency
Description: Enhances the zkey tool to perform a cross check whether the
             APQNs associated with a secure key have the same master key.
             Display the master key verification pattern of a secure key
             during the zkey validate command. This helps to better identify
             which master key is the correct one, in case of master key 
             inconsistencies.
             Select an appropriate APQN when re-enciphering a secure key.
             Re-enciphering is done using the CCA host library. Special
             handling is required to select an appropriate APQN for use with
             the CCA host library.
Upstream-ID: bf8872e94a2dc4810df388d1539560b00b1acf6e
Problem-ID:  SEC1916

Upstream-Description:

             zkey: Add utility function to get the mkvp of a crypto card

             With recent changes in the zcrypt device driver, the master key verifi-
             cation patterns of the AES master key of am APQN can be obtained by
             reading the sysfs attribute 'mkvps' of an APQN device of type CCA-
             Coprocessor. The sysfs attribute can be found under
             '/sys/devices/ap/cardnn/nn.mmmm/', where nn specifies the card number
             in hex, and mmmm specifies the domain number on hex.

             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/utils.c |  140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 zkey/utils.h |   21 ++++++++
 2 files changed, 161 insertions(+)

--- a/zkey/utils.c
+++ b/zkey/utils.c
@@ -159,3 +159,143 @@ out:
 	free(dev_path);
 	return rc;
 }
+
+static int parse_mk_info(char *line, struct mk_info *mk_info)
+{
+	struct mk_info_reg *mk_reg;
+	char *save;
+	char *tok;
+
+	tok = strtok_r(line, " ", &save);
+	if (tok == NULL)
+		return -EIO;
+
+	if (strcasecmp(tok, "AES") != 0)
+		return 0;
+
+	tok = strtok_r(NULL, " ", &save);
+	if (tok == NULL)
+		return -EIO;
+
+	if (strcasecmp(tok, "NEW:") == 0)
+		mk_reg = &mk_info->new_mk;
+	else if (strcasecmp(tok, "CUR:") == 0)
+		mk_reg = &mk_info->cur_mk;
+	else if (strcasecmp(tok, "OLD:") == 0)
+		mk_reg = &mk_info->old_mk;
+	else
+		return -EIO;
+
+	tok = strtok_r(NULL, " ", &save);
+	if (tok == NULL)
+		return -EIO;
+
+	if (strcasecmp(tok, "empty") == 0)
+		mk_reg->mk_state = MK_STATE_EMPTY;
+	else if (strcasecmp(tok, "partial") == 0)
+		mk_reg->mk_state = MK_STATE_PARTIAL;
+	else if (strcasecmp(tok, "full") == 0)
+		mk_reg->mk_state = MK_STATE_FULL;
+	else if (strcasecmp(tok, "valid") == 0)
+		mk_reg->mk_state = MK_STATE_VALID;
+	else if (strcasecmp(tok, "invalid") == 0)
+		mk_reg->mk_state = MK_STATE_INVALID;
+	else
+		mk_reg->mk_state = MK_STATE_UNKNOWN;
+
+	tok = strtok_r(NULL, " ", &save);
+	if (tok == NULL)
+		return -EIO;
+
+	if (sscanf(tok, "%llx", &mk_reg->mkvp) != 1)
+		return -EIO;
+
+	return 0;
+}
+
+/**
+ * Gets the master key states and verification patterns of an APQN from the
+ * sysfs.
+ *
+ * @param[in] card      card number
+ * @param[in] domain    the domain
+ * @param[out] mk_info  structure is filled on return with master key infos
+ * @param[in] verbose   if true, verbose messages are printed
+ *
+ * @returns 0 if the master key info was returned. -ENODEV if the APQN is not
+ *          available, or is not a CCA card. -ENOTSUP if the mkvps sysfs
+ *          attribute is not available, because the zcrypt kernel module is
+ *          on an older level.
+ */
+int sysfs_get_mkvps(int card, int domain, struct mk_info *mk_info, bool verbose)
+{
+	char *dev_path;
+	char *p, *end;
+	char buf[100];
+	int rc = 0;
+	FILE *fp;
+
+	if (mk_info == NULL)
+		return -EINVAL;
+
+	memset(mk_info, 0, sizeof(struct mk_info));
+	mk_info->new_mk.mk_state = MK_STATE_UNKNOWN;
+	mk_info->cur_mk.mk_state = MK_STATE_UNKNOWN;
+	mk_info->old_mk.mk_state = MK_STATE_UNKNOWN;
+
+	if (sysfs_is_apqn_online(card, domain) != 1)
+		return -ENODEV;
+
+	dev_path = util_path_sysfs("bus/ap/devices/card%02x/%02x.%04x/mkvps",
+				   card, card, domain);
+	if (!util_path_is_reg_file(dev_path)) {
+		rc = -ENOTSUP;
+		goto out;
+	}
+
+	fp = fopen(dev_path, "r");
+	if (fp == NULL) {
+		rc = -ENOTSUP;
+		goto out;
+	}
+
+	/*
+	 * Expected contents:
+	 *   AES NEW: <new_mk_state> <new_mk_mkvp>
+	 *   AES CUR: <cur_mk_state> <cur_mk_mkvp>
+	 *   AES OLD: <old_mk_state> <old_mk_mkvp>
+	 * with
+	 *   <new_mk_state>: 'empty' or 'partial' or 'full'
+	 *   <cur_mk_state>, <old_mk_state>: 'valid' or 'invalid'
+	 *   <new_mk_mkvp>, <cur_mk_mkvp>, <old_mk_mkvp:
+	 *        8 byte hex string with leading 0x
+	 */
+	while ((p = fgets(buf, sizeof(buf), fp)) != NULL) {
+		end = memchr(buf, '\n', sizeof(buf));
+		if (end)
+			*end = 0;
+		else
+			buf[sizeof(buf) - 1] = 0;
+
+		pr_verbose(verbose, "mkvp for %02x.%04x: %s", card, domain,
+			   buf);
+
+		rc = parse_mk_info(buf, mk_info);
+		if (rc != 0)
+			break;
+	}
+
+	fclose(fp);
+
+	if (mk_info->new_mk.mk_state == MK_STATE_UNKNOWN &&
+	    mk_info->cur_mk.mk_state == MK_STATE_UNKNOWN &&
+	    mk_info->old_mk.mk_state == MK_STATE_UNKNOWN)
+		rc = -EIO;
+out:
+	if (rc != 0)
+		pr_verbose(verbose, "Failed to get mkvps for %02x.%04x: %s",
+			   card, domain, strerror(-rc));
+
+	free(dev_path);
+	return rc;
+}
--- a/zkey/utils.h
+++ b/zkey/utils.h
@@ -20,4 +20,25 @@ int sysfs_is_apqn_online(int card, int d
 
 int sysfs_get_serialnr(int card, char serialnr[9], bool verbose);
 
+#define MK_STATE_EMPTY		0
+#define MK_STATE_PARTIAL	1
+#define MK_STATE_FULL		2
+#define MK_STATE_VALID		3
+#define MK_STATE_INVALID	4
+#define MK_STATE_UNKNOWN	-1
+
+struct mk_info_reg {
+	int	mk_state;
+	u64	mkvp;
+};
+
+struct mk_info {
+	struct mk_info_reg	new_mk;
+	struct mk_info_reg	cur_mk;
+	struct mk_info_reg	old_mk;
+};
+
+int sysfs_get_mkvps(int card, int domain, struct mk_info *mk_info,
+		    bool verbose);
+
 #endif
openSUSE Build Service is sponsored by