RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / drivers / s390 / crypto / zcrypt_pcixcc.c
blob252443b6bd1b5a2d003d360235aaf7de14c1be67
1 /*
2 * linux/drivers/s390/crypto/zcrypt_pcixcc.c
4 * zcrypt 2.1.0
6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs
8 * Eric Rossman (edrossma@us.ibm.com)
10 * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
11 * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
12 * Ralph Wuerthner <rwuerthn@de.ibm.com>
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #include <linux/module.h>
30 #include <linux/init.h>
31 #include <linux/err.h>
32 #include <linux/delay.h>
33 #include <asm/atomic.h>
34 #include <asm/uaccess.h>
36 #include "ap_bus.h"
37 #include "zcrypt_api.h"
38 #include "zcrypt_error.h"
39 #include "zcrypt_pcicc.h"
40 #include "zcrypt_pcixcc.h"
41 #include "zcrypt_cca_key.h"
43 #define PCIXCC_MIN_MOD_SIZE 16 /* 128 bits */
44 #define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */
45 #define PCIXCC_MAX_MOD_SIZE 256 /* 2048 bits */
47 #define PCIXCC_MCL2_SPEED_RATING 7870 /* FIXME: needs finetuning */
48 #define PCIXCC_MCL3_SPEED_RATING 7870
49 #define CEX2C_SPEED_RATING 8540
51 #define PCIXCC_MAX_ICA_MESSAGE_SIZE 0x77c /* max size type6 v2 crt message */
52 #define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */
54 #define PCIXCC_MAX_XCRB_MESSAGE_SIZE (12*1024)
55 #define PCIXCC_MAX_XCRB_RESPONSE_SIZE PCIXCC_MAX_XCRB_MESSAGE_SIZE
56 #define PCIXCC_MAX_XCRB_DATA_SIZE (11*1024)
57 #define PCIXCC_MAX_XCRB_REPLY_SIZE (5*1024)
59 #define PCIXCC_MAX_RESPONSE_SIZE PCIXCC_MAX_XCRB_RESPONSE_SIZE
61 #define PCIXCC_CLEANUP_TIME (15*HZ)
63 #define CEIL4(x) ((((x)+3)/4)*4)
65 struct response_type {
66 struct completion work;
67 int type;
69 #define PCIXCC_RESPONSE_TYPE_ICA 0
70 #define PCIXCC_RESPONSE_TYPE_XCRB 1
72 static struct ap_device_id zcrypt_pcixcc_ids[] = {
73 { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) },
74 { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) },
75 { /* end of list */ },
78 #ifndef CONFIG_ZCRYPT_MONOLITHIC
79 MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids);
80 MODULE_AUTHOR("IBM Corporation");
81 MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, "
82 "Copyright 2001, 2006 IBM Corporation");
83 MODULE_LICENSE("GPL");
84 #endif
86 static int zcrypt_pcixcc_probe(struct ap_device *ap_dev);
87 static void zcrypt_pcixcc_remove(struct ap_device *ap_dev);
88 static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *,
89 struct ap_message *);
91 static struct ap_driver zcrypt_pcixcc_driver = {
92 .probe = zcrypt_pcixcc_probe,
93 .remove = zcrypt_pcixcc_remove,
94 .receive = zcrypt_pcixcc_receive,
95 .ids = zcrypt_pcixcc_ids,
98 /**
99 * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C
100 * card in a type6 message. The 3 fields that must be filled in at execution
101 * time are req_parml, rpl_parml and usage_domain.
102 * Everything about this interface is ascii/big-endian, since the
103 * device does *not* have 'Intel inside'.
105 * The CPRBX is followed immediately by the parm block.
106 * The parm block contains:
107 * - function code ('PD' 0x5044 or 'PK' 0x504B)
108 * - rule block (one of:)
109 * + 0x000A 'PKCS-1.2' (MCL2 'PD')
110 * + 0x000A 'ZERO-PAD' (MCL2 'PK')
111 * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD')
112 * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK')
113 * - VUD block
115 static struct CPRBX static_cprbx = {
116 .cprb_len = 0x00DC,
117 .cprb_ver_id = 0x02,
118 .func_id = {0x54,0x32},
122 * Convert a ICAMEX message to a type6 MEX message.
124 * @zdev: crypto device pointer
125 * @ap_msg: pointer to AP message
126 * @mex: pointer to user input data
128 * Returns 0 on success or -EFAULT.
130 static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev,
131 struct ap_message *ap_msg,
132 struct ica_rsa_modexpo *mex)
134 static struct type6_hdr static_type6_hdrX = {
135 .type = 0x06,
136 .offset1 = 0x00000058,
137 .agent_id = {'C','A',},
138 .function_code = {'P','K'},
140 static struct function_and_rules_block static_pke_fnr = {
141 .function_code = {'P','K'},
142 .ulen = 10,
143 .only_rule = {'M','R','P',' ',' ',' ',' ',' '}
145 static struct function_and_rules_block static_pke_fnr_MCL2 = {
146 .function_code = {'P','K'},
147 .ulen = 10,
148 .only_rule = {'Z','E','R','O','-','P','A','D'}
150 struct {
151 struct type6_hdr hdr;
152 struct CPRBX cprbx;
153 struct function_and_rules_block fr;
154 unsigned short length;
155 char text[0];
156 } __attribute__((packed)) *msg = ap_msg->message;
157 int size;
159 /* VUD.ciphertext */
160 msg->length = mex->inputdatalength + 2;
161 if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
162 return -EFAULT;
164 /* Set up key which is located after the variable length text. */
165 size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1);
166 if (size < 0)
167 return size;
168 size += sizeof(*msg) + mex->inputdatalength;
170 /* message header, cprbx and f&r */
171 msg->hdr = static_type6_hdrX;
172 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
173 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
175 msg->cprbx = static_cprbx;
176 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
177 msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1;
179 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
180 static_pke_fnr_MCL2 : static_pke_fnr;
182 msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx);
184 ap_msg->length = size;
185 return 0;
189 * Convert a ICACRT message to a type6 CRT message.
191 * @zdev: crypto device pointer
192 * @ap_msg: pointer to AP message
193 * @crt: pointer to user input data
195 * Returns 0 on success or -EFAULT.
197 static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,
198 struct ap_message *ap_msg,
199 struct ica_rsa_modexpo_crt *crt)
201 static struct type6_hdr static_type6_hdrX = {
202 .type = 0x06,
203 .offset1 = 0x00000058,
204 .agent_id = {'C','A',},
205 .function_code = {'P','D'},
207 static struct function_and_rules_block static_pkd_fnr = {
208 .function_code = {'P','D'},
209 .ulen = 10,
210 .only_rule = {'Z','E','R','O','-','P','A','D'}
213 static struct function_and_rules_block static_pkd_fnr_MCL2 = {
214 .function_code = {'P','D'},
215 .ulen = 10,
216 .only_rule = {'P','K','C','S','-','1','.','2'}
218 struct {
219 struct type6_hdr hdr;
220 struct CPRBX cprbx;
221 struct function_and_rules_block fr;
222 unsigned short length;
223 char text[0];
224 } __attribute__((packed)) *msg = ap_msg->message;
225 int size;
227 /* VUD.ciphertext */
228 msg->length = crt->inputdatalength + 2;
229 if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
230 return -EFAULT;
232 /* Set up key which is located after the variable length text. */
233 size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1);
234 if (size < 0)
235 return size;
236 size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */
238 /* message header, cprbx and f&r */
239 msg->hdr = static_type6_hdrX;
240 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
241 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
243 msg->cprbx = static_cprbx;
244 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
245 msg->cprbx.req_parml = msg->cprbx.rpl_msgbl =
246 size - sizeof(msg->hdr) - sizeof(msg->cprbx);
248 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
249 static_pkd_fnr_MCL2 : static_pkd_fnr;
251 ap_msg->length = size;
252 return 0;
256 * Convert a XCRB message to a type6 CPRB message.
258 * @zdev: crypto device pointer
259 * @ap_msg: pointer to AP message
260 * @xcRB: pointer to user input data
262 * Returns 0 on success or -EFAULT.
264 struct type86_fmt2_msg {
265 struct type86_hdr hdr;
266 struct type86_fmt2_ext fmt2;
267 } __attribute__((packed));
269 static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
270 struct ap_message *ap_msg,
271 struct ica_xcRB *xcRB)
273 static struct type6_hdr static_type6_hdrX = {
274 .type = 0x06,
275 .offset1 = 0x00000058,
277 struct {
278 struct type6_hdr hdr;
279 struct ica_CPRBX cprbx;
280 } __attribute__((packed)) *msg = ap_msg->message;
282 int rcblen = CEIL4(xcRB->request_control_blk_length);
283 int replylen;
284 char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
285 char *function_code;
287 /* length checks */
288 ap_msg->length = sizeof(struct type6_hdr) +
289 CEIL4(xcRB->request_control_blk_length) +
290 xcRB->request_data_length;
291 if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE) {
292 PRINTK("Combined message is too large (%ld/%d/%d).\n",
293 sizeof(struct type6_hdr),
294 xcRB->request_control_blk_length,
295 xcRB->request_data_length);
296 return -EFAULT;
298 if (CEIL4(xcRB->reply_control_blk_length) >
299 PCIXCC_MAX_XCRB_REPLY_SIZE) {
300 PDEBUG("Reply CPRB length is too large (%d).\n",
301 xcRB->request_control_blk_length);
302 return -EFAULT;
304 if (CEIL4(xcRB->reply_data_length) > PCIXCC_MAX_XCRB_DATA_SIZE) {
305 PDEBUG("Reply data block length is too large (%d).\n",
306 xcRB->reply_data_length);
307 return -EFAULT;
309 replylen = CEIL4(xcRB->reply_control_blk_length) +
310 CEIL4(xcRB->reply_data_length) +
311 sizeof(struct type86_fmt2_msg);
312 if (replylen > PCIXCC_MAX_XCRB_RESPONSE_SIZE) {
313 PDEBUG("Reply CPRB + data block > PCIXCC_MAX_XCRB_RESPONSE_SIZE"
314 " (%d/%d/%d).\n",
315 sizeof(struct type86_fmt2_msg),
316 xcRB->reply_control_blk_length,
317 xcRB->reply_data_length);
318 xcRB->reply_control_blk_length = PCIXCC_MAX_XCRB_RESPONSE_SIZE -
319 (sizeof(struct type86_fmt2_msg) +
320 CEIL4(xcRB->reply_data_length));
321 PDEBUG("Capping Reply CPRB length at %d\n",
322 xcRB->reply_control_blk_length);
325 /* prepare type6 header */
326 msg->hdr = static_type6_hdrX;
327 memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
328 msg->hdr.ToCardLen1 = xcRB->request_control_blk_length;
329 if (xcRB->request_data_length) {
330 msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
331 msg->hdr.ToCardLen2 = xcRB->request_data_length;
333 msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
334 msg->hdr.FromCardLen2 = xcRB->reply_data_length;
336 /* prepare CPRB */
337 if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
338 xcRB->request_control_blk_length))
339 return -EFAULT;
340 if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
341 xcRB->request_control_blk_length) {
342 PDEBUG("cprb_len too large (%d/%d)\n", msg->cprbx.cprb_len,
343 xcRB->request_control_blk_length);
344 return -EFAULT;
346 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
347 memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code));
349 /* copy data block */
350 if (xcRB->request_data_length &&
351 copy_from_user(req_data, xcRB->request_data_address,
352 xcRB->request_data_length))
353 return -EFAULT;
354 return 0;
358 * Copy results from a type 86 ICA reply message back to user space.
360 * @zdev: crypto device pointer
361 * @reply: reply AP message.
362 * @data: pointer to user output data
363 * @length: size of user output data
365 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
367 struct type86x_reply {
368 struct type86_hdr hdr;
369 struct type86_fmt2_ext fmt2;
370 struct CPRBX cprbx;
371 unsigned char pad[4]; /* 4 byte function code/rules block ? */
372 unsigned short length;
373 char text[0];
374 } __attribute__((packed));
376 static int convert_type86_ica(struct zcrypt_device *zdev,
377 struct ap_message *reply,
378 char __user *outputdata,
379 unsigned int outputdatalength)
381 static unsigned char static_pad[] = {
382 0x00,0x02,
383 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,
384 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57,
385 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,
386 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39,
387 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,
388 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D,
389 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,
390 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F,
391 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,
392 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45,
393 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,
394 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F,
395 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,
396 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D,
397 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,
398 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9,
399 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,
400 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B,
401 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,
402 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD,
403 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,
404 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1,
405 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,
406 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23,
407 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,
408 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43,
409 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,
410 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F,
411 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,
412 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD,
413 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,
414 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09
416 struct type86x_reply *msg = reply->message;
417 unsigned short service_rc, service_rs;
418 unsigned int reply_len, pad_len;
419 char *data;
421 service_rc = msg->cprbx.ccp_rtcode;
422 if (unlikely(service_rc != 0)) {
423 service_rs = msg->cprbx.ccp_rscode;
424 if (service_rc == 8 && service_rs == 66) {
425 PDEBUG("Bad block format on PCIXCC/CEX2C\n");
426 return -EINVAL;
428 if (service_rc == 8 && service_rs == 65) {
429 PDEBUG("Probably an even modulus on PCIXCC/CEX2C\n");
430 return -EINVAL;
432 if (service_rc == 8 && service_rs == 770) {
433 PDEBUG("Invalid key length on PCIXCC/CEX2C\n");
434 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
435 return -EAGAIN;
437 if (service_rc == 8 && service_rs == 783) {
438 PDEBUG("Extended bitlengths not enabled on PCIXCC/CEX2C\n");
439 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
440 return -EAGAIN;
442 PRINTK("Unknown service rc/rs (PCIXCC/CEX2C): %d/%d\n",
443 service_rc, service_rs);
444 zdev->online = 0;
445 return -EAGAIN; /* repeat the request on a different device. */
447 data = msg->text;
448 reply_len = msg->length - 2;
449 if (reply_len > outputdatalength)
450 return -EINVAL;
452 * For all encipher requests, the length of the ciphertext (reply_len)
453 * will always equal the modulus length. For MEX decipher requests
454 * the output needs to get padded. Minimum pad size is 10.
456 * Currently, the cases where padding will be added is for:
457 * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
458 * ZERO-PAD and CRT is only supported for PKD requests)
459 * - PCICC, always
461 pad_len = outputdatalength - reply_len;
462 if (pad_len > 0) {
463 if (pad_len < 10)
464 return -EINVAL;
465 /* 'restore' padding left in the PCICC/PCIXCC card. */
466 if (copy_to_user(outputdata, static_pad, pad_len - 1))
467 return -EFAULT;
468 if (put_user(0, outputdata + pad_len - 1))
469 return -EFAULT;
471 /* Copy the crypto response to user space. */
472 if (copy_to_user(outputdata + pad_len, data, reply_len))
473 return -EFAULT;
474 return 0;
478 * Copy results from a type 86 XCRB reply message back to user space.
480 * @zdev: crypto device pointer
481 * @reply: reply AP message.
482 * @xcRB: pointer to XCRB
484 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
486 static int convert_type86_xcrb(struct zcrypt_device *zdev,
487 struct ap_message *reply,
488 struct ica_xcRB *xcRB)
490 struct type86_fmt2_msg *msg = reply->message;
491 char *data = reply->message;
493 /* Copy CPRB to user */
494 if (copy_to_user(xcRB->reply_control_blk_addr,
495 data + msg->fmt2.offset1, msg->fmt2.count1))
496 return -EFAULT;
497 xcRB->reply_control_blk_length = msg->fmt2.count1;
499 /* Copy data buffer to user */
500 if (msg->fmt2.count2)
501 if (copy_to_user(xcRB->reply_data_addr,
502 data + msg->fmt2.offset2, msg->fmt2.count2))
503 return -EFAULT;
504 xcRB->reply_data_length = msg->fmt2.count2;
505 return 0;
508 static int convert_response_ica(struct zcrypt_device *zdev,
509 struct ap_message *reply,
510 char __user *outputdata,
511 unsigned int outputdatalength)
513 struct type86x_reply *msg = reply->message;
515 /* Response type byte is the second byte in the response. */
516 switch (((unsigned char *) reply->message)[1]) {
517 case TYPE82_RSP_CODE:
518 case TYPE88_RSP_CODE:
519 return convert_error(zdev, reply);
520 case TYPE86_RSP_CODE:
521 if (msg->hdr.reply_code)
522 return convert_error(zdev, reply);
523 if (msg->cprbx.cprb_ver_id == 0x02)
524 return convert_type86_ica(zdev, reply,
525 outputdata, outputdatalength);
526 /* no break, incorrect cprb version is an unknown response */
527 default: /* Unknown response type, this should NEVER EVER happen */
528 PRINTK("Unrecognized Message Header: %08x%08x\n",
529 *(unsigned int *) reply->message,
530 *(unsigned int *) (reply->message+4));
531 zdev->online = 0;
532 return -EAGAIN; /* repeat the request on a different device. */
536 static int convert_response_xcrb(struct zcrypt_device *zdev,
537 struct ap_message *reply,
538 struct ica_xcRB *xcRB)
540 struct type86x_reply *msg = reply->message;
542 /* Response type byte is the second byte in the response. */
543 switch (((unsigned char *) reply->message)[1]) {
544 case TYPE82_RSP_CODE:
545 case TYPE88_RSP_CODE:
546 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
547 return convert_error(zdev, reply);
548 case TYPE86_RSP_CODE:
549 if (msg->hdr.reply_code) {
550 memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
551 return convert_error(zdev, reply);
553 if (msg->cprbx.cprb_ver_id == 0x02)
554 return convert_type86_xcrb(zdev, reply, xcRB);
555 /* no break, incorrect cprb version is an unknown response */
556 default: /* Unknown response type, this should NEVER EVER happen */
557 PRINTK("Unrecognized Message Header: %08x%08x\n",
558 *(unsigned int *) reply->message,
559 *(unsigned int *) (reply->message+4));
560 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
561 zdev->online = 0;
562 return -EAGAIN; /* repeat the request on a different device. */
567 * This function is called from the AP bus code after a crypto request
568 * "msg" has finished with the reply message "reply".
569 * It is called from tasklet context.
570 * @ap_dev: pointer to the AP device
571 * @msg: pointer to the AP message
572 * @reply: pointer to the AP reply message
574 static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
575 struct ap_message *msg,
576 struct ap_message *reply)
578 static struct error_hdr error_reply = {
579 .type = TYPE82_RSP_CODE,
580 .reply_code = REP82_ERROR_MACHINE_FAILURE,
582 struct response_type *resp_type =
583 (struct response_type *) msg->private;
584 struct type86x_reply *t86r = reply->message;
585 int length;
587 /* Copy the reply message to the request message buffer. */
588 if (IS_ERR(reply))
589 memcpy(msg->message, &error_reply, sizeof(error_reply));
590 else if (t86r->hdr.type == TYPE86_RSP_CODE &&
591 t86r->cprbx.cprb_ver_id == 0x02) {
592 switch (resp_type->type) {
593 case PCIXCC_RESPONSE_TYPE_ICA:
594 length = sizeof(struct type86x_reply)
595 + t86r->length - 2;
596 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
597 memcpy(msg->message, reply->message, length);
598 break;
599 case PCIXCC_RESPONSE_TYPE_XCRB:
600 length = t86r->fmt2.offset2 + t86r->fmt2.count2;
601 length = min(PCIXCC_MAX_XCRB_RESPONSE_SIZE, length);
602 memcpy(msg->message, reply->message, length);
603 break;
604 default:
605 PRINTK("Invalid internal response type: %i\n",
606 resp_type->type);
607 memcpy(msg->message, &error_reply,
608 sizeof error_reply);
610 } else
611 memcpy(msg->message, reply->message, sizeof error_reply);
612 complete(&(resp_type->work));
615 static atomic_t zcrypt_step = ATOMIC_INIT(0);
618 * The request distributor calls this function if it picked the PCIXCC/CEX2C
619 * device to handle a modexpo request.
620 * @zdev: pointer to zcrypt_device structure that identifies the
621 * PCIXCC/CEX2C device to the request distributor
622 * @mex: pointer to the modexpo request buffer
624 static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
625 struct ica_rsa_modexpo *mex)
627 struct ap_message ap_msg;
628 struct response_type resp_type = {
629 .type = PCIXCC_RESPONSE_TYPE_ICA,
631 int rc;
633 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
634 if (!ap_msg.message)
635 return -ENOMEM;
636 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
637 atomic_inc_return(&zcrypt_step);
638 ap_msg.private = &resp_type;
639 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
640 if (rc)
641 goto out_free;
642 init_completion(&resp_type.work);
643 ap_queue_message(zdev->ap_dev, &ap_msg);
644 rc = wait_for_completion_interruptible_timeout(
645 &resp_type.work, PCIXCC_CLEANUP_TIME);
646 if (rc > 0)
647 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
648 mex->outputdatalength);
649 else {
650 /* Signal pending or message timed out. */
651 ap_cancel_message(zdev->ap_dev, &ap_msg);
652 if (rc == 0)
653 /* Message timed out. */
654 rc = -ETIME;
656 out_free:
657 free_page((unsigned long) ap_msg.message);
658 return rc;
662 * The request distributor calls this function if it picked the PCIXCC/CEX2C
663 * device to handle a modexpo_crt request.
664 * @zdev: pointer to zcrypt_device structure that identifies the
665 * PCIXCC/CEX2C device to the request distributor
666 * @crt: pointer to the modexpoc_crt request buffer
668 static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
669 struct ica_rsa_modexpo_crt *crt)
671 struct ap_message ap_msg;
672 struct response_type resp_type = {
673 .type = PCIXCC_RESPONSE_TYPE_ICA,
675 int rc;
677 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
678 if (!ap_msg.message)
679 return -ENOMEM;
680 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
681 atomic_inc_return(&zcrypt_step);
682 ap_msg.private = &resp_type;
683 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
684 if (rc)
685 goto out_free;
686 init_completion(&resp_type.work);
687 ap_queue_message(zdev->ap_dev, &ap_msg);
688 rc = wait_for_completion_interruptible_timeout(
689 &resp_type.work, PCIXCC_CLEANUP_TIME);
690 if (rc > 0)
691 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
692 crt->outputdatalength);
693 else {
694 /* Signal pending or message timed out. */
695 ap_cancel_message(zdev->ap_dev, &ap_msg);
696 if (rc == 0)
697 /* Message timed out. */
698 rc = -ETIME;
700 out_free:
701 free_page((unsigned long) ap_msg.message);
702 return rc;
706 * The request distributor calls this function if it picked the PCIXCC/CEX2C
707 * device to handle a send_cprb request.
708 * @zdev: pointer to zcrypt_device structure that identifies the
709 * PCIXCC/CEX2C device to the request distributor
710 * @xcRB: pointer to the send_cprb request buffer
712 static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
713 struct ica_xcRB *xcRB)
715 struct ap_message ap_msg;
716 struct response_type resp_type = {
717 .type = PCIXCC_RESPONSE_TYPE_XCRB,
719 int rc;
721 ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
722 if (!ap_msg.message)
723 return -ENOMEM;
724 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
725 atomic_inc_return(&zcrypt_step);
726 ap_msg.private = &resp_type;
727 rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB);
728 if (rc)
729 goto out_free;
730 init_completion(&resp_type.work);
731 ap_queue_message(zdev->ap_dev, &ap_msg);
732 rc = wait_for_completion_interruptible_timeout(
733 &resp_type.work, PCIXCC_CLEANUP_TIME);
734 if (rc > 0)
735 rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
736 else {
737 /* Signal pending or message timed out. */
738 ap_cancel_message(zdev->ap_dev, &ap_msg);
739 if (rc == 0)
740 /* Message timed out. */
741 rc = -ETIME;
743 out_free:
744 memset(ap_msg.message, 0x0, ap_msg.length);
745 kfree(ap_msg.message);
746 return rc;
750 * The crypto operations for a PCIXCC/CEX2C card.
752 static struct zcrypt_ops zcrypt_pcixcc_ops = {
753 .rsa_modexpo = zcrypt_pcixcc_modexpo,
754 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
755 .send_cprb = zcrypt_pcixcc_send_cprb,
759 * Micro-code detection function. Its sends a message to a pcixcc card
760 * to find out the microcode level.
761 * @ap_dev: pointer to the AP device.
763 static int zcrypt_pcixcc_mcl(struct ap_device *ap_dev)
765 static unsigned char msg[] = {
766 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
767 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
768 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
769 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
770 0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
771 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
772 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00,
773 0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00,
774 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
775 0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00,
776 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
777 0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32,
778 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,
779 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,
780 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
781 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
782 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
783 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
784 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
785 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
786 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
787 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
788 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
789 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
790 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
791 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
792 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
793 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
794 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
795 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
796 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
797 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
798 0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
799 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
800 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
801 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
802 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
803 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
804 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x0A,
805 0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20,
806 0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05,
807 0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
808 0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55,
809 0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,
810 0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,
811 0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,
812 0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB,
813 0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54,
814 0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00,
815 0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00,
816 0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40,
817 0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C,
818 0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF,
819 0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9,
820 0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63,
821 0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5,
822 0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A,
823 0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01,
824 0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28,
825 0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91,
826 0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5,
827 0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C,
828 0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98,
829 0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96,
830 0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19,
831 0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47,
832 0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36,
833 0xF1,0x3D,0x93,0x53
835 unsigned long long psmid;
836 struct CPRBX *cprbx;
837 char *reply;
838 int rc, i;
840 reply = (void *) get_zeroed_page(GFP_KERNEL);
841 if (!reply)
842 return -ENOMEM;
844 rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, msg, sizeof(msg));
845 if (rc)
846 goto out_free;
848 /* Wait for the test message to complete. */
849 for (i = 0; i < 6; i++) {
850 mdelay(300);
851 rc = ap_recv(ap_dev->qid, &psmid, reply, 4096);
852 if (rc == 0 && psmid == 0x0102030405060708ULL)
853 break;
856 if (i >= 6) {
857 /* Got no answer. */
858 rc = -ENODEV;
859 goto out_free;
862 cprbx = (struct CPRBX *) (reply + 48);
863 if (cprbx->ccp_rtcode == 8 && cprbx->ccp_rscode == 33)
864 rc = ZCRYPT_PCIXCC_MCL2;
865 else
866 rc = ZCRYPT_PCIXCC_MCL3;
867 out_free:
868 free_page((unsigned long) reply);
869 return rc;
873 * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device
874 * since the bus_match already checked the hardware type. The PCIXCC
875 * cards come in two flavours: micro code level 2 and micro code level 3.
876 * This is checked by sending a test message to the device.
877 * @ap_dev: pointer to the AP device.
879 static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
881 struct zcrypt_device *zdev;
882 int rc;
884 zdev = zcrypt_device_alloc(PCIXCC_MAX_RESPONSE_SIZE);
885 if (!zdev)
886 return -ENOMEM;
887 zdev->ap_dev = ap_dev;
888 zdev->ops = &zcrypt_pcixcc_ops;
889 zdev->online = 1;
890 if (ap_dev->device_type == AP_DEVICE_TYPE_PCIXCC) {
891 rc = zcrypt_pcixcc_mcl(ap_dev);
892 if (rc < 0) {
893 zcrypt_device_free(zdev);
894 return rc;
896 zdev->user_space_type = rc;
897 if (rc == ZCRYPT_PCIXCC_MCL2) {
898 zdev->type_string = "PCIXCC_MCL2";
899 zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING;
900 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
901 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
902 } else {
903 zdev->type_string = "PCIXCC_MCL3";
904 zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING;
905 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
906 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
908 } else {
909 zdev->user_space_type = ZCRYPT_CEX2C;
910 zdev->type_string = "CEX2C";
911 zdev->speed_rating = CEX2C_SPEED_RATING;
912 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
913 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
915 ap_dev->reply = &zdev->reply;
916 ap_dev->private = zdev;
917 rc = zcrypt_device_register(zdev);
918 if (rc)
919 goto out_free;
920 return 0;
922 out_free:
923 ap_dev->private = NULL;
924 zcrypt_device_free(zdev);
925 return rc;
929 * This is called to remove the extended PCIXCC/CEX2C driver information
930 * if an AP device is removed.
932 static void zcrypt_pcixcc_remove(struct ap_device *ap_dev)
934 struct zcrypt_device *zdev = ap_dev->private;
936 zcrypt_device_unregister(zdev);
939 int __init zcrypt_pcixcc_init(void)
941 return ap_driver_register(&zcrypt_pcixcc_driver, THIS_MODULE, "pcixcc");
944 void zcrypt_pcixcc_exit(void)
946 ap_driver_unregister(&zcrypt_pcixcc_driver);
949 #ifndef CONFIG_ZCRYPT_MONOLITHIC
950 module_init(zcrypt_pcixcc_init);
951 module_exit(zcrypt_pcixcc_exit);
952 #endif