Blob Blame History Raw
From: Harald Freudenberger <freude@linux.ibm.com>
Date: Tue, 23 Nov 2021 15:16:06 +0100
Subject: s390/zcrypt: Support CPRB minor version T7
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Git-commit: 383366b58016361cc8a2e4c585b7d581eb76263a
Patch-mainline: v5.18-rc1
References: jsc#PED-596

There is a new CPRB minor version T7 to be supported with
this patch. Together with this the functions which extract
the CPRB data from userspace and prepare the AP message do
now check the CPRB minor version and provide some info in
the flag field of the ap message struct for further processing.

The 3 functions doing this job have been renamed to
prep_cca_ap_msg, prep_ep11_ap_msg and prep_rng_ap_msg to
reflect their job better (old was get..fc).

This patch also introduces two new flags to be used internal
with the flag field of the struct ap_message:

AP_MSG_FLAG_USAGE is set when prep_cca_ap_msg or prep_ep11_ap_msg
come to the conclusion that this is a ordinary crypto load CPRB
(which means T2 for CCA CPRBs and no admin bit for EP11 CPRBs).

AP_MSG_FLAG_ADMIN is set when prep_cca_ap_msg or prep_ep11_ap_msg
think, this is an administrative (control) crypto load CPRB
(which means T3, T5, T6 or T7 for CCA CPRBs and admin bit set
for EP11 CPRBs).

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Jürgen Christ <jchrist@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/s390/crypto/ap_bus.h           |    4 +-
 drivers/s390/crypto/zcrypt_api.c       |    6 +--
 drivers/s390/crypto/zcrypt_msgtype50.c |    4 +-
 drivers/s390/crypto/zcrypt_msgtype50.h |    4 +-
 drivers/s390/crypto/zcrypt_msgtype6.c  |   56 ++++++++++++++++++++++++---------
 drivers/s390/crypto/zcrypt_msgtype6.h  |   13 ++++---
 6 files changed, 60 insertions(+), 27 deletions(-)

--- a/drivers/s390/crypto/ap_bus.h
+++ b/drivers/s390/crypto/ap_bus.h
@@ -240,7 +240,9 @@ struct ap_message {
 			struct ap_message *);
 };
 
-#define AP_MSG_FLAG_SPECIAL  1		/* flag msg as 'special' with NQAP */
+#define AP_MSG_FLAG_SPECIAL  0x0001	/* flag msg as 'special' with NQAP */
+#define AP_MSG_FLAG_USAGE    0x0002	/* CCA, EP11: usage (no admin) msg */
+#define AP_MSG_FLAG_ADMIN    0x0004	/* CCA, EP11: admin (=control) msg */
 
 /**
  * ap_init_message() - Initialize ap_message.
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -876,7 +876,7 @@ static long _zcrypt_send_cprb(bool users
 	}
 #endif
 
-	rc = get_cprb_fc(userspace, xcRB, &ap_msg, &func_code, &domain);
+	rc = prep_cca_ap_msg(userspace, xcRB, &ap_msg, &func_code, &domain);
 	if (rc)
 		goto out;
 
@@ -1059,7 +1059,7 @@ static long _zcrypt_send_ep11_cprb(bool
 		}
 	}
 
-	rc = get_ep11cprb_fc(userspace, xcrb, &ap_msg, &func_code);
+	rc = prep_ep11_ap_msg(userspace, xcrb, &ap_msg, &func_code);
 	if (rc)
 		goto out_free;
 
@@ -1172,7 +1172,7 @@ static long zcrypt_rng(char *buffer)
 	trace_s390_zcrypt_req(buffer, TP_HWRNGCPRB);
 
 	ap_init_message(&ap_msg);
-	rc = get_rng_fc(&ap_msg, &func_code, &domain);
+	rc = prep_rng_ap_msg(&ap_msg, &func_code, &domain);
 	if (rc)
 		goto out;
 
--- a/drivers/s390/crypto/zcrypt_msgtype50.c
+++ b/drivers/s390/crypto/zcrypt_msgtype50.c
@@ -156,7 +156,7 @@ struct type80_hdr {
 	unsigned char	reserved3[8];
 } __packed;
 
-unsigned int get_rsa_modex_fc(struct ica_rsa_modexpo *mex, int *fcode)
+int get_rsa_modex_fc(struct ica_rsa_modexpo *mex, int *fcode)
 {
 
 	if (!mex->inputdatalength)
@@ -172,7 +172,7 @@ unsigned int get_rsa_modex_fc(struct ica
 	return 0;
 }
 
-unsigned int get_rsa_crt_fc(struct ica_rsa_modexpo_crt *crt, int *fcode)
+int get_rsa_crt_fc(struct ica_rsa_modexpo_crt *crt, int *fcode)
 {
 
 	if (!crt->inputdatalength)
--- a/drivers/s390/crypto/zcrypt_msgtype50.h
+++ b/drivers/s390/crypto/zcrypt_msgtype50.h
@@ -20,8 +20,8 @@
 
 #define MSGTYPE_ADJUSTMENT 0x08  /* type04 extension (not needed in type50) */
 
-unsigned int get_rsa_modex_fc(struct ica_rsa_modexpo *, int *);
-unsigned int get_rsa_crt_fc(struct ica_rsa_modexpo_crt *, int *);
+int get_rsa_modex_fc(struct ica_rsa_modexpo *mex, int *fc);
+int get_rsa_crt_fc(struct ica_rsa_modexpo_crt *crt, int *fc);
 
 void zcrypt_msgtype50_init(void);
 void zcrypt_msgtype50_exit(void);
--- a/drivers/s390/crypto/zcrypt_msgtype6.c
+++ b/drivers/s390/crypto/zcrypt_msgtype6.c
@@ -472,6 +472,7 @@ static int XCRB_msg_to_type6CPRB_msgX(bo
 	*fcode = (msg->hdr.function_code[0] << 8) | msg->hdr.function_code[1];
 	*dom = (unsigned short *)&msg->cprbx.domain;
 
+	/* check subfunction, US and AU need special flag with NQAP */
 	if (memcmp(function_code, "US", 2) == 0
 	    || memcmp(function_code, "AU", 2) == 0)
 		ap_msg->flags |= AP_MSG_FLAG_SPECIAL;
@@ -481,6 +482,23 @@ static int XCRB_msg_to_type6CPRB_msgX(bo
 		ap_msg->flags ^= AP_MSG_FLAG_SPECIAL;
 #endif
 
+	/* check CPRB minor version, set info bits in ap_message flag field */
+	switch (*(unsigned short *)(&msg->cprbx.func_id[0])) {
+	case 0x5432: /* "T2" */
+		ap_msg->flags |= AP_MSG_FLAG_USAGE;
+		break;
+	case 0x5433: /* "T3" */
+	case 0x5435: /* "T5" */
+	case 0x5436: /* "T6" */
+	case 0x5437: /* "T7" */
+		ap_msg->flags |= AP_MSG_FLAG_ADMIN;
+		break;
+	default:
+		ZCRYPT_DBF_DBG("%s unknown CPRB minor version '%c%c'\n",
+			       __func__, msg->cprbx.func_id[0],
+			       msg->cprbx.func_id[1]);
+	}
+
 	/* copy data block */
 	if (xcRB->request_data_length &&
 	    z_copy_from_user(userspace, req_data, xcRB->request_data_address,
@@ -568,6 +586,12 @@ static int xcrb_msg_to_type6_ep11cprb_ms
 		ap_msg->flags ^= AP_MSG_FLAG_SPECIAL;
 #endif
 
+	/* set info bits in ap_message flag field */
+	if (msg->cprbx.flags & 0x80)
+		ap_msg->flags |= AP_MSG_FLAG_ADMIN;
+	else
+		ap_msg->flags |= AP_MSG_FLAG_USAGE;
+
 	return 0;
 }
 
@@ -1131,15 +1155,17 @@ out_free:
 }
 
 /**
- * Fetch function code from cprb.
- * Extracting the fc requires to copy the cprb from userspace.
- * So this function allocates memory and needs an ap_msg prepared
+ * Prepare a CCA AP msg request.
+ * Prepare a CCA AP msg: fetch the required data from userspace,
+ * prepare the AP msg, fill some info into the ap_message struct,
+ * extract some data from the CPRB and give back to the caller.
+ * This function allocates memory and needs an ap_msg prepared
  * by the caller with ap_init_message(). Also the caller has to
  * make sure ap_release_message() is always called even on failure.
  */
-unsigned int get_cprb_fc(bool userspace, struct ica_xcRB *xcRB,
-			 struct ap_message *ap_msg,
-			 unsigned int *func_code, unsigned short **dom)
+int prep_cca_ap_msg(bool userspace, struct ica_xcRB *xcRB,
+		    struct ap_message *ap_msg,
+		    unsigned int *func_code, unsigned short **dom)
 {
 	struct response_type resp_type = {
 		.type = CEXXC_RESPONSE_TYPE_XCRB,
@@ -1193,15 +1219,17 @@ out:
 }
 
 /**
- * Fetch function code from ep11 cprb.
- * Extracting the fc requires to copy the ep11 cprb from userspace.
- * So this function allocates memory and needs an ap_msg prepared
+ * Prepare an EP11 AP msg request.
+ * Prepare an EP11 AP msg: fetch the required data from userspace,
+ * prepare the AP msg, fill some info into the ap_message struct,
+ * extract some data from the CPRB and give back to the caller.
+ * This function allocates memory and needs an ap_msg prepared
  * by the caller with ap_init_message(). Also the caller has to
  * make sure ap_release_message() is always called even on failure.
  */
-unsigned int get_ep11cprb_fc(bool userspace, struct ep11_urb *xcrb,
-			     struct ap_message *ap_msg,
-			     unsigned int *func_code)
+int prep_ep11_ap_msg(bool userspace, struct ep11_urb *xcrb,
+		     struct ap_message *ap_msg,
+		     unsigned int *func_code)
 {
 	struct response_type resp_type = {
 		.type = CEXXC_RESPONSE_TYPE_EP11,
@@ -1301,8 +1329,8 @@ out:
 	return rc;
 }
 
-unsigned int get_rng_fc(struct ap_message *ap_msg, int *func_code,
-						   unsigned int *domain)
+int prep_rng_ap_msg(struct ap_message *ap_msg, int *func_code,
+		    unsigned int *domain)
 {
 	struct response_type resp_type = {
 		.type = CEXXC_RESPONSE_TYPE_XCRB,
--- a/drivers/s390/crypto/zcrypt_msgtype6.h
+++ b/drivers/s390/crypto/zcrypt_msgtype6.h
@@ -94,11 +94,14 @@ struct type86_fmt2_ext {
 	unsigned int	  offset4;	/* 0x00000000			*/
 } __packed;
 
-unsigned int get_cprb_fc(bool userspace, struct ica_xcRB *, struct ap_message *,
-			 unsigned int *, unsigned short **);
-unsigned int get_ep11cprb_fc(bool userspace, struct ep11_urb *, struct ap_message *,
-			     unsigned int *);
-unsigned int get_rng_fc(struct ap_message *, int *, unsigned int *);
+int prep_cca_ap_msg(bool userspace, struct ica_xcRB *xcrb,
+		    struct ap_message *ap_msg,
+		    unsigned int *fc, unsigned short **dom);
+int prep_ep11_ap_msg(bool userspace, struct ep11_urb *xcrb,
+		     struct ap_message *ap_msg,
+		     unsigned int *fc);
+int prep_rng_ap_msg(struct ap_message *ap_msg,
+		    int *fc, unsigned int *dom);
 
 #define LOW	10
 #define MEDIUM	100