s390/zcrypt: Support CPRB minor version T7

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>
This commit is contained in:
Harald Freudenberger 2021-11-23 15:16:06 +01:00 committed by Vasily Gorbik
parent a7e701dba1
commit 383366b580
6 changed files with 60 additions and 27 deletions

View 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.

View 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;

View 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)

View 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);

View 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,

View 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