blob: b7153c1e15cdea786c2fb7c9d453213aaddda39d [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,
96};
97
98/**
99 * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C
100 * card in a type6 message. The 3 fields that must be filled in at execution
101 * time are req_parml, rpl_parml and usage_domain.
102 * Everything about this interface is ascii/big-endian, since the
103 * device does *not* have 'Intel inside'.
104 *
105 * The CPRBX is followed immediately by the parm block.
106 * The parm block contains:
107 * - function code ('PD' 0x5044 or 'PK' 0x504B)
108 * - rule block (one of:)
109 * + 0x000A 'PKCS-1.2' (MCL2 'PD')
110 * + 0x000A 'ZERO-PAD' (MCL2 'PK')
111 * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD')
112 * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK')
113 * - VUD block
114 */
115static struct CPRBX static_cprbx = {
116 .cprb_len = 0x00DC,
117 .cprb_ver_id = 0x02,
118 .func_id = {0x54,0x32},
119};
120
121/**
122 * Convert a ICAMEX message to a type6 MEX message.
123 *
124 * @zdev: crypto device pointer
125 * @ap_msg: pointer to AP message
126 * @mex: pointer to user input data
127 *
128 * Returns 0 on success or -EFAULT.
129 */
130static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev,
131 struct ap_message *ap_msg,
132 struct ica_rsa_modexpo *mex)
133{
134 static struct type6_hdr static_type6_hdrX = {
135 .type = 0x06,
136 .offset1 = 0x00000058,
137 .agent_id = {'C','A',},
138 .function_code = {'P','K'},
139 };
140 static struct function_and_rules_block static_pke_fnr = {
141 .function_code = {'P','K'},
142 .ulen = 10,
143 .only_rule = {'M','R','P',' ',' ',' ',' ',' '}
144 };
145 static struct function_and_rules_block static_pke_fnr_MCL2 = {
146 .function_code = {'P','K'},
147 .ulen = 10,
148 .only_rule = {'Z','E','R','O','-','P','A','D'}
149 };
150 struct {
151 struct type6_hdr hdr;
152 struct CPRBX cprbx;
153 struct function_and_rules_block fr;
154 unsigned short length;
155 char text[0];
156 } __attribute__((packed)) *msg = ap_msg->message;
157 int size;
158
159 /* VUD.ciphertext */
160 msg->length = mex->inputdatalength + 2;
161 if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
162 return -EFAULT;
163
164 /* Set up key which is located after the variable length text. */
165 size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1);
166 if (size < 0)
167 return size;
168 size += sizeof(*msg) + mex->inputdatalength;
169
170 /* message header, cprbx and f&r */
171 msg->hdr = static_type6_hdrX;
172 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
173 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
174
175 msg->cprbx = static_cprbx;
176 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
177 msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1;
178
179 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
180 static_pke_fnr_MCL2 : static_pke_fnr;
181
182 msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx);
183
184 ap_msg->length = size;
185 return 0;
186}
187
188/**
189 * Convert a ICACRT message to a type6 CRT message.
190 *
191 * @zdev: crypto device pointer
192 * @ap_msg: pointer to AP message
193 * @crt: pointer to user input data
194 *
195 * Returns 0 on success or -EFAULT.
196 */
197static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,
198 struct ap_message *ap_msg,
199 struct ica_rsa_modexpo_crt *crt)
200{
201 static struct type6_hdr static_type6_hdrX = {
202 .type = 0x06,
203 .offset1 = 0x00000058,
204 .agent_id = {'C','A',},
205 .function_code = {'P','D'},
206 };
207 static struct function_and_rules_block static_pkd_fnr = {
208 .function_code = {'P','D'},
209 .ulen = 10,
210 .only_rule = {'Z','E','R','O','-','P','A','D'}
211 };
212
213 static struct function_and_rules_block static_pkd_fnr_MCL2 = {
214 .function_code = {'P','D'},
215 .ulen = 10,
216 .only_rule = {'P','K','C','S','-','1','.','2'}
217 };
218 struct {
219 struct type6_hdr hdr;
220 struct CPRBX cprbx;
221 struct function_and_rules_block fr;
222 unsigned short length;
223 char text[0];
224 } __attribute__((packed)) *msg = ap_msg->message;
225 int size;
226
227 /* VUD.ciphertext */
228 msg->length = crt->inputdatalength + 2;
229 if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
230 return -EFAULT;
231
232 /* Set up key which is located after the variable length text. */
233 size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1);
234 if (size < 0)
235 return size;
236 size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */
237
238 /* message header, cprbx and f&r */
239 msg->hdr = static_type6_hdrX;
240 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
241 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
242
243 msg->cprbx = static_cprbx;
244 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
245 msg->cprbx.req_parml = msg->cprbx.rpl_msgbl =
246 size - sizeof(msg->hdr) - sizeof(msg->cprbx);
247
248 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
249 static_pkd_fnr_MCL2 : static_pkd_fnr;
250
251 ap_msg->length = size;
252 return 0;
253}
254
255/**
Ralph Wuerthner54321142006-09-20 15:58:36 +0200256 * Convert a XCRB message to a type6 CPRB message.
257 *
258 * @zdev: crypto device pointer
259 * @ap_msg: pointer to AP message
260 * @xcRB: pointer to user input data
261 *
262 * Returns 0 on success or -EFAULT.
263 */
264struct type86_fmt2_msg {
265 struct type86_hdr hdr;
266 struct type86_fmt2_ext fmt2;
267} __attribute__((packed));
268
269static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
270 struct ap_message *ap_msg,
271 struct ica_xcRB *xcRB)
272{
273 static struct type6_hdr static_type6_hdrX = {
274 .type = 0x06,
275 .offset1 = 0x00000058,
276 };
277 struct {
278 struct type6_hdr hdr;
279 struct ica_CPRBX cprbx;
280 } __attribute__((packed)) *msg = ap_msg->message;
281
282 int rcblen = CEIL4(xcRB->request_control_blk_length);
283 int replylen;
284 char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
285 char *function_code;
286
287 /* length checks */
288 ap_msg->length = sizeof(struct type6_hdr) +
289 CEIL4(xcRB->request_control_blk_length) +
290 xcRB->request_data_length;
291 if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE) {
292 PRINTK("Combined message is too large (%ld/%d/%d).\n",
293 sizeof(struct type6_hdr),
294 xcRB->request_control_blk_length,
295 xcRB->request_data_length);
296 return -EFAULT;
297 }
298 if (CEIL4(xcRB->reply_control_blk_length) >
299 PCIXCC_MAX_XCRB_REPLY_SIZE) {
300 PDEBUG("Reply CPRB length is too large (%d).\n",
301 xcRB->request_control_blk_length);
302 return -EFAULT;
303 }
304 if (CEIL4(xcRB->reply_data_length) > PCIXCC_MAX_XCRB_DATA_SIZE) {
305 PDEBUG("Reply data block length is too large (%d).\n",
306 xcRB->reply_data_length);
307 return -EFAULT;
308 }
309 replylen = CEIL4(xcRB->reply_control_blk_length) +
310 CEIL4(xcRB->reply_data_length) +
311 sizeof(struct type86_fmt2_msg);
312 if (replylen > PCIXCC_MAX_XCRB_RESPONSE_SIZE) {
313 PDEBUG("Reply CPRB + data block > PCIXCC_MAX_XCRB_RESPONSE_SIZE"
314 " (%d/%d/%d).\n",
315 sizeof(struct type86_fmt2_msg),
316 xcRB->reply_control_blk_length,
317 xcRB->reply_data_length);
318 xcRB->reply_control_blk_length = PCIXCC_MAX_XCRB_RESPONSE_SIZE -
319 (sizeof(struct type86_fmt2_msg) +
320 CEIL4(xcRB->reply_data_length));
321 PDEBUG("Capping Reply CPRB length at %d\n",
322 xcRB->reply_control_blk_length);
323 }
324
325 /* prepare type6 header */
326 msg->hdr = static_type6_hdrX;
327 memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
328 msg->hdr.ToCardLen1 = xcRB->request_control_blk_length;
329 if (xcRB->request_data_length) {
330 msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
331 msg->hdr.ToCardLen2 = xcRB->request_data_length;
332 }
333 msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
334 msg->hdr.FromCardLen2 = xcRB->reply_data_length;
335
336 /* prepare CPRB */
337 if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
338 xcRB->request_control_blk_length))
339 return -EFAULT;
340 if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
341 xcRB->request_control_blk_length) {
342 PDEBUG("cprb_len too large (%d/%d)\n", msg->cprbx.cprb_len,
343 xcRB->request_control_blk_length);
344 return -EFAULT;
345 }
346 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
347 memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code));
348
349 /* copy data block */
350 if (xcRB->request_data_length &&
351 copy_from_user(req_data, xcRB->request_data_address,
352 xcRB->request_data_length))
353 return -EFAULT;
354 return 0;
355}
356
357/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200358 * Copy results from a type 86 ICA reply message back to user space.
359 *
360 * @zdev: crypto device pointer
361 * @reply: reply AP message.
362 * @data: pointer to user output data
363 * @length: size of user output data
364 *
365 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
366 */
367struct type86x_reply {
368 struct type86_hdr hdr;
369 struct type86_fmt2_ext fmt2;
370 struct CPRBX cprbx;
371 unsigned char pad[4]; /* 4 byte function code/rules block ? */
372 unsigned short length;
373 char text[0];
374} __attribute__((packed));
375
376static int convert_type86_ica(struct zcrypt_device *zdev,
377 struct ap_message *reply,
378 char __user *outputdata,
379 unsigned int outputdatalength)
380{
381 static unsigned char static_pad[] = {
382 0x00,0x02,
383 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,
384 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57,
385 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,
386 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39,
387 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,
388 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D,
389 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,
390 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F,
391 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,
392 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45,
393 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,
394 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F,
395 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,
396 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D,
397 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,
398 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9,
399 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,
400 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B,
401 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,
402 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD,
403 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,
404 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1,
405 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,
406 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23,
407 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,
408 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43,
409 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,
410 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F,
411 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,
412 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD,
413 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,
414 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09
415 };
416 struct type86x_reply *msg = reply->message;
417 unsigned short service_rc, service_rs;
418 unsigned int reply_len, pad_len;
419 char *data;
420
421 service_rc = msg->cprbx.ccp_rtcode;
422 if (unlikely(service_rc != 0)) {
423 service_rs = msg->cprbx.ccp_rscode;
424 if (service_rc == 8 && service_rs == 66) {
425 PDEBUG("Bad block format on PCIXCC/CEX2C\n");
426 return -EINVAL;
427 }
428 if (service_rc == 8 && service_rs == 65) {
429 PDEBUG("Probably an even modulus on PCIXCC/CEX2C\n");
430 return -EINVAL;
431 }
432 if (service_rc == 8 && service_rs == 770) {
433 PDEBUG("Invalid key length on PCIXCC/CEX2C\n");
434 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
435 return -EAGAIN;
436 }
437 if (service_rc == 8 && service_rs == 783) {
438 PDEBUG("Extended bitlengths not enabled on PCIXCC/CEX2C\n");
439 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
440 return -EAGAIN;
441 }
442 PRINTK("Unknown service rc/rs (PCIXCC/CEX2C): %d/%d\n",
443 service_rc, service_rs);
444 zdev->online = 0;
445 return -EAGAIN; /* repeat the request on a different device. */
446 }
447 data = msg->text;
448 reply_len = msg->length - 2;
449 if (reply_len > outputdatalength)
450 return -EINVAL;
451 /**
452 * For all encipher requests, the length of the ciphertext (reply_len)
453 * will always equal the modulus length. For MEX decipher requests
454 * the output needs to get padded. Minimum pad size is 10.
455 *
456 * Currently, the cases where padding will be added is for:
457 * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
458 * ZERO-PAD and CRT is only supported for PKD requests)
459 * - PCICC, always
460 */
461 pad_len = outputdatalength - reply_len;
462 if (pad_len > 0) {
463 if (pad_len < 10)
464 return -EINVAL;
465 /* 'restore' padding left in the PCICC/PCIXCC card. */
466 if (copy_to_user(outputdata, static_pad, pad_len - 1))
467 return -EFAULT;
468 if (put_user(0, outputdata + pad_len - 1))
469 return -EFAULT;
470 }
471 /* Copy the crypto response to user space. */
472 if (copy_to_user(outputdata + pad_len, data, reply_len))
473 return -EFAULT;
474 return 0;
475}
476
Ralph Wuerthner54321142006-09-20 15:58:36 +0200477/**
478 * Copy results from a type 86 XCRB reply message back to user space.
479 *
480 * @zdev: crypto device pointer
481 * @reply: reply AP message.
482 * @xcRB: pointer to XCRB
483 *
484 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
485 */
486static int convert_type86_xcrb(struct zcrypt_device *zdev,
487 struct ap_message *reply,
488 struct ica_xcRB *xcRB)
489{
490 struct type86_fmt2_msg *msg = reply->message;
491 char *data = reply->message;
492
493 /* Copy CPRB to user */
494 if (copy_to_user(xcRB->reply_control_blk_addr,
495 data + msg->fmt2.offset1, msg->fmt2.count1))
496 return -EFAULT;
497 xcRB->reply_control_blk_length = msg->fmt2.count1;
498
499 /* Copy data buffer to user */
500 if (msg->fmt2.count2)
501 if (copy_to_user(xcRB->reply_data_addr,
502 data + msg->fmt2.offset2, msg->fmt2.count2))
503 return -EFAULT;
504 xcRB->reply_data_length = msg->fmt2.count2;
505 return 0;
506}
507
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200508static int convert_response_ica(struct zcrypt_device *zdev,
509 struct ap_message *reply,
510 char __user *outputdata,
511 unsigned int outputdatalength)
512{
513 struct type86x_reply *msg = reply->message;
514
515 /* Response type byte is the second byte in the response. */
516 switch (((unsigned char *) reply->message)[1]) {
517 case TYPE82_RSP_CODE:
518 case TYPE88_RSP_CODE:
519 return convert_error(zdev, reply);
520 case TYPE86_RSP_CODE:
521 if (msg->hdr.reply_code)
522 return convert_error(zdev, reply);
523 if (msg->cprbx.cprb_ver_id == 0x02)
524 return convert_type86_ica(zdev, reply,
525 outputdata, outputdatalength);
526 /* no break, incorrect cprb version is an unknown response */
527 default: /* Unknown response type, this should NEVER EVER happen */
528 PRINTK("Unrecognized Message Header: %08x%08x\n",
529 *(unsigned int *) reply->message,
530 *(unsigned int *) (reply->message+4));
531 zdev->online = 0;
532 return -EAGAIN; /* repeat the request on a different device. */
533 }
534}
535
Ralph Wuerthner54321142006-09-20 15:58:36 +0200536static int convert_response_xcrb(struct zcrypt_device *zdev,
537 struct ap_message *reply,
538 struct ica_xcRB *xcRB)
539{
540 struct type86x_reply *msg = reply->message;
541
542 /* Response type byte is the second byte in the response. */
543 switch (((unsigned char *) reply->message)[1]) {
544 case TYPE82_RSP_CODE:
545 case TYPE88_RSP_CODE:
546 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
547 return convert_error(zdev, reply);
548 case TYPE86_RSP_CODE:
549 if (msg->hdr.reply_code) {
550 memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
551 return convert_error(zdev, reply);
552 }
553 if (msg->cprbx.cprb_ver_id == 0x02)
554 return convert_type86_xcrb(zdev, reply, xcRB);
555 /* no break, incorrect cprb version is an unknown response */
556 default: /* Unknown response type, this should NEVER EVER happen */
557 PRINTK("Unrecognized Message Header: %08x%08x\n",
558 *(unsigned int *) reply->message,
559 *(unsigned int *) (reply->message+4));
560 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
561 zdev->online = 0;
562 return -EAGAIN; /* repeat the request on a different device. */
563 }
564}
565
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200566/**
567 * This function is called from the AP bus code after a crypto request
568 * "msg" has finished with the reply message "reply".
569 * It is called from tasklet context.
570 * @ap_dev: pointer to the AP device
571 * @msg: pointer to the AP message
572 * @reply: pointer to the AP reply message
573 */
574static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
575 struct ap_message *msg,
576 struct ap_message *reply)
577{
578 static struct error_hdr error_reply = {
579 .type = TYPE82_RSP_CODE,
580 .reply_code = REP82_ERROR_MACHINE_FAILURE,
581 };
Ralph Wuerthner54321142006-09-20 15:58:36 +0200582 struct response_type *resp_type =
583 (struct response_type *) msg->private;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200584 struct type86x_reply *t86r = reply->message;
585 int length;
586
587 /* Copy the reply message to the request message buffer. */
588 if (IS_ERR(reply))
589 memcpy(msg->message, &error_reply, sizeof(error_reply));
590 else if (t86r->hdr.type == TYPE86_RSP_CODE &&
591 t86r->cprbx.cprb_ver_id == 0x02) {
Ralph Wuerthner54321142006-09-20 15:58:36 +0200592 switch (resp_type->type) {
593 case PCIXCC_RESPONSE_TYPE_ICA:
594 length = sizeof(struct type86x_reply)
595 + t86r->length - 2;
596 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
597 memcpy(msg->message, reply->message, length);
598 break;
599 case PCIXCC_RESPONSE_TYPE_XCRB:
600 length = t86r->fmt2.offset2 + t86r->fmt2.count2;
601 length = min(PCIXCC_MAX_XCRB_RESPONSE_SIZE, length);
602 memcpy(msg->message, reply->message, length);
603 break;
604 default:
605 PRINTK("Invalid internal response type: %i\n",
606 resp_type->type);
607 memcpy(msg->message, &error_reply,
608 sizeof error_reply);
609 }
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200610 } else
611 memcpy(msg->message, reply->message, sizeof error_reply);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200612 complete(&(resp_type->work));
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200613}
614
615static atomic_t zcrypt_step = ATOMIC_INIT(0);
616
617/**
618 * The request distributor calls this function if it picked the PCIXCC/CEX2C
619 * device to handle a modexpo request.
620 * @zdev: pointer to zcrypt_device structure that identifies the
621 * PCIXCC/CEX2C device to the request distributor
622 * @mex: pointer to the modexpo request buffer
623 */
624static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
625 struct ica_rsa_modexpo *mex)
626{
627 struct ap_message ap_msg;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200628 struct response_type resp_type = {
629 .type = PCIXCC_RESPONSE_TYPE_ICA,
630 };
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200631 int rc;
632
633 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
634 if (!ap_msg.message)
635 return -ENOMEM;
636 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
637 atomic_inc_return(&zcrypt_step);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200638 ap_msg.private = &resp_type;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200639 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
640 if (rc)
641 goto out_free;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200642 init_completion(&resp_type.work);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200643 ap_queue_message(zdev->ap_dev, &ap_msg);
644 rc = wait_for_completion_interruptible_timeout(
Ralph Wuerthner54321142006-09-20 15:58:36 +0200645 &resp_type.work, PCIXCC_CLEANUP_TIME);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200646 if (rc > 0)
647 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
648 mex->outputdatalength);
649 else {
650 /* Signal pending or message timed out. */
651 ap_cancel_message(zdev->ap_dev, &ap_msg);
652 if (rc == 0)
653 /* Message timed out. */
654 rc = -ETIME;
655 }
656out_free:
657 free_page((unsigned long) ap_msg.message);
658 return rc;
659}
660
661/**
662 * The request distributor calls this function if it picked the PCIXCC/CEX2C
663 * device to handle a modexpo_crt request.
664 * @zdev: pointer to zcrypt_device structure that identifies the
665 * PCIXCC/CEX2C device to the request distributor
666 * @crt: pointer to the modexpoc_crt request buffer
667 */
668static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
669 struct ica_rsa_modexpo_crt *crt)
670{
671 struct ap_message ap_msg;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200672 struct response_type resp_type = {
673 .type = PCIXCC_RESPONSE_TYPE_ICA,
674 };
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200675 int rc;
676
677 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
678 if (!ap_msg.message)
679 return -ENOMEM;
680 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
681 atomic_inc_return(&zcrypt_step);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200682 ap_msg.private = &resp_type;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200683 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
684 if (rc)
685 goto out_free;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200686 init_completion(&resp_type.work);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200687 ap_queue_message(zdev->ap_dev, &ap_msg);
688 rc = wait_for_completion_interruptible_timeout(
Ralph Wuerthner54321142006-09-20 15:58:36 +0200689 &resp_type.work, PCIXCC_CLEANUP_TIME);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200690 if (rc > 0)
691 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
692 crt->outputdatalength);
693 else {
694 /* Signal pending or message timed out. */
695 ap_cancel_message(zdev->ap_dev, &ap_msg);
696 if (rc == 0)
697 /* Message timed out. */
698 rc = -ETIME;
699 }
700out_free:
701 free_page((unsigned long) ap_msg.message);
702 return rc;
703}
704
705/**
Ralph Wuerthner54321142006-09-20 15:58:36 +0200706 * The request distributor calls this function if it picked the PCIXCC/CEX2C
707 * device to handle a send_cprb request.
708 * @zdev: pointer to zcrypt_device structure that identifies the
709 * PCIXCC/CEX2C device to the request distributor
710 * @xcRB: pointer to the send_cprb request buffer
711 */
712long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, struct ica_xcRB *xcRB)
713{
714 struct ap_message ap_msg;
715 struct response_type resp_type = {
716 .type = PCIXCC_RESPONSE_TYPE_XCRB,
717 };
718 int rc;
719
Robert P. J. Day5cbded52006-12-13 00:35:56 -0800720 ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200721 if (!ap_msg.message)
722 return -ENOMEM;
723 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
724 atomic_inc_return(&zcrypt_step);
725 ap_msg.private = &resp_type;
726 rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB);
727 if (rc)
728 goto out_free;
729 init_completion(&resp_type.work);
730 ap_queue_message(zdev->ap_dev, &ap_msg);
731 rc = wait_for_completion_interruptible_timeout(
732 &resp_type.work, PCIXCC_CLEANUP_TIME);
733 if (rc > 0)
734 rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
735 else {
736 /* Signal pending or message timed out. */
737 ap_cancel_message(zdev->ap_dev, &ap_msg);
738 if (rc == 0)
739 /* Message timed out. */
740 rc = -ETIME;
741 }
742out_free:
743 memset(ap_msg.message, 0x0, ap_msg.length);
744 kfree(ap_msg.message);
745 return rc;
746}
747
748/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200749 * The crypto operations for a PCIXCC/CEX2C card.
750 */
751static struct zcrypt_ops zcrypt_pcixcc_ops = {
752 .rsa_modexpo = zcrypt_pcixcc_modexpo,
753 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
Ralph Wuerthner54321142006-09-20 15:58:36 +0200754 .send_cprb = zcrypt_pcixcc_send_cprb,
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200755};
756
757/**
758 * Micro-code detection function. Its sends a message to a pcixcc card
759 * to find out the microcode level.
760 * @ap_dev: pointer to the AP device.
761 */
762static int zcrypt_pcixcc_mcl(struct ap_device *ap_dev)
763{
764 static unsigned char msg[] = {
765 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
766 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
767 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
768 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
769 0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
770 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
771 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00,
772 0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00,
773 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
774 0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00,
775 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
776 0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32,
777 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,
778 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,
779 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
780 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
781 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
782 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
783 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
784 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
785 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
786 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
787 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
788 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
789 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
790 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
791 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
792 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
793 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
794 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
795 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
796 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
797 0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
798 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
799 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
800 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
801 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
802 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
803 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x0A,
804 0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20,
805 0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05,
806 0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
807 0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55,
808 0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,
809 0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,
810 0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,
811 0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB,
812 0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54,
813 0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00,
814 0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00,
815 0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40,
816 0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C,
817 0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF,
818 0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9,
819 0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63,
820 0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5,
821 0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A,
822 0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01,
823 0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28,
824 0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91,
825 0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5,
826 0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C,
827 0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98,
828 0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96,
829 0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19,
830 0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47,
831 0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36,
832 0xF1,0x3D,0x93,0x53
833 };
834 unsigned long long psmid;
835 struct CPRBX *cprbx;
836 char *reply;
837 int rc, i;
838
839 reply = (void *) get_zeroed_page(GFP_KERNEL);
840 if (!reply)
841 return -ENOMEM;
842
843 rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, msg, sizeof(msg));
844 if (rc)
845 goto out_free;
846
847 /* Wait for the test message to complete. */
848 for (i = 0; i < 6; i++) {
849 mdelay(300);
850 rc = ap_recv(ap_dev->qid, &psmid, reply, 4096);
851 if (rc == 0 && psmid == 0x0102030405060708ULL)
852 break;
853 }
854
855 if (i >= 6) {
856 /* Got no answer. */
857 rc = -ENODEV;
858 goto out_free;
859 }
860
861 cprbx = (struct CPRBX *) (reply + 48);
862 if (cprbx->ccp_rtcode == 8 && cprbx->ccp_rscode == 33)
863 rc = ZCRYPT_PCIXCC_MCL2;
864 else
865 rc = ZCRYPT_PCIXCC_MCL3;
866out_free:
867 free_page((unsigned long) reply);
868 return rc;
869}
870
871/**
872 * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device
873 * since the bus_match already checked the hardware type. The PCIXCC
874 * cards come in two flavours: micro code level 2 and micro code level 3.
875 * This is checked by sending a test message to the device.
876 * @ap_dev: pointer to the AP device.
877 */
878static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
879{
880 struct zcrypt_device *zdev;
881 int rc;
882
883 zdev = zcrypt_device_alloc(PCIXCC_MAX_RESPONSE_SIZE);
884 if (!zdev)
885 return -ENOMEM;
886 zdev->ap_dev = ap_dev;
887 zdev->ops = &zcrypt_pcixcc_ops;
888 zdev->online = 1;
889 if (ap_dev->device_type == AP_DEVICE_TYPE_PCIXCC) {
890 rc = zcrypt_pcixcc_mcl(ap_dev);
891 if (rc < 0) {
892 zcrypt_device_free(zdev);
893 return rc;
894 }
895 zdev->user_space_type = rc;
896 if (rc == ZCRYPT_PCIXCC_MCL2) {
897 zdev->type_string = "PCIXCC_MCL2";
898 zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING;
899 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
900 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
901 } else {
902 zdev->type_string = "PCIXCC_MCL3";
903 zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING;
904 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
905 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
906 }
907 } else {
908 zdev->user_space_type = ZCRYPT_CEX2C;
909 zdev->type_string = "CEX2C";
910 zdev->speed_rating = CEX2C_SPEED_RATING;
911 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
912 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
913 }
914 ap_dev->reply = &zdev->reply;
915 ap_dev->private = zdev;
916 rc = zcrypt_device_register(zdev);
917 if (rc)
918 goto out_free;
919 return 0;
920
921 out_free:
922 ap_dev->private = NULL;
923 zcrypt_device_free(zdev);
924 return rc;
925}
926
927/**
928 * This is called to remove the extended PCIXCC/CEX2C driver information
929 * if an AP device is removed.
930 */
931static void zcrypt_pcixcc_remove(struct ap_device *ap_dev)
932{
933 struct zcrypt_device *zdev = ap_dev->private;
934
935 zcrypt_device_unregister(zdev);
936}
937
938int __init zcrypt_pcixcc_init(void)
939{
940 return ap_driver_register(&zcrypt_pcixcc_driver, THIS_MODULE, "pcixcc");
941}
942
943void zcrypt_pcixcc_exit(void)
944{
945 ap_driver_unregister(&zcrypt_pcixcc_driver);
946}
947
948#ifndef CONFIG_ZCRYPT_MONOLITHIC
949module_init(zcrypt_pcixcc_init);
950module_exit(zcrypt_pcixcc_exit);
951#endif