blob: ccb4f8b60c750f9e7b636c4c5e5f900d523b6321 [file] [log] [blame]
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001/*
Ralph Wuerthner54321142006-09-20 15:58:36 +02002 * zcrypt 2.1.0
Martin Schwidefsky6684af12006-09-20 15:58:32 +02003 *
Heiko Carstensa53c8fa2012-07-20 11:15:04 +02004 * Copyright IBM Corp. 2001, 2006
Martin Schwidefsky6684af12006-09-20 15:58:32 +02005 * Author(s): Robert Burroughs
6 * Eric Rossman (edrossma@us.ibm.com)
7 *
8 * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
9 * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
10 * Ralph Wuerthner <rwuerthn@de.ibm.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
15 * any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27#include <linux/module.h>
28#include <linux/init.h>
29#include <linux/err.h>
30#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090031#include <linux/slab.h>
Arun Sharma600634972011-07-26 16:09:06 -070032#include <linux/atomic.h>
Martin Schwidefsky6684af12006-09-20 15:58:32 +020033#include <asm/uaccess.h>
34
35#include "ap_bus.h"
36#include "zcrypt_api.h"
37#include "zcrypt_error.h"
38#include "zcrypt_pcicc.h"
39#include "zcrypt_pcixcc.h"
40#include "zcrypt_cca_key.h"
41
42#define PCIXCC_MIN_MOD_SIZE 16 /* 128 bits */
43#define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */
44#define PCIXCC_MAX_MOD_SIZE 256 /* 2048 bits */
Felix Beck8e89b6b2009-12-07 12:51:57 +010045#define CEX3C_MIN_MOD_SIZE PCIXCC_MIN_MOD_SIZE
Felix Beck2ade1fa2011-01-05 12:47:46 +010046#define CEX3C_MAX_MOD_SIZE 512 /* 4096 bits */
Martin Schwidefsky6684af12006-09-20 15:58:32 +020047
Felix Beck18278df2009-12-07 12:51:58 +010048#define PCIXCC_MCL2_SPEED_RATING 7870
Martin Schwidefsky6684af12006-09-20 15:58:32 +020049#define PCIXCC_MCL3_SPEED_RATING 7870
Felix Beck18278df2009-12-07 12:51:58 +010050#define CEX2C_SPEED_RATING 7000
Felix Beck2ade1fa2011-01-05 12:47:46 +010051#define CEX3C_SPEED_RATING 6500
Martin Schwidefsky6684af12006-09-20 15:58:32 +020052
53#define PCIXCC_MAX_ICA_MESSAGE_SIZE 0x77c /* max size type6 v2 crt message */
54#define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */
55
56#define PCIXCC_MAX_XCRB_MESSAGE_SIZE (12*1024)
Martin Schwidefsky6684af12006-09-20 15:58:32 +020057
58#define PCIXCC_CLEANUP_TIME (15*HZ)
59
Ralph Wuerthner54321142006-09-20 15:58:36 +020060#define CEIL4(x) ((((x)+3)/4)*4)
61
62struct response_type {
63 struct completion work;
64 int type;
65};
66#define PCIXCC_RESPONSE_TYPE_ICA 0
67#define PCIXCC_RESPONSE_TYPE_XCRB 1
68
Martin Schwidefsky6684af12006-09-20 15:58:32 +020069static struct ap_device_id zcrypt_pcixcc_ids[] = {
70 { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) },
71 { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) },
Felix Beckffda4f72009-12-07 12:51:56 +010072 { AP_DEVICE(AP_DEVICE_TYPE_CEX3C) },
Martin Schwidefsky6684af12006-09-20 15:58:32 +020073 { /* end of list */ },
74};
75
Martin Schwidefsky6684af12006-09-20 15:58:32 +020076MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids);
77MODULE_AUTHOR("IBM Corporation");
78MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, "
Heiko Carstensa53c8fa2012-07-20 11:15:04 +020079 "Copyright IBM Corp. 2001, 2006");
Martin Schwidefsky6684af12006-09-20 15:58:32 +020080MODULE_LICENSE("GPL");
Martin Schwidefsky6684af12006-09-20 15:58:32 +020081
82static int zcrypt_pcixcc_probe(struct ap_device *ap_dev);
83static void zcrypt_pcixcc_remove(struct ap_device *ap_dev);
84static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *,
85 struct ap_message *);
86
87static struct ap_driver zcrypt_pcixcc_driver = {
88 .probe = zcrypt_pcixcc_probe,
89 .remove = zcrypt_pcixcc_remove,
Martin Schwidefsky6684af12006-09-20 15:58:32 +020090 .ids = zcrypt_pcixcc_ids,
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +020091 .request_timeout = PCIXCC_CLEANUP_TIME,
Martin Schwidefsky6684af12006-09-20 15:58:32 +020092};
93
94/**
95 * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C
96 * card in a type6 message. The 3 fields that must be filled in at execution
97 * time are req_parml, rpl_parml and usage_domain.
98 * Everything about this interface is ascii/big-endian, since the
99 * device does *not* have 'Intel inside'.
100 *
101 * The CPRBX is followed immediately by the parm block.
102 * The parm block contains:
103 * - function code ('PD' 0x5044 or 'PK' 0x504B)
104 * - rule block (one of:)
105 * + 0x000A 'PKCS-1.2' (MCL2 'PD')
106 * + 0x000A 'ZERO-PAD' (MCL2 'PK')
107 * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD')
108 * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK')
109 * - VUD block
110 */
111static struct CPRBX static_cprbx = {
112 .cprb_len = 0x00DC,
113 .cprb_ver_id = 0x02,
114 .func_id = {0x54,0x32},
115};
116
117/**
118 * Convert a ICAMEX message to a type6 MEX message.
119 *
120 * @zdev: crypto device pointer
121 * @ap_msg: pointer to AP message
122 * @mex: pointer to user input data
123 *
124 * Returns 0 on success or -EFAULT.
125 */
126static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev,
127 struct ap_message *ap_msg,
128 struct ica_rsa_modexpo *mex)
129{
130 static struct type6_hdr static_type6_hdrX = {
131 .type = 0x06,
132 .offset1 = 0x00000058,
133 .agent_id = {'C','A',},
134 .function_code = {'P','K'},
135 };
136 static struct function_and_rules_block static_pke_fnr = {
137 .function_code = {'P','K'},
138 .ulen = 10,
139 .only_rule = {'M','R','P',' ',' ',' ',' ',' '}
140 };
141 static struct function_and_rules_block static_pke_fnr_MCL2 = {
142 .function_code = {'P','K'},
143 .ulen = 10,
144 .only_rule = {'Z','E','R','O','-','P','A','D'}
145 };
146 struct {
147 struct type6_hdr hdr;
148 struct CPRBX cprbx;
149 struct function_and_rules_block fr;
150 unsigned short length;
151 char text[0];
152 } __attribute__((packed)) *msg = ap_msg->message;
153 int size;
154
155 /* VUD.ciphertext */
156 msg->length = mex->inputdatalength + 2;
157 if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
158 return -EFAULT;
159
160 /* Set up key which is located after the variable length text. */
161 size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1);
162 if (size < 0)
163 return size;
164 size += sizeof(*msg) + mex->inputdatalength;
165
166 /* message header, cprbx and f&r */
167 msg->hdr = static_type6_hdrX;
168 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
169 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
170
171 msg->cprbx = static_cprbx;
172 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
173 msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1;
174
175 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
176 static_pke_fnr_MCL2 : static_pke_fnr;
177
178 msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx);
179
180 ap_msg->length = size;
181 return 0;
182}
183
184/**
185 * Convert a ICACRT message to a type6 CRT message.
186 *
187 * @zdev: crypto device pointer
188 * @ap_msg: pointer to AP message
189 * @crt: pointer to user input data
190 *
191 * Returns 0 on success or -EFAULT.
192 */
193static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,
194 struct ap_message *ap_msg,
195 struct ica_rsa_modexpo_crt *crt)
196{
197 static struct type6_hdr static_type6_hdrX = {
198 .type = 0x06,
199 .offset1 = 0x00000058,
200 .agent_id = {'C','A',},
201 .function_code = {'P','D'},
202 };
203 static struct function_and_rules_block static_pkd_fnr = {
204 .function_code = {'P','D'},
205 .ulen = 10,
206 .only_rule = {'Z','E','R','O','-','P','A','D'}
207 };
208
209 static struct function_and_rules_block static_pkd_fnr_MCL2 = {
210 .function_code = {'P','D'},
211 .ulen = 10,
212 .only_rule = {'P','K','C','S','-','1','.','2'}
213 };
214 struct {
215 struct type6_hdr hdr;
216 struct CPRBX cprbx;
217 struct function_and_rules_block fr;
218 unsigned short length;
219 char text[0];
220 } __attribute__((packed)) *msg = ap_msg->message;
221 int size;
222
223 /* VUD.ciphertext */
224 msg->length = crt->inputdatalength + 2;
225 if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
226 return -EFAULT;
227
228 /* Set up key which is located after the variable length text. */
229 size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1);
230 if (size < 0)
231 return size;
232 size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */
233
234 /* message header, cprbx and f&r */
235 msg->hdr = static_type6_hdrX;
236 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
237 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
238
239 msg->cprbx = static_cprbx;
240 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
241 msg->cprbx.req_parml = msg->cprbx.rpl_msgbl =
242 size - sizeof(msg->hdr) - sizeof(msg->cprbx);
243
244 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
245 static_pkd_fnr_MCL2 : static_pkd_fnr;
246
247 ap_msg->length = size;
248 return 0;
249}
250
251/**
Ralph Wuerthner54321142006-09-20 15:58:36 +0200252 * Convert a XCRB message to a type6 CPRB message.
253 *
254 * @zdev: crypto device pointer
255 * @ap_msg: pointer to AP message
256 * @xcRB: pointer to user input data
257 *
Holger Dengler2389aef2011-12-27 11:27:20 +0100258 * Returns 0 on success or -EFAULT, -EINVAL.
Ralph Wuerthner54321142006-09-20 15:58:36 +0200259 */
260struct type86_fmt2_msg {
261 struct type86_hdr hdr;
262 struct type86_fmt2_ext fmt2;
263} __attribute__((packed));
264
265static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
266 struct ap_message *ap_msg,
267 struct ica_xcRB *xcRB)
268{
269 static struct type6_hdr static_type6_hdrX = {
270 .type = 0x06,
271 .offset1 = 0x00000058,
272 };
273 struct {
274 struct type6_hdr hdr;
Ralph Wuerthner16db63f2007-10-12 16:11:28 +0200275 struct CPRBX cprbx;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200276 } __attribute__((packed)) *msg = ap_msg->message;
277
278 int rcblen = CEIL4(xcRB->request_control_blk_length);
279 int replylen;
280 char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
281 char *function_code;
282
283 /* length checks */
284 ap_msg->length = sizeof(struct type6_hdr) +
285 CEIL4(xcRB->request_control_blk_length) +
286 xcRB->request_data_length;
Felix Beck1a89dd82008-07-14 09:59:27 +0200287 if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE)
Holger Dengler2389aef2011-12-27 11:27:20 +0100288 return -EINVAL;
Holger Dengler7fe6f092011-12-27 11:27:19 +0100289 replylen = sizeof(struct type86_fmt2_msg) +
290 CEIL4(xcRB->reply_control_blk_length) +
291 xcRB->reply_data_length;
292 if (replylen > PCIXCC_MAX_XCRB_MESSAGE_SIZE)
Holger Dengler2389aef2011-12-27 11:27:20 +0100293 return -EINVAL;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200294
295 /* prepare type6 header */
296 msg->hdr = static_type6_hdrX;
297 memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
298 msg->hdr.ToCardLen1 = xcRB->request_control_blk_length;
299 if (xcRB->request_data_length) {
300 msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
301 msg->hdr.ToCardLen2 = xcRB->request_data_length;
302 }
303 msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
304 msg->hdr.FromCardLen2 = xcRB->reply_data_length;
305
306 /* prepare CPRB */
307 if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
308 xcRB->request_control_blk_length))
309 return -EFAULT;
310 if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
Felix Beck1a89dd82008-07-14 09:59:27 +0200311 xcRB->request_control_blk_length)
Holger Dengler2389aef2011-12-27 11:27:20 +0100312 return -EINVAL;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200313 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
314 memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code));
315
Felix Becka6a5d732009-12-07 12:51:55 +0100316 if (memcmp(function_code, "US", 2) == 0)
317 ap_msg->special = 1;
318 else
319 ap_msg->special = 0;
320
Ralph Wuerthner54321142006-09-20 15:58:36 +0200321 /* copy data block */
322 if (xcRB->request_data_length &&
323 copy_from_user(req_data, xcRB->request_data_address,
324 xcRB->request_data_length))
325 return -EFAULT;
326 return 0;
327}
328
329/**
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200330 * Prepare a type6 CPRB message for random number generation
331 *
332 * @ap_dev: AP device pointer
333 * @ap_msg: pointer to AP message
334 */
335static void rng_type6CPRB_msgX(struct ap_device *ap_dev,
336 struct ap_message *ap_msg,
337 unsigned random_number_length)
338{
339 struct {
340 struct type6_hdr hdr;
341 struct CPRBX cprbx;
342 char function_code[2];
343 short int rule_length;
344 char rule[8];
345 short int verb_length;
346 short int key_length;
347 } __attribute__((packed)) *msg = ap_msg->message;
348 static struct type6_hdr static_type6_hdrX = {
349 .type = 0x06,
350 .offset1 = 0x00000058,
351 .agent_id = {'C', 'A'},
352 .function_code = {'R', 'L'},
353 .ToCardLen1 = sizeof *msg - sizeof(msg->hdr),
354 .FromCardLen1 = sizeof *msg - sizeof(msg->hdr),
355 };
Felix Beck6458abc2009-10-06 10:34:09 +0200356 static struct CPRBX local_cprbx = {
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200357 .cprb_len = 0x00dc,
358 .cprb_ver_id = 0x02,
359 .func_id = {0x54, 0x32},
360 .req_parml = sizeof *msg - sizeof(msg->hdr) -
361 sizeof(msg->cprbx),
362 .rpl_msgbl = sizeof *msg - sizeof(msg->hdr),
363 };
364
365 msg->hdr = static_type6_hdrX;
366 msg->hdr.FromCardLen2 = random_number_length,
Felix Beck6458abc2009-10-06 10:34:09 +0200367 msg->cprbx = local_cprbx;
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200368 msg->cprbx.rpl_datal = random_number_length,
369 msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid);
370 memcpy(msg->function_code, msg->hdr.function_code, 0x02);
371 msg->rule_length = 0x0a;
372 memcpy(msg->rule, "RANDOM ", 8);
373 msg->verb_length = 0x02;
374 msg->key_length = 0x02;
375 ap_msg->length = sizeof *msg;
376}
377
378/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200379 * Copy results from a type 86 ICA reply message back to user space.
380 *
381 * @zdev: crypto device pointer
382 * @reply: reply AP message.
383 * @data: pointer to user output data
384 * @length: size of user output data
385 *
386 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
387 */
388struct type86x_reply {
389 struct type86_hdr hdr;
390 struct type86_fmt2_ext fmt2;
391 struct CPRBX cprbx;
392 unsigned char pad[4]; /* 4 byte function code/rules block ? */
393 unsigned short length;
394 char text[0];
395} __attribute__((packed));
396
397static int convert_type86_ica(struct zcrypt_device *zdev,
398 struct ap_message *reply,
399 char __user *outputdata,
400 unsigned int outputdatalength)
401{
402 static unsigned char static_pad[] = {
403 0x00,0x02,
404 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,
405 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57,
406 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,
407 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39,
408 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,
409 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D,
410 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,
411 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F,
412 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,
413 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45,
414 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,
415 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F,
416 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,
417 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D,
418 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,
419 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9,
420 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,
421 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B,
422 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,
423 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD,
424 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,
425 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1,
426 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,
427 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23,
428 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,
429 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43,
430 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,
431 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F,
432 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,
433 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD,
434 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,
435 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09
436 };
437 struct type86x_reply *msg = reply->message;
438 unsigned short service_rc, service_rs;
439 unsigned int reply_len, pad_len;
440 char *data;
441
442 service_rc = msg->cprbx.ccp_rtcode;
443 if (unlikely(service_rc != 0)) {
444 service_rs = msg->cprbx.ccp_rscode;
Felix Beck1a89dd82008-07-14 09:59:27 +0200445 if (service_rc == 8 && service_rs == 66)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200446 return -EINVAL;
Felix Beck1a89dd82008-07-14 09:59:27 +0200447 if (service_rc == 8 && service_rs == 65)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200448 return -EINVAL;
Felix Beck1a89dd82008-07-14 09:59:27 +0200449 if (service_rc == 8 && service_rs == 770)
Ralph Wuerthner2af48082007-10-12 16:11:30 +0200450 return -EINVAL;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200451 if (service_rc == 8 && service_rs == 783) {
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200452 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
453 return -EAGAIN;
454 }
Felix Beck1a89dd82008-07-14 09:59:27 +0200455 if (service_rc == 12 && service_rs == 769)
Ralph Wuerthner2af48082007-10-12 16:11:30 +0200456 return -EINVAL;
Felix Beck19b123e2010-01-27 10:12:39 +0100457 if (service_rc == 8 && service_rs == 72)
458 return -EINVAL;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200459 zdev->online = 0;
460 return -EAGAIN; /* repeat the request on a different device. */
461 }
462 data = msg->text;
463 reply_len = msg->length - 2;
464 if (reply_len > outputdatalength)
465 return -EINVAL;
Felix Beck1749a812008-04-17 07:46:28 +0200466 /*
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200467 * For all encipher requests, the length of the ciphertext (reply_len)
468 * will always equal the modulus length. For MEX decipher requests
469 * the output needs to get padded. Minimum pad size is 10.
470 *
471 * Currently, the cases where padding will be added is for:
472 * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
473 * ZERO-PAD and CRT is only supported for PKD requests)
474 * - PCICC, always
475 */
476 pad_len = outputdatalength - reply_len;
477 if (pad_len > 0) {
478 if (pad_len < 10)
479 return -EINVAL;
480 /* 'restore' padding left in the PCICC/PCIXCC card. */
481 if (copy_to_user(outputdata, static_pad, pad_len - 1))
482 return -EFAULT;
483 if (put_user(0, outputdata + pad_len - 1))
484 return -EFAULT;
485 }
486 /* Copy the crypto response to user space. */
487 if (copy_to_user(outputdata + pad_len, data, reply_len))
488 return -EFAULT;
489 return 0;
490}
491
Ralph Wuerthner54321142006-09-20 15:58:36 +0200492/**
493 * Copy results from a type 86 XCRB reply message back to user space.
494 *
495 * @zdev: crypto device pointer
496 * @reply: reply AP message.
497 * @xcRB: pointer to XCRB
498 *
499 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
500 */
501static int convert_type86_xcrb(struct zcrypt_device *zdev,
502 struct ap_message *reply,
503 struct ica_xcRB *xcRB)
504{
505 struct type86_fmt2_msg *msg = reply->message;
506 char *data = reply->message;
507
508 /* Copy CPRB to user */
509 if (copy_to_user(xcRB->reply_control_blk_addr,
510 data + msg->fmt2.offset1, msg->fmt2.count1))
511 return -EFAULT;
512 xcRB->reply_control_blk_length = msg->fmt2.count1;
513
514 /* Copy data buffer to user */
515 if (msg->fmt2.count2)
516 if (copy_to_user(xcRB->reply_data_addr,
517 data + msg->fmt2.offset2, msg->fmt2.count2))
518 return -EFAULT;
519 xcRB->reply_data_length = msg->fmt2.count2;
520 return 0;
521}
522
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200523static int convert_type86_rng(struct zcrypt_device *zdev,
524 struct ap_message *reply,
525 char *buffer)
526{
527 struct {
528 struct type86_hdr hdr;
529 struct type86_fmt2_ext fmt2;
530 struct CPRBX cprbx;
531 } __attribute__((packed)) *msg = reply->message;
532 char *data = reply->message;
533
Felix Beck1a89dd82008-07-14 09:59:27 +0200534 if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0)
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200535 return -EINVAL;
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200536 memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
537 return msg->fmt2.count2;
538}
539
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200540static int convert_response_ica(struct zcrypt_device *zdev,
541 struct ap_message *reply,
542 char __user *outputdata,
543 unsigned int outputdatalength)
544{
545 struct type86x_reply *msg = reply->message;
546
547 /* Response type byte is the second byte in the response. */
548 switch (((unsigned char *) reply->message)[1]) {
549 case TYPE82_RSP_CODE:
550 case TYPE88_RSP_CODE:
551 return convert_error(zdev, reply);
552 case TYPE86_RSP_CODE:
Felix Beckc2567f82011-01-05 12:47:47 +0100553 if (msg->cprbx.ccp_rtcode &&
554 (msg->cprbx.ccp_rscode == 0x14f) &&
555 (outputdatalength > 256)) {
556 if (zdev->max_exp_bit_length <= 17) {
557 zdev->max_exp_bit_length = 17;
558 return -EAGAIN;
559 } else
560 return -EINVAL;
561 }
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200562 if (msg->hdr.reply_code)
563 return convert_error(zdev, reply);
564 if (msg->cprbx.cprb_ver_id == 0x02)
565 return convert_type86_ica(zdev, reply,
566 outputdata, outputdatalength);
Felix Beck942b7e62009-10-06 10:34:10 +0200567 /* Fall through, no break, incorrect cprb version is an unknown
568 * response */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200569 default: /* Unknown response type, this should NEVER EVER happen */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200570 zdev->online = 0;
571 return -EAGAIN; /* repeat the request on a different device. */
572 }
573}
574
Ralph Wuerthner54321142006-09-20 15:58:36 +0200575static int convert_response_xcrb(struct zcrypt_device *zdev,
576 struct ap_message *reply,
577 struct ica_xcRB *xcRB)
578{
579 struct type86x_reply *msg = reply->message;
580
581 /* Response type byte is the second byte in the response. */
582 switch (((unsigned char *) reply->message)[1]) {
583 case TYPE82_RSP_CODE:
584 case TYPE88_RSP_CODE:
585 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
586 return convert_error(zdev, reply);
587 case TYPE86_RSP_CODE:
588 if (msg->hdr.reply_code) {
589 memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
590 return convert_error(zdev, reply);
591 }
592 if (msg->cprbx.cprb_ver_id == 0x02)
593 return convert_type86_xcrb(zdev, reply, xcRB);
Felix Beck942b7e62009-10-06 10:34:10 +0200594 /* Fall through, no break, incorrect cprb version is an unknown
595 * response */
Ralph Wuerthner54321142006-09-20 15:58:36 +0200596 default: /* Unknown response type, this should NEVER EVER happen */
Ralph Wuerthner54321142006-09-20 15:58:36 +0200597 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
598 zdev->online = 0;
599 return -EAGAIN; /* repeat the request on a different device. */
600 }
601}
602
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200603static int convert_response_rng(struct zcrypt_device *zdev,
604 struct ap_message *reply,
605 char *data)
606{
607 struct type86x_reply *msg = reply->message;
608
609 switch (msg->hdr.type) {
610 case TYPE82_RSP_CODE:
611 case TYPE88_RSP_CODE:
612 return -EINVAL;
613 case TYPE86_RSP_CODE:
614 if (msg->hdr.reply_code)
615 return -EINVAL;
616 if (msg->cprbx.cprb_ver_id == 0x02)
617 return convert_type86_rng(zdev, reply, data);
Felix Beck942b7e62009-10-06 10:34:10 +0200618 /* Fall through, no break, incorrect cprb version is an unknown
619 * response */
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200620 default: /* Unknown response type, this should NEVER EVER happen */
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200621 zdev->online = 0;
622 return -EAGAIN; /* repeat the request on a different device. */
623 }
624}
625
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200626/**
627 * This function is called from the AP bus code after a crypto request
628 * "msg" has finished with the reply message "reply".
629 * It is called from tasklet context.
630 * @ap_dev: pointer to the AP device
631 * @msg: pointer to the AP message
632 * @reply: pointer to the AP reply message
633 */
634static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
635 struct ap_message *msg,
636 struct ap_message *reply)
637{
638 static struct error_hdr error_reply = {
639 .type = TYPE82_RSP_CODE,
640 .reply_code = REP82_ERROR_MACHINE_FAILURE,
641 };
Ralph Wuerthner54321142006-09-20 15:58:36 +0200642 struct response_type *resp_type =
643 (struct response_type *) msg->private;
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100644 struct type86x_reply *t86r;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200645 int length;
646
647 /* Copy the reply message to the request message buffer. */
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100648 if (IS_ERR(reply)) {
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200649 memcpy(msg->message, &error_reply, sizeof(error_reply));
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100650 goto out;
651 }
652 t86r = reply->message;
653 if (t86r->hdr.type == TYPE86_RSP_CODE &&
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200654 t86r->cprbx.cprb_ver_id == 0x02) {
Ralph Wuerthner54321142006-09-20 15:58:36 +0200655 switch (resp_type->type) {
656 case PCIXCC_RESPONSE_TYPE_ICA:
657 length = sizeof(struct type86x_reply)
658 + t86r->length - 2;
659 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
660 memcpy(msg->message, reply->message, length);
661 break;
662 case PCIXCC_RESPONSE_TYPE_XCRB:
663 length = t86r->fmt2.offset2 + t86r->fmt2.count2;
Holger Dengler7fe6f092011-12-27 11:27:19 +0100664 length = min(PCIXCC_MAX_XCRB_MESSAGE_SIZE, length);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200665 memcpy(msg->message, reply->message, length);
666 break;
667 default:
Felix Beck1a89dd82008-07-14 09:59:27 +0200668 memcpy(msg->message, &error_reply, sizeof error_reply);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200669 }
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200670 } else
671 memcpy(msg->message, reply->message, sizeof error_reply);
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100672out:
Ralph Wuerthner54321142006-09-20 15:58:36 +0200673 complete(&(resp_type->work));
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200674}
675
676static atomic_t zcrypt_step = ATOMIC_INIT(0);
677
678/**
679 * The request distributor calls this function if it picked the PCIXCC/CEX2C
680 * device to handle a modexpo request.
681 * @zdev: pointer to zcrypt_device structure that identifies the
682 * PCIXCC/CEX2C device to the request distributor
683 * @mex: pointer to the modexpo request buffer
684 */
685static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
686 struct ica_rsa_modexpo *mex)
687{
688 struct ap_message ap_msg;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200689 struct response_type resp_type = {
690 .type = PCIXCC_RESPONSE_TYPE_ICA,
691 };
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200692 int rc;
693
Felix Beck468ffdd2009-12-07 12:51:54 +0100694 ap_init_message(&ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200695 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
696 if (!ap_msg.message)
697 return -ENOMEM;
Holger Dengler54a8f562012-05-16 14:08:22 +0200698 ap_msg.receive = zcrypt_pcixcc_receive;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200699 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
700 atomic_inc_return(&zcrypt_step);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200701 ap_msg.private = &resp_type;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200702 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
703 if (rc)
704 goto out_free;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200705 init_completion(&resp_type.work);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200706 ap_queue_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200707 rc = wait_for_completion_interruptible(&resp_type.work);
708 if (rc == 0)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200709 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
710 mex->outputdatalength);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200711 else
712 /* Signal pending. */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200713 ap_cancel_message(zdev->ap_dev, &ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200714out_free:
715 free_page((unsigned long) ap_msg.message);
716 return rc;
717}
718
719/**
720 * The request distributor calls this function if it picked the PCIXCC/CEX2C
721 * device to handle a modexpo_crt request.
722 * @zdev: pointer to zcrypt_device structure that identifies the
723 * PCIXCC/CEX2C device to the request distributor
724 * @crt: pointer to the modexpoc_crt request buffer
725 */
726static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
727 struct ica_rsa_modexpo_crt *crt)
728{
729 struct ap_message ap_msg;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200730 struct response_type resp_type = {
731 .type = PCIXCC_RESPONSE_TYPE_ICA,
732 };
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200733 int rc;
734
Felix Beck468ffdd2009-12-07 12:51:54 +0100735 ap_init_message(&ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200736 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
737 if (!ap_msg.message)
738 return -ENOMEM;
Holger Dengler54a8f562012-05-16 14:08:22 +0200739 ap_msg.receive = zcrypt_pcixcc_receive;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200740 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;
Holger Dengler54a8f562012-05-16 14:08:22 +0200780 ap_msg.receive = zcrypt_pcixcc_receive;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200781 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
782 atomic_inc_return(&zcrypt_step);
783 ap_msg.private = &resp_type;
784 rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB);
785 if (rc)
786 goto out_free;
787 init_completion(&resp_type.work);
788 ap_queue_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200789 rc = wait_for_completion_interruptible(&resp_type.work);
790 if (rc == 0)
Ralph Wuerthner54321142006-09-20 15:58:36 +0200791 rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200792 else
793 /* Signal pending. */
Ralph Wuerthner54321142006-09-20 15:58:36 +0200794 ap_cancel_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200795out_free:
Johannes Weiner3e75a902009-03-26 15:24:48 +0100796 kzfree(ap_msg.message);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200797 return rc;
798}
799
800/**
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200801 * The request distributor calls this function if it picked the PCIXCC/CEX2C
802 * device to generate random data.
803 * @zdev: pointer to zcrypt_device structure that identifies the
804 * PCIXCC/CEX2C device to the request distributor
805 * @buffer: pointer to a memory page to return random data
806 */
807
808static long zcrypt_pcixcc_rng(struct zcrypt_device *zdev,
809 char *buffer)
810{
811 struct ap_message ap_msg;
812 struct response_type resp_type = {
813 .type = PCIXCC_RESPONSE_TYPE_XCRB,
814 };
815 int rc;
816
Felix Beck468ffdd2009-12-07 12:51:54 +0100817 ap_init_message(&ap_msg);
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200818 ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
819 if (!ap_msg.message)
820 return -ENOMEM;
Holger Dengler54a8f562012-05-16 14:08:22 +0200821 ap_msg.receive = zcrypt_pcixcc_receive;
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200822 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
823 atomic_inc_return(&zcrypt_step);
824 ap_msg.private = &resp_type;
825 rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE);
826 init_completion(&resp_type.work);
827 ap_queue_message(zdev->ap_dev, &ap_msg);
828 rc = wait_for_completion_interruptible(&resp_type.work);
829 if (rc == 0)
830 rc = convert_response_rng(zdev, &ap_msg, buffer);
831 else
832 /* Signal pending. */
833 ap_cancel_message(zdev->ap_dev, &ap_msg);
834 kfree(ap_msg.message);
835 return rc;
836}
837
838/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200839 * The crypto operations for a PCIXCC/CEX2C card.
840 */
841static struct zcrypt_ops zcrypt_pcixcc_ops = {
842 .rsa_modexpo = zcrypt_pcixcc_modexpo,
843 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
Ralph Wuerthner54321142006-09-20 15:58:36 +0200844 .send_cprb = zcrypt_pcixcc_send_cprb,
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200845};
846
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200847static struct zcrypt_ops zcrypt_pcixcc_with_rng_ops = {
848 .rsa_modexpo = zcrypt_pcixcc_modexpo,
849 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
850 .send_cprb = zcrypt_pcixcc_send_cprb,
851 .rng = zcrypt_pcixcc_rng,
852};
853
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200854/**
855 * Micro-code detection function. Its sends a message to a pcixcc card
856 * to find out the microcode level.
857 * @ap_dev: pointer to the AP device.
858 */
859static int zcrypt_pcixcc_mcl(struct ap_device *ap_dev)
860{
861 static unsigned char msg[] = {
862 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
863 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
864 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
865 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
866 0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
867 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
868 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00,
869 0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00,
870 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
871 0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00,
872 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
873 0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32,
874 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,
875 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,
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,0x00,0x00,0x00,0x00,0x00,
893 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
894 0x00,0x00,0x00,0x04,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,0x00,0x00,0x00,0x00,
899 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
900 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x0A,
901 0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20,
902 0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05,
903 0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
904 0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55,
905 0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,
906 0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,
907 0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,
908 0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB,
909 0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54,
910 0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00,
911 0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00,
912 0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40,
913 0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C,
914 0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF,
915 0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9,
916 0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63,
917 0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5,
918 0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A,
919 0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01,
920 0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28,
921 0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91,
922 0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5,
923 0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C,
924 0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98,
925 0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96,
926 0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19,
927 0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47,
928 0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36,
929 0xF1,0x3D,0x93,0x53
930 };
931 unsigned long long psmid;
932 struct CPRBX *cprbx;
933 char *reply;
934 int rc, i;
935
936 reply = (void *) get_zeroed_page(GFP_KERNEL);
937 if (!reply)
938 return -ENOMEM;
939
940 rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, msg, sizeof(msg));
941 if (rc)
942 goto out_free;
943
944 /* Wait for the test message to complete. */
945 for (i = 0; i < 6; i++) {
946 mdelay(300);
947 rc = ap_recv(ap_dev->qid, &psmid, reply, 4096);
948 if (rc == 0 && psmid == 0x0102030405060708ULL)
949 break;
950 }
951
952 if (i >= 6) {
953 /* Got no answer. */
954 rc = -ENODEV;
955 goto out_free;
956 }
957
958 cprbx = (struct CPRBX *) (reply + 48);
959 if (cprbx->ccp_rtcode == 8 && cprbx->ccp_rscode == 33)
960 rc = ZCRYPT_PCIXCC_MCL2;
961 else
962 rc = ZCRYPT_PCIXCC_MCL3;
963out_free:
964 free_page((unsigned long) reply);
965 return rc;
966}
967
968/**
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200969 * Large random number detection function. Its sends a message to a pcixcc
970 * card to find out if large random numbers are supported.
971 * @ap_dev: pointer to the AP device.
972 *
973 * Returns 1 if large random numbers are supported, 0 if not and < 0 on error.
974 */
975static int zcrypt_pcixcc_rng_supported(struct ap_device *ap_dev)
976{
977 struct ap_message ap_msg;
978 unsigned long long psmid;
979 struct {
980 struct type86_hdr hdr;
981 struct type86_fmt2_ext fmt2;
982 struct CPRBX cprbx;
983 } __attribute__((packed)) *reply;
984 int rc, i;
985
Felix Beck468ffdd2009-12-07 12:51:54 +0100986 ap_init_message(&ap_msg);
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200987 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
988 if (!ap_msg.message)
989 return -ENOMEM;
990
991 rng_type6CPRB_msgX(ap_dev, &ap_msg, 4);
992 rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, ap_msg.message,
993 ap_msg.length);
994 if (rc)
995 goto out_free;
996
997 /* Wait for the test message to complete. */
998 for (i = 0; i < 2 * HZ; i++) {
999 msleep(1000 / HZ);
1000 rc = ap_recv(ap_dev->qid, &psmid, ap_msg.message, 4096);
1001 if (rc == 0 && psmid == 0x0102030405060708ULL)
1002 break;
1003 }
1004
1005 if (i >= 2 * HZ) {
1006 /* Got no answer. */
1007 rc = -ENODEV;
1008 goto out_free;
1009 }
1010
1011 reply = ap_msg.message;
1012 if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0)
1013 rc = 1;
1014 else
1015 rc = 0;
1016out_free:
1017 free_page((unsigned long) ap_msg.message);
1018 return rc;
1019}
1020
1021/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001022 * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device
1023 * since the bus_match already checked the hardware type. The PCIXCC
1024 * cards come in two flavours: micro code level 2 and micro code level 3.
1025 * This is checked by sending a test message to the device.
1026 * @ap_dev: pointer to the AP device.
1027 */
1028static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
1029{
1030 struct zcrypt_device *zdev;
Felix Beck8e89b6b2009-12-07 12:51:57 +01001031 int rc = 0;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001032
Holger Dengler7fe6f092011-12-27 11:27:19 +01001033 zdev = zcrypt_device_alloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE);
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001034 if (!zdev)
1035 return -ENOMEM;
1036 zdev->ap_dev = ap_dev;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001037 zdev->online = 1;
Felix Beck8e89b6b2009-12-07 12:51:57 +01001038 switch (ap_dev->device_type) {
1039 case AP_DEVICE_TYPE_PCIXCC:
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001040 rc = zcrypt_pcixcc_mcl(ap_dev);
1041 if (rc < 0) {
1042 zcrypt_device_free(zdev);
1043 return rc;
1044 }
1045 zdev->user_space_type = rc;
1046 if (rc == ZCRYPT_PCIXCC_MCL2) {
1047 zdev->type_string = "PCIXCC_MCL2";
1048 zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING;
1049 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
1050 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
Felix Beckc2567f82011-01-05 12:47:47 +01001051 zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001052 } else {
1053 zdev->type_string = "PCIXCC_MCL3";
1054 zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING;
1055 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
1056 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
Felix Beckc2567f82011-01-05 12:47:47 +01001057 zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001058 }
Felix Beck8e89b6b2009-12-07 12:51:57 +01001059 break;
1060 case AP_DEVICE_TYPE_CEX2C:
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001061 zdev->user_space_type = ZCRYPT_CEX2C;
1062 zdev->type_string = "CEX2C";
1063 zdev->speed_rating = CEX2C_SPEED_RATING;
1064 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
1065 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
Felix Beckc2567f82011-01-05 12:47:47 +01001066 zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
Felix Beck8e89b6b2009-12-07 12:51:57 +01001067 break;
1068 case AP_DEVICE_TYPE_CEX3C:
1069 zdev->user_space_type = ZCRYPT_CEX3C;
1070 zdev->type_string = "CEX3C";
1071 zdev->speed_rating = CEX3C_SPEED_RATING;
1072 zdev->min_mod_size = CEX3C_MIN_MOD_SIZE;
1073 zdev->max_mod_size = CEX3C_MAX_MOD_SIZE;
Felix Beckc2567f82011-01-05 12:47:47 +01001074 zdev->max_exp_bit_length = CEX3C_MAX_MOD_SIZE;
Felix Beck8e89b6b2009-12-07 12:51:57 +01001075 break;
1076 default:
1077 goto out_free;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001078 }
Felix Beck8e89b6b2009-12-07 12:51:57 +01001079
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +02001080 rc = zcrypt_pcixcc_rng_supported(ap_dev);
1081 if (rc < 0) {
1082 zcrypt_device_free(zdev);
1083 return rc;
1084 }
1085 if (rc)
1086 zdev->ops = &zcrypt_pcixcc_with_rng_ops;
1087 else
1088 zdev->ops = &zcrypt_pcixcc_ops;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001089 ap_dev->reply = &zdev->reply;
1090 ap_dev->private = zdev;
1091 rc = zcrypt_device_register(zdev);
1092 if (rc)
1093 goto out_free;
1094 return 0;
1095
1096 out_free:
1097 ap_dev->private = NULL;
1098 zcrypt_device_free(zdev);
1099 return rc;
1100}
1101
1102/**
1103 * This is called to remove the extended PCIXCC/CEX2C driver information
1104 * if an AP device is removed.
1105 */
1106static void zcrypt_pcixcc_remove(struct ap_device *ap_dev)
1107{
1108 struct zcrypt_device *zdev = ap_dev->private;
1109
1110 zcrypt_device_unregister(zdev);
1111}
1112
1113int __init zcrypt_pcixcc_init(void)
1114{
1115 return ap_driver_register(&zcrypt_pcixcc_driver, THIS_MODULE, "pcixcc");
1116}
1117
1118void zcrypt_pcixcc_exit(void)
1119{
1120 ap_driver_unregister(&zcrypt_pcixcc_driver);
1121}
1122
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001123module_init(zcrypt_pcixcc_init);
1124module_exit(zcrypt_pcixcc_exit);