4 * Copyright IBM Corp. 2001, 2012
5 * Author(s): Robert Burroughs
6 * Eric Rossman (edrossma@us.ibm.com)
8 * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
9 * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
10 * Ralph Wuerthner <rwuerthn@de.ibm.com>
11 * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/err.h>
31 #include <linux/delay.h>
32 #include <linux/slab.h>
33 #include <linux/atomic.h>
34 #include <linux/uaccess.h>
37 #include "zcrypt_api.h"
38 #include "zcrypt_error.h"
39 #include "zcrypt_msgtype6.h"
40 #include "zcrypt_cca_key.h"
42 #define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */
43 #define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */
45 #define CEIL4(x) ((((x)+3)/4)*4)
47 struct response_type {
48 struct completion work;
51 #define PCIXCC_RESPONSE_TYPE_ICA 0
52 #define PCIXCC_RESPONSE_TYPE_XCRB 1
54 MODULE_AUTHOR("IBM Corporation");
55 MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \
56 "Copyright IBM Corp. 2001, 2012");
57 MODULE_LICENSE("GPL");
59 static void zcrypt_msgtype6_receive(struct ap_device *, struct ap_message *,
64 * Note that all shorts, ints and longs are little-endian.
65 * All pointer fields are 32-bits long, and mean nothing
67 * A request CPRB is followed by a request_parameter_block.
69 * The request (or reply) parameter block is organized thus:
75 unsigned short cprb_len; /* CPRB length */
76 unsigned char cprb_ver_id; /* CPRB version id. */
77 unsigned char pad_000; /* Alignment pad byte. */
78 unsigned char srpi_rtcode[4]; /* SRPI return code LELONG */
79 unsigned char srpi_verb; /* SRPI verb type */
80 unsigned char flags; /* flags */
81 unsigned char func_id[2]; /* function id */
82 unsigned char checkpoint_flag; /* */
83 unsigned char resv2; /* reserved */
84 unsigned short req_parml; /* request parameter buffer */
85 /* length 16-bit little endian */
86 unsigned char req_parmp[4]; /* request parameter buffer *
87 * pointer (means nothing: the *
88 * parameter buffer follows *
90 unsigned char req_datal[4]; /* request data buffer */
92 unsigned char req_datap[4]; /* request data buffer */
94 unsigned short rpl_parml; /* reply parameter buffer */
95 /* length 16-bit little endian */
96 unsigned char pad_001[2]; /* Alignment pad bytes. ULESHORT */
97 unsigned char rpl_parmp[4]; /* reply parameter buffer *
98 * pointer (means nothing: the *
99 * parameter buffer follows *
101 unsigned char rpl_datal[4]; /* reply data buffer len ULELONG */
102 unsigned char rpl_datap[4]; /* reply data buffer */
104 unsigned short ccp_rscode; /* server reason code ULESHORT */
105 unsigned short ccp_rtcode; /* server return code ULESHORT */
106 unsigned char repd_parml[2]; /* replied parameter len ULESHORT*/
107 unsigned char mac_data_len[2]; /* Mac Data Length ULESHORT */
108 unsigned char repd_datal[4]; /* replied data length ULELONG */
109 unsigned char req_pc[2]; /* PC identifier */
110 unsigned char res_origin[8]; /* resource origin */
111 unsigned char mac_value[8]; /* Mac Value */
112 unsigned char logon_id[8]; /* Logon Identifier */
113 unsigned char usage_domain[2]; /* cdx */
114 unsigned char resv3[18]; /* reserved for requestor */
115 unsigned short svr_namel; /* server name length ULESHORT */
116 unsigned char svr_name[8]; /* server name */
119 struct function_and_rules_block {
120 unsigned char function_code[2];
122 unsigned char only_rule[8];
126 * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C
127 * card in a type6 message. The 3 fields that must be filled in at execution
128 * time are req_parml, rpl_parml and usage_domain.
129 * Everything about this interface is ascii/big-endian, since the
130 * device does *not* have 'Intel inside'.
132 * The CPRBX is followed immediately by the parm block.
133 * The parm block contains:
134 * - function code ('PD' 0x5044 or 'PK' 0x504B)
135 * - rule block (one of:)
136 * + 0x000A 'PKCS-1.2' (MCL2 'PD')
137 * + 0x000A 'ZERO-PAD' (MCL2 'PK')
138 * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD')
139 * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK')
142 static struct CPRBX static_cprbx = {
145 .func_id = {0x54, 0x32},
149 * Convert a ICAMEX message to a type6 MEX message.
151 * @zdev: crypto device pointer
152 * @ap_msg: pointer to AP message
153 * @mex: pointer to user input data
155 * Returns 0 on success or -EFAULT.
157 static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev,
158 struct ap_message *ap_msg,
159 struct ica_rsa_modexpo *mex)
161 static struct type6_hdr static_type6_hdrX = {
163 .offset1 = 0x00000058,
164 .agent_id = {'C', 'A',},
165 .function_code = {'P', 'K'},
167 static struct function_and_rules_block static_pke_fnr = {
168 .function_code = {'P', 'K'},
170 .only_rule = {'M', 'R', 'P', ' ', ' ', ' ', ' ', ' '}
172 static struct function_and_rules_block static_pke_fnr_MCL2 = {
173 .function_code = {'P', 'K'},
175 .only_rule = {'Z', 'E', 'R', 'O', '-', 'P', 'A', 'D'}
178 struct type6_hdr hdr;
180 struct function_and_rules_block fr;
181 unsigned short length;
183 } __packed * msg = ap_msg->message;
187 msg->length = mex->inputdatalength + 2;
188 if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
191 /* Set up key which is located after the variable length text. */
192 size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1);
195 size += sizeof(*msg) + mex->inputdatalength;
197 /* message header, cprbx and f&r */
198 msg->hdr = static_type6_hdrX;
199 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
200 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
202 msg->cprbx = static_cprbx;
203 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
204 msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1;
206 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
207 static_pke_fnr_MCL2 : static_pke_fnr;
209 msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx);
211 ap_msg->length = size;
216 * Convert a ICACRT message to a type6 CRT message.
218 * @zdev: crypto device pointer
219 * @ap_msg: pointer to AP message
220 * @crt: pointer to user input data
222 * Returns 0 on success or -EFAULT.
224 static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,
225 struct ap_message *ap_msg,
226 struct ica_rsa_modexpo_crt *crt)
228 static struct type6_hdr static_type6_hdrX = {
230 .offset1 = 0x00000058,
231 .agent_id = {'C', 'A',},
232 .function_code = {'P', 'D'},
234 static struct function_and_rules_block static_pkd_fnr = {
235 .function_code = {'P', 'D'},
237 .only_rule = {'Z', 'E', 'R', 'O', '-', 'P', 'A', 'D'}
240 static struct function_and_rules_block static_pkd_fnr_MCL2 = {
241 .function_code = {'P', 'D'},
243 .only_rule = {'P', 'K', 'C', 'S', '-', '1', '.', '2'}
246 struct type6_hdr hdr;
248 struct function_and_rules_block fr;
249 unsigned short length;
251 } __packed * msg = ap_msg->message;
255 msg->length = crt->inputdatalength + 2;
256 if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
259 /* Set up key which is located after the variable length text. */
260 size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1);
263 size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */
265 /* message header, cprbx and f&r */
266 msg->hdr = static_type6_hdrX;
267 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
268 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
270 msg->cprbx = static_cprbx;
271 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
272 msg->cprbx.req_parml = msg->cprbx.rpl_msgbl =
273 size - sizeof(msg->hdr) - sizeof(msg->cprbx);
275 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
276 static_pkd_fnr_MCL2 : static_pkd_fnr;
278 ap_msg->length = size;
283 * Convert a XCRB message to a type6 CPRB message.
285 * @zdev: crypto device pointer
286 * @ap_msg: pointer to AP message
287 * @xcRB: pointer to user input data
289 * Returns 0 on success or -EFAULT, -EINVAL.
291 struct type86_fmt2_msg {
292 struct type86_hdr hdr;
293 struct type86_fmt2_ext fmt2;
296 static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
297 struct ap_message *ap_msg,
298 struct ica_xcRB *xcRB)
300 static struct type6_hdr static_type6_hdrX = {
302 .offset1 = 0x00000058,
305 struct type6_hdr hdr;
307 } __packed * msg = ap_msg->message;
309 int rcblen = CEIL4(xcRB->request_control_blk_length);
311 char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
315 ap_msg->length = sizeof(struct type6_hdr) +
316 CEIL4(xcRB->request_control_blk_length) +
317 xcRB->request_data_length;
318 if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE)
320 replylen = sizeof(struct type86_fmt2_msg) +
321 CEIL4(xcRB->reply_control_blk_length) +
322 xcRB->reply_data_length;
323 if (replylen > MSGTYPE06_MAX_MSG_SIZE)
326 /* prepare type6 header */
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;
334 msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
335 msg->hdr.FromCardLen2 = xcRB->reply_data_length;
338 if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
339 xcRB->request_control_blk_length))
341 if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
342 xcRB->request_control_blk_length)
344 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
345 memcpy(msg->hdr.function_code, function_code,
346 sizeof(msg->hdr.function_code));
348 if (memcmp(function_code, "US", 2) == 0)
353 /* copy data block */
354 if (xcRB->request_data_length &&
355 copy_from_user(req_data, xcRB->request_data_address,
356 xcRB->request_data_length))
362 * Copy results from a type 86 ICA reply message back to user space.
364 * @zdev: crypto device pointer
365 * @reply: reply AP message.
366 * @data: pointer to user output data
367 * @length: size of user output data
369 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
371 struct type86x_reply {
372 struct type86_hdr hdr;
373 struct type86_fmt2_ext fmt2;
375 unsigned char pad[4]; /* 4 byte function code/rules block ? */
376 unsigned short length;
380 static int convert_type86_ica(struct zcrypt_device *zdev,
381 struct ap_message *reply,
382 char __user *outputdata,
383 unsigned int outputdatalength)
385 static unsigned char static_pad[] = {
387 0x1B, 0x7B, 0x5D, 0xB5, 0x75, 0x01, 0x3D, 0xFD,
388 0x8D, 0xD1, 0xC7, 0x03, 0x2D, 0x09, 0x23, 0x57,
389 0x89, 0x49, 0xB9, 0x3F, 0xBB, 0x99, 0x41, 0x5B,
390 0x75, 0x21, 0x7B, 0x9D, 0x3B, 0x6B, 0x51, 0x39,
391 0xBB, 0x0D, 0x35, 0xB9, 0x89, 0x0F, 0x93, 0xA5,
392 0x0B, 0x47, 0xF1, 0xD3, 0xBB, 0xCB, 0xF1, 0x9D,
393 0x23, 0x73, 0x71, 0xFF, 0xF3, 0xF5, 0x45, 0xFB,
394 0x61, 0x29, 0x23, 0xFD, 0xF1, 0x29, 0x3F, 0x7F,
395 0x17, 0xB7, 0x1B, 0xA9, 0x19, 0xBD, 0x57, 0xA9,
396 0xD7, 0x95, 0xA3, 0xCB, 0xED, 0x1D, 0xDB, 0x45,
397 0x7D, 0x11, 0xD1, 0x51, 0x1B, 0xED, 0x71, 0xE9,
398 0xB1, 0xD1, 0xAB, 0xAB, 0x21, 0x2B, 0x1B, 0x9F,
399 0x3B, 0x9F, 0xF7, 0xF7, 0xBD, 0x63, 0xEB, 0xAD,
400 0xDF, 0xB3, 0x6F, 0x5B, 0xDB, 0x8D, 0xA9, 0x5D,
401 0xE3, 0x7D, 0x77, 0x49, 0x47, 0xF5, 0xA7, 0xFD,
402 0xAB, 0x2F, 0x27, 0x35, 0x77, 0xD3, 0x49, 0xC9,
403 0x09, 0xEB, 0xB1, 0xF9, 0xBF, 0x4B, 0xCB, 0x2B,
404 0xEB, 0xEB, 0x05, 0xFF, 0x7D, 0xC7, 0x91, 0x8B,
405 0x09, 0x83, 0xB9, 0xB9, 0x69, 0x33, 0x39, 0x6B,
406 0x79, 0x75, 0x19, 0xBF, 0xBB, 0x07, 0x1D, 0xBD,
407 0x29, 0xBF, 0x39, 0x95, 0x93, 0x1D, 0x35, 0xC7,
408 0xC9, 0x4D, 0xE5, 0x97, 0x0B, 0x43, 0x9B, 0xF1,
409 0x16, 0x93, 0x03, 0x1F, 0xA5, 0xFB, 0xDB, 0xF3,
410 0x27, 0x4F, 0x27, 0x61, 0x05, 0x1F, 0xB9, 0x23,
411 0x2F, 0xC3, 0x81, 0xA9, 0x23, 0x71, 0x55, 0x55,
412 0xEB, 0xED, 0x41, 0xE5, 0xF3, 0x11, 0xF1, 0x43,
413 0x69, 0x03, 0xBD, 0x0B, 0x37, 0x0F, 0x51, 0x8F,
414 0x0B, 0xB5, 0x89, 0x5B, 0x67, 0xA9, 0xD9, 0x4F,
415 0x01, 0xF9, 0x21, 0x77, 0x37, 0x73, 0x79, 0xC5,
416 0x7F, 0x51, 0xC1, 0xCF, 0x97, 0xA1, 0x75, 0xAD,
417 0x35, 0x9D, 0xD3, 0xD3, 0xA7, 0x9D, 0x5D, 0x41,
418 0x6F, 0x65, 0x1B, 0xCF, 0xA9, 0x87, 0x91, 0x09
420 struct type86x_reply *msg = reply->message;
421 unsigned short service_rc, service_rs;
422 unsigned int reply_len, pad_len;
425 service_rc = msg->cprbx.ccp_rtcode;
426 if (unlikely(service_rc != 0)) {
427 service_rs = msg->cprbx.ccp_rscode;
428 if (service_rc == 8 && service_rs == 66)
430 if (service_rc == 8 && service_rs == 65)
432 if (service_rc == 8 && service_rs == 770)
434 if (service_rc == 8 && service_rs == 783) {
435 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
438 if (service_rc == 12 && service_rs == 769)
440 if (service_rc == 8 && service_rs == 72)
443 return -EAGAIN; /* repeat the request on a different device. */
446 reply_len = msg->length - 2;
447 if (reply_len > outputdatalength)
450 * For all encipher requests, the length of the ciphertext (reply_len)
451 * will always equal the modulus length. For MEX decipher requests
452 * the output needs to get padded. Minimum pad size is 10.
454 * Currently, the cases where padding will be added is for:
455 * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
456 * ZERO-PAD and CRT is only supported for PKD requests)
459 pad_len = outputdatalength - reply_len;
463 /* 'restore' padding left in the PCICC/PCIXCC card. */
464 if (copy_to_user(outputdata, static_pad, pad_len - 1))
466 if (put_user(0, outputdata + pad_len - 1))
469 /* Copy the crypto response to user space. */
470 if (copy_to_user(outputdata + pad_len, data, reply_len))
476 * Copy results from a type 86 XCRB reply message back to user space.
478 * @zdev: crypto device pointer
479 * @reply: reply AP message.
480 * @xcRB: pointer to XCRB
482 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
484 static int convert_type86_xcrb(struct zcrypt_device *zdev,
485 struct ap_message *reply,
486 struct ica_xcRB *xcRB)
488 struct type86_fmt2_msg *msg = reply->message;
489 char *data = reply->message;
491 /* Copy CPRB to user */
492 if (copy_to_user(xcRB->reply_control_blk_addr,
493 data + msg->fmt2.offset1, msg->fmt2.count1))
495 xcRB->reply_control_blk_length = msg->fmt2.count1;
497 /* Copy data buffer to user */
498 if (msg->fmt2.count2)
499 if (copy_to_user(xcRB->reply_data_addr,
500 data + msg->fmt2.offset2, msg->fmt2.count2))
502 xcRB->reply_data_length = msg->fmt2.count2;
506 static int convert_type86_rng(struct zcrypt_device *zdev,
507 struct ap_message *reply,
511 struct type86_hdr hdr;
512 struct type86_fmt2_ext fmt2;
514 } __packed * msg = reply->message;
515 char *data = reply->message;
517 if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0)
519 memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
520 return msg->fmt2.count2;
523 static int convert_response_ica(struct zcrypt_device *zdev,
524 struct ap_message *reply,
525 char __user *outputdata,
526 unsigned int outputdatalength)
528 struct type86x_reply *msg = reply->message;
530 /* Response type byte is the second byte in the response. */
531 switch (((unsigned char *) reply->message)[1]) {
532 case TYPE82_RSP_CODE:
533 case TYPE88_RSP_CODE:
534 return convert_error(zdev, reply);
535 case TYPE86_RSP_CODE:
536 if (msg->cprbx.ccp_rtcode &&
537 (msg->cprbx.ccp_rscode == 0x14f) &&
538 (outputdatalength > 256)) {
539 if (zdev->max_exp_bit_length <= 17) {
540 zdev->max_exp_bit_length = 17;
545 if (msg->hdr.reply_code)
546 return convert_error(zdev, reply);
547 if (msg->cprbx.cprb_ver_id == 0x02)
548 return convert_type86_ica(zdev, reply,
549 outputdata, outputdatalength);
550 /* Fall through, no break, incorrect cprb version is an unknown
552 default: /* Unknown response type, this should NEVER EVER happen */
554 return -EAGAIN; /* repeat the request on a different device. */
558 static int convert_response_xcrb(struct zcrypt_device *zdev,
559 struct ap_message *reply,
560 struct ica_xcRB *xcRB)
562 struct type86x_reply *msg = reply->message;
564 /* Response type byte is the second byte in the response. */
565 switch (((unsigned char *) reply->message)[1]) {
566 case TYPE82_RSP_CODE:
567 case TYPE88_RSP_CODE:
568 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
569 return convert_error(zdev, reply);
570 case TYPE86_RSP_CODE:
571 if (msg->hdr.reply_code) {
572 memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
573 return convert_error(zdev, reply);
575 if (msg->cprbx.cprb_ver_id == 0x02)
576 return convert_type86_xcrb(zdev, reply, xcRB);
577 /* Fall through, no break, incorrect cprb version is an unknown
579 default: /* Unknown response type, this should NEVER EVER happen */
580 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
582 return -EAGAIN; /* repeat the request on a different device. */
586 static int convert_response_rng(struct zcrypt_device *zdev,
587 struct ap_message *reply,
590 struct type86x_reply *msg = reply->message;
592 switch (msg->hdr.type) {
593 case TYPE82_RSP_CODE:
594 case TYPE88_RSP_CODE:
596 case TYPE86_RSP_CODE:
597 if (msg->hdr.reply_code)
599 if (msg->cprbx.cprb_ver_id == 0x02)
600 return convert_type86_rng(zdev, reply, data);
601 /* Fall through, no break, incorrect cprb version is an unknown
603 default: /* Unknown response type, this should NEVER EVER happen */
605 return -EAGAIN; /* repeat the request on a different device. */
610 * This function is called from the AP bus code after a crypto request
611 * "msg" has finished with the reply message "reply".
612 * It is called from tasklet context.
613 * @ap_dev: pointer to the AP device
614 * @msg: pointer to the AP message
615 * @reply: pointer to the AP reply message
617 static void zcrypt_msgtype6_receive(struct ap_device *ap_dev,
618 struct ap_message *msg,
619 struct ap_message *reply)
621 static struct error_hdr error_reply = {
622 .type = TYPE82_RSP_CODE,
623 .reply_code = REP82_ERROR_MACHINE_FAILURE,
625 struct response_type *resp_type =
626 (struct response_type *) msg->private;
627 struct type86x_reply *t86r;
630 /* Copy the reply message to the request message buffer. */
632 memcpy(msg->message, &error_reply, sizeof(error_reply));
635 t86r = reply->message;
636 if (t86r->hdr.type == TYPE86_RSP_CODE &&
637 t86r->cprbx.cprb_ver_id == 0x02) {
638 switch (resp_type->type) {
639 case PCIXCC_RESPONSE_TYPE_ICA:
640 length = sizeof(struct type86x_reply)
642 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
643 memcpy(msg->message, reply->message, length);
645 case PCIXCC_RESPONSE_TYPE_XCRB:
646 length = t86r->fmt2.offset2 + t86r->fmt2.count2;
647 length = min(MSGTYPE06_MAX_MSG_SIZE, length);
648 memcpy(msg->message, reply->message, length);
651 memcpy(msg->message, &error_reply,
652 sizeof(error_reply));
655 memcpy(msg->message, reply->message, sizeof(error_reply));
657 complete(&(resp_type->work));
660 static atomic_t zcrypt_step = ATOMIC_INIT(0);
663 * The request distributor calls this function if it picked the PCIXCC/CEX2C
664 * device to handle a modexpo request.
665 * @zdev: pointer to zcrypt_device structure that identifies the
666 * PCIXCC/CEX2C device to the request distributor
667 * @mex: pointer to the modexpo request buffer
669 static long zcrypt_msgtype6_modexpo(struct zcrypt_device *zdev,
670 struct ica_rsa_modexpo *mex)
672 struct ap_message ap_msg;
673 struct response_type resp_type = {
674 .type = PCIXCC_RESPONSE_TYPE_ICA,
678 ap_init_message(&ap_msg);
679 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
682 ap_msg.receive = zcrypt_msgtype6_receive;
683 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
684 atomic_inc_return(&zcrypt_step);
685 ap_msg.private = &resp_type;
686 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
689 init_completion(&resp_type.work);
690 ap_queue_message(zdev->ap_dev, &ap_msg);
691 rc = wait_for_completion_interruptible(&resp_type.work);
693 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
694 mex->outputdatalength);
696 /* Signal pending. */
697 ap_cancel_message(zdev->ap_dev, &ap_msg);
699 free_page((unsigned long) ap_msg.message);
704 * The request distributor calls this function if it picked the PCIXCC/CEX2C
705 * device to handle a modexpo_crt request.
706 * @zdev: pointer to zcrypt_device structure that identifies the
707 * PCIXCC/CEX2C device to the request distributor
708 * @crt: pointer to the modexpoc_crt request buffer
710 static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_device *zdev,
711 struct ica_rsa_modexpo_crt *crt)
713 struct ap_message ap_msg;
714 struct response_type resp_type = {
715 .type = PCIXCC_RESPONSE_TYPE_ICA,
719 ap_init_message(&ap_msg);
720 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
723 ap_msg.receive = zcrypt_msgtype6_receive;
724 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
725 atomic_inc_return(&zcrypt_step);
726 ap_msg.private = &resp_type;
727 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
730 init_completion(&resp_type.work);
731 ap_queue_message(zdev->ap_dev, &ap_msg);
732 rc = wait_for_completion_interruptible(&resp_type.work);
734 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
735 crt->outputdatalength);
737 /* Signal pending. */
738 ap_cancel_message(zdev->ap_dev, &ap_msg);
740 free_page((unsigned long) ap_msg.message);
745 * The request distributor calls this function if it picked the PCIXCC/CEX2C
746 * device to handle a send_cprb request.
747 * @zdev: pointer to zcrypt_device structure that identifies the
748 * PCIXCC/CEX2C device to the request distributor
749 * @xcRB: pointer to the send_cprb request buffer
751 static long zcrypt_msgtype6_send_cprb(struct zcrypt_device *zdev,
752 struct ica_xcRB *xcRB)
754 struct ap_message ap_msg;
755 struct response_type resp_type = {
756 .type = PCIXCC_RESPONSE_TYPE_XCRB,
760 ap_init_message(&ap_msg);
761 ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
764 ap_msg.receive = zcrypt_msgtype6_receive;
765 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
766 atomic_inc_return(&zcrypt_step);
767 ap_msg.private = &resp_type;
768 rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB);
771 init_completion(&resp_type.work);
772 ap_queue_message(zdev->ap_dev, &ap_msg);
773 rc = wait_for_completion_interruptible(&resp_type.work);
775 rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
777 /* Signal pending. */
778 ap_cancel_message(zdev->ap_dev, &ap_msg);
780 kzfree(ap_msg.message);
785 * The request distributor calls this function if it picked the PCIXCC/CEX2C
786 * device to generate random data.
787 * @zdev: pointer to zcrypt_device structure that identifies the
788 * PCIXCC/CEX2C device to the request distributor
789 * @buffer: pointer to a memory page to return random data
792 static long zcrypt_msgtype6_rng(struct zcrypt_device *zdev,
795 struct ap_message ap_msg;
796 struct response_type resp_type = {
797 .type = PCIXCC_RESPONSE_TYPE_XCRB,
801 ap_init_message(&ap_msg);
802 ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
805 ap_msg.receive = zcrypt_msgtype6_receive;
806 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
807 atomic_inc_return(&zcrypt_step);
808 ap_msg.private = &resp_type;
809 rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE);
810 init_completion(&resp_type.work);
811 ap_queue_message(zdev->ap_dev, &ap_msg);
812 rc = wait_for_completion_interruptible(&resp_type.work);
814 rc = convert_response_rng(zdev, &ap_msg, buffer);
816 /* Signal pending. */
817 ap_cancel_message(zdev->ap_dev, &ap_msg);
818 kfree(ap_msg.message);
823 * The crypto operations for a PCIXCC/CEX2C card.
825 static struct zcrypt_ops zcrypt_msgtype6_norng_ops = {
826 .owner = THIS_MODULE,
827 .variant = MSGTYPE06_VARIANT_NORNG,
828 .rsa_modexpo = zcrypt_msgtype6_modexpo,
829 .rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt,
830 .send_cprb = zcrypt_msgtype6_send_cprb,
833 static struct zcrypt_ops zcrypt_msgtype6_ops = {
834 .owner = THIS_MODULE,
835 .variant = MSGTYPE06_VARIANT_DEFAULT,
836 .rsa_modexpo = zcrypt_msgtype6_modexpo,
837 .rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt,
838 .send_cprb = zcrypt_msgtype6_send_cprb,
839 .rng = zcrypt_msgtype6_rng,
842 int __init zcrypt_msgtype6_init(void)
844 zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops);
845 zcrypt_msgtype_register(&zcrypt_msgtype6_ops);
849 void __exit zcrypt_msgtype6_exit(void)
851 zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops);
852 zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops);
855 module_init(zcrypt_msgtype6_init);
856 module_exit(zcrypt_msgtype6_exit);