blob: cf1cbd4747f4d1f234695bc27bd147c32ee4f5b8 [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>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090033#include <linux/slab.h>
Arun Sharma60063492011-07-26 16:09:06 -070034#include <linux/atomic.h>
Martin Schwidefsky6684af12006-09-20 15:58:32 +020035#include <asm/uaccess.h>
36
37#include "ap_bus.h"
38#include "zcrypt_api.h"
39#include "zcrypt_error.h"
40#include "zcrypt_pcicc.h"
41#include "zcrypt_pcixcc.h"
42#include "zcrypt_cca_key.h"
43
44#define PCIXCC_MIN_MOD_SIZE 16 /* 128 bits */
45#define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */
46#define PCIXCC_MAX_MOD_SIZE 256 /* 2048 bits */
Felix Beck8e89b6b2009-12-07 12:51:57 +010047#define CEX3C_MIN_MOD_SIZE PCIXCC_MIN_MOD_SIZE
Felix Beck2ade1fa2011-01-05 12:47:46 +010048#define CEX3C_MAX_MOD_SIZE 512 /* 4096 bits */
Martin Schwidefsky6684af12006-09-20 15:58:32 +020049
Felix Beck18278df2009-12-07 12:51:58 +010050#define PCIXCC_MCL2_SPEED_RATING 7870
Martin Schwidefsky6684af12006-09-20 15:58:32 +020051#define PCIXCC_MCL3_SPEED_RATING 7870
Felix Beck18278df2009-12-07 12:51:58 +010052#define CEX2C_SPEED_RATING 7000
Felix Beck2ade1fa2011-01-05 12:47:46 +010053#define CEX3C_SPEED_RATING 6500
Martin Schwidefsky6684af12006-09-20 15:58:32 +020054
55#define PCIXCC_MAX_ICA_MESSAGE_SIZE 0x77c /* max size type6 v2 crt message */
56#define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */
57
58#define PCIXCC_MAX_XCRB_MESSAGE_SIZE (12*1024)
Martin Schwidefsky6684af12006-09-20 15:58:32 +020059
60#define PCIXCC_CLEANUP_TIME (15*HZ)
61
Ralph Wuerthner54321142006-09-20 15:58:36 +020062#define CEIL4(x) ((((x)+3)/4)*4)
63
64struct response_type {
65 struct completion work;
66 int type;
67};
68#define PCIXCC_RESPONSE_TYPE_ICA 0
69#define PCIXCC_RESPONSE_TYPE_XCRB 1
70
Martin Schwidefsky6684af12006-09-20 15:58:32 +020071static struct ap_device_id zcrypt_pcixcc_ids[] = {
72 { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) },
73 { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) },
Felix Beckffda4f72009-12-07 12:51:56 +010074 { AP_DEVICE(AP_DEVICE_TYPE_CEX3C) },
Martin Schwidefsky6684af12006-09-20 15:58:32 +020075 { /* end of list */ },
76};
77
Martin Schwidefsky6684af12006-09-20 15:58:32 +020078MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids);
79MODULE_AUTHOR("IBM Corporation");
80MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, "
81 "Copyright 2001, 2006 IBM Corporation");
82MODULE_LICENSE("GPL");
Martin Schwidefsky6684af12006-09-20 15:58:32 +020083
84static int zcrypt_pcixcc_probe(struct ap_device *ap_dev);
85static void zcrypt_pcixcc_remove(struct ap_device *ap_dev);
86static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *,
87 struct ap_message *);
88
89static struct ap_driver zcrypt_pcixcc_driver = {
90 .probe = zcrypt_pcixcc_probe,
91 .remove = zcrypt_pcixcc_remove,
92 .receive = zcrypt_pcixcc_receive,
93 .ids = zcrypt_pcixcc_ids,
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +020094 .request_timeout = PCIXCC_CLEANUP_TIME,
Martin Schwidefsky6684af12006-09-20 15:58:32 +020095};
96
97/**
98 * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C
99 * card in a type6 message. The 3 fields that must be filled in at execution
100 * time are req_parml, rpl_parml and usage_domain.
101 * Everything about this interface is ascii/big-endian, since the
102 * device does *not* have 'Intel inside'.
103 *
104 * The CPRBX is followed immediately by the parm block.
105 * The parm block contains:
106 * - function code ('PD' 0x5044 or 'PK' 0x504B)
107 * - rule block (one of:)
108 * + 0x000A 'PKCS-1.2' (MCL2 'PD')
109 * + 0x000A 'ZERO-PAD' (MCL2 'PK')
110 * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD')
111 * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK')
112 * - VUD block
113 */
114static struct CPRBX static_cprbx = {
115 .cprb_len = 0x00DC,
116 .cprb_ver_id = 0x02,
117 .func_id = {0x54,0x32},
118};
119
120/**
121 * Convert a ICAMEX message to a type6 MEX message.
122 *
123 * @zdev: crypto device pointer
124 * @ap_msg: pointer to AP message
125 * @mex: pointer to user input data
126 *
127 * Returns 0 on success or -EFAULT.
128 */
129static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev,
130 struct ap_message *ap_msg,
131 struct ica_rsa_modexpo *mex)
132{
133 static struct type6_hdr static_type6_hdrX = {
134 .type = 0x06,
135 .offset1 = 0x00000058,
136 .agent_id = {'C','A',},
137 .function_code = {'P','K'},
138 };
139 static struct function_and_rules_block static_pke_fnr = {
140 .function_code = {'P','K'},
141 .ulen = 10,
142 .only_rule = {'M','R','P',' ',' ',' ',' ',' '}
143 };
144 static struct function_and_rules_block static_pke_fnr_MCL2 = {
145 .function_code = {'P','K'},
146 .ulen = 10,
147 .only_rule = {'Z','E','R','O','-','P','A','D'}
148 };
149 struct {
150 struct type6_hdr hdr;
151 struct CPRBX cprbx;
152 struct function_and_rules_block fr;
153 unsigned short length;
154 char text[0];
155 } __attribute__((packed)) *msg = ap_msg->message;
156 int size;
157
158 /* VUD.ciphertext */
159 msg->length = mex->inputdatalength + 2;
160 if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
161 return -EFAULT;
162
163 /* Set up key which is located after the variable length text. */
164 size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1);
165 if (size < 0)
166 return size;
167 size += sizeof(*msg) + mex->inputdatalength;
168
169 /* message header, cprbx and f&r */
170 msg->hdr = static_type6_hdrX;
171 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
172 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
173
174 msg->cprbx = static_cprbx;
175 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
176 msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1;
177
178 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
179 static_pke_fnr_MCL2 : static_pke_fnr;
180
181 msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx);
182
183 ap_msg->length = size;
184 return 0;
185}
186
187/**
188 * Convert a ICACRT message to a type6 CRT message.
189 *
190 * @zdev: crypto device pointer
191 * @ap_msg: pointer to AP message
192 * @crt: pointer to user input data
193 *
194 * Returns 0 on success or -EFAULT.
195 */
196static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,
197 struct ap_message *ap_msg,
198 struct ica_rsa_modexpo_crt *crt)
199{
200 static struct type6_hdr static_type6_hdrX = {
201 .type = 0x06,
202 .offset1 = 0x00000058,
203 .agent_id = {'C','A',},
204 .function_code = {'P','D'},
205 };
206 static struct function_and_rules_block static_pkd_fnr = {
207 .function_code = {'P','D'},
208 .ulen = 10,
209 .only_rule = {'Z','E','R','O','-','P','A','D'}
210 };
211
212 static struct function_and_rules_block static_pkd_fnr_MCL2 = {
213 .function_code = {'P','D'},
214 .ulen = 10,
215 .only_rule = {'P','K','C','S','-','1','.','2'}
216 };
217 struct {
218 struct type6_hdr hdr;
219 struct CPRBX cprbx;
220 struct function_and_rules_block fr;
221 unsigned short length;
222 char text[0];
223 } __attribute__((packed)) *msg = ap_msg->message;
224 int size;
225
226 /* VUD.ciphertext */
227 msg->length = crt->inputdatalength + 2;
228 if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
229 return -EFAULT;
230
231 /* Set up key which is located after the variable length text. */
232 size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1);
233 if (size < 0)
234 return size;
235 size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */
236
237 /* message header, cprbx and f&r */
238 msg->hdr = static_type6_hdrX;
239 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
240 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
241
242 msg->cprbx = static_cprbx;
243 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
244 msg->cprbx.req_parml = msg->cprbx.rpl_msgbl =
245 size - sizeof(msg->hdr) - sizeof(msg->cprbx);
246
247 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
248 static_pkd_fnr_MCL2 : static_pkd_fnr;
249
250 ap_msg->length = size;
251 return 0;
252}
253
254/**
Ralph Wuerthner54321142006-09-20 15:58:36 +0200255 * Convert a XCRB message to a type6 CPRB message.
256 *
257 * @zdev: crypto device pointer
258 * @ap_msg: pointer to AP message
259 * @xcRB: pointer to user input data
260 *
Holger Dengler2389aef2011-12-27 11:27:20 +0100261 * Returns 0 on success or -EFAULT, -EINVAL.
Ralph Wuerthner54321142006-09-20 15:58:36 +0200262 */
263struct type86_fmt2_msg {
264 struct type86_hdr hdr;
265 struct type86_fmt2_ext fmt2;
266} __attribute__((packed));
267
268static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
269 struct ap_message *ap_msg,
270 struct ica_xcRB *xcRB)
271{
272 static struct type6_hdr static_type6_hdrX = {
273 .type = 0x06,
274 .offset1 = 0x00000058,
275 };
276 struct {
277 struct type6_hdr hdr;
Ralph Wuerthner16db63f2007-10-12 16:11:28 +0200278 struct CPRBX cprbx;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200279 } __attribute__((packed)) *msg = ap_msg->message;
280
281 int rcblen = CEIL4(xcRB->request_control_blk_length);
282 int replylen;
283 char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
284 char *function_code;
285
286 /* length checks */
287 ap_msg->length = sizeof(struct type6_hdr) +
288 CEIL4(xcRB->request_control_blk_length) +
289 xcRB->request_data_length;
Felix Beck1a89dd82008-07-14 09:59:27 +0200290 if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE)
Holger Dengler2389aef2011-12-27 11:27:20 +0100291 return -EINVAL;
Holger Dengler7fe6f092011-12-27 11:27:19 +0100292 replylen = sizeof(struct type86_fmt2_msg) +
293 CEIL4(xcRB->reply_control_blk_length) +
294 xcRB->reply_data_length;
295 if (replylen > PCIXCC_MAX_XCRB_MESSAGE_SIZE)
Holger Dengler2389aef2011-12-27 11:27:20 +0100296 return -EINVAL;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200297
298 /* prepare type6 header */
299 msg->hdr = static_type6_hdrX;
300 memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
301 msg->hdr.ToCardLen1 = xcRB->request_control_blk_length;
302 if (xcRB->request_data_length) {
303 msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
304 msg->hdr.ToCardLen2 = xcRB->request_data_length;
305 }
306 msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
307 msg->hdr.FromCardLen2 = xcRB->reply_data_length;
308
309 /* prepare CPRB */
310 if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
311 xcRB->request_control_blk_length))
312 return -EFAULT;
313 if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
Felix Beck1a89dd82008-07-14 09:59:27 +0200314 xcRB->request_control_blk_length)
Holger Dengler2389aef2011-12-27 11:27:20 +0100315 return -EINVAL;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200316 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
317 memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code));
318
Felix Becka6a5d732009-12-07 12:51:55 +0100319 if (memcmp(function_code, "US", 2) == 0)
320 ap_msg->special = 1;
321 else
322 ap_msg->special = 0;
323
Ralph Wuerthner54321142006-09-20 15:58:36 +0200324 /* copy data block */
325 if (xcRB->request_data_length &&
326 copy_from_user(req_data, xcRB->request_data_address,
327 xcRB->request_data_length))
328 return -EFAULT;
329 return 0;
330}
331
332/**
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200333 * Prepare a type6 CPRB message for random number generation
334 *
335 * @ap_dev: AP device pointer
336 * @ap_msg: pointer to AP message
337 */
338static void rng_type6CPRB_msgX(struct ap_device *ap_dev,
339 struct ap_message *ap_msg,
340 unsigned random_number_length)
341{
342 struct {
343 struct type6_hdr hdr;
344 struct CPRBX cprbx;
345 char function_code[2];
346 short int rule_length;
347 char rule[8];
348 short int verb_length;
349 short int key_length;
350 } __attribute__((packed)) *msg = ap_msg->message;
351 static struct type6_hdr static_type6_hdrX = {
352 .type = 0x06,
353 .offset1 = 0x00000058,
354 .agent_id = {'C', 'A'},
355 .function_code = {'R', 'L'},
356 .ToCardLen1 = sizeof *msg - sizeof(msg->hdr),
357 .FromCardLen1 = sizeof *msg - sizeof(msg->hdr),
358 };
Felix Beck6458abc2009-10-06 10:34:09 +0200359 static struct CPRBX local_cprbx = {
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200360 .cprb_len = 0x00dc,
361 .cprb_ver_id = 0x02,
362 .func_id = {0x54, 0x32},
363 .req_parml = sizeof *msg - sizeof(msg->hdr) -
364 sizeof(msg->cprbx),
365 .rpl_msgbl = sizeof *msg - sizeof(msg->hdr),
366 };
367
368 msg->hdr = static_type6_hdrX;
369 msg->hdr.FromCardLen2 = random_number_length,
Felix Beck6458abc2009-10-06 10:34:09 +0200370 msg->cprbx = local_cprbx;
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200371 msg->cprbx.rpl_datal = random_number_length,
372 msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid);
373 memcpy(msg->function_code, msg->hdr.function_code, 0x02);
374 msg->rule_length = 0x0a;
375 memcpy(msg->rule, "RANDOM ", 8);
376 msg->verb_length = 0x02;
377 msg->key_length = 0x02;
378 ap_msg->length = sizeof *msg;
379}
380
381/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200382 * Copy results from a type 86 ICA reply message back to user space.
383 *
384 * @zdev: crypto device pointer
385 * @reply: reply AP message.
386 * @data: pointer to user output data
387 * @length: size of user output data
388 *
389 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
390 */
391struct type86x_reply {
392 struct type86_hdr hdr;
393 struct type86_fmt2_ext fmt2;
394 struct CPRBX cprbx;
395 unsigned char pad[4]; /* 4 byte function code/rules block ? */
396 unsigned short length;
397 char text[0];
398} __attribute__((packed));
399
400static int convert_type86_ica(struct zcrypt_device *zdev,
401 struct ap_message *reply,
402 char __user *outputdata,
403 unsigned int outputdatalength)
404{
405 static unsigned char static_pad[] = {
406 0x00,0x02,
407 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,
408 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57,
409 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,
410 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39,
411 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,
412 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D,
413 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,
414 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F,
415 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,
416 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45,
417 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,
418 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F,
419 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,
420 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D,
421 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,
422 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9,
423 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,
424 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B,
425 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,
426 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD,
427 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,
428 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1,
429 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,
430 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23,
431 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,
432 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43,
433 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,
434 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F,
435 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,
436 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD,
437 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,
438 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09
439 };
440 struct type86x_reply *msg = reply->message;
441 unsigned short service_rc, service_rs;
442 unsigned int reply_len, pad_len;
443 char *data;
444
445 service_rc = msg->cprbx.ccp_rtcode;
446 if (unlikely(service_rc != 0)) {
447 service_rs = msg->cprbx.ccp_rscode;
Felix Beck1a89dd82008-07-14 09:59:27 +0200448 if (service_rc == 8 && service_rs == 66)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200449 return -EINVAL;
Felix Beck1a89dd82008-07-14 09:59:27 +0200450 if (service_rc == 8 && service_rs == 65)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200451 return -EINVAL;
Felix Beck1a89dd82008-07-14 09:59:27 +0200452 if (service_rc == 8 && service_rs == 770)
Ralph Wuerthner2af48082007-10-12 16:11:30 +0200453 return -EINVAL;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200454 if (service_rc == 8 && service_rs == 783) {
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200455 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
456 return -EAGAIN;
457 }
Felix Beck1a89dd82008-07-14 09:59:27 +0200458 if (service_rc == 12 && service_rs == 769)
Ralph Wuerthner2af48082007-10-12 16:11:30 +0200459 return -EINVAL;
Felix Beck19b123e2010-01-27 10:12:39 +0100460 if (service_rc == 8 && service_rs == 72)
461 return -EINVAL;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200462 zdev->online = 0;
463 return -EAGAIN; /* repeat the request on a different device. */
464 }
465 data = msg->text;
466 reply_len = msg->length - 2;
467 if (reply_len > outputdatalength)
468 return -EINVAL;
Felix Beck1749a812008-04-17 07:46:28 +0200469 /*
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200470 * For all encipher requests, the length of the ciphertext (reply_len)
471 * will always equal the modulus length. For MEX decipher requests
472 * the output needs to get padded. Minimum pad size is 10.
473 *
474 * Currently, the cases where padding will be added is for:
475 * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
476 * ZERO-PAD and CRT is only supported for PKD requests)
477 * - PCICC, always
478 */
479 pad_len = outputdatalength - reply_len;
480 if (pad_len > 0) {
481 if (pad_len < 10)
482 return -EINVAL;
483 /* 'restore' padding left in the PCICC/PCIXCC card. */
484 if (copy_to_user(outputdata, static_pad, pad_len - 1))
485 return -EFAULT;
486 if (put_user(0, outputdata + pad_len - 1))
487 return -EFAULT;
488 }
489 /* Copy the crypto response to user space. */
490 if (copy_to_user(outputdata + pad_len, data, reply_len))
491 return -EFAULT;
492 return 0;
493}
494
Ralph Wuerthner54321142006-09-20 15:58:36 +0200495/**
496 * Copy results from a type 86 XCRB reply message back to user space.
497 *
498 * @zdev: crypto device pointer
499 * @reply: reply AP message.
500 * @xcRB: pointer to XCRB
501 *
502 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
503 */
504static int convert_type86_xcrb(struct zcrypt_device *zdev,
505 struct ap_message *reply,
506 struct ica_xcRB *xcRB)
507{
508 struct type86_fmt2_msg *msg = reply->message;
509 char *data = reply->message;
510
511 /* Copy CPRB to user */
512 if (copy_to_user(xcRB->reply_control_blk_addr,
513 data + msg->fmt2.offset1, msg->fmt2.count1))
514 return -EFAULT;
515 xcRB->reply_control_blk_length = msg->fmt2.count1;
516
517 /* Copy data buffer to user */
518 if (msg->fmt2.count2)
519 if (copy_to_user(xcRB->reply_data_addr,
520 data + msg->fmt2.offset2, msg->fmt2.count2))
521 return -EFAULT;
522 xcRB->reply_data_length = msg->fmt2.count2;
523 return 0;
524}
525
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200526static int convert_type86_rng(struct zcrypt_device *zdev,
527 struct ap_message *reply,
528 char *buffer)
529{
530 struct {
531 struct type86_hdr hdr;
532 struct type86_fmt2_ext fmt2;
533 struct CPRBX cprbx;
534 } __attribute__((packed)) *msg = reply->message;
535 char *data = reply->message;
536
Felix Beck1a89dd82008-07-14 09:59:27 +0200537 if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0)
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200538 return -EINVAL;
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200539 memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
540 return msg->fmt2.count2;
541}
542
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200543static int convert_response_ica(struct zcrypt_device *zdev,
544 struct ap_message *reply,
545 char __user *outputdata,
546 unsigned int outputdatalength)
547{
548 struct type86x_reply *msg = reply->message;
549
550 /* Response type byte is the second byte in the response. */
551 switch (((unsigned char *) reply->message)[1]) {
552 case TYPE82_RSP_CODE:
553 case TYPE88_RSP_CODE:
554 return convert_error(zdev, reply);
555 case TYPE86_RSP_CODE:
Felix Beckc2567f82011-01-05 12:47:47 +0100556 if (msg->cprbx.ccp_rtcode &&
557 (msg->cprbx.ccp_rscode == 0x14f) &&
558 (outputdatalength > 256)) {
559 if (zdev->max_exp_bit_length <= 17) {
560 zdev->max_exp_bit_length = 17;
561 return -EAGAIN;
562 } else
563 return -EINVAL;
564 }
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200565 if (msg->hdr.reply_code)
566 return convert_error(zdev, reply);
567 if (msg->cprbx.cprb_ver_id == 0x02)
568 return convert_type86_ica(zdev, reply,
569 outputdata, outputdatalength);
Felix Beck942b7e62009-10-06 10:34:10 +0200570 /* Fall through, no break, incorrect cprb version is an unknown
571 * response */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200572 default: /* Unknown response type, this should NEVER EVER happen */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200573 zdev->online = 0;
574 return -EAGAIN; /* repeat the request on a different device. */
575 }
576}
577
Ralph Wuerthner54321142006-09-20 15:58:36 +0200578static int convert_response_xcrb(struct zcrypt_device *zdev,
579 struct ap_message *reply,
580 struct ica_xcRB *xcRB)
581{
582 struct type86x_reply *msg = reply->message;
583
584 /* Response type byte is the second byte in the response. */
585 switch (((unsigned char *) reply->message)[1]) {
586 case TYPE82_RSP_CODE:
587 case TYPE88_RSP_CODE:
588 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
589 return convert_error(zdev, reply);
590 case TYPE86_RSP_CODE:
591 if (msg->hdr.reply_code) {
592 memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
593 return convert_error(zdev, reply);
594 }
595 if (msg->cprbx.cprb_ver_id == 0x02)
596 return convert_type86_xcrb(zdev, reply, xcRB);
Felix Beck942b7e62009-10-06 10:34:10 +0200597 /* Fall through, no break, incorrect cprb version is an unknown
598 * response */
Ralph Wuerthner54321142006-09-20 15:58:36 +0200599 default: /* Unknown response type, this should NEVER EVER happen */
Ralph Wuerthner54321142006-09-20 15:58:36 +0200600 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
601 zdev->online = 0;
602 return -EAGAIN; /* repeat the request on a different device. */
603 }
604}
605
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200606static int convert_response_rng(struct zcrypt_device *zdev,
607 struct ap_message *reply,
608 char *data)
609{
610 struct type86x_reply *msg = reply->message;
611
612 switch (msg->hdr.type) {
613 case TYPE82_RSP_CODE:
614 case TYPE88_RSP_CODE:
615 return -EINVAL;
616 case TYPE86_RSP_CODE:
617 if (msg->hdr.reply_code)
618 return -EINVAL;
619 if (msg->cprbx.cprb_ver_id == 0x02)
620 return convert_type86_rng(zdev, reply, data);
Felix Beck942b7e62009-10-06 10:34:10 +0200621 /* Fall through, no break, incorrect cprb version is an unknown
622 * response */
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200623 default: /* Unknown response type, this should NEVER EVER happen */
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200624 zdev->online = 0;
625 return -EAGAIN; /* repeat the request on a different device. */
626 }
627}
628
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200629/**
630 * This function is called from the AP bus code after a crypto request
631 * "msg" has finished with the reply message "reply".
632 * It is called from tasklet context.
633 * @ap_dev: pointer to the AP device
634 * @msg: pointer to the AP message
635 * @reply: pointer to the AP reply message
636 */
637static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
638 struct ap_message *msg,
639 struct ap_message *reply)
640{
641 static struct error_hdr error_reply = {
642 .type = TYPE82_RSP_CODE,
643 .reply_code = REP82_ERROR_MACHINE_FAILURE,
644 };
Ralph Wuerthner54321142006-09-20 15:58:36 +0200645 struct response_type *resp_type =
646 (struct response_type *) msg->private;
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100647 struct type86x_reply *t86r;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200648 int length;
649
650 /* Copy the reply message to the request message buffer. */
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100651 if (IS_ERR(reply)) {
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200652 memcpy(msg->message, &error_reply, sizeof(error_reply));
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100653 goto out;
654 }
655 t86r = reply->message;
656 if (t86r->hdr.type == TYPE86_RSP_CODE &&
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200657 t86r->cprbx.cprb_ver_id == 0x02) {
Ralph Wuerthner54321142006-09-20 15:58:36 +0200658 switch (resp_type->type) {
659 case PCIXCC_RESPONSE_TYPE_ICA:
660 length = sizeof(struct type86x_reply)
661 + t86r->length - 2;
662 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
663 memcpy(msg->message, reply->message, length);
664 break;
665 case PCIXCC_RESPONSE_TYPE_XCRB:
666 length = t86r->fmt2.offset2 + t86r->fmt2.count2;
Holger Dengler7fe6f092011-12-27 11:27:19 +0100667 length = min(PCIXCC_MAX_XCRB_MESSAGE_SIZE, length);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200668 memcpy(msg->message, reply->message, length);
669 break;
670 default:
Felix Beck1a89dd82008-07-14 09:59:27 +0200671 memcpy(msg->message, &error_reply, sizeof error_reply);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200672 }
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200673 } else
674 memcpy(msg->message, reply->message, sizeof error_reply);
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100675out:
Ralph Wuerthner54321142006-09-20 15:58:36 +0200676 complete(&(resp_type->work));
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200677}
678
679static atomic_t zcrypt_step = ATOMIC_INIT(0);
680
681/**
682 * The request distributor calls this function if it picked the PCIXCC/CEX2C
683 * device to handle a modexpo request.
684 * @zdev: pointer to zcrypt_device structure that identifies the
685 * PCIXCC/CEX2C device to the request distributor
686 * @mex: pointer to the modexpo request buffer
687 */
688static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
689 struct ica_rsa_modexpo *mex)
690{
691 struct ap_message ap_msg;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200692 struct response_type resp_type = {
693 .type = PCIXCC_RESPONSE_TYPE_ICA,
694 };
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200695 int rc;
696
Felix Beck468ffdd2009-12-07 12:51:54 +0100697 ap_init_message(&ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200698 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
699 if (!ap_msg.message)
700 return -ENOMEM;
701 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
702 atomic_inc_return(&zcrypt_step);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200703 ap_msg.private = &resp_type;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200704 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
705 if (rc)
706 goto out_free;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200707 init_completion(&resp_type.work);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200708 ap_queue_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200709 rc = wait_for_completion_interruptible(&resp_type.work);
710 if (rc == 0)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200711 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
712 mex->outputdatalength);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200713 else
714 /* Signal pending. */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200715 ap_cancel_message(zdev->ap_dev, &ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200716out_free:
717 free_page((unsigned long) ap_msg.message);
718 return rc;
719}
720
721/**
722 * The request distributor calls this function if it picked the PCIXCC/CEX2C
723 * device to handle a modexpo_crt request.
724 * @zdev: pointer to zcrypt_device structure that identifies the
725 * PCIXCC/CEX2C device to the request distributor
726 * @crt: pointer to the modexpoc_crt request buffer
727 */
728static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
729 struct ica_rsa_modexpo_crt *crt)
730{
731 struct ap_message ap_msg;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200732 struct response_type resp_type = {
733 .type = PCIXCC_RESPONSE_TYPE_ICA,
734 };
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200735 int rc;
736
Felix Beck468ffdd2009-12-07 12:51:54 +0100737 ap_init_message(&ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200738 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
739 if (!ap_msg.message)
740 return -ENOMEM;
741 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
742 atomic_inc_return(&zcrypt_step);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200743 ap_msg.private = &resp_type;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200744 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
745 if (rc)
746 goto out_free;
Ralph Wuerthner54321142006-09-20 15:58:36 +0200747 init_completion(&resp_type.work);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200748 ap_queue_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200749 rc = wait_for_completion_interruptible(&resp_type.work);
750 if (rc == 0)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200751 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
752 crt->outputdatalength);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200753 else
754 /* Signal pending. */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200755 ap_cancel_message(zdev->ap_dev, &ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200756out_free:
757 free_page((unsigned long) ap_msg.message);
758 return rc;
759}
760
761/**
Ralph Wuerthner54321142006-09-20 15:58:36 +0200762 * The request distributor calls this function if it picked the PCIXCC/CEX2C
763 * device to handle a send_cprb request.
764 * @zdev: pointer to zcrypt_device structure that identifies the
765 * PCIXCC/CEX2C device to the request distributor
766 * @xcRB: pointer to the send_cprb request buffer
767 */
Heiko Carstens2b67fc42007-02-05 21:16:47 +0100768static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
769 struct ica_xcRB *xcRB)
Ralph Wuerthner54321142006-09-20 15:58:36 +0200770{
771 struct ap_message ap_msg;
772 struct response_type resp_type = {
773 .type = PCIXCC_RESPONSE_TYPE_XCRB,
774 };
775 int rc;
776
Felix Beck468ffdd2009-12-07 12:51:54 +0100777 ap_init_message(&ap_msg);
Robert P. J. Day5cbded52006-12-13 00:35:56 -0800778 ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
Ralph Wuerthner54321142006-09-20 15:58:36 +0200779 if (!ap_msg.message)
780 return -ENOMEM;
781 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;
821 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
822 atomic_inc_return(&zcrypt_step);
823 ap_msg.private = &resp_type;
824 rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE);
825 init_completion(&resp_type.work);
826 ap_queue_message(zdev->ap_dev, &ap_msg);
827 rc = wait_for_completion_interruptible(&resp_type.work);
828 if (rc == 0)
829 rc = convert_response_rng(zdev, &ap_msg, buffer);
830 else
831 /* Signal pending. */
832 ap_cancel_message(zdev->ap_dev, &ap_msg);
833 kfree(ap_msg.message);
834 return rc;
835}
836
837/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200838 * The crypto operations for a PCIXCC/CEX2C card.
839 */
840static struct zcrypt_ops zcrypt_pcixcc_ops = {
841 .rsa_modexpo = zcrypt_pcixcc_modexpo,
842 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
Ralph Wuerthner54321142006-09-20 15:58:36 +0200843 .send_cprb = zcrypt_pcixcc_send_cprb,
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200844};
845
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200846static struct zcrypt_ops zcrypt_pcixcc_with_rng_ops = {
847 .rsa_modexpo = zcrypt_pcixcc_modexpo,
848 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
849 .send_cprb = zcrypt_pcixcc_send_cprb,
850 .rng = zcrypt_pcixcc_rng,
851};
852
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200853/**
854 * Micro-code detection function. Its sends a message to a pcixcc card
855 * to find out the microcode level.
856 * @ap_dev: pointer to the AP device.
857 */
858static int zcrypt_pcixcc_mcl(struct ap_device *ap_dev)
859{
860 static unsigned char msg[] = {
861 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
862 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
863 0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
864 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
865 0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
866 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
867 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00,
868 0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00,
869 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
870 0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00,
871 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
872 0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32,
873 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,
874 0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,
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,0x00,0x00,0x00,0x00,0x00,
893 0x00,0x00,0x00,0x04,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,0x00,0x00,0x00,0x00,
899 0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x0A,
900 0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20,
901 0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05,
902 0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
903 0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55,
904 0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,
905 0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,
906 0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,
907 0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB,
908 0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54,
909 0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00,
910 0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00,
911 0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40,
912 0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C,
913 0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF,
914 0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9,
915 0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63,
916 0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5,
917 0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A,
918 0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01,
919 0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28,
920 0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91,
921 0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5,
922 0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C,
923 0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98,
924 0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96,
925 0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19,
926 0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47,
927 0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36,
928 0xF1,0x3D,0x93,0x53
929 };
930 unsigned long long psmid;
931 struct CPRBX *cprbx;
932 char *reply;
933 int rc, i;
934
935 reply = (void *) get_zeroed_page(GFP_KERNEL);
936 if (!reply)
937 return -ENOMEM;
938
939 rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, msg, sizeof(msg));
940 if (rc)
941 goto out_free;
942
943 /* Wait for the test message to complete. */
944 for (i = 0; i < 6; i++) {
945 mdelay(300);
946 rc = ap_recv(ap_dev->qid, &psmid, reply, 4096);
947 if (rc == 0 && psmid == 0x0102030405060708ULL)
948 break;
949 }
950
951 if (i >= 6) {
952 /* Got no answer. */
953 rc = -ENODEV;
954 goto out_free;
955 }
956
957 cprbx = (struct CPRBX *) (reply + 48);
958 if (cprbx->ccp_rtcode == 8 && cprbx->ccp_rscode == 33)
959 rc = ZCRYPT_PCIXCC_MCL2;
960 else
961 rc = ZCRYPT_PCIXCC_MCL3;
962out_free:
963 free_page((unsigned long) reply);
964 return rc;
965}
966
967/**
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200968 * Large random number detection function. Its sends a message to a pcixcc
969 * card to find out if large random numbers are supported.
970 * @ap_dev: pointer to the AP device.
971 *
972 * Returns 1 if large random numbers are supported, 0 if not and < 0 on error.
973 */
974static int zcrypt_pcixcc_rng_supported(struct ap_device *ap_dev)
975{
976 struct ap_message ap_msg;
977 unsigned long long psmid;
978 struct {
979 struct type86_hdr hdr;
980 struct type86_fmt2_ext fmt2;
981 struct CPRBX cprbx;
982 } __attribute__((packed)) *reply;
983 int rc, i;
984
Felix Beck468ffdd2009-12-07 12:51:54 +0100985 ap_init_message(&ap_msg);
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200986 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
987 if (!ap_msg.message)
988 return -ENOMEM;
989
990 rng_type6CPRB_msgX(ap_dev, &ap_msg, 4);
991 rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, ap_msg.message,
992 ap_msg.length);
993 if (rc)
994 goto out_free;
995
996 /* Wait for the test message to complete. */
997 for (i = 0; i < 2 * HZ; i++) {
998 msleep(1000 / HZ);
999 rc = ap_recv(ap_dev->qid, &psmid, ap_msg.message, 4096);
1000 if (rc == 0 && psmid == 0x0102030405060708ULL)
1001 break;
1002 }
1003
1004 if (i >= 2 * HZ) {
1005 /* Got no answer. */
1006 rc = -ENODEV;
1007 goto out_free;
1008 }
1009
1010 reply = ap_msg.message;
1011 if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0)
1012 rc = 1;
1013 else
1014 rc = 0;
1015out_free:
1016 free_page((unsigned long) ap_msg.message);
1017 return rc;
1018}
1019
1020/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001021 * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device
1022 * since the bus_match already checked the hardware type. The PCIXCC
1023 * cards come in two flavours: micro code level 2 and micro code level 3.
1024 * This is checked by sending a test message to the device.
1025 * @ap_dev: pointer to the AP device.
1026 */
1027static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
1028{
1029 struct zcrypt_device *zdev;
Felix Beck8e89b6b2009-12-07 12:51:57 +01001030 int rc = 0;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001031
Holger Dengler7fe6f092011-12-27 11:27:19 +01001032 zdev = zcrypt_device_alloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE);
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001033 if (!zdev)
1034 return -ENOMEM;
1035 zdev->ap_dev = ap_dev;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001036 zdev->online = 1;
Felix Beck8e89b6b2009-12-07 12:51:57 +01001037 switch (ap_dev->device_type) {
1038 case AP_DEVICE_TYPE_PCIXCC:
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001039 rc = zcrypt_pcixcc_mcl(ap_dev);
1040 if (rc < 0) {
1041 zcrypt_device_free(zdev);
1042 return rc;
1043 }
1044 zdev->user_space_type = rc;
1045 if (rc == ZCRYPT_PCIXCC_MCL2) {
1046 zdev->type_string = "PCIXCC_MCL2";
1047 zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING;
1048 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
1049 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
Felix Beckc2567f82011-01-05 12:47:47 +01001050 zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001051 } else {
1052 zdev->type_string = "PCIXCC_MCL3";
1053 zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING;
1054 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
1055 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
Felix Beckc2567f82011-01-05 12:47:47 +01001056 zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001057 }
Felix Beck8e89b6b2009-12-07 12:51:57 +01001058 break;
1059 case AP_DEVICE_TYPE_CEX2C:
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001060 zdev->user_space_type = ZCRYPT_CEX2C;
1061 zdev->type_string = "CEX2C";
1062 zdev->speed_rating = CEX2C_SPEED_RATING;
1063 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
1064 zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
Felix Beckc2567f82011-01-05 12:47:47 +01001065 zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
Felix Beck8e89b6b2009-12-07 12:51:57 +01001066 break;
1067 case AP_DEVICE_TYPE_CEX3C:
1068 zdev->user_space_type = ZCRYPT_CEX3C;
1069 zdev->type_string = "CEX3C";
1070 zdev->speed_rating = CEX3C_SPEED_RATING;
1071 zdev->min_mod_size = CEX3C_MIN_MOD_SIZE;
1072 zdev->max_mod_size = CEX3C_MAX_MOD_SIZE;
Felix Beckc2567f82011-01-05 12:47:47 +01001073 zdev->max_exp_bit_length = CEX3C_MAX_MOD_SIZE;
Felix Beck8e89b6b2009-12-07 12:51:57 +01001074 break;
1075 default:
1076 goto out_free;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001077 }
Felix Beck8e89b6b2009-12-07 12:51:57 +01001078
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +02001079 rc = zcrypt_pcixcc_rng_supported(ap_dev);
1080 if (rc < 0) {
1081 zcrypt_device_free(zdev);
1082 return rc;
1083 }
1084 if (rc)
1085 zdev->ops = &zcrypt_pcixcc_with_rng_ops;
1086 else
1087 zdev->ops = &zcrypt_pcixcc_ops;
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001088 ap_dev->reply = &zdev->reply;
1089 ap_dev->private = zdev;
1090 rc = zcrypt_device_register(zdev);
1091 if (rc)
1092 goto out_free;
1093 return 0;
1094
1095 out_free:
1096 ap_dev->private = NULL;
1097 zcrypt_device_free(zdev);
1098 return rc;
1099}
1100
1101/**
1102 * This is called to remove the extended PCIXCC/CEX2C driver information
1103 * if an AP device is removed.
1104 */
1105static void zcrypt_pcixcc_remove(struct ap_device *ap_dev)
1106{
1107 struct zcrypt_device *zdev = ap_dev->private;
1108
1109 zcrypt_device_unregister(zdev);
1110}
1111
1112int __init zcrypt_pcixcc_init(void)
1113{
1114 return ap_driver_register(&zcrypt_pcixcc_driver, THIS_MODULE, "pcixcc");
1115}
1116
1117void zcrypt_pcixcc_exit(void)
1118{
1119 ap_driver_unregister(&zcrypt_pcixcc_driver);
1120}
1121
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001122module_init(zcrypt_pcixcc_init);
1123module_exit(zcrypt_pcixcc_exit);