blob: 46b324ce6c7a8d46fe335b6b994db455e7c3beb8 [file] [log] [blame]
Holger Dengler5e55a482012-08-28 16:45:36 +02001/*
2 * zcrypt 2.1.0
3 *
4 * Copyright IBM Corp. 2001, 2012
5 * Author(s): Robert Burroughs
6 * Eric Rossman (edrossma@us.ibm.com)
7 *
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>
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
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +010028#define KMSG_COMPONENT "zcrypt"
29#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
30
Holger Dengler5e55a482012-08-28 16:45:36 +020031#include <linux/module.h>
32#include <linux/init.h>
33#include <linux/err.h>
34#include <linux/delay.h>
35#include <linux/slab.h>
36#include <linux/atomic.h>
37#include <linux/uaccess.h>
38
39#include "ap_bus.h"
40#include "zcrypt_api.h"
41#include "zcrypt_error.h"
42#include "zcrypt_msgtype6.h"
43#include "zcrypt_cca_key.h"
44
45#define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */
46#define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */
47
48#define CEIL4(x) ((((x)+3)/4)*4)
49
50struct response_type {
51 struct completion work;
52 int type;
53};
54#define PCIXCC_RESPONSE_TYPE_ICA 0
55#define PCIXCC_RESPONSE_TYPE_XCRB 1
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +010056#define PCIXCC_RESPONSE_TYPE_EP11 2
Holger Dengler5e55a482012-08-28 16:45:36 +020057
58MODULE_AUTHOR("IBM Corporation");
59MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \
60 "Copyright IBM Corp. 2001, 2012");
61MODULE_LICENSE("GPL");
62
63static void zcrypt_msgtype6_receive(struct ap_device *, struct ap_message *,
64 struct ap_message *);
65
66/**
67 * CPRB
68 * Note that all shorts, ints and longs are little-endian.
69 * All pointer fields are 32-bits long, and mean nothing
70 *
71 * A request CPRB is followed by a request_parameter_block.
72 *
73 * The request (or reply) parameter block is organized thus:
74 * function code
75 * VUD block
76 * key block
77 */
78struct CPRB {
79 unsigned short cprb_len; /* CPRB length */
80 unsigned char cprb_ver_id; /* CPRB version id. */
81 unsigned char pad_000; /* Alignment pad byte. */
82 unsigned char srpi_rtcode[4]; /* SRPI return code LELONG */
83 unsigned char srpi_verb; /* SRPI verb type */
84 unsigned char flags; /* flags */
85 unsigned char func_id[2]; /* function id */
86 unsigned char checkpoint_flag; /* */
87 unsigned char resv2; /* reserved */
88 unsigned short req_parml; /* request parameter buffer */
89 /* length 16-bit little endian */
90 unsigned char req_parmp[4]; /* request parameter buffer *
91 * pointer (means nothing: the *
92 * parameter buffer follows *
93 * the CPRB). */
94 unsigned char req_datal[4]; /* request data buffer */
95 /* length ULELONG */
96 unsigned char req_datap[4]; /* request data buffer */
97 /* pointer */
98 unsigned short rpl_parml; /* reply parameter buffer */
99 /* length 16-bit little endian */
100 unsigned char pad_001[2]; /* Alignment pad bytes. ULESHORT */
101 unsigned char rpl_parmp[4]; /* reply parameter buffer *
102 * pointer (means nothing: the *
103 * parameter buffer follows *
104 * the CPRB). */
105 unsigned char rpl_datal[4]; /* reply data buffer len ULELONG */
106 unsigned char rpl_datap[4]; /* reply data buffer */
107 /* pointer */
108 unsigned short ccp_rscode; /* server reason code ULESHORT */
109 unsigned short ccp_rtcode; /* server return code ULESHORT */
110 unsigned char repd_parml[2]; /* replied parameter len ULESHORT*/
111 unsigned char mac_data_len[2]; /* Mac Data Length ULESHORT */
112 unsigned char repd_datal[4]; /* replied data length ULELONG */
113 unsigned char req_pc[2]; /* PC identifier */
114 unsigned char res_origin[8]; /* resource origin */
115 unsigned char mac_value[8]; /* Mac Value */
116 unsigned char logon_id[8]; /* Logon Identifier */
117 unsigned char usage_domain[2]; /* cdx */
118 unsigned char resv3[18]; /* reserved for requestor */
119 unsigned short svr_namel; /* server name length ULESHORT */
120 unsigned char svr_name[8]; /* server name */
121} __packed;
122
123struct function_and_rules_block {
124 unsigned char function_code[2];
125 unsigned short ulen;
126 unsigned char only_rule[8];
127} __packed;
128
129/**
130 * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C
131 * card in a type6 message. The 3 fields that must be filled in at execution
132 * time are req_parml, rpl_parml and usage_domain.
133 * Everything about this interface is ascii/big-endian, since the
134 * device does *not* have 'Intel inside'.
135 *
136 * The CPRBX is followed immediately by the parm block.
137 * The parm block contains:
138 * - function code ('PD' 0x5044 or 'PK' 0x504B)
139 * - rule block (one of:)
140 * + 0x000A 'PKCS-1.2' (MCL2 'PD')
141 * + 0x000A 'ZERO-PAD' (MCL2 'PK')
142 * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD')
143 * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK')
144 * - VUD block
145 */
146static struct CPRBX static_cprbx = {
147 .cprb_len = 0x00DC,
148 .cprb_ver_id = 0x02,
149 .func_id = {0x54, 0x32},
150};
151
152/**
153 * Convert a ICAMEX message to a type6 MEX message.
154 *
155 * @zdev: crypto device pointer
156 * @ap_msg: pointer to AP message
157 * @mex: pointer to user input data
158 *
159 * Returns 0 on success or -EFAULT.
160 */
161static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev,
162 struct ap_message *ap_msg,
163 struct ica_rsa_modexpo *mex)
164{
165 static struct type6_hdr static_type6_hdrX = {
166 .type = 0x06,
167 .offset1 = 0x00000058,
168 .agent_id = {'C', 'A',},
169 .function_code = {'P', 'K'},
170 };
171 static struct function_and_rules_block static_pke_fnr = {
172 .function_code = {'P', 'K'},
173 .ulen = 10,
174 .only_rule = {'M', 'R', 'P', ' ', ' ', ' ', ' ', ' '}
175 };
176 static struct function_and_rules_block static_pke_fnr_MCL2 = {
177 .function_code = {'P', 'K'},
178 .ulen = 10,
179 .only_rule = {'Z', 'E', 'R', 'O', '-', 'P', 'A', 'D'}
180 };
181 struct {
182 struct type6_hdr hdr;
183 struct CPRBX cprbx;
184 struct function_and_rules_block fr;
185 unsigned short length;
186 char text[0];
187 } __packed * msg = ap_msg->message;
188 int size;
189
190 /* VUD.ciphertext */
191 msg->length = mex->inputdatalength + 2;
192 if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
193 return -EFAULT;
194
195 /* Set up key which is located after the variable length text. */
196 size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1);
197 if (size < 0)
198 return size;
199 size += sizeof(*msg) + mex->inputdatalength;
200
201 /* message header, cprbx and f&r */
202 msg->hdr = static_type6_hdrX;
203 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
204 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
205
206 msg->cprbx = static_cprbx;
207 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
208 msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1;
209
210 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
211 static_pke_fnr_MCL2 : static_pke_fnr;
212
213 msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx);
214
215 ap_msg->length = size;
216 return 0;
217}
218
219/**
220 * Convert a ICACRT message to a type6 CRT message.
221 *
222 * @zdev: crypto device pointer
223 * @ap_msg: pointer to AP message
224 * @crt: pointer to user input data
225 *
226 * Returns 0 on success or -EFAULT.
227 */
228static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,
229 struct ap_message *ap_msg,
230 struct ica_rsa_modexpo_crt *crt)
231{
232 static struct type6_hdr static_type6_hdrX = {
233 .type = 0x06,
234 .offset1 = 0x00000058,
235 .agent_id = {'C', 'A',},
236 .function_code = {'P', 'D'},
237 };
238 static struct function_and_rules_block static_pkd_fnr = {
239 .function_code = {'P', 'D'},
240 .ulen = 10,
241 .only_rule = {'Z', 'E', 'R', 'O', '-', 'P', 'A', 'D'}
242 };
243
244 static struct function_and_rules_block static_pkd_fnr_MCL2 = {
245 .function_code = {'P', 'D'},
246 .ulen = 10,
247 .only_rule = {'P', 'K', 'C', 'S', '-', '1', '.', '2'}
248 };
249 struct {
250 struct type6_hdr hdr;
251 struct CPRBX cprbx;
252 struct function_and_rules_block fr;
253 unsigned short length;
254 char text[0];
255 } __packed * msg = ap_msg->message;
256 int size;
257
258 /* VUD.ciphertext */
259 msg->length = crt->inputdatalength + 2;
260 if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
261 return -EFAULT;
262
263 /* Set up key which is located after the variable length text. */
264 size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1);
265 if (size < 0)
266 return size;
267 size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */
268
269 /* message header, cprbx and f&r */
270 msg->hdr = static_type6_hdrX;
271 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
272 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
273
274 msg->cprbx = static_cprbx;
275 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
276 msg->cprbx.req_parml = msg->cprbx.rpl_msgbl =
277 size - sizeof(msg->hdr) - sizeof(msg->cprbx);
278
279 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
280 static_pkd_fnr_MCL2 : static_pkd_fnr;
281
282 ap_msg->length = size;
283 return 0;
284}
285
286/**
287 * Convert a XCRB message to a type6 CPRB message.
288 *
289 * @zdev: crypto device pointer
290 * @ap_msg: pointer to AP message
291 * @xcRB: pointer to user input data
292 *
293 * Returns 0 on success or -EFAULT, -EINVAL.
294 */
295struct type86_fmt2_msg {
296 struct type86_hdr hdr;
297 struct type86_fmt2_ext fmt2;
298} __packed;
299
300static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
301 struct ap_message *ap_msg,
302 struct ica_xcRB *xcRB)
303{
304 static struct type6_hdr static_type6_hdrX = {
305 .type = 0x06,
306 .offset1 = 0x00000058,
307 };
308 struct {
309 struct type6_hdr hdr;
310 struct CPRBX cprbx;
311 } __packed * msg = ap_msg->message;
312
313 int rcblen = CEIL4(xcRB->request_control_blk_length);
Ingo Tuchscherer63ef79c2014-02-05 12:29:57 +0100314 int replylen, req_sumlen, resp_sumlen;
Holger Dengler5e55a482012-08-28 16:45:36 +0200315 char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
316 char *function_code;
317
Ingo Tuchschererce1ce2f2014-03-18 16:30:21 +0100318 if (CEIL4(xcRB->request_control_blk_length) <
319 xcRB->request_control_blk_length)
320 return -EINVAL; /* overflow after alignment*/
321
Holger Dengler5e55a482012-08-28 16:45:36 +0200322 /* length checks */
323 ap_msg->length = sizeof(struct type6_hdr) +
324 CEIL4(xcRB->request_control_blk_length) +
325 xcRB->request_data_length;
326 if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE)
327 return -EINVAL;
Ingo Tuchscherer63ef79c2014-02-05 12:29:57 +0100328
329 /* Overflow check
330 sum must be greater (or equal) than the largest operand */
331 req_sumlen = CEIL4(xcRB->request_control_blk_length) +
332 xcRB->request_data_length;
333 if ((CEIL4(xcRB->request_control_blk_length) <=
334 xcRB->request_data_length) ?
335 (req_sumlen < xcRB->request_data_length) :
336 (req_sumlen < CEIL4(xcRB->request_control_blk_length))) {
337 return -EINVAL;
338 }
339
Ingo Tuchschererce1ce2f2014-03-18 16:30:21 +0100340 if (CEIL4(xcRB->reply_control_blk_length) <
341 xcRB->reply_control_blk_length)
342 return -EINVAL; /* overflow after alignment*/
343
Holger Dengler5e55a482012-08-28 16:45:36 +0200344 replylen = sizeof(struct type86_fmt2_msg) +
345 CEIL4(xcRB->reply_control_blk_length) +
346 xcRB->reply_data_length;
347 if (replylen > MSGTYPE06_MAX_MSG_SIZE)
348 return -EINVAL;
349
Ingo Tuchscherer63ef79c2014-02-05 12:29:57 +0100350 /* Overflow check
351 sum must be greater (or equal) than the largest operand */
352 resp_sumlen = CEIL4(xcRB->reply_control_blk_length) +
353 xcRB->reply_data_length;
354 if ((CEIL4(xcRB->reply_control_blk_length) <= xcRB->reply_data_length) ?
355 (resp_sumlen < xcRB->reply_data_length) :
356 (resp_sumlen < CEIL4(xcRB->reply_control_blk_length))) {
357 return -EINVAL;
358 }
359
Holger Dengler5e55a482012-08-28 16:45:36 +0200360 /* prepare type6 header */
361 msg->hdr = static_type6_hdrX;
362 memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
363 msg->hdr.ToCardLen1 = xcRB->request_control_blk_length;
364 if (xcRB->request_data_length) {
365 msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
366 msg->hdr.ToCardLen2 = xcRB->request_data_length;
367 }
368 msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
369 msg->hdr.FromCardLen2 = xcRB->reply_data_length;
370
371 /* prepare CPRB */
372 if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
373 xcRB->request_control_blk_length))
374 return -EFAULT;
375 if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
376 xcRB->request_control_blk_length)
377 return -EINVAL;
378 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
379 memcpy(msg->hdr.function_code, function_code,
380 sizeof(msg->hdr.function_code));
381
382 if (memcmp(function_code, "US", 2) == 0)
383 ap_msg->special = 1;
384 else
385 ap_msg->special = 0;
386
387 /* copy data block */
388 if (xcRB->request_data_length &&
389 copy_from_user(req_data, xcRB->request_data_address,
390 xcRB->request_data_length))
391 return -EFAULT;
392 return 0;
393}
394
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100395static int xcrb_msg_to_type6_ep11cprb_msgx(struct zcrypt_device *zdev,
396 struct ap_message *ap_msg,
397 struct ep11_urb *xcRB)
398{
399 unsigned int lfmt;
400
401 static struct type6_hdr static_type6_ep11_hdr = {
402 .type = 0x06,
403 .rqid = {0x00, 0x01},
404 .function_code = {0x00, 0x00},
405 .agent_id[0] = 0x58, /* {'X'} */
406 .agent_id[1] = 0x43, /* {'C'} */
407 .offset1 = 0x00000058,
408 };
409
410 struct {
411 struct type6_hdr hdr;
412 struct ep11_cprb cprbx;
413 unsigned char pld_tag; /* fixed value 0x30 */
414 unsigned char pld_lenfmt; /* payload length format */
415 } __packed * msg = ap_msg->message;
416
417 struct pld_hdr {
418 unsigned char func_tag; /* fixed value 0x4 */
419 unsigned char func_len; /* fixed value 0x4 */
420 unsigned int func_val; /* function ID */
421 unsigned char dom_tag; /* fixed value 0x4 */
422 unsigned char dom_len; /* fixed value 0x4 */
423 unsigned int dom_val; /* domain id */
424 } __packed * payload_hdr;
425
Ingo Tuchschererce1ce2f2014-03-18 16:30:21 +0100426 if (CEIL4(xcRB->req_len) < xcRB->req_len)
427 return -EINVAL; /* overflow after alignment*/
428
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100429 /* length checks */
430 ap_msg->length = sizeof(struct type6_hdr) + xcRB->req_len;
431 if (CEIL4(xcRB->req_len) > MSGTYPE06_MAX_MSG_SIZE -
432 (sizeof(struct type6_hdr)))
433 return -EINVAL;
434
Ingo Tuchschererce1ce2f2014-03-18 16:30:21 +0100435 if (CEIL4(xcRB->resp_len) < xcRB->resp_len)
436 return -EINVAL; /* overflow after alignment*/
437
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100438 if (CEIL4(xcRB->resp_len) > MSGTYPE06_MAX_MSG_SIZE -
439 (sizeof(struct type86_fmt2_msg)))
440 return -EINVAL;
441
442 /* prepare type6 header */
443 msg->hdr = static_type6_ep11_hdr;
444 msg->hdr.ToCardLen1 = xcRB->req_len;
445 msg->hdr.FromCardLen1 = xcRB->resp_len;
446
447 /* Import CPRB data from the ioctl input parameter */
448 if (copy_from_user(&(msg->cprbx.cprb_len),
Ingo Tuchschererce1ce2f2014-03-18 16:30:21 +0100449 (char __force __user *)xcRB->req, xcRB->req_len)) {
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100450 return -EFAULT;
451 }
452
453 /*
454 The target domain field within the cprb body/payload block will be
455 replaced by the usage domain for non-management commands only.
456 Therefore we check the first bit of the 'flags' parameter for
457 management command indication.
Hendrik Bruecknerb4a96012013-12-13 12:53:42 +0100458 0 - non management command
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100459 1 - management command
460 */
461 if (!((msg->cprbx.flags & 0x80) == 0x80)) {
462 msg->cprbx.target_id = (unsigned int)
463 AP_QID_QUEUE(zdev->ap_dev->qid);
464
465 if ((msg->pld_lenfmt & 0x80) == 0x80) { /*ext.len.fmt 2 or 3*/
466 switch (msg->pld_lenfmt & 0x03) {
467 case 1:
468 lfmt = 2;
469 break;
470 case 2:
471 lfmt = 3;
472 break;
473 default:
474 return -EINVAL;
475 }
476 } else {
477 lfmt = 1; /* length format #1 */
478 }
479 payload_hdr = (struct pld_hdr *)((&(msg->pld_lenfmt))+lfmt);
480 payload_hdr->dom_val = (unsigned int)
481 AP_QID_QUEUE(zdev->ap_dev->qid);
482 }
483 return 0;
484}
485
Holger Dengler5e55a482012-08-28 16:45:36 +0200486/**
487 * Copy results from a type 86 ICA reply message back to user space.
488 *
489 * @zdev: crypto device pointer
490 * @reply: reply AP message.
491 * @data: pointer to user output data
492 * @length: size of user output data
493 *
494 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
495 */
496struct type86x_reply {
497 struct type86_hdr hdr;
498 struct type86_fmt2_ext fmt2;
499 struct CPRBX cprbx;
500 unsigned char pad[4]; /* 4 byte function code/rules block ? */
501 unsigned short length;
502 char text[0];
503} __packed;
504
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100505struct type86_ep11_reply {
506 struct type86_hdr hdr;
507 struct type86_fmt2_ext fmt2;
508 struct ep11_cprb cprbx;
509} __packed;
510
Holger Dengler5e55a482012-08-28 16:45:36 +0200511static int convert_type86_ica(struct zcrypt_device *zdev,
512 struct ap_message *reply,
513 char __user *outputdata,
514 unsigned int outputdatalength)
515{
516 static unsigned char static_pad[] = {
517 0x00, 0x02,
518 0x1B, 0x7B, 0x5D, 0xB5, 0x75, 0x01, 0x3D, 0xFD,
519 0x8D, 0xD1, 0xC7, 0x03, 0x2D, 0x09, 0x23, 0x57,
520 0x89, 0x49, 0xB9, 0x3F, 0xBB, 0x99, 0x41, 0x5B,
521 0x75, 0x21, 0x7B, 0x9D, 0x3B, 0x6B, 0x51, 0x39,
522 0xBB, 0x0D, 0x35, 0xB9, 0x89, 0x0F, 0x93, 0xA5,
523 0x0B, 0x47, 0xF1, 0xD3, 0xBB, 0xCB, 0xF1, 0x9D,
524 0x23, 0x73, 0x71, 0xFF, 0xF3, 0xF5, 0x45, 0xFB,
525 0x61, 0x29, 0x23, 0xFD, 0xF1, 0x29, 0x3F, 0x7F,
526 0x17, 0xB7, 0x1B, 0xA9, 0x19, 0xBD, 0x57, 0xA9,
527 0xD7, 0x95, 0xA3, 0xCB, 0xED, 0x1D, 0xDB, 0x45,
528 0x7D, 0x11, 0xD1, 0x51, 0x1B, 0xED, 0x71, 0xE9,
529 0xB1, 0xD1, 0xAB, 0xAB, 0x21, 0x2B, 0x1B, 0x9F,
530 0x3B, 0x9F, 0xF7, 0xF7, 0xBD, 0x63, 0xEB, 0xAD,
531 0xDF, 0xB3, 0x6F, 0x5B, 0xDB, 0x8D, 0xA9, 0x5D,
532 0xE3, 0x7D, 0x77, 0x49, 0x47, 0xF5, 0xA7, 0xFD,
533 0xAB, 0x2F, 0x27, 0x35, 0x77, 0xD3, 0x49, 0xC9,
534 0x09, 0xEB, 0xB1, 0xF9, 0xBF, 0x4B, 0xCB, 0x2B,
535 0xEB, 0xEB, 0x05, 0xFF, 0x7D, 0xC7, 0x91, 0x8B,
536 0x09, 0x83, 0xB9, 0xB9, 0x69, 0x33, 0x39, 0x6B,
537 0x79, 0x75, 0x19, 0xBF, 0xBB, 0x07, 0x1D, 0xBD,
538 0x29, 0xBF, 0x39, 0x95, 0x93, 0x1D, 0x35, 0xC7,
539 0xC9, 0x4D, 0xE5, 0x97, 0x0B, 0x43, 0x9B, 0xF1,
540 0x16, 0x93, 0x03, 0x1F, 0xA5, 0xFB, 0xDB, 0xF3,
541 0x27, 0x4F, 0x27, 0x61, 0x05, 0x1F, 0xB9, 0x23,
542 0x2F, 0xC3, 0x81, 0xA9, 0x23, 0x71, 0x55, 0x55,
543 0xEB, 0xED, 0x41, 0xE5, 0xF3, 0x11, 0xF1, 0x43,
544 0x69, 0x03, 0xBD, 0x0B, 0x37, 0x0F, 0x51, 0x8F,
545 0x0B, 0xB5, 0x89, 0x5B, 0x67, 0xA9, 0xD9, 0x4F,
546 0x01, 0xF9, 0x21, 0x77, 0x37, 0x73, 0x79, 0xC5,
547 0x7F, 0x51, 0xC1, 0xCF, 0x97, 0xA1, 0x75, 0xAD,
548 0x35, 0x9D, 0xD3, 0xD3, 0xA7, 0x9D, 0x5D, 0x41,
549 0x6F, 0x65, 0x1B, 0xCF, 0xA9, 0x87, 0x91, 0x09
550 };
551 struct type86x_reply *msg = reply->message;
552 unsigned short service_rc, service_rs;
553 unsigned int reply_len, pad_len;
554 char *data;
555
556 service_rc = msg->cprbx.ccp_rtcode;
557 if (unlikely(service_rc != 0)) {
558 service_rs = msg->cprbx.ccp_rscode;
559 if (service_rc == 8 && service_rs == 66)
560 return -EINVAL;
561 if (service_rc == 8 && service_rs == 65)
562 return -EINVAL;
563 if (service_rc == 8 && service_rs == 770)
564 return -EINVAL;
565 if (service_rc == 8 && service_rs == 783) {
566 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
567 return -EAGAIN;
568 }
569 if (service_rc == 12 && service_rs == 769)
570 return -EINVAL;
571 if (service_rc == 8 && service_rs == 72)
572 return -EINVAL;
573 zdev->online = 0;
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100574 pr_err("Cryptographic device %x failed and was set offline\n",
575 zdev->ap_dev->qid);
576 ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
577 zdev->ap_dev->qid, zdev->online,
578 msg->hdr.reply_code);
Holger Dengler5e55a482012-08-28 16:45:36 +0200579 return -EAGAIN; /* repeat the request on a different device. */
580 }
581 data = msg->text;
582 reply_len = msg->length - 2;
583 if (reply_len > outputdatalength)
584 return -EINVAL;
585 /*
586 * For all encipher requests, the length of the ciphertext (reply_len)
587 * will always equal the modulus length. For MEX decipher requests
588 * the output needs to get padded. Minimum pad size is 10.
589 *
590 * Currently, the cases where padding will be added is for:
591 * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
592 * ZERO-PAD and CRT is only supported for PKD requests)
593 * - PCICC, always
594 */
595 pad_len = outputdatalength - reply_len;
596 if (pad_len > 0) {
597 if (pad_len < 10)
598 return -EINVAL;
599 /* 'restore' padding left in the PCICC/PCIXCC card. */
600 if (copy_to_user(outputdata, static_pad, pad_len - 1))
601 return -EFAULT;
602 if (put_user(0, outputdata + pad_len - 1))
603 return -EFAULT;
604 }
605 /* Copy the crypto response to user space. */
606 if (copy_to_user(outputdata + pad_len, data, reply_len))
607 return -EFAULT;
608 return 0;
609}
610
611/**
612 * Copy results from a type 86 XCRB reply message back to user space.
613 *
614 * @zdev: crypto device pointer
615 * @reply: reply AP message.
616 * @xcRB: pointer to XCRB
617 *
618 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
619 */
620static int convert_type86_xcrb(struct zcrypt_device *zdev,
621 struct ap_message *reply,
622 struct ica_xcRB *xcRB)
623{
624 struct type86_fmt2_msg *msg = reply->message;
625 char *data = reply->message;
626
627 /* Copy CPRB to user */
628 if (copy_to_user(xcRB->reply_control_blk_addr,
629 data + msg->fmt2.offset1, msg->fmt2.count1))
630 return -EFAULT;
631 xcRB->reply_control_blk_length = msg->fmt2.count1;
632
633 /* Copy data buffer to user */
634 if (msg->fmt2.count2)
635 if (copy_to_user(xcRB->reply_data_addr,
636 data + msg->fmt2.offset2, msg->fmt2.count2))
637 return -EFAULT;
638 xcRB->reply_data_length = msg->fmt2.count2;
639 return 0;
640}
641
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100642/**
643 * Copy results from a type 86 EP11 XCRB reply message back to user space.
644 *
645 * @zdev: crypto device pointer
646 * @reply: reply AP message.
647 * @xcRB: pointer to EP11 user request block
648 *
649 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
650 */
651static int convert_type86_ep11_xcrb(struct zcrypt_device *zdev,
652 struct ap_message *reply,
653 struct ep11_urb *xcRB)
654{
655 struct type86_fmt2_msg *msg = reply->message;
656 char *data = reply->message;
657
658 if (xcRB->resp_len < msg->fmt2.count1)
659 return -EINVAL;
660
661 /* Copy response CPRB to user */
Ingo Tuchschererce1ce2f2014-03-18 16:30:21 +0100662 if (copy_to_user((char __force __user *)xcRB->resp,
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100663 data + msg->fmt2.offset1, msg->fmt2.count1))
664 return -EFAULT;
665 xcRB->resp_len = msg->fmt2.count1;
666 return 0;
667}
668
Holger Dengler5e55a482012-08-28 16:45:36 +0200669static int convert_type86_rng(struct zcrypt_device *zdev,
670 struct ap_message *reply,
671 char *buffer)
672{
673 struct {
674 struct type86_hdr hdr;
675 struct type86_fmt2_ext fmt2;
676 struct CPRBX cprbx;
677 } __packed * msg = reply->message;
678 char *data = reply->message;
679
680 if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0)
681 return -EINVAL;
682 memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
683 return msg->fmt2.count2;
684}
685
686static int convert_response_ica(struct zcrypt_device *zdev,
687 struct ap_message *reply,
688 char __user *outputdata,
689 unsigned int outputdatalength)
690{
691 struct type86x_reply *msg = reply->message;
692
693 /* Response type byte is the second byte in the response. */
694 switch (((unsigned char *) reply->message)[1]) {
695 case TYPE82_RSP_CODE:
696 case TYPE88_RSP_CODE:
697 return convert_error(zdev, reply);
698 case TYPE86_RSP_CODE:
699 if (msg->cprbx.ccp_rtcode &&
700 (msg->cprbx.ccp_rscode == 0x14f) &&
701 (outputdatalength > 256)) {
702 if (zdev->max_exp_bit_length <= 17) {
703 zdev->max_exp_bit_length = 17;
704 return -EAGAIN;
705 } else
706 return -EINVAL;
707 }
708 if (msg->hdr.reply_code)
709 return convert_error(zdev, reply);
710 if (msg->cprbx.cprb_ver_id == 0x02)
711 return convert_type86_ica(zdev, reply,
712 outputdata, outputdatalength);
713 /* Fall through, no break, incorrect cprb version is an unknown
714 * response */
715 default: /* Unknown response type, this should NEVER EVER happen */
716 zdev->online = 0;
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100717 pr_err("Cryptographic device %x failed and was set offline\n",
718 zdev->ap_dev->qid);
719 ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
720 zdev->ap_dev->qid, zdev->online);
Holger Dengler5e55a482012-08-28 16:45:36 +0200721 return -EAGAIN; /* repeat the request on a different device. */
722 }
723}
724
725static int convert_response_xcrb(struct zcrypt_device *zdev,
726 struct ap_message *reply,
727 struct ica_xcRB *xcRB)
728{
729 struct type86x_reply *msg = reply->message;
730
731 /* Response type byte is the second byte in the response. */
732 switch (((unsigned char *) reply->message)[1]) {
733 case TYPE82_RSP_CODE:
734 case TYPE88_RSP_CODE:
735 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
736 return convert_error(zdev, reply);
737 case TYPE86_RSP_CODE:
738 if (msg->hdr.reply_code) {
739 memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
740 return convert_error(zdev, reply);
741 }
742 if (msg->cprbx.cprb_ver_id == 0x02)
743 return convert_type86_xcrb(zdev, reply, xcRB);
744 /* Fall through, no break, incorrect cprb version is an unknown
745 * response */
746 default: /* Unknown response type, this should NEVER EVER happen */
747 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
748 zdev->online = 0;
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100749 pr_err("Cryptographic device %x failed and was set offline\n",
750 zdev->ap_dev->qid);
751 ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
752 zdev->ap_dev->qid, zdev->online);
Holger Dengler5e55a482012-08-28 16:45:36 +0200753 return -EAGAIN; /* repeat the request on a different device. */
754 }
755}
756
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100757static int convert_response_ep11_xcrb(struct zcrypt_device *zdev,
758 struct ap_message *reply, struct ep11_urb *xcRB)
759{
760 struct type86_ep11_reply *msg = reply->message;
761
762 /* Response type byte is the second byte in the response. */
763 switch (((unsigned char *)reply->message)[1]) {
764 case TYPE82_RSP_CODE:
765 case TYPE87_RSP_CODE:
766 return convert_error(zdev, reply);
767 case TYPE86_RSP_CODE:
768 if (msg->hdr.reply_code)
769 return convert_error(zdev, reply);
770 if (msg->cprbx.cprb_ver_id == 0x04)
771 return convert_type86_ep11_xcrb(zdev, reply, xcRB);
772 /* Fall through, no break, incorrect cprb version is an unknown resp.*/
773 default: /* Unknown response type, this should NEVER EVER happen */
774 zdev->online = 0;
775 pr_err("Cryptographic device %x failed and was set offline\n",
776 zdev->ap_dev->qid);
777 ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
778 zdev->ap_dev->qid, zdev->online);
779 return -EAGAIN; /* repeat the request on a different device. */
780 }
781}
782
Holger Dengler5e55a482012-08-28 16:45:36 +0200783static int convert_response_rng(struct zcrypt_device *zdev,
784 struct ap_message *reply,
785 char *data)
786{
787 struct type86x_reply *msg = reply->message;
788
789 switch (msg->hdr.type) {
790 case TYPE82_RSP_CODE:
791 case TYPE88_RSP_CODE:
792 return -EINVAL;
793 case TYPE86_RSP_CODE:
794 if (msg->hdr.reply_code)
795 return -EINVAL;
796 if (msg->cprbx.cprb_ver_id == 0x02)
797 return convert_type86_rng(zdev, reply, data);
798 /* Fall through, no break, incorrect cprb version is an unknown
799 * response */
800 default: /* Unknown response type, this should NEVER EVER happen */
801 zdev->online = 0;
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100802 pr_err("Cryptographic device %x failed and was set offline\n",
803 zdev->ap_dev->qid);
804 ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
805 zdev->ap_dev->qid, zdev->online);
Holger Dengler5e55a482012-08-28 16:45:36 +0200806 return -EAGAIN; /* repeat the request on a different device. */
807 }
808}
809
810/**
811 * This function is called from the AP bus code after a crypto request
812 * "msg" has finished with the reply message "reply".
813 * It is called from tasklet context.
814 * @ap_dev: pointer to the AP device
815 * @msg: pointer to the AP message
816 * @reply: pointer to the AP reply message
817 */
818static void zcrypt_msgtype6_receive(struct ap_device *ap_dev,
819 struct ap_message *msg,
820 struct ap_message *reply)
821{
822 static struct error_hdr error_reply = {
823 .type = TYPE82_RSP_CODE,
824 .reply_code = REP82_ERROR_MACHINE_FAILURE,
825 };
826 struct response_type *resp_type =
827 (struct response_type *) msg->private;
828 struct type86x_reply *t86r;
829 int length;
830
831 /* Copy the reply message to the request message buffer. */
832 if (IS_ERR(reply)) {
833 memcpy(msg->message, &error_reply, sizeof(error_reply));
834 goto out;
835 }
836 t86r = reply->message;
837 if (t86r->hdr.type == TYPE86_RSP_CODE &&
838 t86r->cprbx.cprb_ver_id == 0x02) {
839 switch (resp_type->type) {
840 case PCIXCC_RESPONSE_TYPE_ICA:
841 length = sizeof(struct type86x_reply)
842 + t86r->length - 2;
843 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
844 memcpy(msg->message, reply->message, length);
845 break;
846 case PCIXCC_RESPONSE_TYPE_XCRB:
847 length = t86r->fmt2.offset2 + t86r->fmt2.count2;
848 length = min(MSGTYPE06_MAX_MSG_SIZE, length);
849 memcpy(msg->message, reply->message, length);
850 break;
851 default:
852 memcpy(msg->message, &error_reply,
853 sizeof(error_reply));
854 }
855 } else
856 memcpy(msg->message, reply->message, sizeof(error_reply));
857out:
858 complete(&(resp_type->work));
859}
860
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100861/**
862 * This function is called from the AP bus code after a crypto request
863 * "msg" has finished with the reply message "reply".
864 * It is called from tasklet context.
865 * @ap_dev: pointer to the AP device
866 * @msg: pointer to the AP message
867 * @reply: pointer to the AP reply message
868 */
869static void zcrypt_msgtype6_receive_ep11(struct ap_device *ap_dev,
870 struct ap_message *msg,
871 struct ap_message *reply)
872{
873 static struct error_hdr error_reply = {
874 .type = TYPE82_RSP_CODE,
875 .reply_code = REP82_ERROR_MACHINE_FAILURE,
876 };
877 struct response_type *resp_type =
878 (struct response_type *)msg->private;
879 struct type86_ep11_reply *t86r;
880 int length;
881
882 /* Copy the reply message to the request message buffer. */
883 if (IS_ERR(reply)) {
884 memcpy(msg->message, &error_reply, sizeof(error_reply));
885 goto out;
886 }
887 t86r = reply->message;
888 if (t86r->hdr.type == TYPE86_RSP_CODE &&
889 t86r->cprbx.cprb_ver_id == 0x04) {
890 switch (resp_type->type) {
891 case PCIXCC_RESPONSE_TYPE_EP11:
892 length = t86r->fmt2.offset1 + t86r->fmt2.count1;
893 length = min(MSGTYPE06_MAX_MSG_SIZE, length);
894 memcpy(msg->message, reply->message, length);
895 break;
896 default:
897 memcpy(msg->message, &error_reply, sizeof(error_reply));
898 }
899 } else {
900 memcpy(msg->message, reply->message, sizeof(error_reply));
901 }
902out:
903 complete(&(resp_type->work));
904}
905
Holger Dengler5e55a482012-08-28 16:45:36 +0200906static atomic_t zcrypt_step = ATOMIC_INIT(0);
907
908/**
909 * The request distributor calls this function if it picked the PCIXCC/CEX2C
910 * device to handle a modexpo request.
911 * @zdev: pointer to zcrypt_device structure that identifies the
912 * PCIXCC/CEX2C device to the request distributor
913 * @mex: pointer to the modexpo request buffer
914 */
915static long zcrypt_msgtype6_modexpo(struct zcrypt_device *zdev,
916 struct ica_rsa_modexpo *mex)
917{
918 struct ap_message ap_msg;
919 struct response_type resp_type = {
920 .type = PCIXCC_RESPONSE_TYPE_ICA,
921 };
922 int rc;
923
924 ap_init_message(&ap_msg);
925 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
926 if (!ap_msg.message)
927 return -ENOMEM;
928 ap_msg.receive = zcrypt_msgtype6_receive;
929 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
930 atomic_inc_return(&zcrypt_step);
931 ap_msg.private = &resp_type;
932 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
933 if (rc)
934 goto out_free;
935 init_completion(&resp_type.work);
936 ap_queue_message(zdev->ap_dev, &ap_msg);
937 rc = wait_for_completion_interruptible(&resp_type.work);
938 if (rc == 0)
939 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
940 mex->outputdatalength);
941 else
942 /* Signal pending. */
943 ap_cancel_message(zdev->ap_dev, &ap_msg);
944out_free:
945 free_page((unsigned long) ap_msg.message);
946 return rc;
947}
948
949/**
950 * The request distributor calls this function if it picked the PCIXCC/CEX2C
951 * device to handle a modexpo_crt request.
952 * @zdev: pointer to zcrypt_device structure that identifies the
953 * PCIXCC/CEX2C device to the request distributor
954 * @crt: pointer to the modexpoc_crt request buffer
955 */
956static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_device *zdev,
957 struct ica_rsa_modexpo_crt *crt)
958{
959 struct ap_message ap_msg;
960 struct response_type resp_type = {
961 .type = PCIXCC_RESPONSE_TYPE_ICA,
962 };
963 int rc;
964
965 ap_init_message(&ap_msg);
966 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
967 if (!ap_msg.message)
968 return -ENOMEM;
969 ap_msg.receive = zcrypt_msgtype6_receive;
970 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
971 atomic_inc_return(&zcrypt_step);
972 ap_msg.private = &resp_type;
973 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
974 if (rc)
975 goto out_free;
976 init_completion(&resp_type.work);
977 ap_queue_message(zdev->ap_dev, &ap_msg);
978 rc = wait_for_completion_interruptible(&resp_type.work);
979 if (rc == 0)
980 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
981 crt->outputdatalength);
982 else
983 /* Signal pending. */
984 ap_cancel_message(zdev->ap_dev, &ap_msg);
985out_free:
986 free_page((unsigned long) ap_msg.message);
987 return rc;
988}
989
990/**
991 * The request distributor calls this function if it picked the PCIXCC/CEX2C
992 * device to handle a send_cprb request.
993 * @zdev: pointer to zcrypt_device structure that identifies the
994 * PCIXCC/CEX2C device to the request distributor
995 * @xcRB: pointer to the send_cprb request buffer
996 */
997static long zcrypt_msgtype6_send_cprb(struct zcrypt_device *zdev,
998 struct ica_xcRB *xcRB)
999{
1000 struct ap_message ap_msg;
1001 struct response_type resp_type = {
1002 .type = PCIXCC_RESPONSE_TYPE_XCRB,
1003 };
1004 int rc;
1005
1006 ap_init_message(&ap_msg);
1007 ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
1008 if (!ap_msg.message)
1009 return -ENOMEM;
1010 ap_msg.receive = zcrypt_msgtype6_receive;
1011 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
1012 atomic_inc_return(&zcrypt_step);
1013 ap_msg.private = &resp_type;
1014 rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB);
1015 if (rc)
1016 goto out_free;
1017 init_completion(&resp_type.work);
1018 ap_queue_message(zdev->ap_dev, &ap_msg);
1019 rc = wait_for_completion_interruptible(&resp_type.work);
1020 if (rc == 0)
1021 rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
1022 else
1023 /* Signal pending. */
1024 ap_cancel_message(zdev->ap_dev, &ap_msg);
1025out_free:
1026 kzfree(ap_msg.message);
1027 return rc;
1028}
1029
1030/**
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +01001031 * The request distributor calls this function if it picked the CEX4P
1032 * device to handle a send_ep11_cprb request.
1033 * @zdev: pointer to zcrypt_device structure that identifies the
1034 * CEX4P device to the request distributor
1035 * @xcRB: pointer to the ep11 user request block
1036 */
1037static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_device *zdev,
1038 struct ep11_urb *xcrb)
1039{
1040 struct ap_message ap_msg;
1041 struct response_type resp_type = {
1042 .type = PCIXCC_RESPONSE_TYPE_EP11,
1043 };
1044 int rc;
1045
1046 ap_init_message(&ap_msg);
1047 ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
1048 if (!ap_msg.message)
1049 return -ENOMEM;
1050 ap_msg.receive = zcrypt_msgtype6_receive_ep11;
1051 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
1052 atomic_inc_return(&zcrypt_step);
1053 ap_msg.private = &resp_type;
1054 rc = xcrb_msg_to_type6_ep11cprb_msgx(zdev, &ap_msg, xcrb);
1055 if (rc)
1056 goto out_free;
1057 init_completion(&resp_type.work);
1058 ap_queue_message(zdev->ap_dev, &ap_msg);
1059 rc = wait_for_completion_interruptible(&resp_type.work);
1060 if (rc == 0)
1061 rc = convert_response_ep11_xcrb(zdev, &ap_msg, xcrb);
1062 else /* Signal pending. */
1063 ap_cancel_message(zdev->ap_dev, &ap_msg);
1064
1065out_free:
1066 kzfree(ap_msg.message);
1067 return rc;
1068}
1069
1070/**
Holger Dengler5e55a482012-08-28 16:45:36 +02001071 * The request distributor calls this function if it picked the PCIXCC/CEX2C
1072 * device to generate random data.
1073 * @zdev: pointer to zcrypt_device structure that identifies the
1074 * PCIXCC/CEX2C device to the request distributor
1075 * @buffer: pointer to a memory page to return random data
1076 */
1077
1078static long zcrypt_msgtype6_rng(struct zcrypt_device *zdev,
1079 char *buffer)
1080{
1081 struct ap_message ap_msg;
1082 struct response_type resp_type = {
1083 .type = PCIXCC_RESPONSE_TYPE_XCRB,
1084 };
1085 int rc;
1086
1087 ap_init_message(&ap_msg);
1088 ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
1089 if (!ap_msg.message)
1090 return -ENOMEM;
1091 ap_msg.receive = zcrypt_msgtype6_receive;
1092 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
1093 atomic_inc_return(&zcrypt_step);
1094 ap_msg.private = &resp_type;
1095 rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE);
1096 init_completion(&resp_type.work);
1097 ap_queue_message(zdev->ap_dev, &ap_msg);
1098 rc = wait_for_completion_interruptible(&resp_type.work);
1099 if (rc == 0)
1100 rc = convert_response_rng(zdev, &ap_msg, buffer);
1101 else
1102 /* Signal pending. */
1103 ap_cancel_message(zdev->ap_dev, &ap_msg);
1104 kfree(ap_msg.message);
1105 return rc;
1106}
1107
1108/**
1109 * The crypto operations for a PCIXCC/CEX2C card.
1110 */
1111static struct zcrypt_ops zcrypt_msgtype6_norng_ops = {
1112 .owner = THIS_MODULE,
1113 .variant = MSGTYPE06_VARIANT_NORNG,
1114 .rsa_modexpo = zcrypt_msgtype6_modexpo,
1115 .rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt,
1116 .send_cprb = zcrypt_msgtype6_send_cprb,
1117};
1118
1119static struct zcrypt_ops zcrypt_msgtype6_ops = {
1120 .owner = THIS_MODULE,
1121 .variant = MSGTYPE06_VARIANT_DEFAULT,
1122 .rsa_modexpo = zcrypt_msgtype6_modexpo,
1123 .rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt,
1124 .send_cprb = zcrypt_msgtype6_send_cprb,
1125 .rng = zcrypt_msgtype6_rng,
1126};
1127
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +01001128static struct zcrypt_ops zcrypt_msgtype6_ep11_ops = {
1129 .owner = THIS_MODULE,
1130 .variant = MSGTYPE06_VARIANT_EP11,
1131 .rsa_modexpo = NULL,
1132 .rsa_modexpo_crt = NULL,
1133 .send_ep11_cprb = zcrypt_msgtype6_send_ep11_cprb,
1134};
1135
Holger Dengler5e55a482012-08-28 16:45:36 +02001136int __init zcrypt_msgtype6_init(void)
1137{
1138 zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops);
1139 zcrypt_msgtype_register(&zcrypt_msgtype6_ops);
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +01001140 zcrypt_msgtype_register(&zcrypt_msgtype6_ep11_ops);
Holger Dengler5e55a482012-08-28 16:45:36 +02001141 return 0;
1142}
1143
1144void __exit zcrypt_msgtype6_exit(void)
1145{
1146 zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops);
1147 zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops);
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +01001148 zcrypt_msgtype_unregister(&zcrypt_msgtype6_ep11_ops);
Holger Dengler5e55a482012-08-28 16:45:36 +02001149}
1150
1151module_init(zcrypt_msgtype6_init);
1152module_exit(zcrypt_msgtype6_exit);