blob: f4b0c47954341d4fcc5d88af1119d4064580db92 [file] [log] [blame]
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001/*
2 * linux/drivers/s390/crypto/zcrypt_pcicc.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 <asm/atomic.h>
33#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_cca_key.h"
40
41#define PCICC_MIN_MOD_SIZE 64 /* 512 bits */
42#define PCICC_MAX_MOD_SIZE_OLD 128 /* 1024 bits */
43#define PCICC_MAX_MOD_SIZE 256 /* 2048 bits */
44
Felix Beck1749a812008-04-17 07:46:28 +020045/*
Martin Schwidefsky6684af12006-09-20 15:58:32 +020046 * PCICC cards need a speed rating of 0. This keeps them at the end of
47 * the zcrypt device list (see zcrypt_api.c). PCICC cards are only
48 * used if no other cards are present because they are slow and can only
49 * cope with PKCS12 padded requests. The logic is queer. PKCS11 padded
50 * requests are rejected. The modexpo function encrypts PKCS12 padded data
51 * and decrypts any non-PKCS12 padded data (except PKCS11) in the assumption
52 * that it's encrypted PKCS12 data. The modexpo_crt function always decrypts
53 * the data in the assumption that its PKCS12 encrypted data.
54 */
55#define PCICC_SPEED_RATING 0
56
57#define PCICC_MAX_MESSAGE_SIZE 0x710 /* max size type6 v1 crt message */
58#define PCICC_MAX_RESPONSE_SIZE 0x710 /* max size type86 v1 reply */
59
60#define PCICC_CLEANUP_TIME (15*HZ)
61
62static struct ap_device_id zcrypt_pcicc_ids[] = {
63 { AP_DEVICE(AP_DEVICE_TYPE_PCICC) },
64 { /* end of list */ },
65};
66
67#ifndef CONFIG_ZCRYPT_MONOLITHIC
68MODULE_DEVICE_TABLE(ap, zcrypt_pcicc_ids);
69MODULE_AUTHOR("IBM Corporation");
70MODULE_DESCRIPTION("PCICC Cryptographic Coprocessor device driver, "
71 "Copyright 2001, 2006 IBM Corporation");
72MODULE_LICENSE("GPL");
73#endif
74
75static int zcrypt_pcicc_probe(struct ap_device *ap_dev);
76static void zcrypt_pcicc_remove(struct ap_device *ap_dev);
77static void zcrypt_pcicc_receive(struct ap_device *, struct ap_message *,
78 struct ap_message *);
79
80static struct ap_driver zcrypt_pcicc_driver = {
81 .probe = zcrypt_pcicc_probe,
82 .remove = zcrypt_pcicc_remove,
83 .receive = zcrypt_pcicc_receive,
84 .ids = zcrypt_pcicc_ids,
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +020085 .request_timeout = PCICC_CLEANUP_TIME,
Martin Schwidefsky6684af12006-09-20 15:58:32 +020086};
87
88/**
89 * The following is used to initialize the CPRB passed to the PCICC card
90 * in a type6 message. The 3 fields that must be filled in at execution
91 * time are req_parml, rpl_parml and usage_domain. Note that all three
92 * fields are *little*-endian. Actually, everything about this interface
93 * is ascii/little-endian, since the device has 'Intel inside'.
94 *
95 * The CPRB is followed immediately by the parm block.
96 * The parm block contains:
97 * - function code ('PD' 0x5044 or 'PK' 0x504B)
98 * - rule block (0x0A00 'PKCS-1.2' or 0x0A00 'ZERO-PAD')
99 * - VUD block
100 */
101static struct CPRB static_cprb = {
102 .cprb_len = __constant_cpu_to_le16(0x0070),
103 .cprb_ver_id = 0x41,
104 .func_id = {0x54,0x32},
105 .checkpoint_flag= 0x01,
106 .svr_namel = __constant_cpu_to_le16(0x0008),
107 .svr_name = {'I','C','S','F',' ',' ',' ',' '}
108};
109
110/**
111 * Check the message for PKCS11 padding.
112 */
113static inline int is_PKCS11_padded(unsigned char *buffer, int length)
114{
115 int i;
116 if ((buffer[0] != 0x00) || (buffer[1] != 0x01))
117 return 0;
118 for (i = 2; i < length; i++)
119 if (buffer[i] != 0xFF)
120 break;
121 if (i < 10 || i == length)
122 return 0;
123 if (buffer[i] != 0x00)
124 return 0;
125 return 1;
126}
127
128/**
129 * Check the message for PKCS12 padding.
130 */
131static inline int is_PKCS12_padded(unsigned char *buffer, int length)
132{
133 int i;
134 if ((buffer[0] != 0x00) || (buffer[1] != 0x02))
135 return 0;
136 for (i = 2; i < length; i++)
137 if (buffer[i] == 0x00)
138 break;
139 if ((i < 10) || (i == length))
140 return 0;
141 if (buffer[i] != 0x00)
142 return 0;
143 return 1;
144}
145
146/**
147 * Convert a ICAMEX message to a type6 MEX message.
148 *
149 * @zdev: crypto device pointer
150 * @zreq: crypto request pointer
151 * @mex: pointer to user input data
152 *
153 * Returns 0 on success or -EFAULT.
154 */
155static int ICAMEX_msg_to_type6MEX_msg(struct zcrypt_device *zdev,
156 struct ap_message *ap_msg,
157 struct ica_rsa_modexpo *mex)
158{
159 static struct type6_hdr static_type6_hdr = {
160 .type = 0x06,
161 .offset1 = 0x00000058,
162 .agent_id = {0x01,0x00,0x43,0x43,0x41,0x2D,0x41,0x50,
163 0x50,0x4C,0x20,0x20,0x20,0x01,0x01,0x01},
164 .function_code = {'P','K'},
165 };
166 static struct function_and_rules_block static_pke_function_and_rules ={
167 .function_code = {'P','K'},
168 .ulen = __constant_cpu_to_le16(10),
169 .only_rule = {'P','K','C','S','-','1','.','2'}
170 };
171 struct {
172 struct type6_hdr hdr;
173 struct CPRB cprb;
174 struct function_and_rules_block fr;
175 unsigned short length;
176 char text[0];
177 } __attribute__((packed)) *msg = ap_msg->message;
178 int vud_len, pad_len, size;
179
180 /* VUD.ciphertext */
181 if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
182 return -EFAULT;
183
184 if (is_PKCS11_padded(msg->text, mex->inputdatalength))
185 return -EINVAL;
186
187 /* static message header and f&r */
188 msg->hdr = static_type6_hdr;
189 msg->fr = static_pke_function_and_rules;
190
191 if (is_PKCS12_padded(msg->text, mex->inputdatalength)) {
192 /* strip the padding and adjust the data length */
193 pad_len = strnlen(msg->text + 2, mex->inputdatalength - 2) + 3;
194 if (pad_len <= 9 || pad_len >= mex->inputdatalength)
195 return -ENODEV;
196 vud_len = mex->inputdatalength - pad_len;
197 memmove(msg->text, msg->text + pad_len, vud_len);
198 msg->length = cpu_to_le16(vud_len + 2);
199
200 /* Set up key after the variable length text. */
201 size = zcrypt_type6_mex_key_en(mex, msg->text + vud_len, 0);
202 if (size < 0)
203 return size;
204 size += sizeof(*msg) + vud_len; /* total size of msg */
205 } else {
206 vud_len = mex->inputdatalength;
207 msg->length = cpu_to_le16(2 + vud_len);
208
209 msg->hdr.function_code[1] = 'D';
210 msg->fr.function_code[1] = 'D';
211
212 /* Set up key after the variable length text. */
213 size = zcrypt_type6_mex_key_de(mex, msg->text + vud_len, 0);
214 if (size < 0)
215 return size;
216 size += sizeof(*msg) + vud_len; /* total size of msg */
217 }
218
219 /* message header, cprb and f&r */
220 msg->hdr.ToCardLen1 = (size - sizeof(msg->hdr) + 3) & -4;
221 msg->hdr.FromCardLen1 = PCICC_MAX_RESPONSE_SIZE - sizeof(msg->hdr);
222
223 msg->cprb = static_cprb;
224 msg->cprb.usage_domain[0]= AP_QID_QUEUE(zdev->ap_dev->qid);
225 msg->cprb.req_parml = cpu_to_le16(size - sizeof(msg->hdr) -
226 sizeof(msg->cprb));
227 msg->cprb.rpl_parml = cpu_to_le16(msg->hdr.FromCardLen1);
228
229 ap_msg->length = (size + 3) & -4;
230 return 0;
231}
232
233/**
234 * Convert a ICACRT message to a type6 CRT message.
235 *
236 * @zdev: crypto device pointer
237 * @zreq: crypto request pointer
238 * @crt: pointer to user input data
239 *
240 * Returns 0 on success or -EFAULT.
241 */
242static int ICACRT_msg_to_type6CRT_msg(struct zcrypt_device *zdev,
243 struct ap_message *ap_msg,
244 struct ica_rsa_modexpo_crt *crt)
245{
246 static struct type6_hdr static_type6_hdr = {
247 .type = 0x06,
248 .offset1 = 0x00000058,
249 .agent_id = {0x01,0x00,0x43,0x43,0x41,0x2D,0x41,0x50,
250 0x50,0x4C,0x20,0x20,0x20,0x01,0x01,0x01},
251 .function_code = {'P','D'},
252 };
253 static struct function_and_rules_block static_pkd_function_and_rules ={
254 .function_code = {'P','D'},
255 .ulen = __constant_cpu_to_le16(10),
256 .only_rule = {'P','K','C','S','-','1','.','2'}
257 };
258 struct {
259 struct type6_hdr hdr;
260 struct CPRB cprb;
261 struct function_and_rules_block fr;
262 unsigned short length;
263 char text[0];
264 } __attribute__((packed)) *msg = ap_msg->message;
265 int size;
266
267 /* VUD.ciphertext */
268 msg->length = cpu_to_le16(2 + crt->inputdatalength);
269 if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
270 return -EFAULT;
271
272 if (is_PKCS11_padded(msg->text, crt->inputdatalength))
273 return -EINVAL;
274
275 /* Set up key after the variable length text. */
276 size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 0);
277 if (size < 0)
278 return size;
279 size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */
280
281 /* message header, cprb and f&r */
282 msg->hdr = static_type6_hdr;
283 msg->hdr.ToCardLen1 = (size - sizeof(msg->hdr) + 3) & -4;
284 msg->hdr.FromCardLen1 = PCICC_MAX_RESPONSE_SIZE - sizeof(msg->hdr);
285
286 msg->cprb = static_cprb;
287 msg->cprb.usage_domain[0] = AP_QID_QUEUE(zdev->ap_dev->qid);
288 msg->cprb.req_parml = msg->cprb.rpl_parml =
289 cpu_to_le16(size - sizeof(msg->hdr) - sizeof(msg->cprb));
290
291 msg->fr = static_pkd_function_and_rules;
292
293 ap_msg->length = (size + 3) & -4;
294 return 0;
295}
296
297/**
298 * Copy results from a type 86 reply message back to user space.
299 *
300 * @zdev: crypto device pointer
301 * @reply: reply AP message.
302 * @data: pointer to user output data
303 * @length: size of user output data
304 *
305 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
306 */
307struct type86_reply {
308 struct type86_hdr hdr;
309 struct type86_fmt2_ext fmt2;
310 struct CPRB cprb;
311 unsigned char pad[4]; /* 4 byte function code/rules block ? */
312 unsigned short length;
313 char text[0];
314} __attribute__((packed));
315
316static int convert_type86(struct zcrypt_device *zdev,
317 struct ap_message *reply,
318 char __user *outputdata,
319 unsigned int outputdatalength)
320{
321 static unsigned char static_pad[] = {
322 0x00,0x02,
323 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,
324 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57,
325 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,
326 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39,
327 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,
328 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D,
329 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,
330 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F,
331 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,
332 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45,
333 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,
334 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F,
335 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,
336 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D,
337 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,
338 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9,
339 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,
340 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B,
341 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,
342 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD,
343 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,
344 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1,
345 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,
346 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23,
347 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,
348 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43,
349 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,
350 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F,
351 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,
352 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD,
353 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,
354 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09
355 };
356 struct type86_reply *msg = reply->message;
357 unsigned short service_rc, service_rs;
358 unsigned int reply_len, pad_len;
359 char *data;
360
361 service_rc = le16_to_cpu(msg->cprb.ccp_rtcode);
362 if (unlikely(service_rc != 0)) {
363 service_rs = le16_to_cpu(msg->cprb.ccp_rscode);
Felix Beck1a89dd82008-07-14 09:59:27 +0200364 if (service_rc == 8 && service_rs == 66)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200365 return -EINVAL;
Felix Beck1a89dd82008-07-14 09:59:27 +0200366 if (service_rc == 8 && service_rs == 65)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200367 return -EINVAL;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200368 if (service_rc == 8 && service_rs == 770) {
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200369 zdev->max_mod_size = PCICC_MAX_MOD_SIZE_OLD;
370 return -EAGAIN;
371 }
372 if (service_rc == 8 && service_rs == 783) {
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200373 zdev->max_mod_size = PCICC_MAX_MOD_SIZE_OLD;
374 return -EAGAIN;
375 }
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200376 zdev->online = 0;
377 return -EAGAIN; /* repeat the request on a different device. */
378 }
379 data = msg->text;
380 reply_len = le16_to_cpu(msg->length) - 2;
381 if (reply_len > outputdatalength)
382 return -EINVAL;
Felix Beck1749a812008-04-17 07:46:28 +0200383 /*
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200384 * For all encipher requests, the length of the ciphertext (reply_len)
385 * will always equal the modulus length. For MEX decipher requests
386 * the output needs to get padded. Minimum pad size is 10.
387 *
388 * Currently, the cases where padding will be added is for:
389 * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
390 * ZERO-PAD and CRT is only supported for PKD requests)
391 * - PCICC, always
392 */
393 pad_len = outputdatalength - reply_len;
394 if (pad_len > 0) {
395 if (pad_len < 10)
396 return -EINVAL;
397 /* 'restore' padding left in the PCICC/PCIXCC card. */
398 if (copy_to_user(outputdata, static_pad, pad_len - 1))
399 return -EFAULT;
400 if (put_user(0, outputdata + pad_len - 1))
401 return -EFAULT;
402 }
403 /* Copy the crypto response to user space. */
404 if (copy_to_user(outputdata + pad_len, data, reply_len))
405 return -EFAULT;
406 return 0;
407}
408
409static int convert_response(struct zcrypt_device *zdev,
410 struct ap_message *reply,
411 char __user *outputdata,
412 unsigned int outputdatalength)
413{
414 struct type86_reply *msg = reply->message;
415
416 /* Response type byte is the second byte in the response. */
417 switch (msg->hdr.type) {
418 case TYPE82_RSP_CODE:
419 case TYPE88_RSP_CODE:
420 return convert_error(zdev, reply);
421 case TYPE86_RSP_CODE:
422 if (msg->hdr.reply_code)
423 return convert_error(zdev, reply);
424 if (msg->cprb.cprb_ver_id == 0x01)
425 return convert_type86(zdev, reply,
426 outputdata, outputdatalength);
427 /* no break, incorrect cprb version is an unknown response */
428 default: /* Unknown response type, this should NEVER EVER happen */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200429 zdev->online = 0;
430 return -EAGAIN; /* repeat the request on a different device. */
431 }
432}
433
434/**
435 * This function is called from the AP bus code after a crypto request
436 * "msg" has finished with the reply message "reply".
437 * It is called from tasklet context.
438 * @ap_dev: pointer to the AP device
439 * @msg: pointer to the AP message
440 * @reply: pointer to the AP reply message
441 */
442static void zcrypt_pcicc_receive(struct ap_device *ap_dev,
443 struct ap_message *msg,
444 struct ap_message *reply)
445{
446 static struct error_hdr error_reply = {
447 .type = TYPE82_RSP_CODE,
448 .reply_code = REP82_ERROR_MACHINE_FAILURE,
449 };
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100450 struct type86_reply *t86r;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200451 int length;
452
453 /* Copy the reply message to the request message buffer. */
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100454 if (IS_ERR(reply)) {
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200455 memcpy(msg->message, &error_reply, sizeof(error_reply));
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100456 goto out;
457 }
458 t86r = reply->message;
459 if (t86r->hdr.type == TYPE86_RSP_CODE &&
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200460 t86r->cprb.cprb_ver_id == 0x01) {
461 length = sizeof(struct type86_reply) + t86r->length - 2;
462 length = min(PCICC_MAX_RESPONSE_SIZE, length);
463 memcpy(msg->message, reply->message, length);
464 } else
465 memcpy(msg->message, reply->message, sizeof error_reply);
Julia Lawall21e7b2c2008-12-25 13:39:28 +0100466out:
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200467 complete((struct completion *) msg->private);
468}
469
470static atomic_t zcrypt_step = ATOMIC_INIT(0);
471
472/**
473 * The request distributor calls this function if it picked the PCICC
474 * device to handle a modexpo request.
475 * @zdev: pointer to zcrypt_device structure that identifies the
476 * PCICC device to the request distributor
477 * @mex: pointer to the modexpo request buffer
478 */
479static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev,
480 struct ica_rsa_modexpo *mex)
481{
482 struct ap_message ap_msg;
483 struct completion work;
484 int rc;
485
486 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
487 if (!ap_msg.message)
488 return -ENOMEM;
489 ap_msg.length = PAGE_SIZE;
490 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
491 atomic_inc_return(&zcrypt_step);
492 ap_msg.private = &work;
493 rc = ICAMEX_msg_to_type6MEX_msg(zdev, &ap_msg, mex);
494 if (rc)
495 goto out_free;
496 init_completion(&work);
497 ap_queue_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200498 rc = wait_for_completion_interruptible(&work);
499 if (rc == 0)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200500 rc = convert_response(zdev, &ap_msg, mex->outputdata,
501 mex->outputdatalength);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200502 else
503 /* Signal pending. */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200504 ap_cancel_message(zdev->ap_dev, &ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200505out_free:
506 free_page((unsigned long) ap_msg.message);
507 return rc;
508}
509
510/**
511 * The request distributor calls this function if it picked the PCICC
512 * device to handle a modexpo_crt request.
513 * @zdev: pointer to zcrypt_device structure that identifies the
514 * PCICC device to the request distributor
515 * @crt: pointer to the modexpoc_crt request buffer
516 */
517static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev,
518 struct ica_rsa_modexpo_crt *crt)
519{
520 struct ap_message ap_msg;
521 struct completion work;
522 int rc;
523
524 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
525 if (!ap_msg.message)
526 return -ENOMEM;
527 ap_msg.length = PAGE_SIZE;
528 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
529 atomic_inc_return(&zcrypt_step);
530 ap_msg.private = &work;
531 rc = ICACRT_msg_to_type6CRT_msg(zdev, &ap_msg, crt);
532 if (rc)
533 goto out_free;
534 init_completion(&work);
535 ap_queue_message(zdev->ap_dev, &ap_msg);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200536 rc = wait_for_completion_interruptible(&work);
537 if (rc == 0)
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200538 rc = convert_response(zdev, &ap_msg, crt->outputdata,
539 crt->outputdatalength);
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +0200540 else
541 /* Signal pending. */
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200542 ap_cancel_message(zdev->ap_dev, &ap_msg);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200543out_free:
544 free_page((unsigned long) ap_msg.message);
545 return rc;
546}
547
548/**
549 * The crypto operations for a PCICC card.
550 */
551static struct zcrypt_ops zcrypt_pcicc_ops = {
552 .rsa_modexpo = zcrypt_pcicc_modexpo,
553 .rsa_modexpo_crt = zcrypt_pcicc_modexpo_crt,
554};
555
556/**
557 * Probe function for PCICC cards. It always accepts the AP device
558 * since the bus_match already checked the hardware type.
559 * @ap_dev: pointer to the AP device.
560 */
561static int zcrypt_pcicc_probe(struct ap_device *ap_dev)
562{
563 struct zcrypt_device *zdev;
564 int rc;
565
566 zdev = zcrypt_device_alloc(PCICC_MAX_RESPONSE_SIZE);
567 if (!zdev)
568 return -ENOMEM;
569 zdev->ap_dev = ap_dev;
570 zdev->ops = &zcrypt_pcicc_ops;
571 zdev->online = 1;
572 zdev->user_space_type = ZCRYPT_PCICC;
573 zdev->type_string = "PCICC";
574 zdev->min_mod_size = PCICC_MIN_MOD_SIZE;
575 zdev->max_mod_size = PCICC_MAX_MOD_SIZE;
576 zdev->speed_rating = PCICC_SPEED_RATING;
577 ap_dev->reply = &zdev->reply;
578 ap_dev->private = zdev;
579 rc = zcrypt_device_register(zdev);
580 if (rc)
581 goto out_free;
582 return 0;
583
584 out_free:
585 ap_dev->private = NULL;
586 zcrypt_device_free(zdev);
587 return rc;
588}
589
590/**
591 * This is called to remove the extended PCICC driver information
592 * if an AP device is removed.
593 */
594static void zcrypt_pcicc_remove(struct ap_device *ap_dev)
595{
596 struct zcrypt_device *zdev = ap_dev->private;
597
598 zcrypt_device_unregister(zdev);
599}
600
601int __init zcrypt_pcicc_init(void)
602{
603 return ap_driver_register(&zcrypt_pcicc_driver, THIS_MODULE, "pcicc");
604}
605
606void zcrypt_pcicc_exit(void)
607{
608 ap_driver_unregister(&zcrypt_pcicc_driver);
609}
610
611#ifndef CONFIG_ZCRYPT_MONOLITHIC
612module_init(zcrypt_pcicc_init);
613module_exit(zcrypt_pcicc_exit);
614#endif