Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
zcrypt_msgtype6.c
Go to the documentation of this file.
1 /*
2  * zcrypt 2.1.0
3  *
4  * Copyright IBM Corp. 2001, 2012
5  * Author(s): Robert Burroughs
6  * Eric Rossman ([email protected])
7  *
8  * Hotplug & misc device support: Jochen Roehrig ([email protected])
9  * Major cleanup & driver split: Martin Schwidefsky <[email protected]>
10  * Ralph Wuerthner <[email protected]>
11  * MSGTYPE restruct: Holger Dengler <[email protected]>
12  *
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)
16  * any later version.
17  *
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.
22  *
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.
26  */
27 
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>
35 
36 #include "ap_bus.h"
37 #include "zcrypt_api.h"
38 #include "zcrypt_error.h"
39 #include "zcrypt_msgtype6.h"
40 #include "zcrypt_cca_key.h"
41 
42 #define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */
43 #define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */
44 
45 #define CEIL4(x) ((((x)+3)/4)*4)
46 
47 struct response_type {
48  struct completion work;
49  int type;
50 };
51 #define PCIXCC_RESPONSE_TYPE_ICA 0
52 #define PCIXCC_RESPONSE_TYPE_XCRB 1
53 
54 MODULE_AUTHOR("IBM Corporation");
55 MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \
56  "Copyright IBM Corp. 2001, 2012");
57 MODULE_LICENSE("GPL");
58 
59 static void zcrypt_msgtype6_receive(struct ap_device *, struct ap_message *,
60  struct ap_message *);
61 
74 struct CPRB {
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 *
89  * the CPRB). */
90  unsigned char req_datal[4]; /* request data buffer */
91  /* length ULELONG */
92  unsigned char req_datap[4]; /* request data buffer */
93  /* pointer */
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 *
100  * the CPRB). */
101  unsigned char rpl_datal[4]; /* reply data buffer len ULELONG */
102  unsigned char rpl_datap[4]; /* reply data buffer */
103  /* pointer */
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 */
117 } __packed;
118 
120  unsigned char function_code[2];
121  unsigned short ulen;
122  unsigned char only_rule[8];
123 } __packed;
124 
142 static struct CPRBX static_cprbx = {
143  .cprb_len = 0x00DC,
144  .cprb_ver_id = 0x02,
145  .func_id = {0x54, 0x32},
146 };
147 
157 static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev,
158  struct ap_message *ap_msg,
159  struct ica_rsa_modexpo *mex)
160 {
161  static struct type6_hdr static_type6_hdrX = {
162  .type = 0x06,
163  .offset1 = 0x00000058,
164  .agent_id = {'C', 'A',},
165  .function_code = {'P', 'K'},
166  };
167  static struct function_and_rules_block static_pke_fnr = {
168  .function_code = {'P', 'K'},
169  .ulen = 10,
170  .only_rule = {'M', 'R', 'P', ' ', ' ', ' ', ' ', ' '}
171  };
172  static struct function_and_rules_block static_pke_fnr_MCL2 = {
173  .function_code = {'P', 'K'},
174  .ulen = 10,
175  .only_rule = {'Z', 'E', 'R', 'O', '-', 'P', 'A', 'D'}
176  };
177  struct {
178  struct type6_hdr hdr;
179  struct CPRBX cprbx;
180  struct function_and_rules_block fr;
181  unsigned short length;
182  char text[0];
183  } __packed * msg = ap_msg->message;
184  int size;
185 
186  /* VUD.ciphertext */
187  msg->length = mex->inputdatalength + 2;
188  if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
189  return -EFAULT;
190 
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);
193  if (size < 0)
194  return size;
195  size += sizeof(*msg) + mex->inputdatalength;
196 
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);
201 
202  msg->cprbx = static_cprbx;
203  msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
204  msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1;
205 
206  msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
207  static_pke_fnr_MCL2 : static_pke_fnr;
208 
209  msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx);
210 
211  ap_msg->length = size;
212  return 0;
213 }
214 
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)
227 {
228  static struct type6_hdr static_type6_hdrX = {
229  .type = 0x06,
230  .offset1 = 0x00000058,
231  .agent_id = {'C', 'A',},
232  .function_code = {'P', 'D'},
233  };
234  static struct function_and_rules_block static_pkd_fnr = {
235  .function_code = {'P', 'D'},
236  .ulen = 10,
237  .only_rule = {'Z', 'E', 'R', 'O', '-', 'P', 'A', 'D'}
238  };
239 
240  static struct function_and_rules_block static_pkd_fnr_MCL2 = {
241  .function_code = {'P', 'D'},
242  .ulen = 10,
243  .only_rule = {'P', 'K', 'C', 'S', '-', '1', '.', '2'}
244  };
245  struct {
246  struct type6_hdr hdr;
247  struct CPRBX cprbx;
248  struct function_and_rules_block fr;
249  unsigned short length;
250  char text[0];
251  } __packed * msg = ap_msg->message;
252  int size;
253 
254  /* VUD.ciphertext */
255  msg->length = crt->inputdatalength + 2;
256  if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
257  return -EFAULT;
258 
259  /* Set up key which is located after the variable length text. */
260  size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1);
261  if (size < 0)
262  return size;
263  size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */
264 
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);
269 
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);
274 
275  msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
276  static_pkd_fnr_MCL2 : static_pkd_fnr;
277 
278  ap_msg->length = size;
279  return 0;
280 }
281 
292  struct type86_hdr hdr;
294 } __packed;
295 
296 static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
297  struct ap_message *ap_msg,
298  struct ica_xcRB *xcRB)
299 {
300  static struct type6_hdr static_type6_hdrX = {
301  .type = 0x06,
302  .offset1 = 0x00000058,
303  };
304  struct {
305  struct type6_hdr hdr;
306  struct CPRBX cprbx;
307  } __packed * msg = ap_msg->message;
308 
309  int rcblen = CEIL4(xcRB->request_control_blk_length);
310  int replylen;
311  char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
312  char *function_code;
313 
314  /* length checks */
315  ap_msg->length = sizeof(struct type6_hdr) +
317  xcRB->request_data_length;
318  if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE)
319  return -EINVAL;
320  replylen = sizeof(struct type86_fmt2_msg) +
322  xcRB->reply_data_length;
323  if (replylen > MSGTYPE06_MAX_MSG_SIZE)
324  return -EINVAL;
325 
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;
333  }
334  msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
335  msg->hdr.FromCardLen2 = xcRB->reply_data_length;
336 
337  /* prepare CPRB */
338  if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
340  return -EFAULT;
341  if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
343  return -EINVAL;
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));
347 
348  if (memcmp(function_code, "US", 2) == 0)
349  ap_msg->special = 1;
350  else
351  ap_msg->special = 0;
352 
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))
357  return -EFAULT;
358  return 0;
359 }
360 
372  struct type86_hdr hdr;
374  struct CPRBX cprbx;
375  unsigned char pad[4]; /* 4 byte function code/rules block ? */
376  unsigned short length;
377  char text[0];
378 } __packed;
379 
380 static int convert_type86_ica(struct zcrypt_device *zdev,
381  struct ap_message *reply,
382  char __user *outputdata,
383  unsigned int outputdatalength)
384 {
385  static unsigned char static_pad[] = {
386  0x00, 0x02,
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
419  };
420  struct type86x_reply *msg = reply->message;
421  unsigned short service_rc, service_rs;
422  unsigned int reply_len, pad_len;
423  char *data;
424 
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)
429  return -EINVAL;
430  if (service_rc == 8 && service_rs == 65)
431  return -EINVAL;
432  if (service_rc == 8 && service_rs == 770)
433  return -EINVAL;
434  if (service_rc == 8 && service_rs == 783) {
436  return -EAGAIN;
437  }
438  if (service_rc == 12 && service_rs == 769)
439  return -EINVAL;
440  if (service_rc == 8 && service_rs == 72)
441  return -EINVAL;
442  zdev->online = 0;
443  return -EAGAIN; /* repeat the request on a different device. */
444  }
445  data = msg->text;
446  reply_len = msg->length - 2;
447  if (reply_len > outputdatalength)
448  return -EINVAL;
449  /*
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.
453  *
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)
457  * - PCICC, always
458  */
459  pad_len = outputdatalength - reply_len;
460  if (pad_len > 0) {
461  if (pad_len < 10)
462  return -EINVAL;
463  /* 'restore' padding left in the PCICC/PCIXCC card. */
464  if (copy_to_user(outputdata, static_pad, pad_len - 1))
465  return -EFAULT;
466  if (put_user(0, outputdata + pad_len - 1))
467  return -EFAULT;
468  }
469  /* Copy the crypto response to user space. */
470  if (copy_to_user(outputdata + pad_len, data, reply_len))
471  return -EFAULT;
472  return 0;
473 }
474 
484 static int convert_type86_xcrb(struct zcrypt_device *zdev,
485  struct ap_message *reply,
486  struct ica_xcRB *xcRB)
487 {
488  struct type86_fmt2_msg *msg = reply->message;
489  char *data = reply->message;
490 
491  /* Copy CPRB to user */
493  data + msg->fmt2.offset1, msg->fmt2.count1))
494  return -EFAULT;
495  xcRB->reply_control_blk_length = msg->fmt2.count1;
496 
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))
501  return -EFAULT;
502  xcRB->reply_data_length = msg->fmt2.count2;
503  return 0;
504 }
505 
506 static int convert_type86_rng(struct zcrypt_device *zdev,
507  struct ap_message *reply,
508  char *buffer)
509 {
510  struct {
511  struct type86_hdr hdr;
512  struct type86_fmt2_ext fmt2;
513  struct CPRBX cprbx;
514  } __packed * msg = reply->message;
515  char *data = reply->message;
516 
517  if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0)
518  return -EINVAL;
519  memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
520  return msg->fmt2.count2;
521 }
522 
523 static int convert_response_ica(struct zcrypt_device *zdev,
524  struct ap_message *reply,
525  char __user *outputdata,
526  unsigned int outputdatalength)
527 {
528  struct type86x_reply *msg = reply->message;
529 
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;
541  return -EAGAIN;
542  } else
543  return -EINVAL;
544  }
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
551  * response */
552  default: /* Unknown response type, this should NEVER EVER happen */
553  zdev->online = 0;
554  return -EAGAIN; /* repeat the request on a different device. */
555  }
556 }
557 
558 static int convert_response_xcrb(struct zcrypt_device *zdev,
559  struct ap_message *reply,
560  struct ica_xcRB *xcRB)
561 {
562  struct type86x_reply *msg = reply->message;
563 
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);
574  }
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
578  * response */
579  default: /* Unknown response type, this should NEVER EVER happen */
580  xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
581  zdev->online = 0;
582  return -EAGAIN; /* repeat the request on a different device. */
583  }
584 }
585 
586 static int convert_response_rng(struct zcrypt_device *zdev,
587  struct ap_message *reply,
588  char *data)
589 {
590  struct type86x_reply *msg = reply->message;
591 
592  switch (msg->hdr.type) {
593  case TYPE82_RSP_CODE:
594  case TYPE88_RSP_CODE:
595  return -EINVAL;
596  case TYPE86_RSP_CODE:
597  if (msg->hdr.reply_code)
598  return -EINVAL;
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
602  * response */
603  default: /* Unknown response type, this should NEVER EVER happen */
604  zdev->online = 0;
605  return -EAGAIN; /* repeat the request on a different device. */
606  }
607 }
608 
617 static void zcrypt_msgtype6_receive(struct ap_device *ap_dev,
618  struct ap_message *msg,
619  struct ap_message *reply)
620 {
621  static struct error_hdr error_reply = {
623  .reply_code = REP82_ERROR_MACHINE_FAILURE,
624  };
625  struct response_type *resp_type =
626  (struct response_type *) msg->private;
627  struct type86x_reply *t86r;
628  int length;
629 
630  /* Copy the reply message to the request message buffer. */
631  if (IS_ERR(reply)) {
632  memcpy(msg->message, &error_reply, sizeof(error_reply));
633  goto out;
634  }
635  t86r = reply->message;
636  if (t86r->hdr.type == TYPE86_RSP_CODE &&
637  t86r->cprbx.cprb_ver_id == 0x02) {
638  switch (resp_type->type) {
640  length = sizeof(struct type86x_reply)
641  + t86r->length - 2;
643  memcpy(msg->message, reply->message, length);
644  break;
646  length = t86r->fmt2.offset2 + t86r->fmt2.count2;
647  length = min(MSGTYPE06_MAX_MSG_SIZE, length);
648  memcpy(msg->message, reply->message, length);
649  break;
650  default:
651  memcpy(msg->message, &error_reply,
652  sizeof(error_reply));
653  }
654  } else
655  memcpy(msg->message, reply->message, sizeof(error_reply));
656 out:
657  complete(&(resp_type->work));
658 }
659 
660 static atomic_t zcrypt_step = ATOMIC_INIT(0);
661 
669 static long zcrypt_msgtype6_modexpo(struct zcrypt_device *zdev,
670  struct ica_rsa_modexpo *mex)
671 {
672  struct ap_message ap_msg;
673  struct response_type resp_type = {
675  };
676  int rc;
677 
678  ap_init_message(&ap_msg);
679  ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
680  if (!ap_msg.message)
681  return -ENOMEM;
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);
687  if (rc)
688  goto out_free;
689  init_completion(&resp_type.work);
690  ap_queue_message(zdev->ap_dev, &ap_msg);
691  rc = wait_for_completion_interruptible(&resp_type.work);
692  if (rc == 0)
693  rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
694  mex->outputdatalength);
695  else
696  /* Signal pending. */
697  ap_cancel_message(zdev->ap_dev, &ap_msg);
698 out_free:
699  free_page((unsigned long) ap_msg.message);
700  return rc;
701 }
702 
710 static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_device *zdev,
711  struct ica_rsa_modexpo_crt *crt)
712 {
713  struct ap_message ap_msg;
714  struct response_type resp_type = {
716  };
717  int rc;
718 
719  ap_init_message(&ap_msg);
720  ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
721  if (!ap_msg.message)
722  return -ENOMEM;
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);
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(&resp_type.work);
733  if (rc == 0)
734  rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
735  crt->outputdatalength);
736  else
737  /* Signal pending. */
738  ap_cancel_message(zdev->ap_dev, &ap_msg);
739 out_free:
740  free_page((unsigned long) ap_msg.message);
741  return rc;
742 }
743 
751 static long zcrypt_msgtype6_send_cprb(struct zcrypt_device *zdev,
752  struct ica_xcRB *xcRB)
753 {
754  struct ap_message ap_msg;
755  struct response_type resp_type = {
757  };
758  int rc;
759 
760  ap_init_message(&ap_msg);
762  if (!ap_msg.message)
763  return -ENOMEM;
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);
769  if (rc)
770  goto out_free;
771  init_completion(&resp_type.work);
772  ap_queue_message(zdev->ap_dev, &ap_msg);
773  rc = wait_for_completion_interruptible(&resp_type.work);
774  if (rc == 0)
775  rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
776  else
777  /* Signal pending. */
778  ap_cancel_message(zdev->ap_dev, &ap_msg);
779 out_free:
780  kzfree(ap_msg.message);
781  return rc;
782 }
783 
792 static long zcrypt_msgtype6_rng(struct zcrypt_device *zdev,
793  char *buffer)
794 {
795  struct ap_message ap_msg;
796  struct response_type resp_type = {
798  };
799  int rc;
800 
801  ap_init_message(&ap_msg);
803  if (!ap_msg.message)
804  return -ENOMEM;
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);
813  if (rc == 0)
814  rc = convert_response_rng(zdev, &ap_msg, buffer);
815  else
816  /* Signal pending. */
817  ap_cancel_message(zdev->ap_dev, &ap_msg);
818  kfree(ap_msg.message);
819  return rc;
820 }
821 
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,
831 };
832 
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,
840 };
841 
843 {
844  zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops);
845  zcrypt_msgtype_register(&zcrypt_msgtype6_ops);
846  return 0;
847 }
848 
850 {
851  zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops);
852  zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops);
853 }
854