blob: 4040c1c981d1a361a72883bf5072740c6d9e0bad [file] [log] [blame]
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001/*
2 * linux/drivers/s390/crypto/zcrypt_pcixcc.c
3 *
Ralph Wuerthner54321142006-09-20 15:58:36 +02004 * zcrypt 2.1.0
Martin Schwidefsky6684af12006-09-20 15:58:32 +02005 *
6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs
8 * Eric Rossman (edrossma@us.ibm.com)
9 *
10 * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
11 * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
12 * Ralph Wuerthner <rwuerthn@de.ibm.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29#include <linux/module.h>
30#include <linux/init.h>
31#include <linux/err.h>
32#include <linux/delay.h>
33#include <asm/atomic.h>
34#include <asm/uaccess.h>
35
36#include "ap_bus.h"
37#include "zcrypt_api.h"
38#include "zcrypt_error.h"
39#include "zcrypt_pcicc.h"
40#include "zcrypt_pcixcc.h"
41#include "zcrypt_cca_key.h"
42
43#define PCIXCC_MIN_MOD_SIZE 16 /* 128 bits */
44#define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */
45#define PCIXCC_MAX_MOD_SIZE 256 /* 2048 bits */
46
47#define PCIXCC_MCL2_SPEED_RATING 7870 /* FIXME: needs finetuning */
48#define PCIXCC_MCL3_SPEED_RATING 7870
49#define CEX2C_SPEED_RATING 8540
50
51#define PCIXCC_MAX_ICA_MESSAGE_SIZE 0x77c /* max size type6 v2 crt message */
52#define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */
53
54#define PCIXCC_MAX_XCRB_MESSAGE_SIZE (12*1024)
55#define PCIXCC_MAX_XCRB_RESPONSE_SIZE PCIXCC_MAX_XCRB_MESSAGE_SIZE
56#define PCIXCC_MAX_XCRB_DATA_SIZE (11*1024)
57#define PCIXCC_MAX_XCRB_REPLY_SIZE (5*1024)
58
59#define PCIXCC_MAX_RESPONSE_SIZE PCIXCC_MAX_XCRB_RESPONSE_SIZE
60
61#define PCIXCC_CLEANUP_TIME (15*HZ)
62
Ralph Wuerthner54321142006-09-20 15:58:36 +020063#define CEIL4(x) ((((x)+3)/4)*4)
64
65struct response_type {
66 struct completion work;
67 int type;
68};
69#define PCIXCC_RESPONSE_TYPE_ICA 0
70#define PCIXCC_RESPONSE_TYPE_XCRB 1
71
Martin Schwidefsky6684af12006-09-20 15:58:32 +020072static struct ap_device_id zcrypt_pcixcc_ids[] = {
73 { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) },
74 { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) },
Ralph Wuerthnerd8c33d32008-07-14 09:59:10 +020075 { AP_DEVICE(AP_DEVICE_TYPE_CEX2C2) },
Martin Schwidefsky6684af12006-09-20 15:58:32 +020076 { /* end of list */ },
77};
78
79#ifndef CONFIG_ZCRYPT_MONOLITHIC
80MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids);
81MODULE_AUTHOR("IBM Corporation");
82MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, "
83 "Copyright 2001, 2006 IBM Corporation");
84MODULE_LICENSE("GPL");
85#endif
86
87static int zcrypt_pcixcc_probe(struct ap_device *ap_dev);
88static void zcrypt_pcixcc_remove(struct ap_device *ap_dev);
89static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *,
90 struct ap_message *);
91
92static struct ap_driver zcrypt_pcixcc_driver = {
93 .probe = zcrypt_pcixcc_probe,
94 .remove = zcrypt_pcixcc_remove,
95 .receive = zcrypt_pcixcc_receive,
96 .ids = zcrypt_pcixcc_ids,
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +020097 .request_timeout = PCIXCC_CLEANUP_TIME,
Martin Schwidefsky6684af12006-09-20 15:58:32 +020098};
99
100/**
101 * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C
102 * card in a type6 message. The 3 fields that must be filled in at execution
103 * time are req_parml, rpl_parml and usage_domain.
104 * Everything about this interface is ascii/big-endian, since the
105 * device does *not* have 'Intel inside'.
106 *
107 * The CPRBX is followed immediately by the parm block.
108 * The parm block contains:
109 * - function code ('PD' 0x5044 or 'PK' 0x504B)
110 * - rule block (one of:)
111 * + 0x000A 'PKCS-1.2' (MCL2 'PD')
112 * + 0x000A 'ZERO-PAD' (MCL2 'PK')
113 * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD')
114 * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK')
115 * - VUD block
116 */
117static struct CPRBX static_cprbx = {
118 .cprb_len = 0x00DC,
119 .cprb_ver_id = 0x02,
120 .func_id = {0x54,0x32},
121};
122
123/**
124 * Convert a ICAMEX message to a type6 MEX message.
125 *
126 * @zdev: crypto device pointer
127 * @ap_msg: pointer to AP message
128 * @mex: pointer to user input data
129 *
130 * Returns 0 on success or -EFAULT.
131 */
132static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev,
133 struct ap_message *ap_msg,
134 struct ica_rsa_modexpo *mex)
135{
136 static struct type6_hdr static_type6_hdrX = {
137 .type = 0x06,
138 .offset1 = 0x00000058,
139 .agent_id = {'C','A',},
140 .function_code = {'P','K'},
141 };
142 static struct function_and_rules_block static_pke_fnr = {
143 .function_code = {'P','K'},
144 .ulen = 10,
145 .only_rule = {'M','R','P',' ',' ',' ',' ',' '}
146 };
147 static struct function_and_rules_block static_pke_fnr_MCL2 = {
148 .function_code = {'P','K'},
149 .ulen = 10,
150 .only_rule = {'Z','E','R','O','-','P','A','D'}
151 };
152 struct {
153 struct type6_hdr hdr;
154 struct CPRBX cprbx;
155 struct function_and_rules_block fr;
156 unsigned short length;
157 char text[0];
158 } __attribute__((packed)) *msg = ap_msg->message;
159 int size;
160
161 /* VUD.ciphertext */
162 msg->length = mex->inputdatalength + 2;
163 if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
164 return -EFAULT;
165
166 /* Set up key which is located after the variable length text. */
167 size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1);
168 if (size < 0)
169 return size;
170 size += sizeof(*msg) + mex->inputdatalength;
171
172 /* message header, cprbx and f&r */
173 msg->hdr = static_type6_hdrX;
174 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
175 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
176
177 msg->cprbx = static_cprbx;
178 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
179 msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1;
180
181 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
182 static_pke_fnr_MCL2 : static_pke_fnr;
183
184 msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx);
185
186 ap_msg->length = size;
187 return 0;
188}
189
190/**
191 * Convert a ICACRT message to a type6 CRT message.
192 *
193 * @zdev: crypto device pointer
194 * @ap_msg: pointer to AP message
195 * @crt: pointer to user input data
196 *
197 * Returns 0 on success or -EFAULT.
198 */
199static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,
200 struct ap_message *ap_msg,
201 struct ica_rsa_modexpo_crt *crt)
202{
203 static struct type6_hdr static_type6_hdrX = {
204 .type = 0x06,
205 .offset1 = 0x00000058,
206 .agent_id = {'C','A',},
207 .function_code = {'P','D'},
208 };
209 static struct function_and_rules_block static_pkd_fnr = {
210 .function_code = {'P','D'},
211 .ulen = 10,
212 .only_rule = {'Z','E','R','O','-','P','A','D'}
213 };
214
215 static struct function_and_rules_block static_pkd_fnr_MCL2 = {
216 .function_code = {'P','D'},
217 .ulen = 10,
218 .only_rule = {'P','K','C','S','-','1','.','2'}
219 };
220 struct {
221 struct type6_hdr hdr;
222 struct CPRBX cprbx;
223 struct function_and_rules_block fr;
224 unsigned short length;
225 char text[0];
226 } __attribute__((packed)) *msg = ap_msg->message;
227 int size;
228
229 /* VUD.ciphertext */
230 msg->length = crt->inputdatalength + 2;
231 if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
232 return -EFAULT;
233
234 /* Set up key which is located after the variable length text. */
235 size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1);
236 if (size < 0)
237 return size;
238 size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */
239
240 /* message header, cprbx and f&r */
241 msg->hdr = static_type6_hdrX;
242 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
243 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
244
245 msg->cprbx = static_cprbx;
246 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
247 msg->cprbx.req_parml = msg->cprbx.rpl_msgbl =
248 size - sizeof(msg->hdr) - sizeof(msg->cprbx);
249
250 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
251 static_pkd_fnr_MCL2 : static_pkd_fnr;
252
253 ap_msg->length = size;
254 return 0;
255}
256
257/**
Ralph Wuerthner54321142006-09-20 15:58:36 +0200258 * Convert a XCRB message to a type6 CPRB message.
259 *
260 * @zdev: crypto device pointer
261 * @ap_msg: pointer to AP message
262 * @xcRB: pointer to user input data
263 *
264 * Returns 0 on success or -EFAULT.
265 */
266struct type86_fmt2_msg {
267 struct type86_hdr hdr;
268 struct type86_fmt2_ext fmt2;
269} __attribute__((packed));
270
271static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
272 struct ap_message *ap_msg,
273 struct ica_xcRB *xcRB)
274{
275 static struct type6_hdr static_type6_hdrX = {
276 .type = 0x06,
277 .offset1 = 0x00000058,
278 };
279 struct {
280 struct type6_hdr hdr;
Ralph Wuerthner16db63f2007-10-12 16:11:28 +0200281 struct CPRBX cprbx;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200282 } __attribute__((packed)) *msg = ap_msg->message;
283
284 int rcblen = CEIL4(xcRB->request_control_blk_length);
285 int replylen;
286 char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
287 char *function_code;
288
289 /* length checks */
290 ap_msg->length = sizeof(struct type6_hdr) +
291 CEIL4(xcRB->request_control_blk_length) +
292 xcRB->request_data_length;
293 if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE) {
294 PRINTK("Combined message is too large (%ld/%d/%d).\n",
295 sizeof(struct type6_hdr),
296 xcRB->request_control_blk_length,
297 xcRB->request_data_length);
298 return -EFAULT;
299 }
300 if (CEIL4(xcRB->reply_control_blk_length) >
301 PCIXCC_MAX_XCRB_REPLY_SIZE) {
302 PDEBUG("Reply CPRB length is too large (%d).\n",
303 xcRB->request_control_blk_length);
304 return -EFAULT;
305 }
306 if (CEIL4(xcRB->reply_data_length) > PCIXCC_MAX_XCRB_DATA_SIZE) {
307 PDEBUG("Reply data block length is too large (%d).\n",
308 xcRB->reply_data_length);
309 return -EFAULT;
310 }
311 replylen = CEIL4(xcRB->reply_control_blk_length) +
312 CEIL4(xcRB->reply_data_length) +
313 sizeof(struct type86_fmt2_msg);
314 if (replylen > PCIXCC_MAX_XCRB_RESPONSE_SIZE) {
315 PDEBUG("Reply CPRB + data block > PCIXCC_MAX_XCRB_RESPONSE_SIZE"
316 " (%d/%d/%d).\n",
317 sizeof(struct type86_fmt2_msg),
318 xcRB->reply_control_blk_length,
319 xcRB->reply_data_length);
320 xcRB->reply_control_blk_length = PCIXCC_MAX_XCRB_RESPONSE_SIZE -
321 (sizeof(struct type86_fmt2_msg) +
322 CEIL4(xcRB->reply_data_length));
323 PDEBUG("Capping Reply CPRB length at %d\n",
324 xcRB->reply_control_blk_length);
325 }
326
327 /* prepare type6 header */
328 msg->hdr = static_type6_hdrX;
329 memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
330 msg->hdr.ToCardLen1 = xcRB->request_control_blk_length;
331 if (xcRB->request_data_length) {
332 msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
333 msg->hdr.ToCardLen2 = xcRB->request_data_length;
334 }
335 msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
336 msg->hdr.FromCardLen2 = xcRB->reply_data_length;
337
338 /* prepare CPRB */
339 if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
340 xcRB->request_control_blk_length))
341 return -EFAULT;
342 if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
343 xcRB->request_control_blk_length) {
344 PDEBUG("cprb_len too large (%d/%d)\n", msg->cprbx.cprb_len,
345 xcRB->request_control_blk_length);
346 return -EFAULT;
347 }
348 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
349 memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code));
350
351 /* copy data block */
352 if (xcRB->request_data_length &&
353 copy_from_user(req_data, xcRB->request_data_address,
354 xcRB->request_data_length))
355 return -EFAULT;
356 return 0;
357}
358
359/**
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200360 * Prepare a type6 CPRB message for random number generation
361 *
362 * @ap_dev: AP device pointer
363 * @ap_msg: pointer to AP message
364 */
365static void rng_type6CPRB_msgX(struct ap_device *ap_dev,
366 struct ap_message *ap_msg,
367 unsigned random_number_length)
368{
369 struct {
370 struct type6_hdr hdr;
371 struct CPRBX cprbx;
372 char function_code[2];
373 short int rule_length;
374 char rule[8];
375 short int verb_length;
376 short int key_length;
377 } __attribute__((packed)) *msg = ap_msg->message;
378 static struct type6_hdr static_type6_hdrX = {
379 .type = 0x06,
380 .offset1 = 0x00000058,
381 .agent_id = {'C', 'A'},
382 .function_code = {'R', 'L'},
383 .ToCardLen1 = sizeof *msg - sizeof(msg->hdr),
384 .FromCardLen1 = sizeof *msg - sizeof(msg->hdr),
385 };
386 static struct CPRBX static_cprbx = {
387 .cprb_len = 0x00dc,
388 .cprb_ver_id = 0x02,
389 .func_id = {0x54, 0x32},
390 .req_parml = sizeof *msg - sizeof(msg->hdr) -
391 sizeof(msg->cprbx),
392 .rpl_msgbl = sizeof *msg - sizeof(msg->hdr),
393 };
394
395 msg->hdr = static_type6_hdrX;
396 msg->hdr.FromCardLen2 = random_number_length,
397 msg->cprbx = static_cprbx;
398 msg->cprbx.rpl_datal = random_number_length,
399 msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid);
400 memcpy(msg->function_code, msg->hdr.function_code, 0x02);
401 msg->rule_length = 0x0a;
402 memcpy(msg->rule, "RANDOM ", 8);
403 msg->verb_length = 0x02;
404 msg->key_length = 0x02;
405 ap_msg->length = sizeof *msg;
406}
407
408/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200409 * Copy results from a type 86 ICA reply message back to user space.
410 *
411 * @zdev: crypto device pointer
412 * @reply: reply AP message.
413 * @data: pointer to user output data
414 * @length: size of user output data
415 *
416 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
417 */
418struct type86x_reply {
419 struct type86_hdr hdr;
420 struct type86_fmt2_ext fmt2;
421 struct CPRBX cprbx;
422 unsigned char pad[4]; /* 4 byte function code/rules block ? */
423 unsigned short length;
424 char text[0];
425} __attribute__((packed));
426
427static int convert_type86_ica(struct zcrypt_device *zdev,
428 struct ap_message *reply,
429 char __user *outputdata,
430 unsigned int outputdatalength)
431{
432 static unsigned char static_pad[] = {
433 0x00,0x02,
434 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,
435 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57,
436 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,
437 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39,
438 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,
439 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D,
440 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,
441 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F,
442 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,
443 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45,
444 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,
445 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F,
446 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,
447 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D,
448 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,
449 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9,
450 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,
451 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B,
452 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,
453 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD,
454 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,
455 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1,
456 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,
457 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23,
458 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,
459 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43,
460 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,
461 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F,
462 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,
463 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD,
464 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,
465 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09
466 };
467 struct type86x_reply *msg = reply->message;
468 unsigned short service_rc, service_rs;
469 unsigned int reply_len, pad_len;
470 char *data;
471
472 service_rc = msg->cprbx.ccp_rtcode;
473 if (unlikely(service_rc != 0)) {
474 service_rs = msg->cprbx.ccp_rscode;
475 if (service_rc == 8 && service_rs == 66) {
476 PDEBUG("Bad block format on PCIXCC/CEX2C\n");
477 return -EINVAL;
478 }
479 if (service_rc == 8 && service_rs == 65) {
480 PDEBUG("Probably an even modulus on PCIXCC/CEX2C\n");
481 return -EINVAL;
482 }
483 if (service_rc == 8 && service_rs == 770) {
484 PDEBUG("Invalid key length on PCIXCC/CEX2C\n");
Ralph Wuerthner2af48082007-10-12 16:11:30 +0200485 return -EINVAL;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200486 }
487 if (service_rc == 8 && service_rs == 783) {
488 PDEBUG("Extended bitlengths not enabled on PCIXCC/CEX2C\n");
489 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
490 return -EAGAIN;
491 }
Ralph Wuerthner2af48082007-10-12 16:11:30 +0200492 if (service_rc == 12 && service_rs == 769) {
493 PDEBUG("Invalid key on PCIXCC/CEX2C\n");
494 return -EINVAL;
495 }
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200496 PRINTK("Unknown service rc/rs (PCIXCC/CEX2C): %d/%d\n",
497 service_rc, service_rs);
498 zdev->online = 0;
499 return -EAGAIN; /* repeat the request on a different device. */
500 }
501 data = msg->text;
502 reply_len = msg->length - 2;
503 if (reply_len > outputdatalength)
504 return -EINVAL;
Felix Beck1749a812008-04-17 07:46:28 +0200505 /*
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200506 * For all encipher requests, the length of the ciphertext (reply_len)
507 * will always equal the modulus length. For MEX decipher requests
508 * the output needs to get padded. Minimum pad size is 10.
509 *
510 * Currently, the cases where padding will be added is for:
511 * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
512 * ZERO-PAD and CRT is only supported for PKD requests)
513 * - PCICC, always
514 */
515 pad_len = outputdatalength - reply_len;
516 if (pad_len > 0) {
517 if (pad_len < 10)
518 return -EINVAL;
519 /* 'restore' padding left in the PCICC/PCIXCC card. */
520 if (copy_to_user(outputdata, static_pad, pad_len - 1))
521 return -EFAULT;
522 if (put_user(0, outputdata + pad_len - 1))
523 return -EFAULT;
524 }
525 /* Copy the crypto response to user space. */
526 if (copy_to_user(outputdata + pad_len, data, reply_len))
527 return -EFAULT;
528 return 0;
529}
530
Ralph Wuerthner54321142006-09-20 15:58:36 +0200531/**
532 * Copy results from a type 86 XCRB reply message back to user space.
533 *
534 * @zdev: crypto device pointer
535 * @reply: reply AP message.
536 * @xcRB: pointer to XCRB
537 *
538 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
539 */
540static int convert_type86_xcrb(struct zcrypt_device *zdev,
541 struct ap_message *reply,
542 struct ica_xcRB *xcRB)
543{
544 struct type86_fmt2_msg *msg = reply->message;
545 char *data = reply->message;
546
547 /* Copy CPRB to user */
548 if (copy_to_user(xcRB->reply_control_blk_addr,
549 data + msg->fmt2.offset1, msg->fmt2.count1))
550 return -EFAULT;
551 xcRB->reply_control_blk_length = msg->fmt2.count1;
552
553 /* Copy data buffer to user */
554 if (msg->fmt2.count2)
555 if (copy_to_user(xcRB->reply_data_addr,
556 data + msg->fmt2.offset2, msg->fmt2.count2))
557 return -EFAULT;
558 xcRB->reply_data_length = msg->fmt2.count2;
559 return 0;
560}
561
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200562static int convert_type86_rng(struct zcrypt_device *zdev,
563 struct ap_message *reply,
564 char *buffer)
565{
566 struct {
567 struct type86_hdr hdr;
568 struct type86_fmt2_ext fmt2;
569 struct CPRBX cprbx;
570 } __attribute__((packed)) *msg = reply->message;
571 char *data = reply->message;
572
573 if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0) {
574 PDEBUG("RNG response error on PCIXCC/CEX2C rc=%hu/rs=%hu\n",
575 rc, rs);
576 return -EINVAL;
577 }
578 memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
579 return msg->fmt2.count2;
580}
581
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200582static int convert_response_ica(struct zcrypt_device *zdev,
583 struct ap_message *reply,
584 char __user *outputdata,
585 unsigned int outputdatalength)
586{
587 struct type86x_reply *msg = reply->message;
588
589 /* Response type byte is the second byte in the response. */
590 switch (((unsigned char *) reply->message)[1]) {
591 case TYPE82_RSP_CODE:
592 case TYPE88_RSP_CODE:
593 return convert_error(zdev, reply);
594 case TYPE86_RSP_CODE:
595 if (msg->hdr.reply_code)
596 return convert_error(zdev, reply);
597 if (msg->cprbx.cprb_ver_id == 0x02)
598 return convert_type86_ica(zdev, reply,
599 outputdata, outputdatalength);
600 /* no break, incorrect cprb version is an unknown response */
601 default: /* Unknown response type, this should NEVER EVER happen */
602 PRINTK("Unrecognized Message Header: %08x%08x\n",
603 *(unsigned int *) reply->message,
604 *(unsigned int *) (reply->message+4));
605 zdev->online = 0;
606 return -EAGAIN; /* repeat the request on a different device. */
607 }
608}
609
Ralph Wuerthner54321142006-09-20 15:58:36 +0200610static int convert_response_xcrb(struct zcrypt_device *zdev,
611 struct ap_message *reply,
612 struct ica_xcRB *xcRB)
613{
614 struct type86x_reply *msg = reply->message;
615
616 /* Response type byte is the second byte in the response. */
617 switch (((unsigned char *) reply->message)[1]) {
618 case TYPE82_RSP_CODE:
619 case TYPE88_RSP_CODE:
620 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
621 return convert_error(zdev, reply);
622 case TYPE86_RSP_CODE:
623 if (msg->hdr.reply_code) {
624 memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
625 return convert_error(zdev, reply);
626 }
627 if (msg->cprbx.cprb_ver_id == 0x02)
628 return convert_type86_xcrb(zdev, reply, xcRB);
629 /* no break, incorrect cprb version is an unknown response */
630 default: /* Unknown response type, this should NEVER EVER happen */
631 PRINTK("Unrecognized Message Header: %08x%08x\n",
632 *(unsigned int *) reply->message,
633 *(unsigned int *) (reply->message+4));
634 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
635 zdev->online = 0;
636 return -EAGAIN; /* repeat the request on a different device. */
637 }
638}
639
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200640static int convert_response_rng(struct zcrypt_device *zdev,
641 struct ap_message *reply,
642 char *data)
643{
644 struct type86x_reply *msg = reply->message;
645
646 switch (msg->hdr.type) {
647 case TYPE82_RSP_CODE:
648 case TYPE88_RSP_CODE:
649 return -EINVAL;
650 case TYPE86_RSP_CODE:
651 if (msg->hdr.reply_code)
652 return -EINVAL;
653 if (msg->cprbx.cprb_ver_id == 0x02)
654 return convert_type86_rng(zdev, reply, data);
655 /* no break, incorrect cprb version is an unknown response */
656 default: /* Unknown response type, this should NEVER EVER happen */
657 PRINTK("Unrecognized Message Header: %08x%08x\n",
658 *(unsigned int *) reply->message,
659 *(unsigned int *) (reply->message+4));
660 zdev->online = 0;
661 return -EAGAIN; /* repeat the request on a different device. */
662 }
663}
664
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200665/**
666 * This function is called from the AP bus code after a crypto request
667 * "msg" has finished with the reply message "reply".
668 * It is called from tasklet context.
669 * @ap_dev: pointer to the AP device
670 * @msg: pointer to the AP message
671 * @reply: pointer to the AP reply message
672 */
673static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
674 struct ap_message *msg,
675 struct ap_message *reply)
676{
677 static struct error_hdr error_reply = {
678 .type = TYPE82_RSP_CODE,
679 .reply_code = REP82_ERROR_MACHINE_FAILURE,
680 };
Ralph Wuerthner54321142006-09-20 15:58:36 +0200681 struct response_type *resp_type =
682 (struct response_type *) msg->private;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200683 struct type86x_reply *t86r = reply->message;
684 int length;
685
686 /* Copy the reply message to the request message buffer. */
687 if (IS_ERR(reply))
688 memcpy(msg->message, &error_reply, sizeof(error_reply));
689 else if (t86r->hdr.type == TYPE86_RSP_CODE &&
690 t86r->cprbx.cprb_ver_id == 0x02) {
Ralph Wuerthner54321142006-09-20 15:58:36 +0200691 switch (resp_type->type) {
692 case PCIXCC_RESPONSE_TYPE_ICA:
693 length = sizeof(struct type86x_reply)
694 + t86r->length - 2;
695 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
696 memcpy(msg->message, reply->message, length);
697 break;
698 case PCIXCC_RESPONSE_TYPE_XCRB:
699 length = t86r->fmt2.offset2 + t86r->fmt2.count2;
700 length = min(PCIXCC_MAX_XCRB_RESPONSE_SIZE, length);
701 memcpy(msg->message, reply->message, length);
702 break;
703 default:
704 PRINTK("Invalid internal response type: %i\n",
705 resp_type->type);
706 memcpy(msg->message, &error_reply,
707 sizeof error_reply);
708 }
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200709 } else
710 memcpy(msg->message, reply->message, sizeof error_reply);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200711 complete(&(resp_type->work));
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200712}
713
714static atomic_t zcrypt_step = ATOMIC_INIT(0);
715
716/**
717 * The request distributor calls this function if it picked the PCIXCC/CEX2C
718 * device to handle a modexpo request.
719 * @zdev: pointer to zcrypt_device structure that identifies the
720 * PCIXCC/CEX2C device to the request distributor
721 * @mex: pointer to the modexpo request buffer
722 */
723static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
724 struct ica_rsa_modexpo *mex)
725{
726 struct ap_message ap_msg;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200727 struct response_type resp_type = {
728 .type = PCIXCC_RESPONSE_TYPE_ICA,
729 };
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200730 int rc;
731
732 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
733 if (!ap_msg.message)
734 return -ENOMEM;
735 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
736 atomic_inc_return(&zcrypt_step);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200737 ap_msg.private = &resp_type;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200738 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
739 if (rc)
740 goto out_free;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200741 init_completion(&resp_type.work);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200742 ap_queue_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200743 rc = wait_for_completion_interruptible(&resp_type.work);
744 if (rc == 0)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200745 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
746 mex->outputdatalength);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200747 else
748 /* Signal pending. */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200749 ap_cancel_message(zdev->ap_dev, &ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200750out_free:
751 free_page((unsigned long) ap_msg.message);
752 return rc;
753}
754
755/**
756 * The request distributor calls this function if it picked the PCIXCC/CEX2C
757 * device to handle a modexpo_crt request.
758 * @zdev: pointer to zcrypt_device structure that identifies the
759 * PCIXCC/CEX2C device to the request distributor
760 * @crt: pointer to the modexpoc_crt request buffer
761 */
762static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
763 struct ica_rsa_modexpo_crt *crt)
764{
765 struct ap_message ap_msg;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200766 struct response_type resp_type = {
767 .type = PCIXCC_RESPONSE_TYPE_ICA,
768 };
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200769 int rc;
770
771 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
772 if (!ap_msg.message)
773 return -ENOMEM;
774 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
775 atomic_inc_return(&zcrypt_step);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200776 ap_msg.private = &resp_type;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200777 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
778 if (rc)
779 goto out_free;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200780 init_completion(&resp_type.work);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200781 ap_queue_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200782 rc = wait_for_completion_interruptible(&resp_type.work);
783 if (rc == 0)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200784 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
785 crt->outputdatalength);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200786 else
787 /* Signal pending. */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200788 ap_cancel_message(zdev->ap_dev, &ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200789out_free:
790 free_page((unsigned long) ap_msg.message);
791 return rc;
792}
793
794/**
Ralph Wuerthner54321142006-09-20 15:58:36 +0200795 * The request distributor calls this function if it picked the PCIXCC/CEX2C
796 * device to handle a send_cprb request.
797 * @zdev: pointer to zcrypt_device structure that identifies the
798 * PCIXCC/CEX2C device to the request distributor
799 * @xcRB: pointer to the send_cprb request buffer
800 */
Heiko Carstens2b67fc42007-02-05 21:16:47 +0100801static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
802 struct ica_xcRB *xcRB)
Ralph Wuerthner54321142006-09-20 15:58:36 +0200803{
804 struct ap_message ap_msg;
805 struct response_type resp_type = {
806 .type = PCIXCC_RESPONSE_TYPE_XCRB,
807 };
808 int rc;
809
Robert P. J. Day5cbded52006-12-13 00:35:56 -0800810 ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200811 if (!ap_msg.message)
812 return -ENOMEM;
813 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
814 atomic_inc_return(&zcrypt_step);
815 ap_msg.private = &resp_type;
816 rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB);
817 if (rc)
818 goto out_free;
819 init_completion(&resp_type.work);
820 ap_queue_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200821 rc = wait_for_completion_interruptible(&resp_type.work);
822 if (rc == 0)
Ralph Wuerthner54321142006-09-20 15:58:36 +0200823 rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200824 else
825 /* Signal pending. */
Ralph Wuerthner54321142006-09-20 15:58:36 +0200826 ap_cancel_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200827out_free:
828 memset(ap_msg.message, 0x0, ap_msg.length);
829 kfree(ap_msg.message);
830 return rc;
831}
832
833/**
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200834 * The request distributor calls this function if it picked the PCIXCC/CEX2C
835 * device to generate random data.
836 * @zdev: pointer to zcrypt_device structure that identifies the
837 * PCIXCC/CEX2C device to the request distributor
838 * @buffer: pointer to a memory page to return random data
839 */
840
841static long zcrypt_pcixcc_rng(struct zcrypt_device *zdev,
842 char *buffer)
843{
844 struct ap_message ap_msg;
845 struct response_type resp_type = {
846 .type = PCIXCC_RESPONSE_TYPE_XCRB,
847 };
848 int rc;
849
850 ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
851 if (!ap_msg.message)
852 return -ENOMEM;
853 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
854 atomic_inc_return(&zcrypt_step);
855 ap_msg.private = &resp_type;
856 rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE);
857 init_completion(&resp_type.work);
858 ap_queue_message(zdev->ap_dev, &ap_msg);
859 rc = wait_for_completion_interruptible(&resp_type.work);
860 if (rc == 0)
861 rc = convert_response_rng(zdev, &ap_msg, buffer);
862 else
863 /* Signal pending. */
864 ap_cancel_message(zdev->ap_dev, &ap_msg);
865 kfree(ap_msg.message);
866 return rc;
867}
868
869/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200870 * The crypto operations for a PCIXCC/CEX2C card.
871 */
872static struct zcrypt_ops zcrypt_pcixcc_ops = {
873 .rsa_modexpo = zcrypt_pcixcc_modexpo,
874 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
Ralph Wuerthner54321142006-09-20 15:58:36 +0200875 .send_cprb = zcrypt_pcixcc_send_cprb,
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200876};
877
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200878static struct zcrypt_ops zcrypt_pcixcc_with_rng_ops = {
879 .rsa_modexpo = zcrypt_pcixcc_modexpo,
880 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
881 .send_cprb = zcrypt_pcixcc_send_cprb,
882 .rng = zcrypt_pcixcc_rng,
883};
884
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200885/**
886 * Micro-code detection function. Its sends a message to a pcixcc card
887 * to find out the microcode level.
888 * @ap_dev: pointer to the AP device.
889 */
890static int zcrypt_pcixcc_mcl(struct ap_device *ap_dev)
891{
892 static unsigned char msg[] = {
893 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
894 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
895 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
896 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
897 0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
898 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
899 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00,
900 0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00,
901 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
902 0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00,
903 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
904 0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32,
905 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,
906 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,
907 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
908 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
909 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
910 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
911 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
912 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
913 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
914 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
915 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
916 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
917 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
918 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
919 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
920 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
921 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
922 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
923 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
924 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
925 0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
926 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
927 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
928 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
929 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
930 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
931 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x0A,
932 0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20,
933 0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05,
934 0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
935 0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55,
936 0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,
937 0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,
938 0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,
939 0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB,
940 0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54,
941 0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00,
942 0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00,
943 0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40,
944 0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C,
945 0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF,
946 0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9,
947 0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63,
948 0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5,
949 0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A,
950 0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01,
951 0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28,
952 0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91,
953 0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5,
954 0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C,
955 0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98,
956 0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96,
957 0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19,
958 0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47,
959 0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36,
960 0xF1,0x3D,0x93,0x53
961 };
962 unsigned long long psmid;
963 struct CPRBX *cprbx;
964 char *reply;
965 int rc, i;
966
967 reply = (void *) get_zeroed_page(GFP_KERNEL);
968 if (!reply)
969 return -ENOMEM;
970
971 rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, msg, sizeof(msg));
972 if (rc)
973 goto out_free;
974
975 /* Wait for the test message to complete. */
976 for (i = 0; i < 6; i++) {
977 mdelay(300);
978 rc = ap_recv(ap_dev->qid, &psmid, reply, 4096);
979 if (rc == 0 && psmid == 0x0102030405060708ULL)
980 break;
981 }
982
983 if (i >= 6) {
984 /* Got no answer. */
985 rc = -ENODEV;
986 goto out_free;
987 }
988
989 cprbx = (struct CPRBX *) (reply + 48);
990 if (cprbx->ccp_rtcode == 8 && cprbx->ccp_rscode == 33)
991 rc = ZCRYPT_PCIXCC_MCL2;
992 else
993 rc = ZCRYPT_PCIXCC_MCL3;
994out_free:
995 free_page((unsigned long) reply);
996 return rc;
997}
998
999/**
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +02001000 * Large random number detection function. Its sends a message to a pcixcc
1001 * card to find out if large random numbers are supported.
1002 * @ap_dev: pointer to the AP device.
1003 *
1004 * Returns 1 if large random numbers are supported, 0 if not and < 0 on error.
1005 */
1006static int zcrypt_pcixcc_rng_supported(struct ap_device *ap_dev)
1007{
1008 struct ap_message ap_msg;
1009 unsigned long long psmid;
1010 struct {
1011 struct type86_hdr hdr;
1012 struct type86_fmt2_ext fmt2;
1013 struct CPRBX cprbx;
1014 } __attribute__((packed)) *reply;
1015 int rc, i;
1016
1017 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
1018 if (!ap_msg.message)
1019 return -ENOMEM;
1020
1021 rng_type6CPRB_msgX(ap_dev, &ap_msg, 4);
1022 rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, ap_msg.message,
1023 ap_msg.length);
1024 if (rc)
1025 goto out_free;
1026
1027 /* Wait for the test message to complete. */
1028 for (i = 0; i < 2 * HZ; i++) {
1029 msleep(1000 / HZ);
1030 rc = ap_recv(ap_dev->qid, &psmid, ap_msg.message, 4096);
1031 if (rc == 0 && psmid == 0x0102030405060708ULL)
1032 break;
1033 }
1034
1035 if (i >= 2 * HZ) {
1036 /* Got no answer. */
1037 rc = -ENODEV;
1038 goto out_free;
1039 }
1040
1041 reply = ap_msg.message;
1042 if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0)
1043 rc = 1;
1044 else
1045 rc = 0;
1046out_free:
1047 free_page((unsigned long) ap_msg.message);
1048 return rc;
1049}
1050
1051/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001052 * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device
1053 * since the bus_match already checked the hardware type. The PCIXCC
1054 * cards come in two flavours: micro code level 2 and micro code level 3.
1055 * This is checked by sending a test message to the device.
1056 * @ap_dev: pointer to the AP device.
1057 */
1058static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
1059{
1060 struct zcrypt_device *zdev;
1061 int rc;
1062
1063 zdev = zcrypt_device_alloc(PCIXCC_MAX_RESPONSE_SIZE);
1064 if (!zdev)
1065 return -ENOMEM;
1066 zdev->ap_dev = ap_dev;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001067 zdev->online = 1;
1068 if (ap_dev->device_type == AP_DEVICE_TYPE_PCIXCC) {
1069 rc = zcrypt_pcixcc_mcl(ap_dev);
1070 if (rc < 0) {
1071 zcrypt_device_free(zdev);
1072 return rc;
1073 }
1074 zdev->user_space_type = rc;
1075 if (rc == ZCRYPT_PCIXCC_MCL2) {
1076 zdev->type_string = "PCIXCC_MCL2";
1077 zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING;
1078 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
1079 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
1080 } else {
1081 zdev->type_string = "PCIXCC_MCL3";
1082 zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING;
1083 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
1084 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
1085 }
1086 } else {
1087 zdev->user_space_type = ZCRYPT_CEX2C;
1088 zdev->type_string = "CEX2C";
1089 zdev->speed_rating = CEX2C_SPEED_RATING;
1090 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
1091 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
1092 }
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +02001093 rc = zcrypt_pcixcc_rng_supported(ap_dev);
1094 if (rc < 0) {
1095 zcrypt_device_free(zdev);
1096 return rc;
1097 }
1098 if (rc)
1099 zdev->ops = &zcrypt_pcixcc_with_rng_ops;
1100 else
1101 zdev->ops = &zcrypt_pcixcc_ops;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001102 ap_dev->reply = &zdev->reply;
1103 ap_dev->private = zdev;
1104 rc = zcrypt_device_register(zdev);
1105 if (rc)
1106 goto out_free;
1107 return 0;
1108
1109 out_free:
1110 ap_dev->private = NULL;
1111 zcrypt_device_free(zdev);
1112 return rc;
1113}
1114
1115/**
1116 * This is called to remove the extended PCIXCC/CEX2C driver information
1117 * if an AP device is removed.
1118 */
1119static void zcrypt_pcixcc_remove(struct ap_device *ap_dev)
1120{
1121 struct zcrypt_device *zdev = ap_dev->private;
1122
1123 zcrypt_device_unregister(zdev);
1124}
1125
1126int __init zcrypt_pcixcc_init(void)
1127{
1128 return ap_driver_register(&zcrypt_pcixcc_driver, THIS_MODULE, "pcixcc");
1129}
1130
1131void zcrypt_pcixcc_exit(void)
1132{
1133 ap_driver_unregister(&zcrypt_pcixcc_driver);
1134}
1135
1136#ifndef CONFIG_ZCRYPT_MONOLITHIC
1137module_init(zcrypt_pcixcc_init);
1138module_exit(zcrypt_pcixcc_exit);
1139#endif