1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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>
35
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"
42
43#define PCIXCC_MIN_MOD_SIZE 16
44#define PCIXCC_MIN_MOD_SIZE_OLD 64
45#define PCIXCC_MAX_MOD_SIZE 256
46
47#define PCIXCC_MCL2_SPEED_RATING 7870
48#define PCIXCC_MCL3_SPEED_RATING 7870
49#define CEX2C_SPEED_RATING 8540
50
51#define PCIXCC_MAX_ICA_MESSAGE_SIZE 0x77c
52#define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c
53
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)
58
59#define PCIXCC_MAX_RESPONSE_SIZE PCIXCC_MAX_XCRB_RESPONSE_SIZE
60
61#define PCIXCC_CLEANUP_TIME (15*HZ)
62
63#define CEIL4(x) ((((x)+3)/4)*4)
64
65struct response_type {
66 struct completion work;
67 int type;
68};
69#define PCIXCC_RESPONSE_TYPE_ICA 0
70#define PCIXCC_RESPONSE_TYPE_XCRB 1
71
72static struct ap_device_id zcrypt_pcixcc_ids[] = {
73 { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) },
74 { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) },
75 { },
76};
77
78#ifndef CONFIG_ZCRYPT_MONOLITHIC
79MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids);
80MODULE_AUTHOR("IBM Corporation");
81MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, "
82 "Copyright 2001, 2006 IBM Corporation");
83MODULE_LICENSE("GPL");
84#endif
85
86static int zcrypt_pcixcc_probe(struct ap_device *ap_dev);
87static void zcrypt_pcixcc_remove(struct ap_device *ap_dev);
88static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *,
89 struct ap_message *);
90
91static 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,
96 .request_timeout = PCIXCC_CLEANUP_TIME,
97};
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116static struct CPRBX static_cprbx = {
117 .cprb_len = 0x00DC,
118 .cprb_ver_id = 0x02,
119 .func_id = {0x54,0x32},
120};
121
122
123
124
125
126
127
128
129
130
131static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev,
132 struct ap_message *ap_msg,
133 struct ica_rsa_modexpo *mex)
134{
135 static struct type6_hdr static_type6_hdrX = {
136 .type = 0x06,
137 .offset1 = 0x00000058,
138 .agent_id = {'C','A',},
139 .function_code = {'P','K'},
140 };
141 static struct function_and_rules_block static_pke_fnr = {
142 .function_code = {'P','K'},
143 .ulen = 10,
144 .only_rule = {'M','R','P',' ',' ',' ',' ',' '}
145 };
146 static struct function_and_rules_block static_pke_fnr_MCL2 = {
147 .function_code = {'P','K'},
148 .ulen = 10,
149 .only_rule = {'Z','E','R','O','-','P','A','D'}
150 };
151 struct {
152 struct type6_hdr hdr;
153 struct CPRBX cprbx;
154 struct function_and_rules_block fr;
155 unsigned short length;
156 char text[0];
157 } __attribute__((packed)) *msg = ap_msg->message;
158 int size;
159
160
161 msg->length = mex->inputdatalength + 2;
162 if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
163 return -EFAULT;
164
165
166 size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1);
167 if (size < 0)
168 return size;
169 size += sizeof(*msg) + mex->inputdatalength;
170
171
172 msg->hdr = static_type6_hdrX;
173 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
174 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
175
176 msg->cprbx = static_cprbx;
177 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
178 msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1;
179
180 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
181 static_pke_fnr_MCL2 : static_pke_fnr;
182
183 msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx);
184
185 ap_msg->length = size;
186 return 0;
187}
188
189
190
191
192
193
194
195
196
197
198static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,
199 struct ap_message *ap_msg,
200 struct ica_rsa_modexpo_crt *crt)
201{
202 static struct type6_hdr static_type6_hdrX = {
203 .type = 0x06,
204 .offset1 = 0x00000058,
205 .agent_id = {'C','A',},
206 .function_code = {'P','D'},
207 };
208 static struct function_and_rules_block static_pkd_fnr = {
209 .function_code = {'P','D'},
210 .ulen = 10,
211 .only_rule = {'Z','E','R','O','-','P','A','D'}
212 };
213
214 static struct function_and_rules_block static_pkd_fnr_MCL2 = {
215 .function_code = {'P','D'},
216 .ulen = 10,
217 .only_rule = {'P','K','C','S','-','1','.','2'}
218 };
219 struct {
220 struct type6_hdr hdr;
221 struct CPRBX cprbx;
222 struct function_and_rules_block fr;
223 unsigned short length;
224 char text[0];
225 } __attribute__((packed)) *msg = ap_msg->message;
226 int size;
227
228
229 msg->length = crt->inputdatalength + 2;
230 if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
231 return -EFAULT;
232
233
234 size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1);
235 if (size < 0)
236 return size;
237 size += sizeof(*msg) + crt->inputdatalength;
238
239
240 msg->hdr = static_type6_hdrX;
241 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
242 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
243
244 msg->cprbx = static_cprbx;
245 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
246 msg->cprbx.req_parml = msg->cprbx.rpl_msgbl =
247 size - sizeof(msg->hdr) - sizeof(msg->cprbx);
248
249 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
250 static_pkd_fnr_MCL2 : static_pkd_fnr;
251
252 ap_msg->length = size;
253 return 0;
254}
255
256
257
258
259
260
261
262
263
264
265struct type86_fmt2_msg {
266 struct type86_hdr hdr;
267 struct type86_fmt2_ext fmt2;
268} __attribute__((packed));
269
270static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
271 struct ap_message *ap_msg,
272 struct ica_xcRB *xcRB)
273{
274 static struct type6_hdr static_type6_hdrX = {
275 .type = 0x06,
276 .offset1 = 0x00000058,
277 };
278 struct {
279 struct type6_hdr hdr;
280 struct CPRBX cprbx;
281 } __attribute__((packed)) *msg = ap_msg->message;
282
283 int rcblen = CEIL4(xcRB->request_control_blk_length);
284 int replylen;
285 char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
286 char *function_code;
287
288
289 ap_msg->length = sizeof(struct type6_hdr) +
290 CEIL4(xcRB->request_control_blk_length) +
291 xcRB->request_data_length;
292 if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE) {
293 PRINTK("Combined message is too large (%ld/%d/%d).\n",
294 sizeof(struct type6_hdr),
295 xcRB->request_control_blk_length,
296 xcRB->request_data_length);
297 return -EFAULT;
298 }
299 if (CEIL4(xcRB->reply_control_blk_length) >
300 PCIXCC_MAX_XCRB_REPLY_SIZE) {
301 PDEBUG("Reply CPRB length is too large (%d).\n",
302 xcRB->request_control_blk_length);
303 return -EFAULT;
304 }
305 if (CEIL4(xcRB->reply_data_length) > PCIXCC_MAX_XCRB_DATA_SIZE) {
306 PDEBUG("Reply data block length is too large (%d).\n",
307 xcRB->reply_data_length);
308 return -EFAULT;
309 }
310 replylen = CEIL4(xcRB->reply_control_blk_length) +
311 CEIL4(xcRB->reply_data_length) +
312 sizeof(struct type86_fmt2_msg);
313 if (replylen > PCIXCC_MAX_XCRB_RESPONSE_SIZE) {
314 PDEBUG("Reply CPRB + data block > PCIXCC_MAX_XCRB_RESPONSE_SIZE"
315 " (%d/%d/%d).\n",
316 sizeof(struct type86_fmt2_msg),
317 xcRB->reply_control_blk_length,
318 xcRB->reply_data_length);
319 xcRB->reply_control_blk_length = PCIXCC_MAX_XCRB_RESPONSE_SIZE -
320 (sizeof(struct type86_fmt2_msg) +
321 CEIL4(xcRB->reply_data_length));
322 PDEBUG("Capping Reply CPRB length at %d\n",
323 xcRB->reply_control_blk_length);
324 }
325
326
327 msg->hdr = static_type6_hdrX;
328 memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
329 msg->hdr.ToCardLen1 = xcRB->request_control_blk_length;
330 if (xcRB->request_data_length) {
331 msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
332 msg->hdr.ToCardLen2 = xcRB->request_data_length;
333 }
334 msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
335 msg->hdr.FromCardLen2 = xcRB->reply_data_length;
336
337
338 if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
339 xcRB->request_control_blk_length))
340 return -EFAULT;
341 if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
342 xcRB->request_control_blk_length) {
343 PDEBUG("cprb_len too large (%d/%d)\n", msg->cprbx.cprb_len,
344 xcRB->request_control_blk_length);
345 return -EFAULT;
346 }
347 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
348 memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code));
349
350
351 if (xcRB->request_data_length &&
352 copy_from_user(req_data, xcRB->request_data_address,
353 xcRB->request_data_length))
354 return -EFAULT;
355 return 0;
356}
357
358
359
360
361
362
363
364
365
366
367
368struct type86x_reply {
369 struct type86_hdr hdr;
370 struct type86_fmt2_ext fmt2;
371 struct CPRBX cprbx;
372 unsigned char pad[4];
373 unsigned short length;
374 char text[0];
375} __attribute__((packed));
376
377static int convert_type86_ica(struct zcrypt_device *zdev,
378 struct ap_message *reply,
379 char __user *outputdata,
380 unsigned int outputdatalength)
381{
382 static unsigned char static_pad[] = {
383 0x00,0x02,
384 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,
385 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57,
386 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,
387 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39,
388 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,
389 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D,
390 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,
391 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F,
392 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,
393 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45,
394 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,
395 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F,
396 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,
397 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D,
398 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,
399 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9,
400 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,
401 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B,
402 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,
403 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD,
404 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,
405 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1,
406 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,
407 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23,
408 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,
409 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43,
410 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,
411 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F,
412 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,
413 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD,
414 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,
415 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09
416 };
417 struct type86x_reply *msg = reply->message;
418 unsigned short service_rc, service_rs;
419 unsigned int reply_len, pad_len;
420 char *data;
421
422 service_rc = msg->cprbx.ccp_rtcode;
423 if (unlikely(service_rc != 0)) {
424 service_rs = msg->cprbx.ccp_rscode;
425 if (service_rc == 8 && service_rs == 66) {
426 PDEBUG("Bad block format on PCIXCC/CEX2C\n");
427 return -EINVAL;
428 }
429 if (service_rc == 8 && service_rs == 65) {
430 PDEBUG("Probably an even modulus on PCIXCC/CEX2C\n");
431 return -EINVAL;
432 }
433 if (service_rc == 8 && service_rs == 770) {
434 PDEBUG("Invalid key length on PCIXCC/CEX2C\n");
435 return -EINVAL;
436 }
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;
441 }
442 if (service_rc == 12 && service_rs == 769) {
443 PDEBUG("Invalid key on PCIXCC/CEX2C\n");
444 return -EINVAL;
445 }
446 PRINTK("Unknown service rc/rs (PCIXCC/CEX2C): %d/%d\n",
447 service_rc, service_rs);
448 zdev->online = 0;
449 return -EAGAIN;
450 }
451 data = msg->text;
452 reply_len = msg->length - 2;
453 if (reply_len > outputdatalength)
454 return -EINVAL;
455
456
457
458
459
460
461
462
463
464
465 pad_len = outputdatalength - reply_len;
466 if (pad_len > 0) {
467 if (pad_len < 10)
468 return -EINVAL;
469
470 if (copy_to_user(outputdata, static_pad, pad_len - 1))
471 return -EFAULT;
472 if (put_user(0, outputdata + pad_len - 1))
473 return -EFAULT;
474 }
475
476 if (copy_to_user(outputdata + pad_len, data, reply_len))
477 return -EFAULT;
478 return 0;
479}
480
481
482
483
484
485
486
487
488
489
490static int convert_type86_xcrb(struct zcrypt_device *zdev,
491 struct ap_message *reply,
492 struct ica_xcRB *xcRB)
493{
494 struct type86_fmt2_msg *msg = reply->message;
495 char *data = reply->message;
496
497
498 if (copy_to_user(xcRB->reply_control_blk_addr,
499 data + msg->fmt2.offset1, msg->fmt2.count1))
500 return -EFAULT;
501 xcRB->reply_control_blk_length = msg->fmt2.count1;
502
503
504 if (msg->fmt2.count2)
505 if (copy_to_user(xcRB->reply_data_addr,
506 data + msg->fmt2.offset2, msg->fmt2.count2))
507 return -EFAULT;
508 xcRB->reply_data_length = msg->fmt2.count2;
509 return 0;
510}
511
512static int convert_response_ica(struct zcrypt_device *zdev,
513 struct ap_message *reply,
514 char __user *outputdata,
515 unsigned int outputdatalength)
516{
517 struct type86x_reply *msg = reply->message;
518
519
520 switch (((unsigned char *) reply->message)[1]) {
521 case TYPE82_RSP_CODE:
522 case TYPE88_RSP_CODE:
523 return convert_error(zdev, reply);
524 case TYPE86_RSP_CODE:
525 if (msg->hdr.reply_code)
526 return convert_error(zdev, reply);
527 if (msg->cprbx.cprb_ver_id == 0x02)
528 return convert_type86_ica(zdev, reply,
529 outputdata, outputdatalength);
530
531 default:
532 PRINTK("Unrecognized Message Header: %08x%08x\n",
533 *(unsigned int *) reply->message,
534 *(unsigned int *) (reply->message+4));
535 zdev->online = 0;
536 return -EAGAIN;
537 }
538}
539
540static int convert_response_xcrb(struct zcrypt_device *zdev,
541 struct ap_message *reply,
542 struct ica_xcRB *xcRB)
543{
544 struct type86x_reply *msg = reply->message;
545
546
547 switch (((unsigned char *) reply->message)[1]) {
548 case TYPE82_RSP_CODE:
549 case TYPE88_RSP_CODE:
550 xcRB->status = 0x0008044DL;
551 return convert_error(zdev, reply);
552 case TYPE86_RSP_CODE:
553 if (msg->hdr.reply_code) {
554 memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
555 return convert_error(zdev, reply);
556 }
557 if (msg->cprbx.cprb_ver_id == 0x02)
558 return convert_type86_xcrb(zdev, reply, xcRB);
559
560 default:
561 PRINTK("Unrecognized Message Header: %08x%08x\n",
562 *(unsigned int *) reply->message,
563 *(unsigned int *) (reply->message+4));
564 xcRB->status = 0x0008044DL;
565 zdev->online = 0;
566 return -EAGAIN;
567 }
568}
569
570
571
572
573
574
575
576
577
578static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
579 struct ap_message *msg,
580 struct ap_message *reply)
581{
582 static struct error_hdr error_reply = {
583 .type = TYPE82_RSP_CODE,
584 .reply_code = REP82_ERROR_MACHINE_FAILURE,
585 };
586 struct response_type *resp_type =
587 (struct response_type *) msg->private;
588 struct type86x_reply *t86r = reply->message;
589 int length;
590
591
592 if (IS_ERR(reply))
593 memcpy(msg->message, &error_reply, sizeof(error_reply));
594 else if (t86r->hdr.type == TYPE86_RSP_CODE &&
595 t86r->cprbx.cprb_ver_id == 0x02) {
596 switch (resp_type->type) {
597 case PCIXCC_RESPONSE_TYPE_ICA:
598 length = sizeof(struct type86x_reply)
599 + t86r->length - 2;
600 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
601 memcpy(msg->message, reply->message, length);
602 break;
603 case PCIXCC_RESPONSE_TYPE_XCRB:
604 length = t86r->fmt2.offset2 + t86r->fmt2.count2;
605 length = min(PCIXCC_MAX_XCRB_RESPONSE_SIZE, length);
606 memcpy(msg->message, reply->message, length);
607 break;
608 default:
609 PRINTK("Invalid internal response type: %i\n",
610 resp_type->type);
611 memcpy(msg->message, &error_reply,
612 sizeof error_reply);
613 }
614 } else
615 memcpy(msg->message, reply->message, sizeof error_reply);
616 complete(&(resp_type->work));
617}
618
619static atomic_t zcrypt_step = ATOMIC_INIT(0);
620
621
622
623
624
625
626
627
628static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
629 struct ica_rsa_modexpo *mex)
630{
631 struct ap_message ap_msg;
632 struct response_type resp_type = {
633 .type = PCIXCC_RESPONSE_TYPE_ICA,
634 };
635 int rc;
636
637 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
638 if (!ap_msg.message)
639 return -ENOMEM;
640 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
641 atomic_inc_return(&zcrypt_step);
642 ap_msg.private = &resp_type;
643 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
644 if (rc)
645 goto out_free;
646 init_completion(&resp_type.work);
647 ap_queue_message(zdev->ap_dev, &ap_msg);
648 rc = wait_for_completion_interruptible(&resp_type.work);
649 if (rc == 0)
650 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
651 mex->outputdatalength);
652 else
653
654 ap_cancel_message(zdev->ap_dev, &ap_msg);
655out_free:
656 free_page((unsigned long) ap_msg.message);
657 return rc;
658}
659
660
661
662
663
664
665
666
667static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
668 struct ica_rsa_modexpo_crt *crt)
669{
670 struct ap_message ap_msg;
671 struct response_type resp_type = {
672 .type = PCIXCC_RESPONSE_TYPE_ICA,
673 };
674 int rc;
675
676 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
677 if (!ap_msg.message)
678 return -ENOMEM;
679 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
680 atomic_inc_return(&zcrypt_step);
681 ap_msg.private = &resp_type;
682 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
683 if (rc)
684 goto out_free;
685 init_completion(&resp_type.work);
686 ap_queue_message(zdev->ap_dev, &ap_msg);
687 rc = wait_for_completion_interruptible(&resp_type.work);
688 if (rc == 0)
689 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
690 crt->outputdatalength);
691 else
692
693 ap_cancel_message(zdev->ap_dev, &ap_msg);
694out_free:
695 free_page((unsigned long) ap_msg.message);
696 return rc;
697}
698
699
700
701
702
703
704
705
706static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
707 struct ica_xcRB *xcRB)
708{
709 struct ap_message ap_msg;
710 struct response_type resp_type = {
711 .type = PCIXCC_RESPONSE_TYPE_XCRB,
712 };
713 int rc;
714
715 ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
716 if (!ap_msg.message)
717 return -ENOMEM;
718 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
719 atomic_inc_return(&zcrypt_step);
720 ap_msg.private = &resp_type;
721 rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB);
722 if (rc)
723 goto out_free;
724 init_completion(&resp_type.work);
725 ap_queue_message(zdev->ap_dev, &ap_msg);
726 rc = wait_for_completion_interruptible(&resp_type.work);
727 if (rc == 0)
728 rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
729 else
730
731 ap_cancel_message(zdev->ap_dev, &ap_msg);
732out_free:
733 memset(ap_msg.message, 0x0, ap_msg.length);
734 kfree(ap_msg.message);
735 return rc;
736}
737
738
739
740
741static struct zcrypt_ops zcrypt_pcixcc_ops = {
742 .rsa_modexpo = zcrypt_pcixcc_modexpo,
743 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
744 .send_cprb = zcrypt_pcixcc_send_cprb,
745};
746
747
748
749
750
751
752static int zcrypt_pcixcc_mcl(struct ap_device *ap_dev)
753{
754 static unsigned char msg[] = {
755 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
756 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
757 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
758 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
759 0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
760 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
761 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00,
762 0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00,
763 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
764 0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00,
765 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
766 0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32,
767 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,
768 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,
769 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
770 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
771 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
772 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
773 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
774 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
775 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
776 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
777 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
778 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
779 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
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,0x04,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,0x50,0x4B,0x00,0x0A,
794 0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20,
795 0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05,
796 0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
797 0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55,
798 0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,
799 0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,
800 0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,
801 0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB,
802 0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54,
803 0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00,
804 0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00,
805 0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40,
806 0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C,
807 0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF,
808 0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9,
809 0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63,
810 0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5,
811 0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A,
812 0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01,
813 0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28,
814 0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91,
815 0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5,
816 0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C,
817 0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98,
818 0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96,
819 0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19,
820 0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47,
821 0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36,
822 0xF1,0x3D,0x93,0x53
823 };
824 unsigned long long psmid;
825 struct CPRBX *cprbx;
826 char *reply;
827 int rc, i;
828
829 reply = (void *) get_zeroed_page(GFP_KERNEL);
830 if (!reply)
831 return -ENOMEM;
832
833 rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, msg, sizeof(msg));
834 if (rc)
835 goto out_free;
836
837
838 for (i = 0; i < 6; i++) {
839 mdelay(300);
840 rc = ap_recv(ap_dev->qid, &psmid, reply, 4096);
841 if (rc == 0 && psmid == 0x0102030405060708ULL)
842 break;
843 }
844
845 if (i >= 6) {
846
847 rc = -ENODEV;
848 goto out_free;
849 }
850
851 cprbx = (struct CPRBX *) (reply + 48);
852 if (cprbx->ccp_rtcode == 8 && cprbx->ccp_rscode == 33)
853 rc = ZCRYPT_PCIXCC_MCL2;
854 else
855 rc = ZCRYPT_PCIXCC_MCL3;
856out_free:
857 free_page((unsigned long) reply);
858 return rc;
859}
860
861
862
863
864
865
866
867
868static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
869{
870 struct zcrypt_device *zdev;
871 int rc;
872
873 zdev = zcrypt_device_alloc(PCIXCC_MAX_RESPONSE_SIZE);
874 if (!zdev)
875 return -ENOMEM;
876 zdev->ap_dev = ap_dev;
877 zdev->ops = &zcrypt_pcixcc_ops;
878 zdev->online = 1;
879 if (ap_dev->device_type == AP_DEVICE_TYPE_PCIXCC) {
880 rc = zcrypt_pcixcc_mcl(ap_dev);
881 if (rc < 0) {
882 zcrypt_device_free(zdev);
883 return rc;
884 }
885 zdev->user_space_type = rc;
886 if (rc == ZCRYPT_PCIXCC_MCL2) {
887 zdev->type_string = "PCIXCC_MCL2";
888 zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING;
889 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
890 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
891 } else {
892 zdev->type_string = "PCIXCC_MCL3";
893 zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING;
894 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
895 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
896 }
897 } else {
898 zdev->user_space_type = ZCRYPT_CEX2C;
899 zdev->type_string = "CEX2C";
900 zdev->speed_rating = CEX2C_SPEED_RATING;
901 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
902 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
903 }
904 ap_dev->reply = &zdev->reply;
905 ap_dev->private = zdev;
906 rc = zcrypt_device_register(zdev);
907 if (rc)
908 goto out_free;
909 return 0;
910
911 out_free:
912 ap_dev->private = NULL;
913 zcrypt_device_free(zdev);
914 return rc;
915}
916
917
918
919
920
921static void zcrypt_pcixcc_remove(struct ap_device *ap_dev)
922{
923 struct zcrypt_device *zdev = ap_dev->private;
924
925 zcrypt_device_unregister(zdev);
926}
927
928int __init zcrypt_pcixcc_init(void)
929{
930 return ap_driver_register(&zcrypt_pcixcc_driver, THIS_MODULE, "pcixcc");
931}
932
933void zcrypt_pcixcc_exit(void)
934{
935 ap_driver_unregister(&zcrypt_pcixcc_driver);
936}
937
938#ifndef CONFIG_ZCRYPT_MONOLITHIC
939module_init(zcrypt_pcixcc_init);
940module_exit(zcrypt_pcixcc_exit);
941#endif
942