Commit 88fbf183 authored by Eric Rossman's avatar Eric Rossman Committed by Linus Torvalds

[PATCH] s390: add support for cex2a crypto cards

Signed-off-by: default avatarEric Rossman <edrossma@us.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent fb6958a5
/* /*
* linux/drivers/s390/crypto/z90common.h * linux/drivers/s390/crypto/z90common.h
* *
* z90crypt 1.3.2 * z90crypt 1.3.3
* *
* Copyright (C) 2001, 2004 IBM Corporation * Copyright (C) 2001, 2005 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com) * Author(s): Robert Burroughs (burrough@us.ibm.com)
* Eric Rossman (edrossma@us.ibm.com) * Eric Rossman (edrossma@us.ibm.com)
* *
...@@ -91,12 +91,13 @@ enum hdstat { ...@@ -91,12 +91,13 @@ enum hdstat {
#define TSQ_FATAL_ERROR 34 #define TSQ_FATAL_ERROR 34
#define RSQ_FATAL_ERROR 35 #define RSQ_FATAL_ERROR 35
#define Z90CRYPT_NUM_TYPES 5 #define Z90CRYPT_NUM_TYPES 6
#define PCICA 0 #define PCICA 0
#define PCICC 1 #define PCICC 1
#define PCIXCC_MCL2 2 #define PCIXCC_MCL2 2
#define PCIXCC_MCL3 3 #define PCIXCC_MCL3 3
#define CEX2C 4 #define CEX2C 4
#define CEX2A 5
#define NILDEV -1 #define NILDEV -1
#define ANYDEV -1 #define ANYDEV -1
#define PCIXCC_UNK -2 #define PCIXCC_UNK -2
...@@ -105,7 +106,7 @@ enum hdevice_type { ...@@ -105,7 +106,7 @@ enum hdevice_type {
PCICC_HW = 3, PCICC_HW = 3,
PCICA_HW = 4, PCICA_HW = 4,
PCIXCC_HW = 5, PCIXCC_HW = 5,
OTHER_HW = 6, CEX2A_HW = 6,
CEX2C_HW = 7 CEX2C_HW = 7
}; };
......
/* /*
* linux/drivers/s390/crypto/z90crypt.h * linux/drivers/s390/crypto/z90crypt.h
* *
* z90crypt 1.3.2 * z90crypt 1.3.3
* *
* Copyright (C) 2001, 2004 IBM Corporation * Copyright (C) 2001, 2005 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com) * Author(s): Robert Burroughs (burrough@us.ibm.com)
* Eric Rossman (edrossma@us.ibm.com) * Eric Rossman (edrossma@us.ibm.com)
* *
...@@ -29,11 +29,11 @@ ...@@ -29,11 +29,11 @@
#include <linux/ioctl.h> #include <linux/ioctl.h>
#define VERSION_Z90CRYPT_H "$Revision: 1.11 $" #define VERSION_Z90CRYPT_H "$Revision: 1.2.2.4 $"
#define z90crypt_VERSION 1 #define z90crypt_VERSION 1
#define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards #define z90crypt_RELEASE 3 // 2 = PCIXCC, 3 = rewrite for coding standards
#define z90crypt_VARIANT 2 // 2 = added PCIXCC MCL3 and CEX2C support #define z90crypt_VARIANT 3 // 3 = CEX2A support
/** /**
* struct ica_rsa_modexpo * struct ica_rsa_modexpo
...@@ -122,6 +122,9 @@ struct ica_rsa_modexpo_crt { ...@@ -122,6 +122,9 @@ struct ica_rsa_modexpo_crt {
* Z90STAT_CEX2CCOUNT * Z90STAT_CEX2CCOUNT
* Return an integer count of all CEX2Cs. * Return an integer count of all CEX2Cs.
* *
* Z90STAT_CEX2ACOUNT
* Return an integer count of all CEX2As.
*
* Z90STAT_REQUESTQ_COUNT * Z90STAT_REQUESTQ_COUNT
* Return an integer count of the number of entries waiting to be * Return an integer count of the number of entries waiting to be
* sent to a device. * sent to a device.
...@@ -144,6 +147,7 @@ struct ica_rsa_modexpo_crt { ...@@ -144,6 +147,7 @@ struct ica_rsa_modexpo_crt {
* 0x03: PCIXCC_MCL2 * 0x03: PCIXCC_MCL2
* 0x04: PCIXCC_MCL3 * 0x04: PCIXCC_MCL3
* 0x05: CEX2C * 0x05: CEX2C
* 0x06: CEX2A
* 0x0d: device is disabled via the proc filesystem * 0x0d: device is disabled via the proc filesystem
* *
* Z90STAT_QDEPTH_MASK * Z90STAT_QDEPTH_MASK
...@@ -199,6 +203,7 @@ struct ica_rsa_modexpo_crt { ...@@ -199,6 +203,7 @@ struct ica_rsa_modexpo_crt {
#define Z90STAT_PCIXCCMCL2COUNT _IOR(Z90_IOCTL_MAGIC, 0x4b, int) #define Z90STAT_PCIXCCMCL2COUNT _IOR(Z90_IOCTL_MAGIC, 0x4b, int)
#define Z90STAT_PCIXCCMCL3COUNT _IOR(Z90_IOCTL_MAGIC, 0x4c, int) #define Z90STAT_PCIXCCMCL3COUNT _IOR(Z90_IOCTL_MAGIC, 0x4c, int)
#define Z90STAT_CEX2CCOUNT _IOR(Z90_IOCTL_MAGIC, 0x4d, int) #define Z90STAT_CEX2CCOUNT _IOR(Z90_IOCTL_MAGIC, 0x4d, int)
#define Z90STAT_CEX2ACOUNT _IOR(Z90_IOCTL_MAGIC, 0x4e, int)
#define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int) #define Z90STAT_REQUESTQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x44, int)
#define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int) #define Z90STAT_PENDINGQ_COUNT _IOR(Z90_IOCTL_MAGIC, 0x45, int)
#define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int) #define Z90STAT_TOTALOPEN_COUNT _IOR(Z90_IOCTL_MAGIC, 0x46, int)
......
/* /*
* linux/drivers/s390/crypto/z90hardware.c * linux/drivers/s390/crypto/z90hardware.c
* *
* z90crypt 1.3.2 * z90crypt 1.3.3
* *
* Copyright (C) 2001, 2004 IBM Corporation * Copyright (C) 2001, 2005 IBM Corporation
* Author(s): Robert Burroughs (burrough@us.ibm.com) * Author(s): Robert Burroughs (burrough@us.ibm.com)
* Eric Rossman (edrossma@us.ibm.com) * Eric Rossman (edrossma@us.ibm.com)
* *
...@@ -648,6 +648,87 @@ static struct cca_public_sec static_cca_pub_sec = { ...@@ -648,6 +648,87 @@ static struct cca_public_sec static_cca_pub_sec = {
#define RESPONSE_CPRB_SIZE 0x000006B8 #define RESPONSE_CPRB_SIZE 0x000006B8
#define RESPONSE_CPRBX_SIZE 0x00000724 #define RESPONSE_CPRBX_SIZE 0x00000724
struct type50_hdr {
u8 reserved1;
u8 msg_type_code;
u16 msg_len;
u8 reserved2;
u8 ignored;
u16 reserved3;
};
#define TYPE50_TYPE_CODE 0x50
#define TYPE50_MEB1_LEN (sizeof(struct type50_meb1_msg))
#define TYPE50_MEB2_LEN (sizeof(struct type50_meb2_msg))
#define TYPE50_CRB1_LEN (sizeof(struct type50_crb1_msg))
#define TYPE50_CRB2_LEN (sizeof(struct type50_crb2_msg))
#define TYPE50_MEB1_FMT 0x0001
#define TYPE50_MEB2_FMT 0x0002
#define TYPE50_CRB1_FMT 0x0011
#define TYPE50_CRB2_FMT 0x0012
struct type50_meb1_msg {
struct type50_hdr header;
u16 keyblock_type;
u8 reserved[6];
u8 exponent[128];
u8 modulus[128];
u8 message[128];
};
struct type50_meb2_msg {
struct type50_hdr header;
u16 keyblock_type;
u8 reserved[6];
u8 exponent[256];
u8 modulus[256];
u8 message[256];
};
struct type50_crb1_msg {
struct type50_hdr header;
u16 keyblock_type;
u8 reserved[6];
u8 p[64];
u8 q[64];
u8 dp[64];
u8 dq[64];
u8 u[64];
u8 message[128];
};
struct type50_crb2_msg {
struct type50_hdr header;
u16 keyblock_type;
u8 reserved[6];
u8 p[128];
u8 q[128];
u8 dp[128];
u8 dq[128];
u8 u[128];
u8 message[256];
};
union type50_msg {
struct type50_meb1_msg meb1;
struct type50_meb2_msg meb2;
struct type50_crb1_msg crb1;
struct type50_crb2_msg crb2;
};
struct type80_hdr {
u8 reserved1;
u8 type;
u16 len;
u8 code;
u8 reserved2[3];
u8 reserved3[8];
};
#define TYPE80_RSP_CODE 0x80
struct error_hdr { struct error_hdr {
unsigned char reserved1; unsigned char reserved1;
unsigned char type; unsigned char type;
...@@ -657,6 +738,7 @@ struct error_hdr { ...@@ -657,6 +738,7 @@ struct error_hdr {
}; };
#define TYPE82_RSP_CODE 0x82 #define TYPE82_RSP_CODE 0x82
#define TYPE88_RSP_CODE 0x88
#define REP82_ERROR_MACHINE_FAILURE 0x10 #define REP82_ERROR_MACHINE_FAILURE 0x10
#define REP82_ERROR_PREEMPT_FAILURE 0x12 #define REP82_ERROR_PREEMPT_FAILURE 0x12
...@@ -679,6 +761,22 @@ struct error_hdr { ...@@ -679,6 +761,22 @@ struct error_hdr {
#define REP82_ERROR_PACKET_TRUNCATED 0xA0 #define REP82_ERROR_PACKET_TRUNCATED 0xA0
#define REP82_ERROR_ZERO_BUFFER_LEN 0xB0 #define REP82_ERROR_ZERO_BUFFER_LEN 0xB0
#define REP88_ERROR_MODULE_FAILURE 0x10
#define REP88_ERROR_MODULE_TIMEOUT 0x11
#define REP88_ERROR_MODULE_NOTINIT 0x13
#define REP88_ERROR_MODULE_NOTAVAIL 0x14
#define REP88_ERROR_MODULE_DISABLED 0x15
#define REP88_ERROR_MODULE_IN_DIAGN 0x17
#define REP88_ERROR_FASTPATH_DISABLD 0x19
#define REP88_ERROR_MESSAGE_TYPE 0x20
#define REP88_ERROR_MESSAGE_MALFORMD 0x22
#define REP88_ERROR_MESSAGE_LENGTH 0x23
#define REP88_ERROR_RESERVED_FIELD 0x24
#define REP88_ERROR_KEY_TYPE 0x34
#define REP88_ERROR_INVALID_KEY 0x82
#define REP88_ERROR_OPERAND 0x84
#define REP88_ERROR_OPERAND_EVEN_MOD 0x85
#define CALLER_HEADER 12 #define CALLER_HEADER 12
static inline int static inline int
...@@ -1029,10 +1127,6 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type) ...@@ -1029,10 +1127,6 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
stat = HD_ONLINE; stat = HD_ONLINE;
*q_depth = t_depth + 1; *q_depth = t_depth + 1;
switch (t_dev_type) { switch (t_dev_type) {
case OTHER_HW:
stat = HD_NOT_THERE;
*dev_type = NILDEV;
break;
case PCICA_HW: case PCICA_HW:
*dev_type = PCICA; *dev_type = PCICA;
break; break;
...@@ -1045,6 +1139,9 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type) ...@@ -1045,6 +1139,9 @@ query_online(int deviceNr, int cdx, int resetNr, int *q_depth, int *dev_type)
case CEX2C_HW: case CEX2C_HW:
*dev_type = CEX2C; *dev_type = CEX2C;
break; break;
case CEX2A_HW:
*dev_type = CEX2A;
break;
default: default:
*dev_type = NILDEV; *dev_type = NILDEV;
break; break;
...@@ -2029,6 +2126,177 @@ ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx, ...@@ -2029,6 +2126,177 @@ ICACRT_msg_to_type6CRT_msgX(struct ica_rsa_modexpo_crt *icaMsg_p, int cdx,
return 0; return 0;
} }
static int
ICAMEX_msg_to_type50MEX_msg(struct ica_rsa_modexpo *icaMex_p, int *z90cMsg_l_p,
union type50_msg *z90cMsg_p)
{
int mod_len, msg_size, mod_tgt_len, exp_tgt_len, inp_tgt_len;
unsigned char *mod_tgt, *exp_tgt, *inp_tgt;
union type50_msg *tmp_type50_msg;
mod_len = icaMex_p->inputdatalength;
msg_size = ((mod_len <= 128) ? TYPE50_MEB1_LEN : TYPE50_MEB2_LEN) +
CALLER_HEADER;
memset(z90cMsg_p, 0, msg_size);
tmp_type50_msg = (union type50_msg *)
((unsigned char *) z90cMsg_p + CALLER_HEADER);
tmp_type50_msg->meb1.header.msg_type_code = TYPE50_TYPE_CODE;
if (mod_len <= 128) {
tmp_type50_msg->meb1.header.msg_len = TYPE50_MEB1_LEN;
tmp_type50_msg->meb1.keyblock_type = TYPE50_MEB1_FMT;
mod_tgt = tmp_type50_msg->meb1.modulus;
mod_tgt_len = sizeof(tmp_type50_msg->meb1.modulus);
exp_tgt = tmp_type50_msg->meb1.exponent;
exp_tgt_len = sizeof(tmp_type50_msg->meb1.exponent);
inp_tgt = tmp_type50_msg->meb1.message;
inp_tgt_len = sizeof(tmp_type50_msg->meb1.message);
} else {
tmp_type50_msg->meb2.header.msg_len = TYPE50_MEB2_LEN;
tmp_type50_msg->meb2.keyblock_type = TYPE50_MEB2_FMT;
mod_tgt = tmp_type50_msg->meb2.modulus;
mod_tgt_len = sizeof(tmp_type50_msg->meb2.modulus);
exp_tgt = tmp_type50_msg->meb2.exponent;
exp_tgt_len = sizeof(tmp_type50_msg->meb2.exponent);
inp_tgt = tmp_type50_msg->meb2.message;
inp_tgt_len = sizeof(tmp_type50_msg->meb2.message);
}
mod_tgt += (mod_tgt_len - mod_len);
if (copy_from_user(mod_tgt, icaMex_p->n_modulus, mod_len))
return SEN_RELEASED;
if (is_empty(mod_tgt, mod_len))
return SEN_USER_ERROR;
exp_tgt += (exp_tgt_len - mod_len);
if (copy_from_user(exp_tgt, icaMex_p->b_key, mod_len))
return SEN_RELEASED;
if (is_empty(exp_tgt, mod_len))
return SEN_USER_ERROR;
inp_tgt += (inp_tgt_len - mod_len);
if (copy_from_user(inp_tgt, icaMex_p->inputdata, mod_len))
return SEN_RELEASED;
if (is_empty(inp_tgt, mod_len))
return SEN_USER_ERROR;
*z90cMsg_l_p = msg_size - CALLER_HEADER;
return 0;
}
static int
ICACRT_msg_to_type50CRT_msg(struct ica_rsa_modexpo_crt *icaMsg_p,
int *z90cMsg_l_p, union type50_msg *z90cMsg_p)
{
int mod_len, short_len, long_len, tmp_size, p_tgt_len, q_tgt_len,
dp_tgt_len, dq_tgt_len, u_tgt_len, inp_tgt_len, long_offset;
unsigned char *p_tgt, *q_tgt, *dp_tgt, *dq_tgt, *u_tgt, *inp_tgt,
temp[8];
union type50_msg *tmp_type50_msg;
mod_len = icaMsg_p->inputdatalength;
short_len = mod_len / 2;
long_len = mod_len / 2 + 8;
long_offset = 0;
if (long_len > 128) {
memset(temp, 0x00, sizeof(temp));
if (copy_from_user(temp, icaMsg_p->np_prime, long_len-128))
return SEN_RELEASED;
if (!is_empty(temp, 8))
return SEN_NOT_AVAIL;
if (copy_from_user(temp, icaMsg_p->bp_key, long_len-128))
return SEN_RELEASED;
if (!is_empty(temp, 8))
return SEN_NOT_AVAIL;
if (copy_from_user(temp, icaMsg_p->u_mult_inv, long_len-128))
return SEN_RELEASED;
if (!is_empty(temp, 8))
return SEN_NOT_AVAIL;
long_offset = long_len - 128;
long_len = 128;
}
tmp_size = ((mod_len <= 128) ? TYPE50_CRB1_LEN : TYPE50_CRB2_LEN) +
CALLER_HEADER;
memset(z90cMsg_p, 0, tmp_size);
tmp_type50_msg = (union type50_msg *)
((unsigned char *) z90cMsg_p + CALLER_HEADER);
tmp_type50_msg->crb1.header.msg_type_code = TYPE50_TYPE_CODE;
if (long_len <= 64) {
tmp_type50_msg->crb1.header.msg_len = TYPE50_CRB1_LEN;
tmp_type50_msg->crb1.keyblock_type = TYPE50_CRB1_FMT;
p_tgt = tmp_type50_msg->crb1.p;
p_tgt_len = sizeof(tmp_type50_msg->crb1.p);
q_tgt = tmp_type50_msg->crb1.q;
q_tgt_len = sizeof(tmp_type50_msg->crb1.q);
dp_tgt = tmp_type50_msg->crb1.dp;
dp_tgt_len = sizeof(tmp_type50_msg->crb1.dp);
dq_tgt = tmp_type50_msg->crb1.dq;
dq_tgt_len = sizeof(tmp_type50_msg->crb1.dq);
u_tgt = tmp_type50_msg->crb1.u;
u_tgt_len = sizeof(tmp_type50_msg->crb1.u);
inp_tgt = tmp_type50_msg->crb1.message;
inp_tgt_len = sizeof(tmp_type50_msg->crb1.message);
} else {
tmp_type50_msg->crb2.header.msg_len = TYPE50_CRB2_LEN;
tmp_type50_msg->crb2.keyblock_type = TYPE50_CRB2_FMT;
p_tgt = tmp_type50_msg->crb2.p;
p_tgt_len = sizeof(tmp_type50_msg->crb2.p);
q_tgt = tmp_type50_msg->crb2.q;
q_tgt_len = sizeof(tmp_type50_msg->crb2.q);
dp_tgt = tmp_type50_msg->crb2.dp;
dp_tgt_len = sizeof(tmp_type50_msg->crb2.dp);
dq_tgt = tmp_type50_msg->crb2.dq;
dq_tgt_len = sizeof(tmp_type50_msg->crb2.dq);
u_tgt = tmp_type50_msg->crb2.u;
u_tgt_len = sizeof(tmp_type50_msg->crb2.u);
inp_tgt = tmp_type50_msg->crb2.message;
inp_tgt_len = sizeof(tmp_type50_msg->crb2.message);
}
p_tgt += (p_tgt_len - long_len);
if (copy_from_user(p_tgt, icaMsg_p->np_prime + long_offset, long_len))
return SEN_RELEASED;
if (is_empty(p_tgt, long_len))
return SEN_USER_ERROR;
q_tgt += (q_tgt_len - short_len);
if (copy_from_user(q_tgt, icaMsg_p->nq_prime, short_len))
return SEN_RELEASED;
if (is_empty(q_tgt, short_len))
return SEN_USER_ERROR;
dp_tgt += (dp_tgt_len - long_len);
if (copy_from_user(dp_tgt, icaMsg_p->bp_key + long_offset, long_len))
return SEN_RELEASED;
if (is_empty(dp_tgt, long_len))
return SEN_USER_ERROR;
dq_tgt += (dq_tgt_len - short_len);
if (copy_from_user(dq_tgt, icaMsg_p->bq_key, short_len))
return SEN_RELEASED;
if (is_empty(dq_tgt, short_len))
return SEN_USER_ERROR;
u_tgt += (u_tgt_len - long_len);
if (copy_from_user(u_tgt, icaMsg_p->u_mult_inv + long_offset, long_len))
return SEN_RELEASED;
if (is_empty(u_tgt, long_len))
return SEN_USER_ERROR;
inp_tgt += (inp_tgt_len - mod_len);
if (copy_from_user(inp_tgt, icaMsg_p->inputdata, mod_len))
return SEN_RELEASED;
if (is_empty(inp_tgt, mod_len))
return SEN_USER_ERROR;
*z90cMsg_l_p = tmp_size - CALLER_HEADER;
return 0;
}
int int
convert_request(unsigned char *buffer, int func, unsigned short function, convert_request(unsigned char *buffer, int func, unsigned short function,
int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p) int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p)
...@@ -2071,6 +2339,16 @@ convert_request(unsigned char *buffer, int func, unsigned short function, ...@@ -2071,6 +2339,16 @@ convert_request(unsigned char *buffer, int func, unsigned short function,
cdx, msg_l_p, (struct type6_msg *) msg_p, cdx, msg_l_p, (struct type6_msg *) msg_p,
dev_type); dev_type);
} }
if (dev_type == CEX2A) {
if (func == ICARSACRT)
return ICACRT_msg_to_type50CRT_msg(
(struct ica_rsa_modexpo_crt *) buffer,
msg_l_p, (union type50_msg *) msg_p);
else
return ICAMEX_msg_to_type50MEX_msg(
(struct ica_rsa_modexpo *) buffer,
msg_l_p, (union type50_msg *) msg_p);
}
return 0; return 0;
} }
...@@ -2081,8 +2359,8 @@ unset_ext_bitlens(void) ...@@ -2081,8 +2359,8 @@ unset_ext_bitlens(void)
{ {
if (!ext_bitlens_msg_count) { if (!ext_bitlens_msg_count) {
PRINTK("Unable to use coprocessors for extended bitlengths. " PRINTK("Unable to use coprocessors for extended bitlengths. "
"Using PCICAs (if present) for extended bitlengths. " "Using PCICAs/CEX2As (if present) for extended "
"This is not an error.\n"); "bitlengths. This is not an error.\n");
ext_bitlens_msg_count++; ext_bitlens_msg_count++;
} }
ext_bitlens = 0; ext_bitlens = 0;
...@@ -2094,6 +2372,7 @@ convert_response(unsigned char *response, unsigned char *buffer, ...@@ -2094,6 +2372,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
{ {
struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer; struct ica_rsa_modexpo *icaMsg_p = (struct ica_rsa_modexpo *) buffer;
struct error_hdr *errh_p = (struct error_hdr *) response; struct error_hdr *errh_p = (struct error_hdr *) response;
struct type80_hdr *t80h_p = (struct type80_hdr *) response;
struct type84_hdr *t84h_p = (struct type84_hdr *) response; struct type84_hdr *t84h_p = (struct type84_hdr *) response;
struct type86_fmt2_msg *t86m_p = (struct type86_fmt2_msg *) response; struct type86_fmt2_msg *t86m_p = (struct type86_fmt2_msg *) response;
int reply_code, service_rc, service_rs, src_l; int reply_code, service_rc, service_rs, src_l;
...@@ -2108,6 +2387,7 @@ convert_response(unsigned char *response, unsigned char *buffer, ...@@ -2108,6 +2387,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
src_l = 0; src_l = 0;
switch (errh_p->type) { switch (errh_p->type) {
case TYPE82_RSP_CODE: case TYPE82_RSP_CODE:
case TYPE88_RSP_CODE:
reply_code = errh_p->reply_code; reply_code = errh_p->reply_code;
src_p = (unsigned char *)errh_p; src_p = (unsigned char *)errh_p;
PRINTK("Hardware error: Type %02X Message Header: " PRINTK("Hardware error: Type %02X Message Header: "
...@@ -2116,6 +2396,10 @@ convert_response(unsigned char *response, unsigned char *buffer, ...@@ -2116,6 +2396,10 @@ convert_response(unsigned char *response, unsigned char *buffer,
src_p[0], src_p[1], src_p[2], src_p[3], src_p[0], src_p[1], src_p[2], src_p[3],
src_p[4], src_p[5], src_p[6], src_p[7]); src_p[4], src_p[5], src_p[6], src_p[7]);
break; break;
case TYPE80_RSP_CODE:
src_l = icaMsg_p->outputdatalength;
src_p = response + (int)t80h_p->len - src_l;
break;
case TYPE84_RSP_CODE: case TYPE84_RSP_CODE:
src_l = icaMsg_p->outputdatalength; src_l = icaMsg_p->outputdatalength;
src_p = response + (int)t84h_p->len - src_l; src_p = response + (int)t84h_p->len - src_l;
...@@ -2202,6 +2486,7 @@ convert_response(unsigned char *response, unsigned char *buffer, ...@@ -2202,6 +2486,7 @@ convert_response(unsigned char *response, unsigned char *buffer,
if (reply_code) if (reply_code)
switch (reply_code) { switch (reply_code) {
case REP82_ERROR_OPERAND_INVALID: case REP82_ERROR_OPERAND_INVALID:
case REP88_ERROR_MESSAGE_MALFORMD:
return REC_OPERAND_INV; return REC_OPERAND_INV;
case REP82_ERROR_OPERAND_SIZE: case REP82_ERROR_OPERAND_SIZE:
return REC_OPERAND_SIZE; return REC_OPERAND_SIZE;
......
...@@ -228,7 +228,7 @@ struct device_x { ...@@ -228,7 +228,7 @@ struct device_x {
*/ */
struct device { struct device {
int dev_type; // PCICA, PCICC, PCIXCC_MCL2, int dev_type; // PCICA, PCICC, PCIXCC_MCL2,
// PCIXCC_MCL3, CEX2C // PCIXCC_MCL3, CEX2C, CEX2A
enum devstat dev_stat; // current device status enum devstat dev_stat; // current device status
int dev_self_x; // Index in array int dev_self_x; // Index in array
int disabled; // Set when device is in error int disabled; // Set when device is in error
...@@ -295,26 +295,30 @@ struct caller { ...@@ -295,26 +295,30 @@ struct caller {
/** /**
* Function prototypes from z90hardware.c * Function prototypes from z90hardware.c
*/ */
enum hdstat query_online(int, int, int, int *, int *); enum hdstat query_online(int deviceNr, int cdx, int resetNr, int *q_depth,
enum devstat reset_device(int, int, int); int *dev_type);
enum devstat send_to_AP(int, int, int, unsigned char *); enum devstat reset_device(int deviceNr, int cdx, int resetNr);
enum devstat receive_from_AP(int, int, int, unsigned char *, unsigned char *); enum devstat send_to_AP(int dev_nr, int cdx, int msg_len, unsigned char *msg_ext);
int convert_request(unsigned char *, int, short, int, int, int *, enum devstat receive_from_AP(int dev_nr, int cdx, int resplen,
unsigned char *); unsigned char *resp, unsigned char *psmid);
int convert_response(unsigned char *, unsigned char *, int *, unsigned char *); int convert_request(unsigned char *buffer, int func, unsigned short function,
int cdx, int dev_type, int *msg_l_p, unsigned char *msg_p);
int convert_response(unsigned char *response, unsigned char *buffer,
int *respbufflen_p, unsigned char *resp_buff);
/** /**
* Low level function prototypes * Low level function prototypes
*/ */
static int create_z90crypt(int *); static int create_z90crypt(int *cdx_p);
static int refresh_z90crypt(int *); static int refresh_z90crypt(int *cdx_p);
static int find_crypto_devices(struct status *); static int find_crypto_devices(struct status *deviceMask);
static int create_crypto_device(int); static int create_crypto_device(int index);
static int destroy_crypto_device(int); static int destroy_crypto_device(int index);
static void destroy_z90crypt(void); static void destroy_z90crypt(void);
static int refresh_index_array(struct status *, struct device_x *); static int refresh_index_array(struct status *status_str,
static int probe_device_type(struct device *); struct device_x *index_array);
static int probe_PCIXCC_type(struct device *); static int probe_device_type(struct device *devPtr);
static int probe_PCIXCC_type(struct device *devPtr);
/** /**
* proc fs definitions * proc fs definitions
...@@ -425,7 +429,7 @@ static struct miscdevice z90crypt_misc_device = { ...@@ -425,7 +429,7 @@ static struct miscdevice z90crypt_misc_device = {
MODULE_AUTHOR("zSeries Linux Crypto Team: Robert H. Burroughs, Eric D. Rossman" MODULE_AUTHOR("zSeries Linux Crypto Team: Robert H. Burroughs, Eric D. Rossman"
"and Jochen Roehrig"); "and Jochen Roehrig");
MODULE_DESCRIPTION("zSeries Linux Cryptographic Coprocessor device driver, " MODULE_DESCRIPTION("zSeries Linux Cryptographic Coprocessor device driver, "
"Copyright 2001, 2004 IBM Corporation"); "Copyright 2001, 2005 IBM Corporation");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_param(domain, int, 0); module_param(domain, int, 0);
MODULE_PARM_DESC(domain, "domain index for device"); MODULE_PARM_DESC(domain, "domain index for device");
...@@ -859,6 +863,12 @@ get_status_CEX2Ccount(void) ...@@ -859,6 +863,12 @@ get_status_CEX2Ccount(void)
return z90crypt.hdware_info->type_mask[CEX2C].st_count; return z90crypt.hdware_info->type_mask[CEX2C].st_count;
} }
static inline int
get_status_CEX2Acount(void)
{
return z90crypt.hdware_info->type_mask[CEX2A].st_count;
}
static inline int static inline int
get_status_requestq_count(void) get_status_requestq_count(void)
{ {
...@@ -1008,11 +1018,13 @@ static inline int ...@@ -1008,11 +1018,13 @@ static inline int
select_device_type(int *dev_type_p, int bytelength) select_device_type(int *dev_type_p, int bytelength)
{ {
static int count = 0; static int count = 0;
int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, index_to_use; int PCICA_avail, PCIXCC_MCL3_avail, CEX2C_avail, CEX2A_avail,
index_to_use;
struct status *stat; struct status *stat;
if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) && if ((*dev_type_p != PCICC) && (*dev_type_p != PCICA) &&
(*dev_type_p != PCIXCC_MCL2) && (*dev_type_p != PCIXCC_MCL3) && (*dev_type_p != PCIXCC_MCL2) && (*dev_type_p != PCIXCC_MCL3) &&
(*dev_type_p != CEX2C) && (*dev_type_p != ANYDEV)) (*dev_type_p != CEX2C) && (*dev_type_p != CEX2A) &&
(*dev_type_p != ANYDEV))
return -1; return -1;
if (*dev_type_p != ANYDEV) { if (*dev_type_p != ANYDEV) {
stat = &z90crypt.hdware_info->type_mask[*dev_type_p]; stat = &z90crypt.hdware_info->type_mask[*dev_type_p];
...@@ -1022,7 +1034,13 @@ select_device_type(int *dev_type_p, int bytelength) ...@@ -1022,7 +1034,13 @@ select_device_type(int *dev_type_p, int bytelength)
return -1; return -1;
} }
/* Assumption: PCICA, PCIXCC_MCL3, and CEX2C are all similar in speed */ /**
* Assumption: PCICA, PCIXCC_MCL3, CEX2C, and CEX2A are all similar in
* speed.
*
* PCICA and CEX2A do NOT co-exist, so it would be either one or the
* other present.
*/
stat = &z90crypt.hdware_info->type_mask[PCICA]; stat = &z90crypt.hdware_info->type_mask[PCICA];
PCICA_avail = stat->st_count - PCICA_avail = stat->st_count -
(stat->disabled_count + stat->user_disabled_count); (stat->disabled_count + stat->user_disabled_count);
...@@ -1032,29 +1050,38 @@ select_device_type(int *dev_type_p, int bytelength) ...@@ -1032,29 +1050,38 @@ select_device_type(int *dev_type_p, int bytelength)
stat = &z90crypt.hdware_info->type_mask[CEX2C]; stat = &z90crypt.hdware_info->type_mask[CEX2C];
CEX2C_avail = stat->st_count - CEX2C_avail = stat->st_count -
(stat->disabled_count + stat->user_disabled_count); (stat->disabled_count + stat->user_disabled_count);
if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail) { stat = &z90crypt.hdware_info->type_mask[CEX2A];
CEX2A_avail = stat->st_count -
(stat->disabled_count + stat->user_disabled_count);
if (PCICA_avail || PCIXCC_MCL3_avail || CEX2C_avail || CEX2A_avail) {
/** /**
* bitlength is a factor, PCICA is the most capable, even with * bitlength is a factor, PCICA or CEX2A are the most capable,
* the new MCL for PCIXCC. * even with the new MCL for PCIXCC.
*/ */
if ((bytelength < PCIXCC_MIN_MOD_SIZE) || if ((bytelength < PCIXCC_MIN_MOD_SIZE) ||
(!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) { (!ext_bitlens && (bytelength < OLD_PCIXCC_MIN_MOD_SIZE))) {
if (!PCICA_avail) if (PCICA_avail) {
return -1;
else {
*dev_type_p = PCICA; *dev_type_p = PCICA;
return 0; return 0;
} }
if (CEX2A_avail) {
*dev_type_p = CEX2A;
return 0;
}
return -1;
} }
index_to_use = count % (PCICA_avail + PCIXCC_MCL3_avail + index_to_use = count % (PCICA_avail + PCIXCC_MCL3_avail +
CEX2C_avail); CEX2C_avail + CEX2A_avail);
if (index_to_use < PCICA_avail) if (index_to_use < PCICA_avail)
*dev_type_p = PCICA; *dev_type_p = PCICA;
else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail)) else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail))
*dev_type_p = PCIXCC_MCL3; *dev_type_p = PCIXCC_MCL3;
else else if (index_to_use < (PCICA_avail + PCIXCC_MCL3_avail +
CEX2C_avail))
*dev_type_p = CEX2C; *dev_type_p = CEX2C;
else
*dev_type_p = CEX2A;
count++; count++;
return 0; return 0;
} }
...@@ -1359,7 +1386,7 @@ build_caller(struct work_element *we_p, short function) ...@@ -1359,7 +1386,7 @@ build_caller(struct work_element *we_p, short function)
if ((we_p->devtype != PCICC) && (we_p->devtype != PCICA) && if ((we_p->devtype != PCICC) && (we_p->devtype != PCICA) &&
(we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) && (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
(we_p->devtype != CEX2C)) (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A))
return SEN_NOT_AVAIL; return SEN_NOT_AVAIL;
memcpy(caller_p->caller_id, we_p->caller_id, memcpy(caller_p->caller_id, we_p->caller_id,
...@@ -1428,7 +1455,8 @@ get_crypto_request_buffer(struct work_element *we_p) ...@@ -1428,7 +1455,8 @@ get_crypto_request_buffer(struct work_element *we_p)
if ((we_p->devtype != PCICA) && (we_p->devtype != PCICC) && if ((we_p->devtype != PCICA) && (we_p->devtype != PCICC) &&
(we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) && (we_p->devtype != PCIXCC_MCL2) && (we_p->devtype != PCIXCC_MCL3) &&
(we_p->devtype != CEX2C) && (we_p->devtype != ANYDEV)) { (we_p->devtype != CEX2C) && (we_p->devtype != CEX2A) &&
(we_p->devtype != ANYDEV)) {
PRINTK("invalid device type\n"); PRINTK("invalid device type\n");
return SEN_USER_ERROR; return SEN_USER_ERROR;
} }
...@@ -1503,8 +1531,9 @@ get_crypto_request_buffer(struct work_element *we_p) ...@@ -1503,8 +1531,9 @@ get_crypto_request_buffer(struct work_element *we_p)
function = PCI_FUNC_KEY_ENCRYPT; function = PCI_FUNC_KEY_ENCRYPT;
switch (we_p->devtype) { switch (we_p->devtype) {
/* PCICA does everything with a simple RSA mod-expo operation */ /* PCICA and CEX2A do everything with a simple RSA mod-expo operation */
case PCICA: case PCICA:
case CEX2A:
function = PCI_FUNC_KEY_ENCRYPT; function = PCI_FUNC_KEY_ENCRYPT;
break; break;
/** /**
...@@ -1662,7 +1691,8 @@ z90crypt_rsa(struct priv_data *private_data_p, pid_t pid, ...@@ -1662,7 +1691,8 @@ z90crypt_rsa(struct priv_data *private_data_p, pid_t pid,
* trigger a fallback to software. * trigger a fallback to software.
*/ */
case -EINVAL: case -EINVAL:
if (we_p->devtype != PCICA) if ((we_p->devtype != PCICA) &&
(we_p->devtype != CEX2A))
rv = -EGETBUFF; rv = -EGETBUFF;
break; break;
case -ETIMEOUT: case -ETIMEOUT:
...@@ -1779,6 +1809,12 @@ z90crypt_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -1779,6 +1809,12 @@ z90crypt_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
ret = -EFAULT; ret = -EFAULT;
break; break;
case Z90STAT_CEX2ACOUNT:
tempstat = get_status_CEX2Acount();
if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
ret = -EFAULT;
break;
case Z90STAT_REQUESTQ_COUNT: case Z90STAT_REQUESTQ_COUNT:
tempstat = get_status_requestq_count(); tempstat = get_status_requestq_count();
if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0) if (copy_to_user((int __user *)arg, &tempstat, sizeof(int)) != 0)
...@@ -2019,6 +2055,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset, ...@@ -2019,6 +2055,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
get_status_PCIXCCMCL3count()); get_status_PCIXCCMCL3count());
len += sprintf(resp_buff+len, "CEX2C count: %d\n", len += sprintf(resp_buff+len, "CEX2C count: %d\n",
get_status_CEX2Ccount()); get_status_CEX2Ccount());
len += sprintf(resp_buff+len, "CEX2A count: %d\n",
get_status_CEX2Acount());
len += sprintf(resp_buff+len, "requestq count: %d\n", len += sprintf(resp_buff+len, "requestq count: %d\n",
get_status_requestq_count()); get_status_requestq_count());
len += sprintf(resp_buff+len, "pendingq count: %d\n", len += sprintf(resp_buff+len, "pendingq count: %d\n",
...@@ -2026,8 +2064,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset, ...@@ -2026,8 +2064,8 @@ z90crypt_status(char *resp_buff, char **start, off_t offset,
len += sprintf(resp_buff+len, "Total open handles: %d\n\n", len += sprintf(resp_buff+len, "Total open handles: %d\n\n",
get_status_totalopen_count()); get_status_totalopen_count());
len += sprinthx( len += sprinthx(
"Online devices: 1: PCICA, 2: PCICC, 3: PCIXCC (MCL2), " "Online devices: 1=PCICA 2=PCICC 3=PCIXCC(MCL2) "
"4: PCIXCC (MCL3), 5: CEX2C", "4=PCIXCC(MCL3) 5=CEX2C 6=CEX2A",
resp_buff+len, resp_buff+len,
get_status_status_mask(workarea), get_status_status_mask(workarea),
Z90CRYPT_NUM_APS); Z90CRYPT_NUM_APS);
...@@ -2140,6 +2178,7 @@ z90crypt_status_write(struct file *file, const char __user *buffer, ...@@ -2140,6 +2178,7 @@ z90crypt_status_write(struct file *file, const char __user *buffer,
case '3': // PCIXCC_MCL2 case '3': // PCIXCC_MCL2
case '4': // PCIXCC_MCL3 case '4': // PCIXCC_MCL3
case '5': // CEX2C case '5': // CEX2C
case '6': // CEX2A
j++; j++;
break; break;
case 'd': case 'd':
...@@ -3007,7 +3046,9 @@ create_crypto_device(int index) ...@@ -3007,7 +3046,9 @@ create_crypto_device(int index)
z90crypt.hdware_info->device_type_array[index] = 4; z90crypt.hdware_info->device_type_array[index] = 4;
else if (deviceType == CEX2C) else if (deviceType == CEX2C)
z90crypt.hdware_info->device_type_array[index] = 5; z90crypt.hdware_info->device_type_array[index] = 5;
else else if (deviceType == CEX2A)
z90crypt.hdware_info->device_type_array[index] = 6;
else // No idea how this would happen.
z90crypt.hdware_info->device_type_array[index] = -1; z90crypt.hdware_info->device_type_array[index] = -1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment