blob: 0bc91e46395a8d84ad8c989b6d2a7844593c3ba0 [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
318 /* length checks */
319 ap_msg->length = sizeof(struct type6_hdr) +
320 CEIL4(xcRB->request_control_blk_length) +
321 xcRB->request_data_length;
322 if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE)
323 return -EINVAL;
Ingo Tuchscherer63ef79c2014-02-05 12:29:57 +0100324
325 /* Overflow check
326 sum must be greater (or equal) than the largest operand */
327 req_sumlen = CEIL4(xcRB->request_control_blk_length) +
328 xcRB->request_data_length;
329 if ((CEIL4(xcRB->request_control_blk_length) <=
330 xcRB->request_data_length) ?
331 (req_sumlen < xcRB->request_data_length) :
332 (req_sumlen < CEIL4(xcRB->request_control_blk_length))) {
333 return -EINVAL;
334 }
335
Holger Dengler5e55a482012-08-28 16:45:36 +0200336 replylen = sizeof(struct type86_fmt2_msg) +
337 CEIL4(xcRB->reply_control_blk_length) +
338 xcRB->reply_data_length;
339 if (replylen > MSGTYPE06_MAX_MSG_SIZE)
340 return -EINVAL;
341
Ingo Tuchscherer63ef79c2014-02-05 12:29:57 +0100342 /* Overflow check
343 sum must be greater (or equal) than the largest operand */
344 resp_sumlen = CEIL4(xcRB->reply_control_blk_length) +
345 xcRB->reply_data_length;
346 if ((CEIL4(xcRB->reply_control_blk_length) <= xcRB->reply_data_length) ?
347 (resp_sumlen < xcRB->reply_data_length) :
348 (resp_sumlen < CEIL4(xcRB->reply_control_blk_length))) {
349 return -EINVAL;
350 }
351
Holger Dengler5e55a482012-08-28 16:45:36 +0200352 /* prepare type6 header */
353 msg->hdr = static_type6_hdrX;
354 memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
355 msg->hdr.ToCardLen1 = xcRB->request_control_blk_length;
356 if (xcRB->request_data_length) {
357 msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
358 msg->hdr.ToCardLen2 = xcRB->request_data_length;
359 }
360 msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
361 msg->hdr.FromCardLen2 = xcRB->reply_data_length;
362
363 /* prepare CPRB */
364 if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
365 xcRB->request_control_blk_length))
366 return -EFAULT;
367 if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
368 xcRB->request_control_blk_length)
369 return -EINVAL;
370 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
371 memcpy(msg->hdr.function_code, function_code,
372 sizeof(msg->hdr.function_code));
373
374 if (memcmp(function_code, "US", 2) == 0)
375 ap_msg->special = 1;
376 else
377 ap_msg->special = 0;
378
379 /* copy data block */
380 if (xcRB->request_data_length &&
381 copy_from_user(req_data, xcRB->request_data_address,
382 xcRB->request_data_length))
383 return -EFAULT;
384 return 0;
385}
386
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100387static int xcrb_msg_to_type6_ep11cprb_msgx(struct zcrypt_device *zdev,
388 struct ap_message *ap_msg,
389 struct ep11_urb *xcRB)
390{
391 unsigned int lfmt;
392
393 static struct type6_hdr static_type6_ep11_hdr = {
394 .type = 0x06,
395 .rqid = {0x00, 0x01},
396 .function_code = {0x00, 0x00},
397 .agent_id[0] = 0x58, /* {'X'} */
398 .agent_id[1] = 0x43, /* {'C'} */
399 .offset1 = 0x00000058,
400 };
401
402 struct {
403 struct type6_hdr hdr;
404 struct ep11_cprb cprbx;
405 unsigned char pld_tag; /* fixed value 0x30 */
406 unsigned char pld_lenfmt; /* payload length format */
407 } __packed * msg = ap_msg->message;
408
409 struct pld_hdr {
410 unsigned char func_tag; /* fixed value 0x4 */
411 unsigned char func_len; /* fixed value 0x4 */
412 unsigned int func_val; /* function ID */
413 unsigned char dom_tag; /* fixed value 0x4 */
414 unsigned char dom_len; /* fixed value 0x4 */
415 unsigned int dom_val; /* domain id */
416 } __packed * payload_hdr;
417
418 /* length checks */
419 ap_msg->length = sizeof(struct type6_hdr) + xcRB->req_len;
420 if (CEIL4(xcRB->req_len) > MSGTYPE06_MAX_MSG_SIZE -
421 (sizeof(struct type6_hdr)))
422 return -EINVAL;
423
424 if (CEIL4(xcRB->resp_len) > MSGTYPE06_MAX_MSG_SIZE -
425 (sizeof(struct type86_fmt2_msg)))
426 return -EINVAL;
427
428 /* prepare type6 header */
429 msg->hdr = static_type6_ep11_hdr;
430 msg->hdr.ToCardLen1 = xcRB->req_len;
431 msg->hdr.FromCardLen1 = xcRB->resp_len;
432
433 /* Import CPRB data from the ioctl input parameter */
434 if (copy_from_user(&(msg->cprbx.cprb_len),
435 (char *)xcRB->req, xcRB->req_len)) {
436 return -EFAULT;
437 }
438
439 /*
440 The target domain field within the cprb body/payload block will be
441 replaced by the usage domain for non-management commands only.
442 Therefore we check the first bit of the 'flags' parameter for
443 management command indication.
Hendrik Bruecknerb4a96012013-12-13 12:53:42 +0100444 0 - non management command
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100445 1 - management command
446 */
447 if (!((msg->cprbx.flags & 0x80) == 0x80)) {
448 msg->cprbx.target_id = (unsigned int)
449 AP_QID_QUEUE(zdev->ap_dev->qid);
450
451 if ((msg->pld_lenfmt & 0x80) == 0x80) { /*ext.len.fmt 2 or 3*/
452 switch (msg->pld_lenfmt & 0x03) {
453 case 1:
454 lfmt = 2;
455 break;
456 case 2:
457 lfmt = 3;
458 break;
459 default:
460 return -EINVAL;
461 }
462 } else {
463 lfmt = 1; /* length format #1 */
464 }
465 payload_hdr = (struct pld_hdr *)((&(msg->pld_lenfmt))+lfmt);
466 payload_hdr->dom_val = (unsigned int)
467 AP_QID_QUEUE(zdev->ap_dev->qid);
468 }
469 return 0;
470}
471
Holger Dengler5e55a482012-08-28 16:45:36 +0200472/**
473 * Copy results from a type 86 ICA reply message back to user space.
474 *
475 * @zdev: crypto device pointer
476 * @reply: reply AP message.
477 * @data: pointer to user output data
478 * @length: size of user output data
479 *
480 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
481 */
482struct type86x_reply {
483 struct type86_hdr hdr;
484 struct type86_fmt2_ext fmt2;
485 struct CPRBX cprbx;
486 unsigned char pad[4]; /* 4 byte function code/rules block ? */
487 unsigned short length;
488 char text[0];
489} __packed;
490
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100491struct type86_ep11_reply {
492 struct type86_hdr hdr;
493 struct type86_fmt2_ext fmt2;
494 struct ep11_cprb cprbx;
495} __packed;
496
Holger Dengler5e55a482012-08-28 16:45:36 +0200497static int convert_type86_ica(struct zcrypt_device *zdev,
498 struct ap_message *reply,
499 char __user *outputdata,
500 unsigned int outputdatalength)
501{
502 static unsigned char static_pad[] = {
503 0x00, 0x02,
504 0x1B, 0x7B, 0x5D, 0xB5, 0x75, 0x01, 0x3D, 0xFD,
505 0x8D, 0xD1, 0xC7, 0x03, 0x2D, 0x09, 0x23, 0x57,
506 0x89, 0x49, 0xB9, 0x3F, 0xBB, 0x99, 0x41, 0x5B,
507 0x75, 0x21, 0x7B, 0x9D, 0x3B, 0x6B, 0x51, 0x39,
508 0xBB, 0x0D, 0x35, 0xB9, 0x89, 0x0F, 0x93, 0xA5,
509 0x0B, 0x47, 0xF1, 0xD3, 0xBB, 0xCB, 0xF1, 0x9D,
510 0x23, 0x73, 0x71, 0xFF, 0xF3, 0xF5, 0x45, 0xFB,
511 0x61, 0x29, 0x23, 0xFD, 0xF1, 0x29, 0x3F, 0x7F,
512 0x17, 0xB7, 0x1B, 0xA9, 0x19, 0xBD, 0x57, 0xA9,
513 0xD7, 0x95, 0xA3, 0xCB, 0xED, 0x1D, 0xDB, 0x45,
514 0x7D, 0x11, 0xD1, 0x51, 0x1B, 0xED, 0x71, 0xE9,
515 0xB1, 0xD1, 0xAB, 0xAB, 0x21, 0x2B, 0x1B, 0x9F,
516 0x3B, 0x9F, 0xF7, 0xF7, 0xBD, 0x63, 0xEB, 0xAD,
517 0xDF, 0xB3, 0x6F, 0x5B, 0xDB, 0x8D, 0xA9, 0x5D,
518 0xE3, 0x7D, 0x77, 0x49, 0x47, 0xF5, 0xA7, 0xFD,
519 0xAB, 0x2F, 0x27, 0x35, 0x77, 0xD3, 0x49, 0xC9,
520 0x09, 0xEB, 0xB1, 0xF9, 0xBF, 0x4B, 0xCB, 0x2B,
521 0xEB, 0xEB, 0x05, 0xFF, 0x7D, 0xC7, 0x91, 0x8B,
522 0x09, 0x83, 0xB9, 0xB9, 0x69, 0x33, 0x39, 0x6B,
523 0x79, 0x75, 0x19, 0xBF, 0xBB, 0x07, 0x1D, 0xBD,
524 0x29, 0xBF, 0x39, 0x95, 0x93, 0x1D, 0x35, 0xC7,
525 0xC9, 0x4D, 0xE5, 0x97, 0x0B, 0x43, 0x9B, 0xF1,
526 0x16, 0x93, 0x03, 0x1F, 0xA5, 0xFB, 0xDB, 0xF3,
527 0x27, 0x4F, 0x27, 0x61, 0x05, 0x1F, 0xB9, 0x23,
528 0x2F, 0xC3, 0x81, 0xA9, 0x23, 0x71, 0x55, 0x55,
529 0xEB, 0xED, 0x41, 0xE5, 0xF3, 0x11, 0xF1, 0x43,
530 0x69, 0x03, 0xBD, 0x0B, 0x37, 0x0F, 0x51, 0x8F,
531 0x0B, 0xB5, 0x89, 0x5B, 0x67, 0xA9, 0xD9, 0x4F,
532 0x01, 0xF9, 0x21, 0x77, 0x37, 0x73, 0x79, 0xC5,
533 0x7F, 0x51, 0xC1, 0xCF, 0x97, 0xA1, 0x75, 0xAD,
534 0x35, 0x9D, 0xD3, 0xD3, 0xA7, 0x9D, 0x5D, 0x41,
535 0x6F, 0x65, 0x1B, 0xCF, 0xA9, 0x87, 0x91, 0x09
536 };
537 struct type86x_reply *msg = reply->message;
538 unsigned short service_rc, service_rs;
539 unsigned int reply_len, pad_len;
540 char *data;
541
542 service_rc = msg->cprbx.ccp_rtcode;
543 if (unlikely(service_rc != 0)) {
544 service_rs = msg->cprbx.ccp_rscode;
545 if (service_rc == 8 && service_rs == 66)
546 return -EINVAL;
547 if (service_rc == 8 && service_rs == 65)
548 return -EINVAL;
549 if (service_rc == 8 && service_rs == 770)
550 return -EINVAL;
551 if (service_rc == 8 && service_rs == 783) {
552 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
553 return -EAGAIN;
554 }
555 if (service_rc == 12 && service_rs == 769)
556 return -EINVAL;
557 if (service_rc == 8 && service_rs == 72)
558 return -EINVAL;
559 zdev->online = 0;
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100560 pr_err("Cryptographic device %x failed and was set offline\n",
561 zdev->ap_dev->qid);
562 ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d",
563 zdev->ap_dev->qid, zdev->online,
564 msg->hdr.reply_code);
Holger Dengler5e55a482012-08-28 16:45:36 +0200565 return -EAGAIN; /* repeat the request on a different device. */
566 }
567 data = msg->text;
568 reply_len = msg->length - 2;
569 if (reply_len > outputdatalength)
570 return -EINVAL;
571 /*
572 * For all encipher requests, the length of the ciphertext (reply_len)
573 * will always equal the modulus length. For MEX decipher requests
574 * the output needs to get padded. Minimum pad size is 10.
575 *
576 * Currently, the cases where padding will be added is for:
577 * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
578 * ZERO-PAD and CRT is only supported for PKD requests)
579 * - PCICC, always
580 */
581 pad_len = outputdatalength - reply_len;
582 if (pad_len > 0) {
583 if (pad_len < 10)
584 return -EINVAL;
585 /* 'restore' padding left in the PCICC/PCIXCC card. */
586 if (copy_to_user(outputdata, static_pad, pad_len - 1))
587 return -EFAULT;
588 if (put_user(0, outputdata + pad_len - 1))
589 return -EFAULT;
590 }
591 /* Copy the crypto response to user space. */
592 if (copy_to_user(outputdata + pad_len, data, reply_len))
593 return -EFAULT;
594 return 0;
595}
596
597/**
598 * Copy results from a type 86 XCRB reply message back to user space.
599 *
600 * @zdev: crypto device pointer
601 * @reply: reply AP message.
602 * @xcRB: pointer to XCRB
603 *
604 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
605 */
606static int convert_type86_xcrb(struct zcrypt_device *zdev,
607 struct ap_message *reply,
608 struct ica_xcRB *xcRB)
609{
610 struct type86_fmt2_msg *msg = reply->message;
611 char *data = reply->message;
612
613 /* Copy CPRB to user */
614 if (copy_to_user(xcRB->reply_control_blk_addr,
615 data + msg->fmt2.offset1, msg->fmt2.count1))
616 return -EFAULT;
617 xcRB->reply_control_blk_length = msg->fmt2.count1;
618
619 /* Copy data buffer to user */
620 if (msg->fmt2.count2)
621 if (copy_to_user(xcRB->reply_data_addr,
622 data + msg->fmt2.offset2, msg->fmt2.count2))
623 return -EFAULT;
624 xcRB->reply_data_length = msg->fmt2.count2;
625 return 0;
626}
627
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100628/**
629 * Copy results from a type 86 EP11 XCRB reply message back to user space.
630 *
631 * @zdev: crypto device pointer
632 * @reply: reply AP message.
633 * @xcRB: pointer to EP11 user request block
634 *
635 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
636 */
637static int convert_type86_ep11_xcrb(struct zcrypt_device *zdev,
638 struct ap_message *reply,
639 struct ep11_urb *xcRB)
640{
641 struct type86_fmt2_msg *msg = reply->message;
642 char *data = reply->message;
643
644 if (xcRB->resp_len < msg->fmt2.count1)
645 return -EINVAL;
646
647 /* Copy response CPRB to user */
648 if (copy_to_user((char *)xcRB->resp,
649 data + msg->fmt2.offset1, msg->fmt2.count1))
650 return -EFAULT;
651 xcRB->resp_len = msg->fmt2.count1;
652 return 0;
653}
654
Holger Dengler5e55a482012-08-28 16:45:36 +0200655static int convert_type86_rng(struct zcrypt_device *zdev,
656 struct ap_message *reply,
657 char *buffer)
658{
659 struct {
660 struct type86_hdr hdr;
661 struct type86_fmt2_ext fmt2;
662 struct CPRBX cprbx;
663 } __packed * msg = reply->message;
664 char *data = reply->message;
665
666 if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0)
667 return -EINVAL;
668 memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
669 return msg->fmt2.count2;
670}
671
672static int convert_response_ica(struct zcrypt_device *zdev,
673 struct ap_message *reply,
674 char __user *outputdata,
675 unsigned int outputdatalength)
676{
677 struct type86x_reply *msg = reply->message;
678
679 /* Response type byte is the second byte in the response. */
680 switch (((unsigned char *) reply->message)[1]) {
681 case TYPE82_RSP_CODE:
682 case TYPE88_RSP_CODE:
683 return convert_error(zdev, reply);
684 case TYPE86_RSP_CODE:
685 if (msg->cprbx.ccp_rtcode &&
686 (msg->cprbx.ccp_rscode == 0x14f) &&
687 (outputdatalength > 256)) {
688 if (zdev->max_exp_bit_length <= 17) {
689 zdev->max_exp_bit_length = 17;
690 return -EAGAIN;
691 } else
692 return -EINVAL;
693 }
694 if (msg->hdr.reply_code)
695 return convert_error(zdev, reply);
696 if (msg->cprbx.cprb_ver_id == 0x02)
697 return convert_type86_ica(zdev, reply,
698 outputdata, outputdatalength);
699 /* Fall through, no break, incorrect cprb version is an unknown
700 * response */
701 default: /* Unknown response type, this should NEVER EVER happen */
702 zdev->online = 0;
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100703 pr_err("Cryptographic device %x failed and was set offline\n",
704 zdev->ap_dev->qid);
705 ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
706 zdev->ap_dev->qid, zdev->online);
Holger Dengler5e55a482012-08-28 16:45:36 +0200707 return -EAGAIN; /* repeat the request on a different device. */
708 }
709}
710
711static int convert_response_xcrb(struct zcrypt_device *zdev,
712 struct ap_message *reply,
713 struct ica_xcRB *xcRB)
714{
715 struct type86x_reply *msg = reply->message;
716
717 /* Response type byte is the second byte in the response. */
718 switch (((unsigned char *) reply->message)[1]) {
719 case TYPE82_RSP_CODE:
720 case TYPE88_RSP_CODE:
721 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
722 return convert_error(zdev, reply);
723 case TYPE86_RSP_CODE:
724 if (msg->hdr.reply_code) {
725 memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
726 return convert_error(zdev, reply);
727 }
728 if (msg->cprbx.cprb_ver_id == 0x02)
729 return convert_type86_xcrb(zdev, reply, xcRB);
730 /* Fall through, no break, incorrect cprb version is an unknown
731 * response */
732 default: /* Unknown response type, this should NEVER EVER happen */
733 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
734 zdev->online = 0;
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100735 pr_err("Cryptographic device %x failed and was set offline\n",
736 zdev->ap_dev->qid);
737 ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
738 zdev->ap_dev->qid, zdev->online);
Holger Dengler5e55a482012-08-28 16:45:36 +0200739 return -EAGAIN; /* repeat the request on a different device. */
740 }
741}
742
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100743static int convert_response_ep11_xcrb(struct zcrypt_device *zdev,
744 struct ap_message *reply, struct ep11_urb *xcRB)
745{
746 struct type86_ep11_reply *msg = reply->message;
747
748 /* Response type byte is the second byte in the response. */
749 switch (((unsigned char *)reply->message)[1]) {
750 case TYPE82_RSP_CODE:
751 case TYPE87_RSP_CODE:
752 return convert_error(zdev, reply);
753 case TYPE86_RSP_CODE:
754 if (msg->hdr.reply_code)
755 return convert_error(zdev, reply);
756 if (msg->cprbx.cprb_ver_id == 0x04)
757 return convert_type86_ep11_xcrb(zdev, reply, xcRB);
758 /* Fall through, no break, incorrect cprb version is an unknown resp.*/
759 default: /* Unknown response type, this should NEVER EVER happen */
760 zdev->online = 0;
761 pr_err("Cryptographic device %x failed and was set offline\n",
762 zdev->ap_dev->qid);
763 ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
764 zdev->ap_dev->qid, zdev->online);
765 return -EAGAIN; /* repeat the request on a different device. */
766 }
767}
768
Holger Dengler5e55a482012-08-28 16:45:36 +0200769static int convert_response_rng(struct zcrypt_device *zdev,
770 struct ap_message *reply,
771 char *data)
772{
773 struct type86x_reply *msg = reply->message;
774
775 switch (msg->hdr.type) {
776 case TYPE82_RSP_CODE:
777 case TYPE88_RSP_CODE:
778 return -EINVAL;
779 case TYPE86_RSP_CODE:
780 if (msg->hdr.reply_code)
781 return -EINVAL;
782 if (msg->cprbx.cprb_ver_id == 0x02)
783 return convert_type86_rng(zdev, reply, data);
784 /* Fall through, no break, incorrect cprb version is an unknown
785 * response */
786 default: /* Unknown response type, this should NEVER EVER happen */
787 zdev->online = 0;
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100788 pr_err("Cryptographic device %x failed and was set offline\n",
789 zdev->ap_dev->qid);
790 ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail",
791 zdev->ap_dev->qid, zdev->online);
Holger Dengler5e55a482012-08-28 16:45:36 +0200792 return -EAGAIN; /* repeat the request on a different device. */
793 }
794}
795
796/**
797 * This function is called from the AP bus code after a crypto request
798 * "msg" has finished with the reply message "reply".
799 * It is called from tasklet context.
800 * @ap_dev: pointer to the AP device
801 * @msg: pointer to the AP message
802 * @reply: pointer to the AP reply message
803 */
804static void zcrypt_msgtype6_receive(struct ap_device *ap_dev,
805 struct ap_message *msg,
806 struct ap_message *reply)
807{
808 static struct error_hdr error_reply = {
809 .type = TYPE82_RSP_CODE,
810 .reply_code = REP82_ERROR_MACHINE_FAILURE,
811 };
812 struct response_type *resp_type =
813 (struct response_type *) msg->private;
814 struct type86x_reply *t86r;
815 int length;
816
817 /* Copy the reply message to the request message buffer. */
818 if (IS_ERR(reply)) {
819 memcpy(msg->message, &error_reply, sizeof(error_reply));
820 goto out;
821 }
822 t86r = reply->message;
823 if (t86r->hdr.type == TYPE86_RSP_CODE &&
824 t86r->cprbx.cprb_ver_id == 0x02) {
825 switch (resp_type->type) {
826 case PCIXCC_RESPONSE_TYPE_ICA:
827 length = sizeof(struct type86x_reply)
828 + t86r->length - 2;
829 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
830 memcpy(msg->message, reply->message, length);
831 break;
832 case PCIXCC_RESPONSE_TYPE_XCRB:
833 length = t86r->fmt2.offset2 + t86r->fmt2.count2;
834 length = min(MSGTYPE06_MAX_MSG_SIZE, length);
835 memcpy(msg->message, reply->message, length);
836 break;
837 default:
838 memcpy(msg->message, &error_reply,
839 sizeof(error_reply));
840 }
841 } else
842 memcpy(msg->message, reply->message, sizeof(error_reply));
843out:
844 complete(&(resp_type->work));
845}
846
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +0100847/**
848 * This function is called from the AP bus code after a crypto request
849 * "msg" has finished with the reply message "reply".
850 * It is called from tasklet context.
851 * @ap_dev: pointer to the AP device
852 * @msg: pointer to the AP message
853 * @reply: pointer to the AP reply message
854 */
855static void zcrypt_msgtype6_receive_ep11(struct ap_device *ap_dev,
856 struct ap_message *msg,
857 struct ap_message *reply)
858{
859 static struct error_hdr error_reply = {
860 .type = TYPE82_RSP_CODE,
861 .reply_code = REP82_ERROR_MACHINE_FAILURE,
862 };
863 struct response_type *resp_type =
864 (struct response_type *)msg->private;
865 struct type86_ep11_reply *t86r;
866 int length;
867
868 /* Copy the reply message to the request message buffer. */
869 if (IS_ERR(reply)) {
870 memcpy(msg->message, &error_reply, sizeof(error_reply));
871 goto out;
872 }
873 t86r = reply->message;
874 if (t86r->hdr.type == TYPE86_RSP_CODE &&
875 t86r->cprbx.cprb_ver_id == 0x04) {
876 switch (resp_type->type) {
877 case PCIXCC_RESPONSE_TYPE_EP11:
878 length = t86r->fmt2.offset1 + t86r->fmt2.count1;
879 length = min(MSGTYPE06_MAX_MSG_SIZE, length);
880 memcpy(msg->message, reply->message, length);
881 break;
882 default:
883 memcpy(msg->message, &error_reply, sizeof(error_reply));
884 }
885 } else {
886 memcpy(msg->message, reply->message, sizeof(error_reply));
887 }
888out:
889 complete(&(resp_type->work));
890}
891
Holger Dengler5e55a482012-08-28 16:45:36 +0200892static atomic_t zcrypt_step = ATOMIC_INIT(0);
893
894/**
895 * The request distributor calls this function if it picked the PCIXCC/CEX2C
896 * device to handle a modexpo request.
897 * @zdev: pointer to zcrypt_device structure that identifies the
898 * PCIXCC/CEX2C device to the request distributor
899 * @mex: pointer to the modexpo request buffer
900 */
901static long zcrypt_msgtype6_modexpo(struct zcrypt_device *zdev,
902 struct ica_rsa_modexpo *mex)
903{
904 struct ap_message ap_msg;
905 struct response_type resp_type = {
906 .type = PCIXCC_RESPONSE_TYPE_ICA,
907 };
908 int rc;
909
910 ap_init_message(&ap_msg);
911 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
912 if (!ap_msg.message)
913 return -ENOMEM;
914 ap_msg.receive = zcrypt_msgtype6_receive;
915 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
916 atomic_inc_return(&zcrypt_step);
917 ap_msg.private = &resp_type;
918 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
919 if (rc)
920 goto out_free;
921 init_completion(&resp_type.work);
922 ap_queue_message(zdev->ap_dev, &ap_msg);
923 rc = wait_for_completion_interruptible(&resp_type.work);
924 if (rc == 0)
925 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
926 mex->outputdatalength);
927 else
928 /* Signal pending. */
929 ap_cancel_message(zdev->ap_dev, &ap_msg);
930out_free:
931 free_page((unsigned long) ap_msg.message);
932 return rc;
933}
934
935/**
936 * The request distributor calls this function if it picked the PCIXCC/CEX2C
937 * device to handle a modexpo_crt request.
938 * @zdev: pointer to zcrypt_device structure that identifies the
939 * PCIXCC/CEX2C device to the request distributor
940 * @crt: pointer to the modexpoc_crt request buffer
941 */
942static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_device *zdev,
943 struct ica_rsa_modexpo_crt *crt)
944{
945 struct ap_message ap_msg;
946 struct response_type resp_type = {
947 .type = PCIXCC_RESPONSE_TYPE_ICA,
948 };
949 int rc;
950
951 ap_init_message(&ap_msg);
952 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
953 if (!ap_msg.message)
954 return -ENOMEM;
955 ap_msg.receive = zcrypt_msgtype6_receive;
956 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
957 atomic_inc_return(&zcrypt_step);
958 ap_msg.private = &resp_type;
959 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
960 if (rc)
961 goto out_free;
962 init_completion(&resp_type.work);
963 ap_queue_message(zdev->ap_dev, &ap_msg);
964 rc = wait_for_completion_interruptible(&resp_type.work);
965 if (rc == 0)
966 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
967 crt->outputdatalength);
968 else
969 /* Signal pending. */
970 ap_cancel_message(zdev->ap_dev, &ap_msg);
971out_free:
972 free_page((unsigned long) ap_msg.message);
973 return rc;
974}
975
976/**
977 * The request distributor calls this function if it picked the PCIXCC/CEX2C
978 * device to handle a send_cprb request.
979 * @zdev: pointer to zcrypt_device structure that identifies the
980 * PCIXCC/CEX2C device to the request distributor
981 * @xcRB: pointer to the send_cprb request buffer
982 */
983static long zcrypt_msgtype6_send_cprb(struct zcrypt_device *zdev,
984 struct ica_xcRB *xcRB)
985{
986 struct ap_message ap_msg;
987 struct response_type resp_type = {
988 .type = PCIXCC_RESPONSE_TYPE_XCRB,
989 };
990 int rc;
991
992 ap_init_message(&ap_msg);
993 ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
994 if (!ap_msg.message)
995 return -ENOMEM;
996 ap_msg.receive = zcrypt_msgtype6_receive;
997 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
998 atomic_inc_return(&zcrypt_step);
999 ap_msg.private = &resp_type;
1000 rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB);
1001 if (rc)
1002 goto out_free;
1003 init_completion(&resp_type.work);
1004 ap_queue_message(zdev->ap_dev, &ap_msg);
1005 rc = wait_for_completion_interruptible(&resp_type.work);
1006 if (rc == 0)
1007 rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
1008 else
1009 /* Signal pending. */
1010 ap_cancel_message(zdev->ap_dev, &ap_msg);
1011out_free:
1012 kzfree(ap_msg.message);
1013 return rc;
1014}
1015
1016/**
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +01001017 * The request distributor calls this function if it picked the CEX4P
1018 * device to handle a send_ep11_cprb request.
1019 * @zdev: pointer to zcrypt_device structure that identifies the
1020 * CEX4P device to the request distributor
1021 * @xcRB: pointer to the ep11 user request block
1022 */
1023static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_device *zdev,
1024 struct ep11_urb *xcrb)
1025{
1026 struct ap_message ap_msg;
1027 struct response_type resp_type = {
1028 .type = PCIXCC_RESPONSE_TYPE_EP11,
1029 };
1030 int rc;
1031
1032 ap_init_message(&ap_msg);
1033 ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
1034 if (!ap_msg.message)
1035 return -ENOMEM;
1036 ap_msg.receive = zcrypt_msgtype6_receive_ep11;
1037 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
1038 atomic_inc_return(&zcrypt_step);
1039 ap_msg.private = &resp_type;
1040 rc = xcrb_msg_to_type6_ep11cprb_msgx(zdev, &ap_msg, xcrb);
1041 if (rc)
1042 goto out_free;
1043 init_completion(&resp_type.work);
1044 ap_queue_message(zdev->ap_dev, &ap_msg);
1045 rc = wait_for_completion_interruptible(&resp_type.work);
1046 if (rc == 0)
1047 rc = convert_response_ep11_xcrb(zdev, &ap_msg, xcrb);
1048 else /* Signal pending. */
1049 ap_cancel_message(zdev->ap_dev, &ap_msg);
1050
1051out_free:
1052 kzfree(ap_msg.message);
1053 return rc;
1054}
1055
1056/**
Holger Dengler5e55a482012-08-28 16:45:36 +02001057 * The request distributor calls this function if it picked the PCIXCC/CEX2C
1058 * device to generate random data.
1059 * @zdev: pointer to zcrypt_device structure that identifies the
1060 * PCIXCC/CEX2C device to the request distributor
1061 * @buffer: pointer to a memory page to return random data
1062 */
1063
1064static long zcrypt_msgtype6_rng(struct zcrypt_device *zdev,
1065 char *buffer)
1066{
1067 struct ap_message ap_msg;
1068 struct response_type resp_type = {
1069 .type = PCIXCC_RESPONSE_TYPE_XCRB,
1070 };
1071 int rc;
1072
1073 ap_init_message(&ap_msg);
1074 ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL);
1075 if (!ap_msg.message)
1076 return -ENOMEM;
1077 ap_msg.receive = zcrypt_msgtype6_receive;
1078 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
1079 atomic_inc_return(&zcrypt_step);
1080 ap_msg.private = &resp_type;
1081 rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE);
1082 init_completion(&resp_type.work);
1083 ap_queue_message(zdev->ap_dev, &ap_msg);
1084 rc = wait_for_completion_interruptible(&resp_type.work);
1085 if (rc == 0)
1086 rc = convert_response_rng(zdev, &ap_msg, buffer);
1087 else
1088 /* Signal pending. */
1089 ap_cancel_message(zdev->ap_dev, &ap_msg);
1090 kfree(ap_msg.message);
1091 return rc;
1092}
1093
1094/**
1095 * The crypto operations for a PCIXCC/CEX2C card.
1096 */
1097static struct zcrypt_ops zcrypt_msgtype6_norng_ops = {
1098 .owner = THIS_MODULE,
1099 .variant = MSGTYPE06_VARIANT_NORNG,
1100 .rsa_modexpo = zcrypt_msgtype6_modexpo,
1101 .rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt,
1102 .send_cprb = zcrypt_msgtype6_send_cprb,
1103};
1104
1105static struct zcrypt_ops zcrypt_msgtype6_ops = {
1106 .owner = THIS_MODULE,
1107 .variant = MSGTYPE06_VARIANT_DEFAULT,
1108 .rsa_modexpo = zcrypt_msgtype6_modexpo,
1109 .rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt,
1110 .send_cprb = zcrypt_msgtype6_send_cprb,
1111 .rng = zcrypt_msgtype6_rng,
1112};
1113
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +01001114static struct zcrypt_ops zcrypt_msgtype6_ep11_ops = {
1115 .owner = THIS_MODULE,
1116 .variant = MSGTYPE06_VARIANT_EP11,
1117 .rsa_modexpo = NULL,
1118 .rsa_modexpo_crt = NULL,
1119 .send_ep11_cprb = zcrypt_msgtype6_send_ep11_cprb,
1120};
1121
Holger Dengler5e55a482012-08-28 16:45:36 +02001122int __init zcrypt_msgtype6_init(void)
1123{
1124 zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops);
1125 zcrypt_msgtype_register(&zcrypt_msgtype6_ops);
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +01001126 zcrypt_msgtype_register(&zcrypt_msgtype6_ep11_ops);
Holger Dengler5e55a482012-08-28 16:45:36 +02001127 return 0;
1128}
1129
1130void __exit zcrypt_msgtype6_exit(void)
1131{
1132 zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops);
1133 zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops);
Ingo Tuchscherer91f3e3e2013-11-20 10:47:13 +01001134 zcrypt_msgtype_unregister(&zcrypt_msgtype6_ep11_ops);
Holger Dengler5e55a482012-08-28 16:45:36 +02001135}
1136
1137module_init(zcrypt_msgtype6_init);
1138module_exit(zcrypt_msgtype6_exit);