File s390-tools-sles15sp2-05-zkey-add-function-to-iterate-over-all-available-CCA-.patch of Package s390-tools.18357

Subject: zkey: add function to iterate over all available CCA APQNs
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: 625b81130ab2c9d184aaede2749f1fd776f51062
Problem-ID:  SEC1916

Upstream-Description:

             zkey: add function to iterate over all available CCA APQNs

             Add a utility function to iterate over all available APQNs of
             type CCA-Coprocessor. This function is required for various
             future enhancements.

             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 |  127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 zkey/utils.h |    5 ++
 2 files changed, 132 insertions(+)

--- a/zkey/utils.c
+++ b/zkey/utils.c
@@ -7,6 +7,7 @@
  * it under the terms of the MIT license. See LICENSE for details.
  */
 
+#include <dirent.h>
 #include <err.h>
 #include <errno.h>
 #include <stdbool.h>
@@ -19,8 +20,13 @@
 
 #include "lib/util_path.h"
 #include "lib/util_file.h"
+#include "lib/util_scandir.h"
+#include "lib/util_libc.h"
+#include "lib/util_rec.h"
+#include "lib/util_base.h"
 
 #include "utils.h"
+#include "properties.h"
 
 #define pr_verbose(verbose, fmt...)	do {				\
 						if (verbose)		\
@@ -299,3 +305,124 @@ out:
 	free(dev_path);
 	return rc;
 }
+
+static int scan_for_domains(int card, apqn_handler_t handler,
+			    void *handler_data, bool verbose)
+{
+	struct dirent **namelist;
+	char fname[290];
+	int i, n, domain, rc = 0;
+
+	sprintf(fname, "/sys/devices/ap/card%02x/", card);
+	n = util_scandir(&namelist, alphasort, fname,
+			 "[0-9a-fA-F]+\\.[0-9a-fA-F]+");
+
+	if (n < 0)
+		return -EIO;
+
+	for (i = 0; i < n; i++) {
+		if (sscanf(namelist[i]->d_name, "%x.%x", &card, &domain) != 2)
+			continue;
+
+		pr_verbose(verbose, "Found %02x.%04x", card, domain);
+
+		if (sysfs_is_apqn_online(card, domain) != 1) {
+			pr_verbose(verbose, "APQN %02x.%04x is offline or not "
+				   "CCA", card, domain);
+			continue;
+		}
+
+		rc = handler(card, domain, handler_data);
+		if (rc != 0)
+			break;
+	}
+
+	util_scandir_free(namelist, n);
+	return rc;
+}
+
+
+static int scan_for_apqns(apqn_handler_t handler, void *handler_data,
+			  bool verbose)
+{
+	struct dirent **namelist;
+	int i, n, card, rc = 0;
+
+	if (handler == NULL)
+		return -EINVAL;
+
+	n = util_scandir(&namelist, alphasort, "/sys/devices/ap/",
+			 "card[0-9a-fA-F]+");
+	if (n < 0)
+		return -EIO;
+
+	for (i = 0; i < n; i++) {
+		if (sscanf(namelist[i]->d_name, "card%x", &card) != 1)
+			continue;
+
+		pr_verbose(verbose, "Found card %02x", card);
+
+		if (sysfs_is_card_online(card) != 1) {
+			pr_verbose(verbose, "Card %02x is offline or not CCA",
+				   card);
+			continue;
+		}
+
+		rc = scan_for_domains(card, handler, handler_data, verbose);
+		if (rc != 0)
+			break;
+	}
+
+	util_scandir_free(namelist, n);
+	return rc;
+}
+
+/**
+ * Calls the handler for all APQNs specified in the apqns parameter, or of this
+ * is NULL, for all online CCA APQNs found in sysfs. In case sysfs is inspected,
+ * the cards and domains are processed in alphabetical order.
+ *
+ * @param[in] apqns     a comma separated list of APQNs. If NULL is specified,
+ *                      or an empty string, then all online CCA APQNs are
+ *                      handled.
+ * @param[in] handler   a handler function that is called for each APQN
+ * @param[in] handler_data private data that is passed to the handler
+ * @param[in] verbose   if true, verbose messages are printed
+ *
+ * @returns 0 for success or a negative errno in case of an error
+ */
+int handle_apqns(const char *apqns, apqn_handler_t handler, void *handler_data,
+		 bool verbose)
+{
+	int card, domain;
+	char *copy, *tok;
+	char *save;
+	int rc = 0;
+
+	if (apqns == NULL || (apqns != NULL && strlen(apqns) == 0)) {
+		rc = scan_for_apqns(handler, handler_data, verbose);
+	} else {
+		copy = util_strdup(apqns);
+		tok = strtok_r(copy, ",", &save);
+		while (tok != NULL) {
+
+			if (sscanf(tok, "%x.%x", &card, &domain) != 2) {
+				warnx("the APQN '%s' is not valid",
+				      tok);
+				rc = -EINVAL;
+				break;
+			}
+
+			pr_verbose(verbose, "Specified: %02x.%04x", card,
+				   domain);
+			rc = handler(card, domain, handler_data);
+			if (rc != 0)
+				break;
+
+			tok = strtok_r(NULL, ",", &save);
+		}
+		free(copy);
+	}
+
+	return rc;
+}
--- a/zkey/utils.h
+++ b/zkey/utils.h
@@ -41,4 +41,9 @@ struct mk_info {
 int sysfs_get_mkvps(int card, int domain, struct mk_info *mk_info,
 		    bool verbose);
 
+typedef int(*apqn_handler_t) (int card, int domain, void *handler_data);
+
+int handle_apqns(const char *apqns, apqn_handler_t handler, void *handler_data,
+		 bool verbose);
+
 #endif
openSUSE Build Service is sponsored by