From patchwork Mon Feb 17 17:37:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Frank Heimes X-Patchwork-Id: 1239418 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48LrnC6N7Gz9sRJ; Tue, 18 Feb 2020 04:38:39 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1j3kLs-0002TI-M4; Mon, 17 Feb 2020 17:38:36 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1j3kLq-0002SW-DZ for kernel-team@lists.ubuntu.com; Mon, 17 Feb 2020 17:38:34 +0000 Received: from 2.general.fheimes.uk.vpn ([10.172.194.67] helo=T570.fritz.box) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1j3kLq-00038A-2Y for kernel-team@lists.ubuntu.com; Mon, 17 Feb 2020 17:38:34 +0000 From: frank.heimes@canonical.com To: kernel-team@lists.ubuntu.com Subject: [F][PATCH 4/5] s390/zcrypt: extend EP11 card and queue sysfs attributes Date: Mon, 17 Feb 2020 18:37:13 +0100 Message-Id: <20200217173715.32789-5-frank.heimes@canonical.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200217173715.32789-1-frank.heimes@canonical.com> References: <20200217173715.32789-1-frank.heimes@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Harald Freudenberger BugLink: https://bugs.launchpad.net/bugs/1853303 This patch introduces new sysfs attributes for EP11 cards and queues: An EP11 card gets four new sysfs attributes: /sys/devices/ap/cardxx/API_ordinalnr The EP11 card firmware API ordinal number. /sys/devices/ap/cardxx/FW_version The EP11 card firmware major and minor version. /sys/devices/ap/cardxx/serialnr Displays the serial number of the EP11 card. The serial number is a 16 character string unique for this EP11 card. /sys/devices/ap/cardxx/op_modes Displays operation modes for this EP11 card. Known operation modes are: FIPS2009, BSI2009, FIPS2011, BSI2011 and BSICC2017. The EP11 queues get two new sysfs attributes: /sys/devices/ap/cardxx/xx.yyyy/mkvps Displays information about the master key(s) states and verification patterns. Two lines are displayed: WK CUR: WK NEW: with : 'invalid' or 'valid' : 'empty' or 'uncommitted' or 'committed' and : '-' or a 32 byte hash pattern /sys/devices/ap/cardxx/xx.yyyy/op_modes Displays operation modes for this EP11 queue. Known operation modes are: FIPS2009, BSI2009, FIPS2011, BSI2011 and BSICC2017. The card information displayed with the sysfs attributes is fresh fetched from the card if the card is online, otherwise cached values are used. The queue information displayed with the sysfs attributes is always fetched on the fly and not cached. So each read of any of these sysfs attributes will cause an request/reply CPRB communication with the EP11 crypto card. The queue attributes address the corresponding EP11 domain within the EP11 card. The card attributes addresses any domain within the EP11 card (subject to the dispatch algorithm within the zcrypt device driver). If the addressed domain is offline or for card addressing all domains are offline the attributes will display '-' for state and verification patterns and an empty string for op mode, serial number, API_ordinalnr and FW_version. Signed-off-by: Harald Freudenberger Signed-off-by: Vasily Gorbik (cherry picked from commit a17becc112535b912f2165f80a98c21b59655119) Signed-off-by: Frank Heimes --- drivers/s390/crypto/zcrypt_cex4.c | 273 +++++++++++++++++++++++++++--- 1 file changed, 253 insertions(+), 20 deletions(-) diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c index 6fabc906114c..9a9d02e19774 100644 --- a/drivers/s390/crypto/zcrypt_cex4.c +++ b/drivers/s390/crypto/zcrypt_cex4.c @@ -19,6 +19,7 @@ #include "zcrypt_error.h" #include "zcrypt_cex4.h" #include "zcrypt_ccamisc.h" +#include "zcrypt_ep11misc.h" #define CEX4A_MIN_MOD_SIZE 1 /* 8 bits */ #define CEX4A_MAX_MOD_SIZE_2K 256 /* 2048 bits */ @@ -71,11 +72,11 @@ static struct ap_device_id zcrypt_cex4_queue_ids[] = { MODULE_DEVICE_TABLE(ap, zcrypt_cex4_queue_ids); /* - * CCA card addditional device attributes + * CCA card additional device attributes */ -static ssize_t serialnr_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t cca_serialnr_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct cca_info ci; struct ap_card *ac = to_ap_card(dev); @@ -88,23 +89,25 @@ static ssize_t serialnr_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%s\n", ci.serial); } -static DEVICE_ATTR_RO(serialnr); + +static struct device_attribute dev_attr_cca_serialnr = + __ATTR(serialnr, 0444, cca_serialnr_show, NULL); static struct attribute *cca_card_attrs[] = { - &dev_attr_serialnr.attr, + &dev_attr_cca_serialnr.attr, NULL, }; -static const struct attribute_group cca_card_attr_group = { +static const struct attribute_group cca_card_attr_grp = { .attrs = cca_card_attrs, }; -/* - * CCA queue addditional device attributes - */ -static ssize_t mkvps_show(struct device *dev, - struct device_attribute *attr, - char *buf) + /* + * CCA queue additional device attributes + */ +static ssize_t cca_mkvps_show(struct device *dev, + struct device_attribute *attr, + char *buf) { int n = 0; struct cca_info ci; @@ -138,17 +141,233 @@ static ssize_t mkvps_show(struct device *dev, return n; } -static DEVICE_ATTR_RO(mkvps); + +static struct device_attribute dev_attr_cca_mkvps = + __ATTR(mkvps, 0444, cca_mkvps_show, NULL); static struct attribute *cca_queue_attrs[] = { - &dev_attr_mkvps.attr, + &dev_attr_cca_mkvps.attr, NULL, }; -static const struct attribute_group cca_queue_attr_group = { +static const struct attribute_group cca_queue_attr_grp = { .attrs = cca_queue_attrs, }; +/* + * EP11 card additional device attributes + */ +static ssize_t ep11_api_ordinalnr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ep11_card_info ci; + struct ap_card *ac = to_ap_card(dev); + struct zcrypt_card *zc = ac->private; + + memset(&ci, 0, sizeof(ci)); + + ep11_get_card_info(ac->id, &ci, zc->online); + + if (ci.API_ord_nr > 0) + return snprintf(buf, PAGE_SIZE, "%u\n", ci.API_ord_nr); + else + return snprintf(buf, PAGE_SIZE, "\n"); +} + +static struct device_attribute dev_attr_ep11_api_ordinalnr = + __ATTR(API_ordinalnr, 0444, ep11_api_ordinalnr_show, NULL); + +static ssize_t ep11_fw_version_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ep11_card_info ci; + struct ap_card *ac = to_ap_card(dev); + struct zcrypt_card *zc = ac->private; + + memset(&ci, 0, sizeof(ci)); + + ep11_get_card_info(ac->id, &ci, zc->online); + + if (ci.FW_version > 0) + return snprintf(buf, PAGE_SIZE, "%d.%d\n", + (int)(ci.FW_version >> 8), + (int)(ci.FW_version & 0xFF)); + else + return snprintf(buf, PAGE_SIZE, "\n"); +} + +static struct device_attribute dev_attr_ep11_fw_version = + __ATTR(FW_version, 0444, ep11_fw_version_show, NULL); + +static ssize_t ep11_serialnr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ep11_card_info ci; + struct ap_card *ac = to_ap_card(dev); + struct zcrypt_card *zc = ac->private; + + memset(&ci, 0, sizeof(ci)); + + ep11_get_card_info(ac->id, &ci, zc->online); + + if (ci.serial[0]) + return snprintf(buf, PAGE_SIZE, "%16.16s\n", ci.serial); + else + return snprintf(buf, PAGE_SIZE, "\n"); +} + +static struct device_attribute dev_attr_ep11_serialnr = + __ATTR(serialnr, 0444, ep11_serialnr_show, NULL); + +static const struct { + int mode_bit; + const char *mode_txt; +} ep11_op_modes[] = { + { 0, "FIPS2009" }, + { 1, "BSI2009" }, + { 2, "FIPS2011" }, + { 3, "BSI2011" }, + { 6, "BSICC2017" }, + { 0, NULL } +}; + +static ssize_t ep11_card_op_modes_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int i, n = 0; + struct ep11_card_info ci; + struct ap_card *ac = to_ap_card(dev); + struct zcrypt_card *zc = ac->private; + + memset(&ci, 0, sizeof(ci)); + + ep11_get_card_info(ac->id, &ci, zc->online); + + for (i = 0; ep11_op_modes[i].mode_txt; i++) { + if (ci.op_mode & (1 << ep11_op_modes[i].mode_bit)) { + if (n > 0) + buf[n++] = ' '; + n += snprintf(buf + n, PAGE_SIZE - n, + "%s", ep11_op_modes[i].mode_txt); + } + } + n += snprintf(buf + n, PAGE_SIZE - n, "\n"); + + return n; +} + +static struct device_attribute dev_attr_ep11_card_op_modes = + __ATTR(op_modes, 0444, ep11_card_op_modes_show, NULL); + +static struct attribute *ep11_card_attrs[] = { + &dev_attr_ep11_api_ordinalnr.attr, + &dev_attr_ep11_fw_version.attr, + &dev_attr_ep11_serialnr.attr, + &dev_attr_ep11_card_op_modes.attr, + NULL, +}; + +static const struct attribute_group ep11_card_attr_grp = { + .attrs = ep11_card_attrs, +}; + +/* + * EP11 queue additional device attributes + */ + +static ssize_t ep11_mkvps_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int n = 0; + struct ep11_domain_info di; + struct zcrypt_queue *zq = to_ap_queue(dev)->private; + static const char * const cwk_state[] = { "invalid", "valid" }; + static const char * const nwk_state[] = { "empty", "uncommitted", + "committed" }; + + memset(&di, 0, sizeof(di)); + + if (zq->online) + ep11_get_domain_info(AP_QID_CARD(zq->queue->qid), + AP_QID_QUEUE(zq->queue->qid), + &di); + + if (di.cur_wk_state == '0') { + n = snprintf(buf, PAGE_SIZE, "WK CUR: %s -\n", + cwk_state[di.cur_wk_state - '0']); + } else if (di.cur_wk_state == '1') { + n = snprintf(buf, PAGE_SIZE, "WK CUR: %s 0x", + cwk_state[di.cur_wk_state - '0']); + bin2hex(buf + n, di.cur_wkvp, sizeof(di.cur_wkvp)); + n += 2 * sizeof(di.cur_wkvp); + n += snprintf(buf + n, PAGE_SIZE - n, "\n"); + } else + n = snprintf(buf, PAGE_SIZE, "WK CUR: - -\n"); + + if (di.new_wk_state == '0') { + n += snprintf(buf + n, PAGE_SIZE - n, "WK NEW: %s -\n", + nwk_state[di.new_wk_state - '0']); + } else if (di.new_wk_state >= '1' && di.new_wk_state <= '2') { + n += snprintf(buf + n, PAGE_SIZE - n, "WK NEW: %s 0x", + nwk_state[di.new_wk_state - '0']); + bin2hex(buf + n, di.new_wkvp, sizeof(di.new_wkvp)); + n += 2 * sizeof(di.new_wkvp); + n += snprintf(buf + n, PAGE_SIZE - n, "\n"); + } else + n += snprintf(buf + n, PAGE_SIZE - n, "WK NEW: - -\n"); + + return n; +} + +static struct device_attribute dev_attr_ep11_mkvps = + __ATTR(mkvps, 0444, ep11_mkvps_show, NULL); + +static ssize_t ep11_queue_op_modes_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int i, n = 0; + struct ep11_domain_info di; + struct zcrypt_queue *zq = to_ap_queue(dev)->private; + + memset(&di, 0, sizeof(di)); + + if (zq->online) + ep11_get_domain_info(AP_QID_CARD(zq->queue->qid), + AP_QID_QUEUE(zq->queue->qid), + &di); + + for (i = 0; ep11_op_modes[i].mode_txt; i++) { + if (di.op_mode & (1 << ep11_op_modes[i].mode_bit)) { + if (n > 0) + buf[n++] = ' '; + n += snprintf(buf + n, PAGE_SIZE - n, + "%s", ep11_op_modes[i].mode_txt); + } + } + n += snprintf(buf + n, PAGE_SIZE - n, "\n"); + + return n; +} + +static struct device_attribute dev_attr_ep11_queue_op_modes = + __ATTR(op_modes, 0444, ep11_queue_op_modes_show, NULL); + +static struct attribute *ep11_queue_attrs[] = { + &dev_attr_ep11_mkvps.attr, + &dev_attr_ep11_queue_op_modes.attr, + NULL, +}; + +static const struct attribute_group ep11_queue_attr_grp = { + .attrs = ep11_queue_attrs, +}; + /** * Probe function for CEX4/CEX5/CEX6/CEX7 card device. It always * accepts the AP device since the bus_match already checked @@ -313,7 +532,12 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev) if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) { rc = sysfs_create_group(&ap_dev->device.kobj, - &cca_card_attr_group); + &cca_card_attr_grp); + if (rc) + zcrypt_card_unregister(zc); + } else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) { + rc = sysfs_create_group(&ap_dev->device.kobj, + &ep11_card_attr_grp); if (rc) zcrypt_card_unregister(zc); } @@ -332,7 +556,9 @@ static void zcrypt_cex4_card_remove(struct ap_device *ap_dev) struct zcrypt_card *zc = ac->private; if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) - sysfs_remove_group(&ap_dev->device.kobj, &cca_card_attr_group); + sysfs_remove_group(&ap_dev->device.kobj, &cca_card_attr_grp); + else if (ap_test_bit(&ac->functions, AP_FUNC_EP11)) + sysfs_remove_group(&ap_dev->device.kobj, &ep11_card_attr_grp); if (zc) zcrypt_card_unregister(zc); } @@ -394,7 +620,12 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev) if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) { rc = sysfs_create_group(&ap_dev->device.kobj, - &cca_queue_attr_group); + &cca_queue_attr_grp); + if (rc) + zcrypt_queue_unregister(zq); + } else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) { + rc = sysfs_create_group(&ap_dev->device.kobj, + &ep11_queue_attr_grp); if (rc) zcrypt_queue_unregister(zq); } @@ -413,7 +644,9 @@ static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev) struct zcrypt_queue *zq = aq->private; if (ap_test_bit(&aq->card->functions, AP_FUNC_COPRO)) - sysfs_remove_group(&ap_dev->device.kobj, &cca_queue_attr_group); + sysfs_remove_group(&ap_dev->device.kobj, &cca_queue_attr_grp); + else if (ap_test_bit(&aq->card->functions, AP_FUNC_EP11)) + sysfs_remove_group(&ap_dev->device.kobj, &ep11_queue_attr_grp); if (zq) zcrypt_queue_unregister(zq); }