From c2567f8ffa2704f6f2f81013e9a590deca5a865f Mon Sep 17 00:00:00 2001 From: Felix Beck Date: Wed, 5 Jan 2011 12:47:47 +0100 Subject: [S390] zcrypt: cope with cca restriction of cex3 The cca on the crypto adapter has a restriction in the size of the exponent if a key with a modulus bigger than 2048 bit is used. Thus in that case we have to avoid that the crypto device driver thinks the adapter is defect and sets it offline. Therfore a new member for the zcrypt_device struct called max_exp_bit_length is introduced. This will be set the first time the cca returns the error code function not implemented. If this is done with an adapter twice it will return -EINVAL. Signed-off-by: Felix Beck Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index 8e7ffbf..88ebd11 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h @@ -109,6 +109,7 @@ struct zcrypt_device { int request_count; /* # current requests. */ struct ap_message reply; /* Per-device reply structure. */ + int max_exp_bit_length; }; struct zcrypt_device *zcrypt_device_alloc(size_t); diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c index def0901..2176d00 100644 --- a/drivers/s390/crypto/zcrypt_cex2a.c +++ b/drivers/s390/crypto/zcrypt_cex2a.c @@ -441,6 +441,7 @@ static int zcrypt_cex2a_probe(struct ap_device *ap_dev) zdev->max_mod_size = CEX2A_MAX_MOD_SIZE; zdev->short_crt = 1; zdev->speed_rating = CEX2A_SPEED_RATING; + zdev->max_exp_bit_length = CEX2A_MAX_MOD_SIZE; break; case AP_DEVICE_TYPE_CEX3A: zdev = zcrypt_device_alloc(CEX3A_MAX_RESPONSE_SIZE); @@ -450,8 +451,11 @@ static int zcrypt_cex2a_probe(struct ap_device *ap_dev) zdev->type_string = "CEX3A"; zdev->min_mod_size = CEX2A_MIN_MOD_SIZE; zdev->max_mod_size = CEX2A_MAX_MOD_SIZE; - if (ap_4096_commands_available(ap_dev->qid)) + zdev->max_exp_bit_length = CEX2A_MAX_MOD_SIZE; + if (ap_4096_commands_available(ap_dev->qid)) { zdev->max_mod_size = CEX3A_MAX_MOD_SIZE; + zdev->max_exp_bit_length = CEX3A_MAX_MOD_SIZE; + } zdev->short_crt = 1; zdev->speed_rating = CEX3A_SPEED_RATING; break; diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c index 09e934b..1afb69c 100644 --- a/drivers/s390/crypto/zcrypt_pcica.c +++ b/drivers/s390/crypto/zcrypt_pcica.c @@ -373,6 +373,7 @@ static int zcrypt_pcica_probe(struct ap_device *ap_dev) zdev->min_mod_size = PCICA_MIN_MOD_SIZE; zdev->max_mod_size = PCICA_MAX_MOD_SIZE; zdev->speed_rating = PCICA_SPEED_RATING; + zdev->max_exp_bit_length = PCICA_MAX_MOD_SIZE; ap_dev->reply = &zdev->reply; ap_dev->private = zdev; rc = zcrypt_device_register(zdev); diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c index 9dec5c7..aa4c050 100644 --- a/drivers/s390/crypto/zcrypt_pcicc.c +++ b/drivers/s390/crypto/zcrypt_pcicc.c @@ -579,6 +579,7 @@ static int zcrypt_pcicc_probe(struct ap_device *ap_dev) zdev->min_mod_size = PCICC_MIN_MOD_SIZE; zdev->max_mod_size = PCICC_MAX_MOD_SIZE; zdev->speed_rating = PCICC_SPEED_RATING; + zdev->max_exp_bit_length = PCICC_MAX_MOD_SIZE; ap_dev->reply = &zdev->reply; ap_dev->private = zdev; rc = zcrypt_device_register(zdev); diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c index fc8eb9d..4f85eb7 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/drivers/s390/crypto/zcrypt_pcixcc.c @@ -567,6 +567,15 @@ static int convert_response_ica(struct zcrypt_device *zdev, case TYPE88_RSP_CODE: return convert_error(zdev, reply); case TYPE86_RSP_CODE: + if (msg->cprbx.ccp_rtcode && + (msg->cprbx.ccp_rscode == 0x14f) && + (outputdatalength > 256)) { + if (zdev->max_exp_bit_length <= 17) { + zdev->max_exp_bit_length = 17; + return -EAGAIN; + } else + return -EINVAL; + } if (msg->hdr.reply_code) return convert_error(zdev, reply); if (msg->cprbx.cprb_ver_id == 0x02) @@ -1052,11 +1061,13 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING; zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE; + zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE; } else { zdev->type_string = "PCIXCC_MCL3"; zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING; zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE; zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE; + zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE; } break; case AP_DEVICE_TYPE_CEX2C: @@ -1065,6 +1076,7 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) zdev->speed_rating = CEX2C_SPEED_RATING; zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE; zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE; + zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE; break; case AP_DEVICE_TYPE_CEX3C: zdev->user_space_type = ZCRYPT_CEX3C; @@ -1072,6 +1084,7 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) zdev->speed_rating = CEX3C_SPEED_RATING; zdev->min_mod_size = CEX3C_MIN_MOD_SIZE; zdev->max_mod_size = CEX3C_MAX_MOD_SIZE; + zdev->max_exp_bit_length = CEX3C_MAX_MOD_SIZE; break; default: goto out_free; -- cgit v0.10.2