s390/zcrypt: Support CPRB minor version T7
authorHarald Freudenberger <freude@linux.ibm.com>
Tue, 23 Nov 2021 14:16:06 +0000 (15:16 +0100)
committerVasily Gorbik <gor@linux.ibm.com>
Mon, 7 Mar 2022 23:33:00 +0000 (00:33 +0100)
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>
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_msgtype50.c
drivers/s390/crypto/zcrypt_msgtype50.h
drivers/s390/crypto/zcrypt_msgtype6.c
drivers/s390/crypto/zcrypt_msgtype6.h

index 703d6782ce65ca00758e700815293733dec5a703..8fd5a17bdf994a0db39c58ab37e5e725c2b8a078 100644 (file)
@@ -251,7 +251,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.
index 8b81e6385d556d2b910b0eadfd7b6dba88fcea9f..af3e835418863a6a8c34fbe38a2be9701e419bcb 100644 (file)
@@ -876,7 +876,7 @@ static long _zcrypt_send_cprb(bool userspace, struct ap_perms *perms,
        }
 #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;
 
@@ -1058,7 +1058,7 @@ static long _zcrypt_send_ep11_cprb(bool userspace, struct ap_perms *perms,
                }
        }
 
-       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;
 
@@ -1171,7 +1171,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;
 
index b6dcdd2a66d41c5d0b386a8bdc3f780fd7ea7f0a..259145aa393f8c080c630868d104abf0d80b6576 100644 (file)
@@ -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_rsa_modexpo *mex, int *fcode)
        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)
index 66bec4f45c560a0ad4835a8ecb7187bf3b526260..eb49f06bed2993b4be70f9f44a25787ac33f691f 100644 (file)
@@ -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);
index df283729191a5c6d08c7f89e9e4bd342548ae82a..98755b57104f6b443b553fc77a44e65409f3216b 100644 (file)
@@ -472,6 +472,7 @@ static int XCRB_msg_to_type6CPRB_msgX(bool userspace, struct ap_message *ap_msg,
        *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(bool userspace, struct ap_message *ap_msg,
                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_msgx(bool userspace, struct ap_message *ap
                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,
index 155c73514bacfdf06526d29ae5324f4f9001cc5c..ec960d01cca01c64a5603f64e850f6a065bc673f 100644 (file)
@@ -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