aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2006-09-20 09:58:29 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-09-20 09:58:29 -0400
commit963ed931c3fd18082bfde0e8704a28955663abf4 (patch)
tree3d7fb72d8aca7b4020e8bfe0b055c71f3d7de5c7 /drivers
parent2dbc2418bac32a18a372ae9aec386f0fe9174389 (diff)
[S390] zcrypt CEX2A, CEX2C, PCICA accelerator card ap bus drivers.
Signed-off-by: Ralph Wuerthner <rwuerthn@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/crypto/zcrypt_cex2a.c435
-rw-r--r--drivers/s390/crypto/zcrypt_cex2a.h126
-rw-r--r--drivers/s390/crypto/zcrypt_error.h133
-rw-r--r--drivers/s390/crypto/zcrypt_pcica.c418
-rw-r--r--drivers/s390/crypto/zcrypt_pcica.h117
5 files changed, 1229 insertions, 0 deletions
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
new file mode 100644
index 000000000000..350248e5cd93
--- /dev/null
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -0,0 +1,435 @@
1/*
2 * linux/drivers/s390/crypto/zcrypt_cex2a.c
3 *
4 * zcrypt 2.0.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/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_cex2a.h"
39
40#define CEX2A_MIN_MOD_SIZE 1 /* 8 bits */
41#define CEX2A_MAX_MOD_SIZE 256 /* 2048 bits */
42
43#define CEX2A_SPEED_RATING 970
44
45#define CEX2A_MAX_MESSAGE_SIZE 0x390 /* sizeof(struct type50_crb2_msg) */
46#define CEX2A_MAX_RESPONSE_SIZE 0x110 /* max outputdatalength + type80_hdr */
47
48#define CEX2A_CLEANUP_TIME (15*HZ)
49
50static struct ap_device_id zcrypt_cex2a_ids[] = {
51 { AP_DEVICE(AP_DEVICE_TYPE_CEX2A) },
52 { /* end of list */ },
53};
54
55#ifndef CONFIG_ZCRYPT_MONOLITHIC
56MODULE_DEVICE_TABLE(ap, zcrypt_cex2a_ids);
57MODULE_AUTHOR("IBM Corporation");
58MODULE_DESCRIPTION("CEX2A Cryptographic Coprocessor device driver, "
59 "Copyright 2001, 2006 IBM Corporation");
60MODULE_LICENSE("GPL");
61#endif
62
63static int zcrypt_cex2a_probe(struct ap_device *ap_dev);
64static void zcrypt_cex2a_remove(struct ap_device *ap_dev);
65static void zcrypt_cex2a_receive(struct ap_device *, struct ap_message *,
66 struct ap_message *);
67
68static struct ap_driver zcrypt_cex2a_driver = {
69 .probe = zcrypt_cex2a_probe,
70 .remove = zcrypt_cex2a_remove,
71 .receive = zcrypt_cex2a_receive,
72 .ids = zcrypt_cex2a_ids,
73};
74
75/**
76 * Convert a ICAMEX message to a type50 MEX message.
77 *
78 * @zdev: crypto device pointer
79 * @zreq: crypto request pointer
80 * @mex: pointer to user input data
81 *
82 * Returns 0 on success or -EFAULT.
83 */
84static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_device *zdev,
85 struct ap_message *ap_msg,
86 struct ica_rsa_modexpo *mex)
87{
88 unsigned char *mod, *exp, *inp;
89 int mod_len;
90
91 mod_len = mex->inputdatalength;
92
93 if (mod_len <= 128) {
94 struct type50_meb1_msg *meb1 = ap_msg->message;
95 memset(meb1, 0, sizeof(*meb1));
96 ap_msg->length = sizeof(*meb1);
97 meb1->header.msg_type_code = TYPE50_TYPE_CODE;
98 meb1->header.msg_len = sizeof(*meb1);
99 meb1->keyblock_type = TYPE50_MEB1_FMT;
100 mod = meb1->modulus + sizeof(meb1->modulus) - mod_len;
101 exp = meb1->exponent + sizeof(meb1->exponent) - mod_len;
102 inp = meb1->message + sizeof(meb1->message) - mod_len;
103 } else {
104 struct type50_meb2_msg *meb2 = ap_msg->message;
105 memset(meb2, 0, sizeof(*meb2));
106 ap_msg->length = sizeof(*meb2);
107 meb2->header.msg_type_code = TYPE50_TYPE_CODE;
108 meb2->header.msg_len = sizeof(*meb2);
109 meb2->keyblock_type = TYPE50_MEB2_FMT;
110 mod = meb2->modulus + sizeof(meb2->modulus) - mod_len;
111 exp = meb2->exponent + sizeof(meb2->exponent) - mod_len;
112 inp = meb2->message + sizeof(meb2->message) - mod_len;
113 }
114
115 if (copy_from_user(mod, mex->n_modulus, mod_len) ||
116 copy_from_user(exp, mex->b_key, mod_len) ||
117 copy_from_user(inp, mex->inputdata, mod_len))
118 return -EFAULT;
119 return 0;
120}
121
122/**
123 * Convert a ICACRT message to a type50 CRT message.
124 *
125 * @zdev: crypto device pointer
126 * @zreq: crypto request pointer
127 * @crt: pointer to user input data
128 *
129 * Returns 0 on success or -EFAULT.
130 */
131static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_device *zdev,
132 struct ap_message *ap_msg,
133 struct ica_rsa_modexpo_crt *crt)
134{
135 int mod_len, short_len, long_len, long_offset;
136 unsigned char *p, *q, *dp, *dq, *u, *inp;
137
138 mod_len = crt->inputdatalength;
139 short_len = mod_len / 2;
140 long_len = mod_len / 2 + 8;
141
142 /*
143 * CEX2A cannot handle p, dp, or U > 128 bytes.
144 * If we have one of these, we need to do extra checking.
145 */
146 if (long_len > 128) {
147 /*
148 * zcrypt_rsa_crt already checked for the leading
149 * zeroes of np_prime, bp_key and u_mult_inc.
150 */
151 long_offset = long_len - 128;
152 long_len = 128;
153 } else
154 long_offset = 0;
155
156 /*
157 * Instead of doing extra work for p, dp, U > 64 bytes, we'll just use
158 * the larger message structure.
159 */
160 if (long_len <= 64) {
161 struct type50_crb1_msg *crb1 = ap_msg->message;
162 memset(crb1, 0, sizeof(*crb1));
163 ap_msg->length = sizeof(*crb1);
164 crb1->header.msg_type_code = TYPE50_TYPE_CODE;
165 crb1->header.msg_len = sizeof(*crb1);
166 crb1->keyblock_type = TYPE50_CRB1_FMT;
167 p = crb1->p + sizeof(crb1->p) - long_len;
168 q = crb1->q + sizeof(crb1->q) - short_len;
169 dp = crb1->dp + sizeof(crb1->dp) - long_len;
170 dq = crb1->dq + sizeof(crb1->dq) - short_len;
171 u = crb1->u + sizeof(crb1->u) - long_len;
172 inp = crb1->message + sizeof(crb1->message) - mod_len;
173 } else {
174 struct type50_crb2_msg *crb2 = ap_msg->message;
175 memset(crb2, 0, sizeof(*crb2));
176 ap_msg->length = sizeof(*crb2);
177 crb2->header.msg_type_code = TYPE50_TYPE_CODE;
178 crb2->header.msg_len = sizeof(*crb2);
179 crb2->keyblock_type = TYPE50_CRB2_FMT;
180 p = crb2->p + sizeof(crb2->p) - long_len;
181 q = crb2->q + sizeof(crb2->q) - short_len;
182 dp = crb2->dp + sizeof(crb2->dp) - long_len;
183 dq = crb2->dq + sizeof(crb2->dq) - short_len;
184 u = crb2->u + sizeof(crb2->u) - long_len;
185 inp = crb2->message + sizeof(crb2->message) - mod_len;
186 }
187
188 if (copy_from_user(p, crt->np_prime + long_offset, long_len) ||
189 copy_from_user(q, crt->nq_prime, short_len) ||
190 copy_from_user(dp, crt->bp_key + long_offset, long_len) ||
191 copy_from_user(dq, crt->bq_key, short_len) ||
192 copy_from_user(u, crt->u_mult_inv + long_offset, long_len) ||
193 copy_from_user(inp, crt->inputdata, mod_len))
194 return -EFAULT;
195
196
197 return 0;
198}
199
200/**
201 * Copy results from a type 80 reply message back to user space.
202 *
203 * @zdev: crypto device pointer
204 * @reply: reply AP message.
205 * @data: pointer to user output data
206 * @length: size of user output data
207 *
208 * Returns 0 on success or -EFAULT.
209 */
210static int convert_type80(struct zcrypt_device *zdev,
211 struct ap_message *reply,
212 char __user *outputdata,
213 unsigned int outputdatalength)
214{
215 struct type80_hdr *t80h = reply->message;
216 unsigned char *data;
217
218 if (t80h->len < sizeof(*t80h) + outputdatalength) {
219 /* The result is too short, the CEX2A card may not do that.. */
220 zdev->online = 0;
221 return -EAGAIN; /* repeat the request on a different device. */
222 }
223 BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE);
224 data = reply->message + t80h->len - outputdatalength;
225 if (copy_to_user(outputdata, data, outputdatalength))
226 return -EFAULT;
227 return 0;
228}
229
230static int convert_response(struct zcrypt_device *zdev,
231 struct ap_message *reply,
232 char __user *outputdata,
233 unsigned int outputdatalength)
234{
235 /* Response type byte is the second byte in the response. */
236 switch (((unsigned char *) reply->message)[1]) {
237 case TYPE82_RSP_CODE:
238 case TYPE88_RSP_CODE:
239 return convert_error(zdev, reply);
240 case TYPE80_RSP_CODE:
241 return convert_type80(zdev, reply,
242 outputdata, outputdatalength);
243 default: /* Unknown response type, this should NEVER EVER happen */
244 PRINTK("Unrecognized Message Header: %08x%08x\n",
245 *(unsigned int *) reply->message,
246 *(unsigned int *) (reply->message+4));
247 zdev->online = 0;
248 return -EAGAIN; /* repeat the request on a different device. */
249 }
250}
251
252/**
253 * This function is called from the AP bus code after a crypto request
254 * "msg" has finished with the reply message "reply".
255 * It is called from tasklet context.
256 * @ap_dev: pointer to the AP device
257 * @msg: pointer to the AP message
258 * @reply: pointer to the AP reply message
259 */
260static void zcrypt_cex2a_receive(struct ap_device *ap_dev,
261 struct ap_message *msg,
262 struct ap_message *reply)
263{
264 static struct error_hdr error_reply = {
265 .type = TYPE82_RSP_CODE,
266 .reply_code = REP82_ERROR_MACHINE_FAILURE,
267 };
268 struct type80_hdr *t80h = reply->message;
269 int length;
270
271 /* Copy the reply message to the request message buffer. */
272 if (IS_ERR(reply))
273 memcpy(msg->message, &error_reply, sizeof(error_reply));
274 else if (t80h->type == TYPE80_RSP_CODE) {
275 length = min(CEX2A_MAX_RESPONSE_SIZE, (int) t80h->len);
276 memcpy(msg->message, reply->message, length);
277 } else
278 memcpy(msg->message, reply->message, sizeof error_reply);
279 complete((struct completion *) msg->private);
280}
281
282static atomic_t zcrypt_step = ATOMIC_INIT(0);
283
284/**
285 * The request distributor calls this function if it picked the CEX2A
286 * device to handle a modexpo request.
287 * @zdev: pointer to zcrypt_device structure that identifies the
288 * CEX2A device to the request distributor
289 * @mex: pointer to the modexpo request buffer
290 */
291static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev,
292 struct ica_rsa_modexpo *mex)
293{
294 struct ap_message ap_msg;
295 struct completion work;
296 int rc;
297
298 ap_msg.message = (void *) kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
299 if (!ap_msg.message)
300 return -ENOMEM;
301 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
302 atomic_inc_return(&zcrypt_step);
303 ap_msg.private = &work;
304 rc = ICAMEX_msg_to_type50MEX_msg(zdev, &ap_msg, mex);
305 if (rc)
306 goto out_free;
307 init_completion(&work);
308 ap_queue_message(zdev->ap_dev, &ap_msg);
309 rc = wait_for_completion_interruptible_timeout(
310 &work, CEX2A_CLEANUP_TIME);
311 if (rc > 0)
312 rc = convert_response(zdev, &ap_msg, mex->outputdata,
313 mex->outputdatalength);
314 else {
315 /* Signal pending or message timed out. */
316 ap_cancel_message(zdev->ap_dev, &ap_msg);
317 if (rc == 0)
318 /* Message timed out. */
319 rc = -ETIME;
320 }
321out_free:
322 kfree(ap_msg.message);
323 return rc;
324}
325
326/**
327 * The request distributor calls this function if it picked the CEX2A
328 * device to handle a modexpo_crt request.
329 * @zdev: pointer to zcrypt_device structure that identifies the
330 * CEX2A device to the request distributor
331 * @crt: pointer to the modexpoc_crt request buffer
332 */
333static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev,
334 struct ica_rsa_modexpo_crt *crt)
335{
336 struct ap_message ap_msg;
337 struct completion work;
338 int rc;
339
340 ap_msg.message = (void *) kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL);
341 if (!ap_msg.message)
342 return -ENOMEM;
343 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
344 atomic_inc_return(&zcrypt_step);
345 ap_msg.private = &work;
346 rc = ICACRT_msg_to_type50CRT_msg(zdev, &ap_msg, crt);
347 if (rc)
348 goto out_free;
349 init_completion(&work);
350 ap_queue_message(zdev->ap_dev, &ap_msg);
351 rc = wait_for_completion_interruptible_timeout(
352 &work, CEX2A_CLEANUP_TIME);
353 if (rc > 0)
354 rc = convert_response(zdev, &ap_msg, crt->outputdata,
355 crt->outputdatalength);
356 else {
357 /* Signal pending or message timed out. */
358 ap_cancel_message(zdev->ap_dev, &ap_msg);
359 if (rc == 0)
360 /* Message timed out. */
361 rc = -ETIME;
362 }
363out_free:
364 kfree(ap_msg.message);
365 return rc;
366}
367
368/**
369 * The crypto operations for a CEX2A card.
370 */
371static struct zcrypt_ops zcrypt_cex2a_ops = {
372 .rsa_modexpo = zcrypt_cex2a_modexpo,
373 .rsa_modexpo_crt = zcrypt_cex2a_modexpo_crt,
374};
375
376/**
377 * Probe function for CEX2A cards. It always accepts the AP device
378 * since the bus_match already checked the hardware type.
379 * @ap_dev: pointer to the AP device.
380 */
381static int zcrypt_cex2a_probe(struct ap_device *ap_dev)
382{
383 struct zcrypt_device *zdev;
384 int rc;
385
386 zdev = zcrypt_device_alloc(CEX2A_MAX_RESPONSE_SIZE);
387 if (!zdev)
388 return -ENOMEM;
389 zdev->ap_dev = ap_dev;
390 zdev->ops = &zcrypt_cex2a_ops;
391 zdev->online = 1;
392 zdev->user_space_type = ZCRYPT_CEX2A;
393 zdev->type_string = "CEX2A";
394 zdev->min_mod_size = CEX2A_MIN_MOD_SIZE;
395 zdev->max_mod_size = CEX2A_MAX_MOD_SIZE;
396 zdev->short_crt = 1;
397 zdev->speed_rating = CEX2A_SPEED_RATING;
398 ap_dev->reply = &zdev->reply;
399 ap_dev->private = zdev;
400 rc = zcrypt_device_register(zdev);
401 if (rc)
402 goto out_free;
403 return 0;
404
405out_free:
406 ap_dev->private = NULL;
407 zcrypt_device_free(zdev);
408 return rc;
409}
410
411/**
412 * This is called to remove the extended CEX2A driver information
413 * if an AP device is removed.
414 */
415static void zcrypt_cex2a_remove(struct ap_device *ap_dev)
416{
417 struct zcrypt_device *zdev = ap_dev->private;
418
419 zcrypt_device_unregister(zdev);
420}
421
422int __init zcrypt_cex2a_init(void)
423{
424 return ap_driver_register(&zcrypt_cex2a_driver, THIS_MODULE, "cex2a");
425}
426
427void __exit zcrypt_cex2a_exit(void)
428{
429 ap_driver_unregister(&zcrypt_cex2a_driver);
430}
431
432#ifndef CONFIG_ZCRYPT_MONOLITHIC
433module_init(zcrypt_cex2a_init);
434module_exit(zcrypt_cex2a_exit);
435#endif
diff --git a/drivers/s390/crypto/zcrypt_cex2a.h b/drivers/s390/crypto/zcrypt_cex2a.h
new file mode 100644
index 000000000000..61a78c32dce4
--- /dev/null
+++ b/drivers/s390/crypto/zcrypt_cex2a.h
@@ -0,0 +1,126 @@
1/*
2 * linux/drivers/s390/crypto/zcrypt_cex2a.h
3 *
4 * zcrypt 2.0.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 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
28#ifndef _ZCRYPT_CEX2A_H_
29#define _ZCRYPT_CEX2A_H_
30
31/**
32 * The type 50 message family is associated with a CEX2A card.
33 *
34 * The four members of the family are described below.
35 *
36 * Note that all unsigned char arrays are right-justified and left-padded
37 * with zeroes.
38 *
39 * Note that all reserved fields must be zeroes.
40 */
41struct type50_hdr {
42 unsigned char reserved1;
43 unsigned char msg_type_code; /* 0x50 */
44 unsigned short msg_len;
45 unsigned char reserved2;
46 unsigned char ignored;
47 unsigned short reserved3;
48} __attribute__((packed));
49
50#define TYPE50_TYPE_CODE 0x50
51
52#define TYPE50_MEB1_FMT 0x0001
53#define TYPE50_MEB2_FMT 0x0002
54#define TYPE50_CRB1_FMT 0x0011
55#define TYPE50_CRB2_FMT 0x0012
56
57/* Mod-Exp, with a small modulus */
58struct type50_meb1_msg {
59 struct type50_hdr header;
60 unsigned short keyblock_type; /* 0x0001 */
61 unsigned char reserved[6];
62 unsigned char exponent[128];
63 unsigned char modulus[128];
64 unsigned char message[128];
65} __attribute__((packed));
66
67/* Mod-Exp, with a large modulus */
68struct type50_meb2_msg {
69 struct type50_hdr header;
70 unsigned short keyblock_type; /* 0x0002 */
71 unsigned char reserved[6];
72 unsigned char exponent[256];
73 unsigned char modulus[256];
74 unsigned char message[256];
75} __attribute__((packed));
76
77/* CRT, with a small modulus */
78struct type50_crb1_msg {
79 struct type50_hdr header;
80 unsigned short keyblock_type; /* 0x0011 */
81 unsigned char reserved[6];
82 unsigned char p[64];
83 unsigned char q[64];
84 unsigned char dp[64];
85 unsigned char dq[64];
86 unsigned char u[64];
87 unsigned char message[128];
88} __attribute__((packed));
89
90/* CRT, with a large modulus */
91struct type50_crb2_msg {
92 struct type50_hdr header;
93 unsigned short keyblock_type; /* 0x0012 */
94 unsigned char reserved[6];
95 unsigned char p[128];
96 unsigned char q[128];
97 unsigned char dp[128];
98 unsigned char dq[128];
99 unsigned char u[128];
100 unsigned char message[256];
101} __attribute__((packed));
102
103/**
104 * The type 80 response family is associated with a CEX2A card.
105 *
106 * Note that all unsigned char arrays are right-justified and left-padded
107 * with zeroes.
108 *
109 * Note that all reserved fields must be zeroes.
110 */
111
112#define TYPE80_RSP_CODE 0x80
113
114struct type80_hdr {
115 unsigned char reserved1;
116 unsigned char type; /* 0x80 */
117 unsigned short len;
118 unsigned char code; /* 0x00 */
119 unsigned char reserved2[3];
120 unsigned char reserved3[8];
121} __attribute__((packed));
122
123int zcrypt_cex2a_init(void);
124void zcrypt_cex2a_exit(void);
125
126#endif /* _ZCRYPT_CEX2A_H_ */
diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h
new file mode 100644
index 000000000000..b22bd055a03b
--- /dev/null
+++ b/drivers/s390/crypto/zcrypt_error.h
@@ -0,0 +1,133 @@
1/*
2 * linux/drivers/s390/crypto/zcrypt_error.h
3 *
4 * zcrypt 2.0.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 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
28#ifndef _ZCRYPT_ERROR_H_
29#define _ZCRYPT_ERROR_H_
30
31#include "zcrypt_api.h"
32
33/**
34 * Reply Messages
35 *
36 * Error reply messages are of two types:
37 * 82: Error (see below)
38 * 88: Error (see below)
39 * Both type 82 and type 88 have the same structure in the header.
40 *
41 * Request reply messages are of three known types:
42 * 80: Reply from a Type 50 Request (see CEX2A-RELATED STRUCTS)
43 * 84: Reply from a Type 4 Request (see PCICA-RELATED STRUCTS)
44 * 86: Reply from a Type 6 Request (see PCICC/PCIXCC/CEX2C-RELATED STRUCTS)
45 *
46 */
47struct error_hdr {
48 unsigned char reserved1; /* 0x00 */
49 unsigned char type; /* 0x82 or 0x88 */
50 unsigned char reserved2[2]; /* 0x0000 */
51 unsigned char reply_code; /* reply code */
52 unsigned char reserved3[3]; /* 0x000000 */
53};
54
55#define TYPE82_RSP_CODE 0x82
56#define TYPE88_RSP_CODE 0x88
57
58#define REP82_ERROR_MACHINE_FAILURE 0x10
59#define REP82_ERROR_PREEMPT_FAILURE 0x12
60#define REP82_ERROR_CHECKPT_FAILURE 0x14
61#define REP82_ERROR_MESSAGE_TYPE 0x20
62#define REP82_ERROR_INVALID_COMM_CD 0x21 /* Type 84 */
63#define REP82_ERROR_INVALID_MSG_LEN 0x23
64#define REP82_ERROR_RESERVD_FIELD 0x24 /* was 0x50 */
65#define REP82_ERROR_FORMAT_FIELD 0x29
66#define REP82_ERROR_INVALID_COMMAND 0x30
67#define REP82_ERROR_MALFORMED_MSG 0x40
68#define REP82_ERROR_RESERVED_FIELDO 0x50 /* old value */
69#define REP82_ERROR_WORD_ALIGNMENT 0x60
70#define REP82_ERROR_MESSAGE_LENGTH 0x80
71#define REP82_ERROR_OPERAND_INVALID 0x82
72#define REP82_ERROR_OPERAND_SIZE 0x84
73#define REP82_ERROR_EVEN_MOD_IN_OPND 0x85
74#define REP82_ERROR_RESERVED_FIELD 0x88
75#define REP82_ERROR_TRANSPORT_FAIL 0x90
76#define REP82_ERROR_PACKET_TRUNCATED 0xA0
77#define REP82_ERROR_ZERO_BUFFER_LEN 0xB0
78
79#define REP88_ERROR_MODULE_FAILURE 0x10
80
81#define REP88_ERROR_MESSAGE_TYPE 0x20
82#define REP88_ERROR_MESSAGE_MALFORMD 0x22
83#define REP88_ERROR_MESSAGE_LENGTH 0x23
84#define REP88_ERROR_RESERVED_FIELD 0x24
85#define REP88_ERROR_KEY_TYPE 0x34
86#define REP88_ERROR_INVALID_KEY 0x82 /* CEX2A */
87#define REP88_ERROR_OPERAND 0x84 /* CEX2A */
88#define REP88_ERROR_OPERAND_EVEN_MOD 0x85 /* CEX2A */
89
90static inline int convert_error(struct zcrypt_device *zdev,
91 struct ap_message *reply)
92{
93 struct error_hdr *ehdr = reply->message;
94
95 PRINTK("Hardware error : Type %02x Message Header: %08x%08x\n",
96 ehdr->type, *(unsigned int *) reply->message,
97 *(unsigned int *) (reply->message + 4));
98
99 switch (ehdr->reply_code) {
100 case REP82_ERROR_OPERAND_INVALID:
101 case REP82_ERROR_OPERAND_SIZE:
102 case REP82_ERROR_EVEN_MOD_IN_OPND:
103 case REP88_ERROR_MESSAGE_MALFORMD:
104 // REP88_ERROR_INVALID_KEY // '82' CEX2A
105 // REP88_ERROR_OPERAND // '84' CEX2A
106 // REP88_ERROR_OPERAND_EVEN_MOD // '85' CEX2A
107 /* Invalid input data. */
108 return -EINVAL;
109 case REP82_ERROR_MESSAGE_TYPE:
110 // REP88_ERROR_MESSAGE_TYPE // '20' CEX2A
111 /**
112 * To sent a message of the wrong type is a bug in the
113 * device driver. Warn about it, disable the device
114 * and then repeat the request.
115 */
116 WARN_ON(1);
117 zdev->online = 0;
118 return -EAGAIN;
119 case REP82_ERROR_TRANSPORT_FAIL:
120 case REP82_ERROR_MACHINE_FAILURE:
121 // REP88_ERROR_MODULE_FAILURE // '10' CEX2A
122 /* If a card fails disable it and repeat the request. */
123 zdev->online = 0;
124 return -EAGAIN;
125 default:
126 PRINTKW("unknown type %02x reply code = %d\n",
127 ehdr->type, ehdr->reply_code);
128 zdev->online = 0;
129 return -EAGAIN; /* repeat the request on a different device. */
130 }
131}
132
133#endif /* _ZCRYPT_ERROR_H_ */
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
new file mode 100644
index 000000000000..0ff56e86caae
--- /dev/null
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -0,0 +1,418 @@
1/*
2 * linux/drivers/s390/crypto/zcrypt_pcica.c
3 *
4 * zcrypt 2.0.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/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_pcica.h"
39
40#define PCICA_MIN_MOD_SIZE 1 /* 8 bits */
41#define PCICA_MAX_MOD_SIZE 256 /* 2048 bits */
42
43#define PCICA_SPEED_RATING 2800
44
45#define PCICA_MAX_MESSAGE_SIZE 0x3a0 /* sizeof(struct type4_lcr) */
46#define PCICA_MAX_RESPONSE_SIZE 0x110 /* max outputdatalength + type80_hdr */
47
48#define PCICA_CLEANUP_TIME (15*HZ)
49
50static struct ap_device_id zcrypt_pcica_ids[] = {
51 { AP_DEVICE(AP_DEVICE_TYPE_PCICA) },
52 { /* end of list */ },
53};
54
55#ifndef CONFIG_ZCRYPT_MONOLITHIC
56MODULE_DEVICE_TABLE(ap, zcrypt_pcica_ids);
57MODULE_AUTHOR("IBM Corporation");
58MODULE_DESCRIPTION("PCICA Cryptographic Coprocessor device driver, "
59 "Copyright 2001, 2006 IBM Corporation");
60MODULE_LICENSE("GPL");
61#endif
62
63static int zcrypt_pcica_probe(struct ap_device *ap_dev);
64static void zcrypt_pcica_remove(struct ap_device *ap_dev);
65static void zcrypt_pcica_receive(struct ap_device *, struct ap_message *,
66 struct ap_message *);
67
68static struct ap_driver zcrypt_pcica_driver = {
69 .probe = zcrypt_pcica_probe,
70 .remove = zcrypt_pcica_remove,
71 .receive = zcrypt_pcica_receive,
72 .ids = zcrypt_pcica_ids,
73};
74
75/**
76 * Convert a ICAMEX message to a type4 MEX message.
77 *
78 * @zdev: crypto device pointer
79 * @zreq: crypto request pointer
80 * @mex: pointer to user input data
81 *
82 * Returns 0 on success or -EFAULT.
83 */
84static int ICAMEX_msg_to_type4MEX_msg(struct zcrypt_device *zdev,
85 struct ap_message *ap_msg,
86 struct ica_rsa_modexpo *mex)
87{
88 unsigned char *modulus, *exponent, *message;
89 int mod_len;
90
91 mod_len = mex->inputdatalength;
92
93 if (mod_len <= 128) {
94 struct type4_sme *sme = ap_msg->message;
95 memset(sme, 0, sizeof(*sme));
96 ap_msg->length = sizeof(*sme);
97 sme->header.msg_fmt = TYPE4_SME_FMT;
98 sme->header.msg_len = sizeof(*sme);
99 sme->header.msg_type_code = TYPE4_TYPE_CODE;
100 sme->header.request_code = TYPE4_REQU_CODE;
101 modulus = sme->modulus + sizeof(sme->modulus) - mod_len;
102 exponent = sme->exponent + sizeof(sme->exponent) - mod_len;
103 message = sme->message + sizeof(sme->message) - mod_len;
104 } else {
105 struct type4_lme *lme = ap_msg->message;
106 memset(lme, 0, sizeof(*lme));
107 ap_msg->length = sizeof(*lme);
108 lme->header.msg_fmt = TYPE4_LME_FMT;
109 lme->header.msg_len = sizeof(*lme);
110 lme->header.msg_type_code = TYPE4_TYPE_CODE;
111 lme->header.request_code = TYPE4_REQU_CODE;
112 modulus = lme->modulus + sizeof(lme->modulus) - mod_len;
113 exponent = lme->exponent + sizeof(lme->exponent) - mod_len;
114 message = lme->message + sizeof(lme->message) - mod_len;
115 }
116
117 if (copy_from_user(modulus, mex->n_modulus, mod_len) ||
118 copy_from_user(exponent, mex->b_key, mod_len) ||
119 copy_from_user(message, mex->inputdata, mod_len))
120 return -EFAULT;
121 return 0;
122}
123
124/**
125 * Convert a ICACRT message to a type4 CRT message.
126 *
127 * @zdev: crypto device pointer
128 * @zreq: crypto request pointer
129 * @crt: pointer to user input data
130 *
131 * Returns 0 on success or -EFAULT.
132 */
133static int ICACRT_msg_to_type4CRT_msg(struct zcrypt_device *zdev,
134 struct ap_message *ap_msg,
135 struct ica_rsa_modexpo_crt *crt)
136{
137 unsigned char *p, *q, *dp, *dq, *u, *inp;
138 int mod_len, short_len, long_len;
139
140 mod_len = crt->inputdatalength;
141 short_len = mod_len / 2;
142 long_len = mod_len / 2 + 8;
143
144 if (mod_len <= 128) {
145 struct type4_scr *scr = ap_msg->message;
146 memset(scr, 0, sizeof(*scr));
147 ap_msg->length = sizeof(*scr);
148 scr->header.msg_type_code = TYPE4_TYPE_CODE;
149 scr->header.request_code = TYPE4_REQU_CODE;
150 scr->header.msg_fmt = TYPE4_SCR_FMT;
151 scr->header.msg_len = sizeof(*scr);
152 p = scr->p + sizeof(scr->p) - long_len;
153 q = scr->q + sizeof(scr->q) - short_len;
154 dp = scr->dp + sizeof(scr->dp) - long_len;
155 dq = scr->dq + sizeof(scr->dq) - short_len;
156 u = scr->u + sizeof(scr->u) - long_len;
157 inp = scr->message + sizeof(scr->message) - mod_len;
158 } else {
159 struct type4_lcr *lcr = ap_msg->message;
160 memset(lcr, 0, sizeof(*lcr));
161 ap_msg->length = sizeof(*lcr);
162 lcr->header.msg_type_code = TYPE4_TYPE_CODE;
163 lcr->header.request_code = TYPE4_REQU_CODE;
164 lcr->header.msg_fmt = TYPE4_LCR_FMT;
165 lcr->header.msg_len = sizeof(*lcr);
166 p = lcr->p + sizeof(lcr->p) - long_len;
167 q = lcr->q + sizeof(lcr->q) - short_len;
168 dp = lcr->dp + sizeof(lcr->dp) - long_len;
169 dq = lcr->dq + sizeof(lcr->dq) - short_len;
170 u = lcr->u + sizeof(lcr->u) - long_len;
171 inp = lcr->message + sizeof(lcr->message) - mod_len;
172 }
173
174 if (copy_from_user(p, crt->np_prime, long_len) ||
175 copy_from_user(q, crt->nq_prime, short_len) ||
176 copy_from_user(dp, crt->bp_key, long_len) ||
177 copy_from_user(dq, crt->bq_key, short_len) ||
178 copy_from_user(u, crt->u_mult_inv, long_len) ||
179 copy_from_user(inp, crt->inputdata, mod_len))
180 return -EFAULT;
181 return 0;
182}
183
184/**
185 * Copy results from a type 84 reply message back to user space.
186 *
187 * @zdev: crypto device pointer
188 * @reply: reply AP message.
189 * @data: pointer to user output data
190 * @length: size of user output data
191 *
192 * Returns 0 on success or -EFAULT.
193 */
194static inline int convert_type84(struct zcrypt_device *zdev,
195 struct ap_message *reply,
196 char __user *outputdata,
197 unsigned int outputdatalength)
198{
199 struct type84_hdr *t84h = reply->message;
200 char *data;
201
202 if (t84h->len < sizeof(*t84h) + outputdatalength) {
203 /* The result is too short, the PCICA card may not do that.. */
204 zdev->online = 0;
205 return -EAGAIN; /* repeat the request on a different device. */
206 }
207 BUG_ON(t84h->len > PCICA_MAX_RESPONSE_SIZE);
208 data = reply->message + t84h->len - outputdatalength;
209 if (copy_to_user(outputdata, data, outputdatalength))
210 return -EFAULT;
211 return 0;
212}
213
214static int convert_response(struct zcrypt_device *zdev,
215 struct ap_message *reply,
216 char __user *outputdata,
217 unsigned int outputdatalength)
218{
219 /* Response type byte is the second byte in the response. */
220 switch (((unsigned char *) reply->message)[1]) {
221 case TYPE82_RSP_CODE:
222 case TYPE88_RSP_CODE:
223 return convert_error(zdev, reply);
224 case TYPE84_RSP_CODE:
225 return convert_type84(zdev, reply,
226 outputdata, outputdatalength);
227 default: /* Unknown response type, this should NEVER EVER happen */
228 PRINTK("Unrecognized Message Header: %08x%08x\n",
229 *(unsigned int *) reply->message,
230 *(unsigned int *) (reply->message+4));
231 zdev->online = 0;
232 return -EAGAIN; /* repeat the request on a different device. */
233 }
234}
235
236/**
237 * This function is called from the AP bus code after a crypto request
238 * "msg" has finished with the reply message "reply".
239 * It is called from tasklet context.
240 * @ap_dev: pointer to the AP device
241 * @msg: pointer to the AP message
242 * @reply: pointer to the AP reply message
243 */
244static void zcrypt_pcica_receive(struct ap_device *ap_dev,
245 struct ap_message *msg,
246 struct ap_message *reply)
247{
248 static struct error_hdr error_reply = {
249 .type = TYPE82_RSP_CODE,
250 .reply_code = REP82_ERROR_MACHINE_FAILURE,
251 };
252 struct type84_hdr *t84h = reply->message;
253 int length;
254
255 /* Copy the reply message to the request message buffer. */
256 if (IS_ERR(reply))
257 memcpy(msg->message, &error_reply, sizeof(error_reply));
258 else if (t84h->code == TYPE84_RSP_CODE) {
259 length = min(PCICA_MAX_RESPONSE_SIZE, (int) t84h->len);
260 memcpy(msg->message, reply->message, length);
261 } else
262 memcpy(msg->message, reply->message, sizeof error_reply);
263 complete((struct completion *) msg->private);
264}
265
266static atomic_t zcrypt_step = ATOMIC_INIT(0);
267
268/**
269 * The request distributor calls this function if it picked the PCICA
270 * device to handle a modexpo request.
271 * @zdev: pointer to zcrypt_device structure that identifies the
272 * PCICA device to the request distributor
273 * @mex: pointer to the modexpo request buffer
274 */
275static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev,
276 struct ica_rsa_modexpo *mex)
277{
278 struct ap_message ap_msg;
279 struct completion work;
280 int rc;
281
282 ap_msg.message = (void *) kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
283 if (!ap_msg.message)
284 return -ENOMEM;
285 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
286 atomic_inc_return(&zcrypt_step);
287 ap_msg.private = &work;
288 rc = ICAMEX_msg_to_type4MEX_msg(zdev, &ap_msg, mex);
289 if (rc)
290 goto out_free;
291 init_completion(&work);
292 ap_queue_message(zdev->ap_dev, &ap_msg);
293 rc = wait_for_completion_interruptible_timeout(
294 &work, PCICA_CLEANUP_TIME);
295 if (rc > 0)
296 rc = convert_response(zdev, &ap_msg, mex->outputdata,
297 mex->outputdatalength);
298 else {
299 /* Signal pending or message timed out. */
300 ap_cancel_message(zdev->ap_dev, &ap_msg);
301 if (rc == 0)
302 /* Message timed out. */
303 rc = -ETIME;
304 }
305out_free:
306 kfree(ap_msg.message);
307 return rc;
308}
309
310/**
311 * The request distributor calls this function if it picked the PCICA
312 * device to handle a modexpo_crt request.
313 * @zdev: pointer to zcrypt_device structure that identifies the
314 * PCICA device to the request distributor
315 * @crt: pointer to the modexpoc_crt request buffer
316 */
317static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev,
318 struct ica_rsa_modexpo_crt *crt)
319{
320 struct ap_message ap_msg;
321 struct completion work;
322 int rc;
323
324 ap_msg.message = (void *) kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL);
325 if (!ap_msg.message)
326 return -ENOMEM;
327 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
328 atomic_inc_return(&zcrypt_step);
329 ap_msg.private = &work;
330 rc = ICACRT_msg_to_type4CRT_msg(zdev, &ap_msg, crt);
331 if (rc)
332 goto out_free;
333 init_completion(&work);
334 ap_queue_message(zdev->ap_dev, &ap_msg);
335 rc = wait_for_completion_interruptible_timeout(
336 &work, PCICA_CLEANUP_TIME);
337 if (rc > 0)
338 rc = convert_response(zdev, &ap_msg, crt->outputdata,
339 crt->outputdatalength);
340 else {
341 /* Signal pending or message timed out. */
342 ap_cancel_message(zdev->ap_dev, &ap_msg);
343 if (rc == 0)
344 /* Message timed out. */
345 rc = -ETIME;
346 }
347out_free:
348 kfree(ap_msg.message);
349 return rc;
350}
351
352/**
353 * The crypto operations for a PCICA card.
354 */
355static struct zcrypt_ops zcrypt_pcica_ops = {
356 .rsa_modexpo = zcrypt_pcica_modexpo,
357 .rsa_modexpo_crt = zcrypt_pcica_modexpo_crt,
358};
359
360/**
361 * Probe function for PCICA cards. It always accepts the AP device
362 * since the bus_match already checked the hardware type.
363 * @ap_dev: pointer to the AP device.
364 */
365static int zcrypt_pcica_probe(struct ap_device *ap_dev)
366{
367 struct zcrypt_device *zdev;
368 int rc;
369
370 zdev = zcrypt_device_alloc(PCICA_MAX_RESPONSE_SIZE);
371 if (!zdev)
372 return -ENOMEM;
373 zdev->ap_dev = ap_dev;
374 zdev->ops = &zcrypt_pcica_ops;
375 zdev->online = 1;
376 zdev->user_space_type = ZCRYPT_PCICA;
377 zdev->type_string = "PCICA";
378 zdev->min_mod_size = PCICA_MIN_MOD_SIZE;
379 zdev->max_mod_size = PCICA_MAX_MOD_SIZE;
380 zdev->speed_rating = PCICA_SPEED_RATING;
381 ap_dev->reply = &zdev->reply;
382 ap_dev->private = zdev;
383 rc = zcrypt_device_register(zdev);
384 if (rc)
385 goto out_free;
386 return 0;
387
388out_free:
389 ap_dev->private = NULL;
390 zcrypt_device_free(zdev);
391 return rc;
392}
393
394/**
395 * This is called to remove the extended PCICA driver information
396 * if an AP device is removed.
397 */
398static void zcrypt_pcica_remove(struct ap_device *ap_dev)
399{
400 struct zcrypt_device *zdev = ap_dev->private;
401
402 zcrypt_device_unregister(zdev);
403}
404
405int __init zcrypt_pcica_init(void)
406{
407 return ap_driver_register(&zcrypt_pcica_driver, THIS_MODULE, "pcica");
408}
409
410void zcrypt_pcica_exit(void)
411{
412 ap_driver_unregister(&zcrypt_pcica_driver);
413}
414
415#ifndef CONFIG_ZCRYPT_MONOLITHIC
416module_init(zcrypt_pcica_init);
417module_exit(zcrypt_pcica_exit);
418#endif
diff --git a/drivers/s390/crypto/zcrypt_pcica.h b/drivers/s390/crypto/zcrypt_pcica.h
new file mode 100644
index 000000000000..a08a4f8c33c9
--- /dev/null
+++ b/drivers/s390/crypto/zcrypt_pcica.h
@@ -0,0 +1,117 @@
1/*
2 * linux/drivers/s390/crypto/zcrypt_pcica.h
3 *
4 * zcrypt 2.0.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 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */
27
28#ifndef _ZCRYPT_PCICA_H_
29#define _ZCRYPT_PCICA_H_
30
31/**
32 * The type 4 message family is associated with a PCICA card.
33 *
34 * The four members of the family are described below.
35 *
36 * Note that all unsigned char arrays are right-justified and left-padded
37 * with zeroes.
38 *
39 * Note that all reserved fields must be zeroes.
40 */
41struct type4_hdr {
42 unsigned char reserved1;
43 unsigned char msg_type_code; /* 0x04 */
44 unsigned short msg_len;
45 unsigned char request_code; /* 0x40 */
46 unsigned char msg_fmt;
47 unsigned short reserved2;
48} __attribute__((packed));
49
50#define TYPE4_TYPE_CODE 0x04
51#define TYPE4_REQU_CODE 0x40
52
53#define TYPE4_SME_FMT 0x00
54#define TYPE4_LME_FMT 0x10
55#define TYPE4_SCR_FMT 0x40
56#define TYPE4_LCR_FMT 0x50
57
58/* Mod-Exp, with a small modulus */
59struct type4_sme {
60 struct type4_hdr header;
61 unsigned char message[128];
62 unsigned char exponent[128];
63 unsigned char modulus[128];
64} __attribute__((packed));
65
66/* Mod-Exp, with a large modulus */
67struct type4_lme {
68 struct type4_hdr header;
69 unsigned char message[256];
70 unsigned char exponent[256];
71 unsigned char modulus[256];
72} __attribute__((packed));
73
74/* CRT, with a small modulus */
75struct type4_scr {
76 struct type4_hdr header;
77 unsigned char message[128];
78 unsigned char dp[72];
79 unsigned char dq[64];
80 unsigned char p[72];
81 unsigned char q[64];
82 unsigned char u[72];
83} __attribute__((packed));
84
85/* CRT, with a large modulus */
86struct type4_lcr {
87 struct type4_hdr header;
88 unsigned char message[256];
89 unsigned char dp[136];
90 unsigned char dq[128];
91 unsigned char p[136];
92 unsigned char q[128];
93 unsigned char u[136];
94} __attribute__((packed));
95
96/**
97 * The type 84 response family is associated with a PCICA card.
98 *
99 * Note that all unsigned char arrays are right-justified and left-padded
100 * with zeroes.
101 *
102 * Note that all reserved fields must be zeroes.
103 */
104
105struct type84_hdr {
106 unsigned char reserved1;
107 unsigned char code;
108 unsigned short len;
109 unsigned char reserved2[4];
110} __attribute__((packed));
111
112#define TYPE84_RSP_CODE 0x84
113
114int zcrypt_pcica_init(void);
115void zcrypt_pcica_exit(void);
116
117#endif /* _ZCRYPT_PCICA_H_ */