Skip to content

Commit

Permalink
s390/zcrypt: CEX8S exploitation support
Browse files Browse the repository at this point in the history
This patch adds CEX8 exploitation support for the AP bus code,
the zcrypt device driver zoo and the vfio device driver.

Signed-off-by: Harald Freudenberger <[email protected]>
Reviewed-by: Jürgen Christ <[email protected]>
Signed-off-by: Vasily Gorbik <[email protected]>
  • Loading branch information
hfreude authored and Vasily Gorbik committed Mar 7, 2022
1 parent d64e5e9 commit 985214a
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 27 deletions.
2 changes: 1 addition & 1 deletion arch/s390/include/uapi/asm/zcrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ struct zcrypt_device_matrix_ext {
* 0x08: CEX3A
* 0x0a: CEX4
* 0x0b: CEX5
* 0x0c: CEX6 and CEX7
* 0x0c: CEX6, CEX7 or CEX8
* 0x0d: device is disabled
*
* ZCRYPT_QDEPTH_MASK
Expand Down
12 changes: 6 additions & 6 deletions drivers/s390/crypto/ap_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -1589,24 +1589,24 @@ static int ap_get_compatible_type(ap_qid_t qid, int rawtype, unsigned int func)
AP_QID_QUEUE(qid), rawtype);
return 0;
}
/* up to CEX7 known and fully supported */
if (rawtype <= AP_DEVICE_TYPE_CEX7)
/* up to CEX8 known and fully supported */
if (rawtype <= AP_DEVICE_TYPE_CEX8)
return rawtype;
/*
* unknown new type > CEX7, check for compatibility
* unknown new type > CEX8, check for compatibility
* to the highest known and supported type which is
* currently CEX7 with the help of the QACT function.
* currently CEX8 with the help of the QACT function.
*/
if (ap_qact_available()) {
struct ap_queue_status status;
union ap_qact_ap_info apinfo = {0};

apinfo.mode = (func >> 26) & 0x07;
apinfo.cat = AP_DEVICE_TYPE_CEX7;
apinfo.cat = AP_DEVICE_TYPE_CEX8;
status = ap_qact(qid, 0, &apinfo);
if (status.response_code == AP_RESPONSE_NORMAL
&& apinfo.cat >= AP_DEVICE_TYPE_CEX2A
&& apinfo.cat <= AP_DEVICE_TYPE_CEX7)
&& apinfo.cat <= AP_DEVICE_TYPE_CEX8)
comp_type = apinfo.cat;
}
if (!comp_type)
Expand Down
1 change: 1 addition & 0 deletions drivers/s390/crypto/ap_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr)
#define AP_DEVICE_TYPE_CEX5 11
#define AP_DEVICE_TYPE_CEX6 12
#define AP_DEVICE_TYPE_CEX7 13
#define AP_DEVICE_TYPE_CEX8 14

/*
* Known function facilities
Expand Down
2 changes: 2 additions & 0 deletions drivers/s390/crypto/vfio_ap_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ static struct ap_device_id ap_queue_ids[] = {
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
{ .dev_type = AP_DEVICE_TYPE_CEX7,
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
{ .dev_type = AP_DEVICE_TYPE_CEX8,
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
{ /* end of sibling */ },
};

Expand Down
71 changes: 51 additions & 20 deletions drivers/s390/crypto/zcrypt_cex4.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright IBM Corp. 2012, 2019
* Copyright IBM Corp. 2012, 2022
* Author(s): Holger Dengler <[email protected]>
*/

Expand Down Expand Up @@ -36,8 +36,8 @@
#define CEX4_CLEANUP_TIME (900*HZ)

MODULE_AUTHOR("IBM Corporation");
MODULE_DESCRIPTION("CEX4/CEX5/CEX6/CEX7 Cryptographic Card device driver, " \
"Copyright IBM Corp. 2019");
MODULE_DESCRIPTION("CEX[45678] Cryptographic Card device driver, " \
"Copyright IBM Corp. 2022");
MODULE_LICENSE("GPL");

static struct ap_device_id zcrypt_cex4_card_ids[] = {
Expand All @@ -49,6 +49,8 @@ static struct ap_device_id zcrypt_cex4_card_ids[] = {
.match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
{ .dev_type = AP_DEVICE_TYPE_CEX7,
.match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
{ .dev_type = AP_DEVICE_TYPE_CEX8,
.match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
{ /* end of list */ },
};

Expand All @@ -63,6 +65,8 @@ static struct ap_device_id zcrypt_cex4_queue_ids[] = {
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
{ .dev_type = AP_DEVICE_TYPE_CEX7,
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
{ .dev_type = AP_DEVICE_TYPE_CEX8,
.match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
{ /* end of list */ },
};

Expand Down Expand Up @@ -395,7 +399,7 @@ static const struct attribute_group ep11_queue_attr_grp = {
};

/*
* Probe function for CEX4/CEX5/CEX6/CEX7 card device. It always
* Probe function for CEX[45678] card device. It always
* accepts the AP device since the bus_match already checked
* the hardware type.
* @ap_dev: pointer to the AP device.
Expand All @@ -414,6 +418,8 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
6, 9, 20, 17, 65, 438, 0, 0};
static const int CEX7A_SPEED_IDX[NUM_OPS] = {
6, 8, 17, 15, 54, 362, 0, 0};
static const int CEX8A_SPEED_IDX[NUM_OPS] = {
6, 8, 17, 15, 54, 362, 0, 0};

static const int CEX4C_SPEED_IDX[NUM_OPS] = {
59, 69, 308, 83, 278, 2204, 209, 40};
Expand All @@ -423,6 +429,8 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
16, 20, 32, 27, 77, 455, 24, 9};
static const int CEX7C_SPEED_IDX[NUM_OPS] = {
14, 16, 26, 23, 64, 376, 23, 8};
static const int CEX8C_SPEED_IDX[NUM_OPS] = {
14, 16, 26, 23, 64, 376, 23, 8};

static const int CEX4P_SPEED_IDX[NUM_OPS] = {
0, 0, 0, 0, 0, 0, 0, 50};
Expand All @@ -432,6 +440,8 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
0, 0, 0, 0, 0, 0, 0, 9};
static const int CEX7P_SPEED_IDX[NUM_OPS] = {
0, 0, 0, 0, 0, 0, 0, 8};
static const int CEX8P_SPEED_IDX[NUM_OPS] = {
0, 0, 0, 0, 0, 0, 0, 8};

struct ap_card *ac = to_ap_card(&ap_dev->device);
struct zcrypt_card *zc;
Expand All @@ -455,13 +465,20 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
zc->type_string = "CEX6A";
zc->user_space_type = ZCRYPT_CEX6;
zc->speed_rating = CEX6A_SPEED_IDX;
} else {
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX7) {
zc->type_string = "CEX7A";
zc->speed_rating = CEX7A_SPEED_IDX;
/* wrong user space type, just for compatibility
* with the ZCRYPT_STATUS_MASK ioctl.
*/
zc->user_space_type = ZCRYPT_CEX6;
} else {
zc->type_string = "CEX8A";
zc->speed_rating = CEX8A_SPEED_IDX;
/* wrong user space type, just for compatibility
* with the ZCRYPT_STATUS_MASK ioctl.
*/
zc->user_space_type = ZCRYPT_CEX6;
zc->speed_rating = CEX7A_SPEED_IDX;
}
zc->min_mod_size = CEX4A_MIN_MOD_SIZE;
if (ap_test_bit(&ac->functions, AP_FUNC_MEX4K) &&
Expand All @@ -477,32 +494,39 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
} else if (ap_test_bit(&ac->functions, AP_FUNC_COPRO)) {
if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX4) {
zc->type_string = "CEX4C";
/* wrong user space type, must be CEX4
zc->speed_rating = CEX4C_SPEED_IDX;
/* wrong user space type, must be CEX3C
* just keep it for cca compatibility
*/
zc->user_space_type = ZCRYPT_CEX3C;
zc->speed_rating = CEX4C_SPEED_IDX;
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX5) {
zc->type_string = "CEX5C";
/* wrong user space type, must be CEX5
zc->speed_rating = CEX5C_SPEED_IDX;
/* wrong user space type, must be CEX3C
* just keep it for cca compatibility
*/
zc->user_space_type = ZCRYPT_CEX3C;
zc->speed_rating = CEX5C_SPEED_IDX;
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX6) {
zc->type_string = "CEX6C";
/* wrong user space type, must be CEX6
zc->speed_rating = CEX6C_SPEED_IDX;
/* wrong user space type, must be CEX3C
* just keep it for cca compatibility
*/
zc->user_space_type = ZCRYPT_CEX3C;
zc->speed_rating = CEX6C_SPEED_IDX;
} else {
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX7) {
zc->type_string = "CEX7C";
/* wrong user space type, must be CEX7
zc->speed_rating = CEX7C_SPEED_IDX;
/* wrong user space type, must be CEX3C
* just keep it for cca compatibility
*/
zc->user_space_type = ZCRYPT_CEX3C;
} else {
zc->type_string = "CEX8C";
zc->speed_rating = CEX8C_SPEED_IDX;
/* wrong user space type, must be CEX3C
* just keep it for cca compatibility
*/
zc->user_space_type = ZCRYPT_CEX3C;
zc->speed_rating = CEX7C_SPEED_IDX;
}
zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
Expand All @@ -520,13 +544,20 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
zc->type_string = "CEX6P";
zc->user_space_type = ZCRYPT_CEX6;
zc->speed_rating = CEX6P_SPEED_IDX;
} else {
} else if (ac->ap_dev.device_type == AP_DEVICE_TYPE_CEX7) {
zc->type_string = "CEX7P";
zc->speed_rating = CEX7P_SPEED_IDX;
/* wrong user space type, just for compatibility
* with the ZCRYPT_STATUS_MASK ioctl.
*/
zc->user_space_type = ZCRYPT_CEX6;
} else {
zc->type_string = "CEX8P";
zc->speed_rating = CEX8P_SPEED_IDX;
/* wrong user space type, just for compatibility
* with the ZCRYPT_STATUS_MASK ioctl.
*/
zc->user_space_type = ZCRYPT_CEX6;
zc->speed_rating = CEX7P_SPEED_IDX;
}
zc->min_mod_size = CEX4C_MIN_MOD_SIZE;
zc->max_mod_size = CEX4C_MAX_MOD_SIZE;
Expand Down Expand Up @@ -563,7 +594,7 @@ static int zcrypt_cex4_card_probe(struct ap_device *ap_dev)
}

/*
* This is called to remove the CEX4/CEX5/CEX6/CEX7 card driver
* This is called to remove the CEX[45678] card driver
* information if an AP card device is removed.
*/
static void zcrypt_cex4_card_remove(struct ap_device *ap_dev)
Expand All @@ -587,7 +618,7 @@ static struct ap_driver zcrypt_cex4_card_driver = {
};

/*
* Probe function for CEX4/CEX5/CEX6/CEX7 queue device. It always
* Probe function for CEX[45678] queue device. It always
* accepts the AP device since the bus_match already checked
* the hardware type.
* @ap_dev: pointer to the AP device.
Expand Down Expand Up @@ -653,7 +684,7 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev)
}

/*
* This is called to remove the CEX4/CEX5/CEX6/CEX7 queue driver
* This is called to remove the CEX[45678] queue driver
* information if an AP queue device is removed.
*/
static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev)
Expand Down

0 comments on commit 985214a

Please sign in to comment.