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