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