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