blob: cdaa401f20cd1a7ae866d8181c38e19392074e12 [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) },
Felix Beckffda4f72009-12-07 12:51:56 +010075 { AP_DEVICE(AP_DEVICE_TYPE_CEX3C) },
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;
Felix Beck1a89dd82008-07-14 09:59:27 +0200293 if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE)
Ralph Wuerthner54321142006-09-20 15:58:36 +0200294 return -EFAULT;
Felix Beck1a89dd82008-07-14 09:59:27 +0200295 if (CEIL4(xcRB->reply_control_blk_length) > PCIXCC_MAX_XCRB_REPLY_SIZE)
Ralph Wuerthner54321142006-09-20 15:58:36 +0200296 return -EFAULT;
Felix Beck1a89dd82008-07-14 09:59:27 +0200297 if (CEIL4(xcRB->reply_data_length) > PCIXCC_MAX_XCRB_DATA_SIZE)
Ralph Wuerthner54321142006-09-20 15:58:36 +0200298 return -EFAULT;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200299 replylen = CEIL4(xcRB->reply_control_blk_length) +
300 CEIL4(xcRB->reply_data_length) +
301 sizeof(struct type86_fmt2_msg);
302 if (replylen > PCIXCC_MAX_XCRB_RESPONSE_SIZE) {
Ralph Wuerthner54321142006-09-20 15:58:36 +0200303 xcRB->reply_control_blk_length = PCIXCC_MAX_XCRB_RESPONSE_SIZE -
304 (sizeof(struct type86_fmt2_msg) +
305 CEIL4(xcRB->reply_data_length));
Ralph Wuerthner54321142006-09-20 15:58:36 +0200306 }
307
308 /* prepare type6 header */
309 msg->hdr = static_type6_hdrX;
310 memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
311 msg->hdr.ToCardLen1 = xcRB->request_control_blk_length;
312 if (xcRB->request_data_length) {
313 msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
314 msg->hdr.ToCardLen2 = xcRB->request_data_length;
315 }
316 msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
317 msg->hdr.FromCardLen2 = xcRB->reply_data_length;
318
319 /* prepare CPRB */
320 if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
321 xcRB->request_control_blk_length))
322 return -EFAULT;
323 if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
Felix Beck1a89dd82008-07-14 09:59:27 +0200324 xcRB->request_control_blk_length)
Ralph Wuerthner54321142006-09-20 15:58:36 +0200325 return -EFAULT;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200326 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
327 memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code));
328
Felix Becka6a5d732009-12-07 12:51:55 +0100329 if (memcmp(function_code, "US", 2) == 0)
330 ap_msg->special = 1;
331 else
332 ap_msg->special = 0;
333
Ralph Wuerthner54321142006-09-20 15:58:36 +0200334 /* copy data block */
335 if (xcRB->request_data_length &&
336 copy_from_user(req_data, xcRB->request_data_address,
337 xcRB->request_data_length))
338 return -EFAULT;
339 return 0;
340}
341
342/**
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200343 * Prepare a type6 CPRB message for random number generation
344 *
345 * @ap_dev: AP device pointer
346 * @ap_msg: pointer to AP message
347 */
348static void rng_type6CPRB_msgX(struct ap_device *ap_dev,
349 struct ap_message *ap_msg,
350 unsigned random_number_length)
351{
352 struct {
353 struct type6_hdr hdr;
354 struct CPRBX cprbx;
355 char function_code[2];
356 short int rule_length;
357 char rule[8];
358 short int verb_length;
359 short int key_length;
360 } __attribute__((packed)) *msg = ap_msg->message;
361 static struct type6_hdr static_type6_hdrX = {
362 .type = 0x06,
363 .offset1 = 0x00000058,
364 .agent_id = {'C', 'A'},
365 .function_code = {'R', 'L'},
366 .ToCardLen1 = sizeof *msg - sizeof(msg->hdr),
367 .FromCardLen1 = sizeof *msg - sizeof(msg->hdr),
368 };
Felix Beck6458abc2009-10-06 10:34:09 +0200369 static struct CPRBX local_cprbx = {
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200370 .cprb_len = 0x00dc,
371 .cprb_ver_id = 0x02,
372 .func_id = {0x54, 0x32},
373 .req_parml = sizeof *msg - sizeof(msg->hdr) -
374 sizeof(msg->cprbx),
375 .rpl_msgbl = sizeof *msg - sizeof(msg->hdr),
376 };
377
378 msg->hdr = static_type6_hdrX;
379 msg->hdr.FromCardLen2 = random_number_length,
Felix Beck6458abc2009-10-06 10:34:09 +0200380 msg->cprbx = local_cprbx;
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200381 msg->cprbx.rpl_datal = random_number_length,
382 msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid);
383 memcpy(msg->function_code, msg->hdr.function_code, 0x02);
384 msg->rule_length = 0x0a;
385 memcpy(msg->rule, "RANDOM ", 8);
386 msg->verb_length = 0x02;
387 msg->key_length = 0x02;
388 ap_msg->length = sizeof *msg;
389}
390
391/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200392 * Copy results from a type 86 ICA reply message back to user space.
393 *
394 * @zdev: crypto device pointer
395 * @reply: reply AP message.
396 * @data: pointer to user output data
397 * @length: size of user output data
398 *
399 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
400 */
401struct type86x_reply {
402 struct type86_hdr hdr;
403 struct type86_fmt2_ext fmt2;
404 struct CPRBX cprbx;
405 unsigned char pad[4]; /* 4 byte function code/rules block ? */
406 unsigned short length;
407 char text[0];
408} __attribute__((packed));
409
410static int convert_type86_ica(struct zcrypt_device *zdev,
411 struct ap_message *reply,
412 char __user *outputdata,
413 unsigned int outputdatalength)
414{
415 static unsigned char static_pad[] = {
416 0x00,0x02,
417 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,
418 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57,
419 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,
420 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39,
421 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,
422 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D,
423 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,
424 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F,
425 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,
426 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45,
427 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,
428 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F,
429 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,
430 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D,
431 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,
432 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9,
433 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,
434 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B,
435 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,
436 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD,
437 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,
438 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1,
439 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,
440 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23,
441 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,
442 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43,
443 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,
444 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F,
445 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,
446 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD,
447 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,
448 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09
449 };
450 struct type86x_reply *msg = reply->message;
451 unsigned short service_rc, service_rs;
452 unsigned int reply_len, pad_len;
453 char *data;
454
455 service_rc = msg->cprbx.ccp_rtcode;
456 if (unlikely(service_rc != 0)) {
457 service_rs = msg->cprbx.ccp_rscode;
Felix Beck1a89dd82008-07-14 09:59:27 +0200458 if (service_rc == 8 && service_rs == 66)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200459 return -EINVAL;
Felix Beck1a89dd82008-07-14 09:59:27 +0200460 if (service_rc == 8 && service_rs == 65)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200461 return -EINVAL;
Felix Beck1a89dd82008-07-14 09:59:27 +0200462 if (service_rc == 8 && service_rs == 770)
Ralph Wuerthner2af48082007-10-12 16:11:30 +0200463 return -EINVAL;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200464 if (service_rc == 8 && service_rs == 783) {
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200465 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
466 return -EAGAIN;
467 }
Felix Beck1a89dd82008-07-14 09:59:27 +0200468 if (service_rc == 12 && service_rs == 769)
Ralph Wuerthner2af48082007-10-12 16:11:30 +0200469 return -EINVAL;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200470 zdev->online = 0;
471 return -EAGAIN; /* repeat the request on a different device. */
472 }
473 data = msg->text;
474 reply_len = msg->length - 2;
475 if (reply_len > outputdatalength)
476 return -EINVAL;
Felix Beck1749a812008-04-17 07:46:28 +0200477 /*
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200478 * For all encipher requests, the length of the ciphertext (reply_len)
479 * will always equal the modulus length. For MEX decipher requests
480 * the output needs to get padded. Minimum pad size is 10.
481 *
482 * Currently, the cases where padding will be added is for:
483 * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
484 * ZERO-PAD and CRT is only supported for PKD requests)
485 * - PCICC, always
486 */
487 pad_len = outputdatalength - reply_len;
488 if (pad_len > 0) {
489 if (pad_len < 10)
490 return -EINVAL;
491 /* 'restore' padding left in the PCICC/PCIXCC card. */
492 if (copy_to_user(outputdata, static_pad, pad_len - 1))
493 return -EFAULT;
494 if (put_user(0, outputdata + pad_len - 1))
495 return -EFAULT;
496 }
497 /* Copy the crypto response to user space. */
498 if (copy_to_user(outputdata + pad_len, data, reply_len))
499 return -EFAULT;
500 return 0;
501}
502
Ralph Wuerthner54321142006-09-20 15:58:36 +0200503/**
504 * Copy results from a type 86 XCRB reply message back to user space.
505 *
506 * @zdev: crypto device pointer
507 * @reply: reply AP message.
508 * @xcRB: pointer to XCRB
509 *
510 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
511 */
512static int convert_type86_xcrb(struct zcrypt_device *zdev,
513 struct ap_message *reply,
514 struct ica_xcRB *xcRB)
515{
516 struct type86_fmt2_msg *msg = reply->message;
517 char *data = reply->message;
518
519 /* Copy CPRB to user */
520 if (copy_to_user(xcRB->reply_control_blk_addr,
521 data + msg->fmt2.offset1, msg->fmt2.count1))
522 return -EFAULT;
523 xcRB->reply_control_blk_length = msg->fmt2.count1;
524
525 /* Copy data buffer to user */
526 if (msg->fmt2.count2)
527 if (copy_to_user(xcRB->reply_data_addr,
528 data + msg->fmt2.offset2, msg->fmt2.count2))
529 return -EFAULT;
530 xcRB->reply_data_length = msg->fmt2.count2;
531 return 0;
532}
533
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200534static int convert_type86_rng(struct zcrypt_device *zdev,
535 struct ap_message *reply,
536 char *buffer)
537{
538 struct {
539 struct type86_hdr hdr;
540 struct type86_fmt2_ext fmt2;
541 struct CPRBX cprbx;
542 } __attribute__((packed)) *msg = reply->message;
543 char *data = reply->message;
544
Felix Beck1a89dd82008-07-14 09:59:27 +0200545 if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0)
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200546 return -EINVAL;
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200547 memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
548 return msg->fmt2.count2;
549}
550
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200551static int convert_response_ica(struct zcrypt_device *zdev,
552 struct ap_message *reply,
553 char __user *outputdata,
554 unsigned int outputdatalength)
555{
556 struct type86x_reply *msg = reply->message;
557
558 /* Response type byte is the second byte in the response. */
559 switch (((unsigned char *) reply->message)[1]) {
560 case TYPE82_RSP_CODE:
561 case TYPE88_RSP_CODE:
562 return convert_error(zdev, reply);
563 case TYPE86_RSP_CODE:
564 if (msg->hdr.reply_code)
565 return convert_error(zdev, reply);
566 if (msg->cprbx.cprb_ver_id == 0x02)
567 return convert_type86_ica(zdev, reply,
568 outputdata, outputdatalength);
Felix Beck942b7e62009-10-06 10:34:10 +0200569 /* Fall through, no break, incorrect cprb version is an unknown
570 * response */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200571 default: /* Unknown response type, this should NEVER EVER happen */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200572 zdev->online = 0;
573 return -EAGAIN; /* repeat the request on a different device. */
574 }
575}
576
Ralph Wuerthner54321142006-09-20 15:58:36 +0200577static int convert_response_xcrb(struct zcrypt_device *zdev,
578 struct ap_message *reply,
579 struct ica_xcRB *xcRB)
580{
581 struct type86x_reply *msg = reply->message;
582
583 /* Response type byte is the second byte in the response. */
584 switch (((unsigned char *) reply->message)[1]) {
585 case TYPE82_RSP_CODE:
586 case TYPE88_RSP_CODE:
587 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
588 return convert_error(zdev, reply);
589 case TYPE86_RSP_CODE:
590 if (msg->hdr.reply_code) {
591 memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
592 return convert_error(zdev, reply);
593 }
594 if (msg->cprbx.cprb_ver_id == 0x02)
595 return convert_type86_xcrb(zdev, reply, xcRB);
Felix Beck942b7e62009-10-06 10:34:10 +0200596 /* Fall through, no break, incorrect cprb version is an unknown
597 * response */
Ralph Wuerthner54321142006-09-20 15:58:36 +0200598 default: /* Unknown response type, this should NEVER EVER happen */
Ralph Wuerthner54321142006-09-20 15:58:36 +0200599 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
600 zdev->online = 0;
601 return -EAGAIN; /* repeat the request on a different device. */
602 }
603}
604
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200605static int convert_response_rng(struct zcrypt_device *zdev,
606 struct ap_message *reply,
607 char *data)
608{
609 struct type86x_reply *msg = reply->message;
610
611 switch (msg->hdr.type) {
612 case TYPE82_RSP_CODE:
613 case TYPE88_RSP_CODE:
614 return -EINVAL;
615 case TYPE86_RSP_CODE:
616 if (msg->hdr.reply_code)
617 return -EINVAL;
618 if (msg->cprbx.cprb_ver_id == 0x02)
619 return convert_type86_rng(zdev, reply, data);
Felix Beck942b7e62009-10-06 10:34:10 +0200620 /* Fall through, no break, incorrect cprb version is an unknown
621 * response */
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200622 default: /* Unknown response type, this should NEVER EVER happen */
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200623 zdev->online = 0;
624 return -EAGAIN; /* repeat the request on a different device. */
625 }
626}
627
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200628/**
629 * This function is called from the AP bus code after a crypto request
630 * "msg" has finished with the reply message "reply".
631 * It is called from tasklet context.
632 * @ap_dev: pointer to the AP device
633 * @msg: pointer to the AP message
634 * @reply: pointer to the AP reply message
635 */
636static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
637 struct ap_message *msg,
638 struct ap_message *reply)
639{
640 static struct error_hdr error_reply = {
641 .type = TYPE82_RSP_CODE,
642 .reply_code = REP82_ERROR_MACHINE_FAILURE,
643 };
Ralph Wuerthner54321142006-09-20 15:58:36 +0200644 struct response_type *resp_type =
645 (struct response_type *) msg->private;
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100646 struct type86x_reply *t86r;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200647 int length;
648
649 /* Copy the reply message to the request message buffer. */
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100650 if (IS_ERR(reply)) {
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200651 memcpy(msg->message, &error_reply, sizeof(error_reply));
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100652 goto out;
653 }
654 t86r = reply->message;
655 if (t86r->hdr.type == TYPE86_RSP_CODE &&
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200656 t86r->cprbx.cprb_ver_id == 0x02) {
Ralph Wuerthner54321142006-09-20 15:58:36 +0200657 switch (resp_type->type) {
658 case PCIXCC_RESPONSE_TYPE_ICA:
659 length = sizeof(struct type86x_reply)
660 + t86r->length - 2;
661 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
662 memcpy(msg->message, reply->message, length);
663 break;
664 case PCIXCC_RESPONSE_TYPE_XCRB:
665 length = t86r->fmt2.offset2 + t86r->fmt2.count2;
666 length = min(PCIXCC_MAX_XCRB_RESPONSE_SIZE, length);
667 memcpy(msg->message, reply->message, length);
668 break;
669 default:
Felix Beck1a89dd82008-07-14 09:59:27 +0200670 memcpy(msg->message, &error_reply, sizeof error_reply);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200671 }
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200672 } else
673 memcpy(msg->message, reply->message, sizeof error_reply);
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100674out:
Ralph Wuerthner54321142006-09-20 15:58:36 +0200675 complete(&(resp_type->work));
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200676}
677
678static atomic_t zcrypt_step = ATOMIC_INIT(0);
679
680/**
681 * The request distributor calls this function if it picked the PCIXCC/CEX2C
682 * device to handle a modexpo request.
683 * @zdev: pointer to zcrypt_device structure that identifies the
684 * PCIXCC/CEX2C device to the request distributor
685 * @mex: pointer to the modexpo request buffer
686 */
687static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
688 struct ica_rsa_modexpo *mex)
689{
690 struct ap_message ap_msg;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200691 struct response_type resp_type = {
692 .type = PCIXCC_RESPONSE_TYPE_ICA,
693 };
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200694 int rc;
695
Felix Beck468ffdd2009-12-07 12:51:54 +0100696 ap_init_message(&ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200697 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
698 if (!ap_msg.message)
699 return -ENOMEM;
700 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
701 atomic_inc_return(&zcrypt_step);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200702 ap_msg.private = &resp_type;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200703 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
704 if (rc)
705 goto out_free;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200706 init_completion(&resp_type.work);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200707 ap_queue_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200708 rc = wait_for_completion_interruptible(&resp_type.work);
709 if (rc == 0)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200710 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
711 mex->outputdatalength);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200712 else
713 /* Signal pending. */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200714 ap_cancel_message(zdev->ap_dev, &ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200715out_free:
716 free_page((unsigned long) ap_msg.message);
717 return rc;
718}
719
720/**
721 * The request distributor calls this function if it picked the PCIXCC/CEX2C
722 * device to handle a modexpo_crt request.
723 * @zdev: pointer to zcrypt_device structure that identifies the
724 * PCIXCC/CEX2C device to the request distributor
725 * @crt: pointer to the modexpoc_crt request buffer
726 */
727static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
728 struct ica_rsa_modexpo_crt *crt)
729{
730 struct ap_message ap_msg;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200731 struct response_type resp_type = {
732 .type = PCIXCC_RESPONSE_TYPE_ICA,
733 };
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200734 int rc;
735
Felix Beck468ffdd2009-12-07 12:51:54 +0100736 ap_init_message(&ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200737 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
738 if (!ap_msg.message)
739 return -ENOMEM;
740 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
741 atomic_inc_return(&zcrypt_step);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200742 ap_msg.private = &resp_type;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200743 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
744 if (rc)
745 goto out_free;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200746 init_completion(&resp_type.work);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200747 ap_queue_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200748 rc = wait_for_completion_interruptible(&resp_type.work);
749 if (rc == 0)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200750 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
751 crt->outputdatalength);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200752 else
753 /* Signal pending. */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200754 ap_cancel_message(zdev->ap_dev, &ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200755out_free:
756 free_page((unsigned long) ap_msg.message);
757 return rc;
758}
759
760/**
Ralph Wuerthner54321142006-09-20 15:58:36 +0200761 * The request distributor calls this function if it picked the PCIXCC/CEX2C
762 * device to handle a send_cprb request.
763 * @zdev: pointer to zcrypt_device structure that identifies the
764 * PCIXCC/CEX2C device to the request distributor
765 * @xcRB: pointer to the send_cprb request buffer
766 */
Heiko Carstens2b67fc42007-02-05 21:16:47 +0100767static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
768 struct ica_xcRB *xcRB)
Ralph Wuerthner54321142006-09-20 15:58:36 +0200769{
770 struct ap_message ap_msg;
771 struct response_type resp_type = {
772 .type = PCIXCC_RESPONSE_TYPE_XCRB,
773 };
774 int rc;
775
Felix Beck468ffdd2009-12-07 12:51:54 +0100776 ap_init_message(&ap_msg);
Robert P. J. Day5cbded52006-12-13 00:35:56 -0800777 ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200778 if (!ap_msg.message)
779 return -ENOMEM;
780 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
781 atomic_inc_return(&zcrypt_step);
782 ap_msg.private = &resp_type;
783 rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB);
784 if (rc)
785 goto out_free;
786 init_completion(&resp_type.work);
787 ap_queue_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200788 rc = wait_for_completion_interruptible(&resp_type.work);
789 if (rc == 0)
Ralph Wuerthner54321142006-09-20 15:58:36 +0200790 rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200791 else
792 /* Signal pending. */
Ralph Wuerthner54321142006-09-20 15:58:36 +0200793 ap_cancel_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200794out_free:
Johannes Weiner3e75a902009-03-26 15:24:48 +0100795 kzfree(ap_msg.message);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200796 return rc;
797}
798
799/**
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200800 * The request distributor calls this function if it picked the PCIXCC/CEX2C
801 * device to generate random data.
802 * @zdev: pointer to zcrypt_device structure that identifies the
803 * PCIXCC/CEX2C device to the request distributor
804 * @buffer: pointer to a memory page to return random data
805 */
806
807static long zcrypt_pcixcc_rng(struct zcrypt_device *zdev,
808 char *buffer)
809{
810 struct ap_message ap_msg;
811 struct response_type resp_type = {
812 .type = PCIXCC_RESPONSE_TYPE_XCRB,
813 };
814 int rc;
815
Felix Beck468ffdd2009-12-07 12:51:54 +0100816 ap_init_message(&ap_msg);
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200817 ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
818 if (!ap_msg.message)
819 return -ENOMEM;
820 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
821 atomic_inc_return(&zcrypt_step);
822 ap_msg.private = &resp_type;
823 rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE);
824 init_completion(&resp_type.work);
825 ap_queue_message(zdev->ap_dev, &ap_msg);
826 rc = wait_for_completion_interruptible(&resp_type.work);
827 if (rc == 0)
828 rc = convert_response_rng(zdev, &ap_msg, buffer);
829 else
830 /* Signal pending. */
831 ap_cancel_message(zdev->ap_dev, &ap_msg);
832 kfree(ap_msg.message);
833 return rc;
834}
835
836/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200837 * The crypto operations for a PCIXCC/CEX2C card.
838 */
839static struct zcrypt_ops zcrypt_pcixcc_ops = {
840 .rsa_modexpo = zcrypt_pcixcc_modexpo,
841 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
Ralph Wuerthner54321142006-09-20 15:58:36 +0200842 .send_cprb = zcrypt_pcixcc_send_cprb,
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200843};
844
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200845static struct zcrypt_ops zcrypt_pcixcc_with_rng_ops = {
846 .rsa_modexpo = zcrypt_pcixcc_modexpo,
847 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
848 .send_cprb = zcrypt_pcixcc_send_cprb,
849 .rng = zcrypt_pcixcc_rng,
850};
851
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200852/**
853 * Micro-code detection function. Its sends a message to a pcixcc card
854 * to find out the microcode level.
855 * @ap_dev: pointer to the AP device.
856 */
857static int zcrypt_pcixcc_mcl(struct ap_device *ap_dev)
858{
859 static unsigned char msg[] = {
860 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
861 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
862 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
863 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
864 0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
865 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
866 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00,
867 0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00,
868 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
869 0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00,
870 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
871 0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32,
872 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,
873 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,
874 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
875 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
876 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
877 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
878 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
879 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
880 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
881 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
882 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
883 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
884 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
885 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
886 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
887 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
888 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
889 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
890 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
891 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
892 0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
893 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
894 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
895 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
896 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
897 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
898 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x0A,
899 0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20,
900 0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05,
901 0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
902 0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55,
903 0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,
904 0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,
905 0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,
906 0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB,
907 0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54,
908 0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00,
909 0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00,
910 0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40,
911 0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C,
912 0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF,
913 0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9,
914 0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63,
915 0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5,
916 0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A,
917 0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01,
918 0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28,
919 0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91,
920 0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5,
921 0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C,
922 0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98,
923 0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96,
924 0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19,
925 0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47,
926 0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36,
927 0xF1,0x3D,0x93,0x53
928 };
929 unsigned long long psmid;
930 struct CPRBX *cprbx;
931 char *reply;
932 int rc, i;
933
934 reply = (void *) get_zeroed_page(GFP_KERNEL);
935 if (!reply)
936 return -ENOMEM;
937
938 rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, msg, sizeof(msg));
939 if (rc)
940 goto out_free;
941
942 /* Wait for the test message to complete. */
943 for (i = 0; i < 6; i++) {
944 mdelay(300);
945 rc = ap_recv(ap_dev->qid, &psmid, reply, 4096);
946 if (rc == 0 && psmid == 0x0102030405060708ULL)
947 break;
948 }
949
950 if (i >= 6) {
951 /* Got no answer. */
952 rc = -ENODEV;
953 goto out_free;
954 }
955
956 cprbx = (struct CPRBX *) (reply + 48);
957 if (cprbx->ccp_rtcode == 8 && cprbx->ccp_rscode == 33)
958 rc = ZCRYPT_PCIXCC_MCL2;
959 else
960 rc = ZCRYPT_PCIXCC_MCL3;
961out_free:
962 free_page((unsigned long) reply);
963 return rc;
964}
965
966/**
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200967 * Large random number detection function. Its sends a message to a pcixcc
968 * card to find out if large random numbers are supported.
969 * @ap_dev: pointer to the AP device.
970 *
971 * Returns 1 if large random numbers are supported, 0 if not and < 0 on error.
972 */
973static int zcrypt_pcixcc_rng_supported(struct ap_device *ap_dev)
974{
975 struct ap_message ap_msg;
976 unsigned long long psmid;
977 struct {
978 struct type86_hdr hdr;
979 struct type86_fmt2_ext fmt2;
980 struct CPRBX cprbx;
981 } __attribute__((packed)) *reply;
982 int rc, i;
983
Felix Beck468ffdd2009-12-07 12:51:54 +0100984 ap_init_message(&ap_msg);
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200985 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
986 if (!ap_msg.message)
987 return -ENOMEM;
988
989 rng_type6CPRB_msgX(ap_dev, &ap_msg, 4);
990 rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, ap_msg.message,
991 ap_msg.length);
992 if (rc)
993 goto out_free;
994
995 /* Wait for the test message to complete. */
996 for (i = 0; i < 2 * HZ; i++) {
997 msleep(1000 / HZ);
998 rc = ap_recv(ap_dev->qid, &psmid, ap_msg.message, 4096);
999 if (rc == 0 && psmid == 0x0102030405060708ULL)
1000 break;
1001 }
1002
1003 if (i >= 2 * HZ) {
1004 /* Got no answer. */
1005 rc = -ENODEV;
1006 goto out_free;
1007 }
1008
1009 reply = ap_msg.message;
1010 if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0)
1011 rc = 1;
1012 else
1013 rc = 0;
1014out_free:
1015 free_page((unsigned long) ap_msg.message);
1016 return rc;
1017}
1018
1019/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001020 * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device
1021 * since the bus_match already checked the hardware type. The PCIXCC
1022 * cards come in two flavours: micro code level 2 and micro code level 3.
1023 * This is checked by sending a test message to the device.
1024 * @ap_dev: pointer to the AP device.
1025 */
1026static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
1027{
1028 struct zcrypt_device *zdev;
1029 int rc;
1030
1031 zdev = zcrypt_device_alloc(PCIXCC_MAX_RESPONSE_SIZE);
1032 if (!zdev)
1033 return -ENOMEM;
1034 zdev->ap_dev = ap_dev;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001035 zdev->online = 1;
1036 if (ap_dev->device_type == AP_DEVICE_TYPE_PCIXCC) {
1037 rc = zcrypt_pcixcc_mcl(ap_dev);
1038 if (rc < 0) {
1039 zcrypt_device_free(zdev);
1040 return rc;
1041 }
1042 zdev->user_space_type = rc;
1043 if (rc == ZCRYPT_PCIXCC_MCL2) {
1044 zdev->type_string = "PCIXCC_MCL2";
1045 zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING;
1046 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
1047 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
1048 } else {
1049 zdev->type_string = "PCIXCC_MCL3";
1050 zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING;
1051 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
1052 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
1053 }
1054 } else {
1055 zdev->user_space_type = ZCRYPT_CEX2C;
1056 zdev->type_string = "CEX2C";
1057 zdev->speed_rating = CEX2C_SPEED_RATING;
1058 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
1059 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
1060 }
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +02001061 rc = zcrypt_pcixcc_rng_supported(ap_dev);
1062 if (rc < 0) {
1063 zcrypt_device_free(zdev);
1064 return rc;
1065 }
1066 if (rc)
1067 zdev->ops = &zcrypt_pcixcc_with_rng_ops;
1068 else
1069 zdev->ops = &zcrypt_pcixcc_ops;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001070 ap_dev->reply = &zdev->reply;
1071 ap_dev->private = zdev;
1072 rc = zcrypt_device_register(zdev);
1073 if (rc)
1074 goto out_free;
1075 return 0;
1076
1077 out_free:
1078 ap_dev->private = NULL;
1079 zcrypt_device_free(zdev);
1080 return rc;
1081}
1082
1083/**
1084 * This is called to remove the extended PCIXCC/CEX2C driver information
1085 * if an AP device is removed.
1086 */
1087static void zcrypt_pcixcc_remove(struct ap_device *ap_dev)
1088{
1089 struct zcrypt_device *zdev = ap_dev->private;
1090
1091 zcrypt_device_unregister(zdev);
1092}
1093
1094int __init zcrypt_pcixcc_init(void)
1095{
1096 return ap_driver_register(&zcrypt_pcixcc_driver, THIS_MODULE, "pcixcc");
1097}
1098
1099void zcrypt_pcixcc_exit(void)
1100{
1101 ap_driver_unregister(&zcrypt_pcixcc_driver);
1102}
1103
1104#ifndef CONFIG_ZCRYPT_MONOLITHIC
1105module_init(zcrypt_pcixcc_init);
1106module_exit(zcrypt_pcixcc_exit);
1107#endif