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