aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorRalph Wuerthner <rwuerthn@de.ibm.com>2006-09-20 09:58:36 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-09-20 09:58:36 -0400
commit5432114baf0300286a6ca1b0aea549492a379432 (patch)
tree6a9cf64c86e4ee4d439f91e9bd4485688d28ddd7 /drivers/s390
parentfe3a1be59c851aba2330387596c6134bc5ec8397 (diff)
[S390] zcrypt secure key cryptography extension.
Allow the user space to send extended cprb messages directly to the PCIXCC / CEX2C cards. This allows the CCA library to construct special crypto requests that use "secure" keys that are stored on the card. Signed-off-by: Ralph Wuerthner <rwuerthn@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/crypto/zcrypt_api.c112
-rw-r--r--drivers/s390/crypto/zcrypt_api.h3
-rw-r--r--drivers/s390/crypto/zcrypt_cca_key.h2
-rw-r--r--drivers/s390/crypto/zcrypt_cex2a.c2
-rw-r--r--drivers/s390/crypto/zcrypt_cex2a.h2
-rw-r--r--drivers/s390/crypto/zcrypt_error.h2
-rw-r--r--drivers/s390/crypto/zcrypt_mono.c2
-rw-r--r--drivers/s390/crypto/zcrypt_pcica.c2
-rw-r--r--drivers/s390/crypto/zcrypt_pcica.h2
-rw-r--r--drivers/s390/crypto/zcrypt_pcicc.c2
-rw-r--r--drivers/s390/crypto/zcrypt_pcicc.h2
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.c263
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.h2
13 files changed, 373 insertions, 25 deletions
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
index b3fe003b3d2d..1edc10a7a6f2 100644
--- a/drivers/s390/crypto/zcrypt_api.c
+++ b/drivers/s390/crypto/zcrypt_api.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_api.c 2 * linux/drivers/s390/crypto/zcrypt_api.c
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs
@@ -392,6 +392,41 @@ static long zcrypt_rsa_crt(struct ica_rsa_modexpo_crt *crt)
392 return -ENODEV; 392 return -ENODEV;
393} 393}
394 394
395static long zcrypt_send_cprb(struct ica_xcRB *xcRB)
396{
397 struct zcrypt_device *zdev;
398 int rc;
399
400 spin_lock_bh(&zcrypt_device_lock);
401 list_for_each_entry(zdev, &zcrypt_device_list, list) {
402 if (!zdev->online || !zdev->ops->send_cprb ||
403 (xcRB->user_defined != AUTOSELECT &&
404 AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined)
405 )
406 continue;
407 zcrypt_device_get(zdev);
408 get_device(&zdev->ap_dev->device);
409 zdev->request_count++;
410 __zcrypt_decrease_preference(zdev);
411 spin_unlock_bh(&zcrypt_device_lock);
412 if (try_module_get(zdev->ap_dev->drv->driver.owner)) {
413 rc = zdev->ops->send_cprb(zdev, xcRB);
414 module_put(zdev->ap_dev->drv->driver.owner);
415 }
416 else
417 rc = -EAGAIN;
418 spin_lock_bh(&zcrypt_device_lock);
419 zdev->request_count--;
420 __zcrypt_increase_preference(zdev);
421 put_device(&zdev->ap_dev->device);
422 zcrypt_device_put(zdev);
423 spin_unlock_bh(&zcrypt_device_lock);
424 return rc;
425 }
426 spin_unlock_bh(&zcrypt_device_lock);
427 return -ENODEV;
428}
429
395static void zcrypt_status_mask(char status[AP_DEVICES]) 430static void zcrypt_status_mask(char status[AP_DEVICES])
396{ 431{
397 struct zcrypt_device *zdev; 432 struct zcrypt_device *zdev;
@@ -535,6 +570,18 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
535 return rc; 570 return rc;
536 return put_user(crt.outputdatalength, &ucrt->outputdatalength); 571 return put_user(crt.outputdatalength, &ucrt->outputdatalength);
537 } 572 }
573 case ZSECSENDCPRB: {
574 struct ica_xcRB __user *uxcRB = (void __user *) arg;
575 struct ica_xcRB xcRB;
576 if (copy_from_user(&xcRB, uxcRB, sizeof(xcRB)))
577 return -EFAULT;
578 do {
579 rc = zcrypt_send_cprb(&xcRB);
580 } while (rc == -EAGAIN);
581 if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB)))
582 return -EFAULT;
583 return rc;
584 }
538 case Z90STAT_STATUS_MASK: { 585 case Z90STAT_STATUS_MASK: {
539 char status[AP_DEVICES]; 586 char status[AP_DEVICES];
540 zcrypt_status_mask(status); 587 zcrypt_status_mask(status);
@@ -683,6 +730,67 @@ static long trans_modexpo_crt32(struct file *filp, unsigned int cmd,
683 return rc; 730 return rc;
684} 731}
685 732
733struct compat_ica_xcRB {
734 unsigned short agent_ID;
735 unsigned int user_defined;
736 unsigned short request_ID;
737 unsigned int request_control_blk_length;
738 unsigned char padding1[16 - sizeof (compat_uptr_t)];
739 compat_uptr_t request_control_blk_addr;
740 unsigned int request_data_length;
741 char padding2[16 - sizeof (compat_uptr_t)];
742 compat_uptr_t request_data_address;
743 unsigned int reply_control_blk_length;
744 char padding3[16 - sizeof (compat_uptr_t)];
745 compat_uptr_t reply_control_blk_addr;
746 unsigned int reply_data_length;
747 char padding4[16 - sizeof (compat_uptr_t)];
748 compat_uptr_t reply_data_addr;
749 unsigned short priority_window;
750 unsigned int status;
751} __attribute__((packed));
752
753static long trans_xcRB32(struct file *filp, unsigned int cmd,
754 unsigned long arg)
755{
756 struct compat_ica_xcRB __user *uxcRB32 = compat_ptr(arg);
757 struct compat_ica_xcRB xcRB32;
758 struct ica_xcRB xcRB64;
759 long rc;
760
761 if (copy_from_user(&xcRB32, uxcRB32, sizeof(xcRB32)))
762 return -EFAULT;
763 xcRB64.agent_ID = xcRB32.agent_ID;
764 xcRB64.user_defined = xcRB32.user_defined;
765 xcRB64.request_ID = xcRB32.request_ID;
766 xcRB64.request_control_blk_length =
767 xcRB32.request_control_blk_length;
768 xcRB64.request_control_blk_addr =
769 compat_ptr(xcRB32.request_control_blk_addr);
770 xcRB64.request_data_length =
771 xcRB32.request_data_length;
772 xcRB64.request_data_address =
773 compat_ptr(xcRB32.request_data_address);
774 xcRB64.reply_control_blk_length =
775 xcRB32.reply_control_blk_length;
776 xcRB64.reply_control_blk_addr =
777 compat_ptr(xcRB32.reply_control_blk_addr);
778 xcRB64.reply_data_length = xcRB32.reply_data_length;
779 xcRB64.reply_data_addr =
780 compat_ptr(xcRB32.reply_data_addr);
781 xcRB64.priority_window = xcRB32.priority_window;
782 xcRB64.status = xcRB32.status;
783 do {
784 rc = zcrypt_send_cprb(&xcRB64);
785 } while (rc == -EAGAIN);
786 xcRB32.reply_control_blk_length = xcRB64.reply_control_blk_length;
787 xcRB32.reply_data_length = xcRB64.reply_data_length;
788 xcRB32.status = xcRB64.status;
789 if (copy_to_user(uxcRB32, &xcRB32, sizeof(xcRB32)))
790 return -EFAULT;
791 return rc;
792}
793
686long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd, 794long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd,
687 unsigned long arg) 795 unsigned long arg)
688{ 796{
@@ -690,6 +798,8 @@ long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd,
690 return trans_modexpo32(filp, cmd, arg); 798 return trans_modexpo32(filp, cmd, arg);
691 if (cmd == ICARSACRT) 799 if (cmd == ICARSACRT)
692 return trans_modexpo_crt32(filp, cmd, arg); 800 return trans_modexpo_crt32(filp, cmd, arg);
801 if (cmd == ZSECSENDCPRB)
802 return trans_xcRB32(filp, cmd, arg);
693 return zcrypt_unlocked_ioctl(filp, cmd, arg); 803 return zcrypt_unlocked_ioctl(filp, cmd, arg);
694} 804}
695#endif 805#endif
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h
index 1f0e61f2e9b4..de4877ee618f 100644
--- a/drivers/s390/crypto/zcrypt_api.h
+++ b/drivers/s390/crypto/zcrypt_api.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_api.h 2 * linux/drivers/s390/crypto/zcrypt_api.h
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs
@@ -106,6 +106,7 @@ struct zcrypt_ops {
106 long (*rsa_modexpo)(struct zcrypt_device *, struct ica_rsa_modexpo *); 106 long (*rsa_modexpo)(struct zcrypt_device *, struct ica_rsa_modexpo *);
107 long (*rsa_modexpo_crt)(struct zcrypt_device *, 107 long (*rsa_modexpo_crt)(struct zcrypt_device *,
108 struct ica_rsa_modexpo_crt *); 108 struct ica_rsa_modexpo_crt *);
109 long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *);
109}; 110};
110 111
111struct zcrypt_device { 112struct zcrypt_device {
diff --git a/drivers/s390/crypto/zcrypt_cca_key.h b/drivers/s390/crypto/zcrypt_cca_key.h
index c80f40d44197..8dbcf0eef3e5 100644
--- a/drivers/s390/crypto/zcrypt_cca_key.h
+++ b/drivers/s390/crypto/zcrypt_cca_key.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_cca_key.h 2 * linux/drivers/s390/crypto/zcrypt_cca_key.h
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c
index 350248e5cd93..a62b00083d0c 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.c
+++ b/drivers/s390/crypto/zcrypt_cex2a.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_cex2a.c 2 * linux/drivers/s390/crypto/zcrypt_cex2a.c
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs
diff --git a/drivers/s390/crypto/zcrypt_cex2a.h b/drivers/s390/crypto/zcrypt_cex2a.h
index 61a78c32dce4..8f69d1dacab8 100644
--- a/drivers/s390/crypto/zcrypt_cex2a.h
+++ b/drivers/s390/crypto/zcrypt_cex2a.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_cex2a.h 2 * linux/drivers/s390/crypto/zcrypt_cex2a.h
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs
diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h
index b22bd055a03b..2cb616ba8bec 100644
--- a/drivers/s390/crypto/zcrypt_error.h
+++ b/drivers/s390/crypto/zcrypt_error.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_error.h 2 * linux/drivers/s390/crypto/zcrypt_error.h
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs
diff --git a/drivers/s390/crypto/zcrypt_mono.c b/drivers/s390/crypto/zcrypt_mono.c
index f48b61a6126c..2a9349ad68b7 100644
--- a/drivers/s390/crypto/zcrypt_mono.c
+++ b/drivers/s390/crypto/zcrypt_mono.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_mono.c 2 * linux/drivers/s390/crypto/zcrypt_mono.c
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c
index 0ff56e86caae..b6a4ecdc8025 100644
--- a/drivers/s390/crypto/zcrypt_pcica.c
+++ b/drivers/s390/crypto/zcrypt_pcica.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_pcica.c 2 * linux/drivers/s390/crypto/zcrypt_pcica.c
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs
diff --git a/drivers/s390/crypto/zcrypt_pcica.h b/drivers/s390/crypto/zcrypt_pcica.h
index a08a4f8c33c9..3be11187f6df 100644
--- a/drivers/s390/crypto/zcrypt_pcica.h
+++ b/drivers/s390/crypto/zcrypt_pcica.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_pcica.h 2 * linux/drivers/s390/crypto/zcrypt_pcica.h
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c
index 900362983fec..f295a403b29a 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.c
+++ b/drivers/s390/crypto/zcrypt_pcicc.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_pcicc.c 2 * linux/drivers/s390/crypto/zcrypt_pcicc.c
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs
diff --git a/drivers/s390/crypto/zcrypt_pcicc.h b/drivers/s390/crypto/zcrypt_pcicc.h
index 027bafc7312a..6d4454846c8f 100644
--- a/drivers/s390/crypto/zcrypt_pcicc.h
+++ b/drivers/s390/crypto/zcrypt_pcicc.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_pcicc.h 2 * linux/drivers/s390/crypto/zcrypt_pcicc.h
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 6064cf58be43..2da8b9381407 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_pcixcc.c 2 * linux/drivers/s390/crypto/zcrypt_pcixcc.c
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs
@@ -60,6 +60,15 @@
60 60
61#define PCIXCC_CLEANUP_TIME (15*HZ) 61#define PCIXCC_CLEANUP_TIME (15*HZ)
62 62
63#define CEIL4(x) ((((x)+3)/4)*4)
64
65struct response_type {
66 struct completion work;
67 int type;
68};
69#define PCIXCC_RESPONSE_TYPE_ICA 0
70#define PCIXCC_RESPONSE_TYPE_XCRB 1
71
63static struct ap_device_id zcrypt_pcixcc_ids[] = { 72static struct ap_device_id zcrypt_pcixcc_ids[] = {
64 { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) }, 73 { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) },
65 { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) }, 74 { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) },
@@ -244,6 +253,108 @@ static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,
244} 253}
245 254
246/** 255/**
256 * Convert a XCRB message to a type6 CPRB message.
257 *
258 * @zdev: crypto device pointer
259 * @ap_msg: pointer to AP message
260 * @xcRB: pointer to user input data
261 *
262 * Returns 0 on success or -EFAULT.
263 */
264struct type86_fmt2_msg {
265 struct type86_hdr hdr;
266 struct type86_fmt2_ext fmt2;
267} __attribute__((packed));
268
269static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
270 struct ap_message *ap_msg,
271 struct ica_xcRB *xcRB)
272{
273 static struct type6_hdr static_type6_hdrX = {
274 .type = 0x06,
275 .offset1 = 0x00000058,
276 };
277 struct {
278 struct type6_hdr hdr;
279 struct ica_CPRBX cprbx;
280 } __attribute__((packed)) *msg = ap_msg->message;
281
282 int rcblen = CEIL4(xcRB->request_control_blk_length);
283 int replylen;
284 char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
285 char *function_code;
286
287 /* length checks */
288 ap_msg->length = sizeof(struct type6_hdr) +
289 CEIL4(xcRB->request_control_blk_length) +
290 xcRB->request_data_length;
291 if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE) {
292 PRINTK("Combined message is too large (%ld/%d/%d).\n",
293 sizeof(struct type6_hdr),
294 xcRB->request_control_blk_length,
295 xcRB->request_data_length);
296 return -EFAULT;
297 }
298 if (CEIL4(xcRB->reply_control_blk_length) >
299 PCIXCC_MAX_XCRB_REPLY_SIZE) {
300 PDEBUG("Reply CPRB length is too large (%d).\n",
301 xcRB->request_control_blk_length);
302 return -EFAULT;
303 }
304 if (CEIL4(xcRB->reply_data_length) > PCIXCC_MAX_XCRB_DATA_SIZE) {
305 PDEBUG("Reply data block length is too large (%d).\n",
306 xcRB->reply_data_length);
307 return -EFAULT;
308 }
309 replylen = CEIL4(xcRB->reply_control_blk_length) +
310 CEIL4(xcRB->reply_data_length) +
311 sizeof(struct type86_fmt2_msg);
312 if (replylen > PCIXCC_MAX_XCRB_RESPONSE_SIZE) {
313 PDEBUG("Reply CPRB + data block > PCIXCC_MAX_XCRB_RESPONSE_SIZE"
314 " (%d/%d/%d).\n",
315 sizeof(struct type86_fmt2_msg),
316 xcRB->reply_control_blk_length,
317 xcRB->reply_data_length);
318 xcRB->reply_control_blk_length = PCIXCC_MAX_XCRB_RESPONSE_SIZE -
319 (sizeof(struct type86_fmt2_msg) +
320 CEIL4(xcRB->reply_data_length));
321 PDEBUG("Capping Reply CPRB length at %d\n",
322 xcRB->reply_control_blk_length);
323 }
324
325 /* prepare type6 header */
326 msg->hdr = static_type6_hdrX;
327 memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
328 msg->hdr.ToCardLen1 = xcRB->request_control_blk_length;
329 if (xcRB->request_data_length) {
330 msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
331 msg->hdr.ToCardLen2 = xcRB->request_data_length;
332 }
333 msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
334 msg->hdr.FromCardLen2 = xcRB->reply_data_length;
335
336 /* prepare CPRB */
337 if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
338 xcRB->request_control_blk_length))
339 return -EFAULT;
340 if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
341 xcRB->request_control_blk_length) {
342 PDEBUG("cprb_len too large (%d/%d)\n", msg->cprbx.cprb_len,
343 xcRB->request_control_blk_length);
344 return -EFAULT;
345 }
346 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
347 memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code));
348
349 /* copy data block */
350 if (xcRB->request_data_length &&
351 copy_from_user(req_data, xcRB->request_data_address,
352 xcRB->request_data_length))
353 return -EFAULT;
354 return 0;
355}
356
357/**
247 * Copy results from a type 86 ICA reply message back to user space. 358 * Copy results from a type 86 ICA reply message back to user space.
248 * 359 *
249 * @zdev: crypto device pointer 360 * @zdev: crypto device pointer
@@ -363,6 +474,37 @@ static int convert_type86_ica(struct zcrypt_device *zdev,
363 return 0; 474 return 0;
364} 475}
365 476
477/**
478 * Copy results from a type 86 XCRB reply message back to user space.
479 *
480 * @zdev: crypto device pointer
481 * @reply: reply AP message.
482 * @xcRB: pointer to XCRB
483 *
484 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
485 */
486static int convert_type86_xcrb(struct zcrypt_device *zdev,
487 struct ap_message *reply,
488 struct ica_xcRB *xcRB)
489{
490 struct type86_fmt2_msg *msg = reply->message;
491 char *data = reply->message;
492
493 /* Copy CPRB to user */
494 if (copy_to_user(xcRB->reply_control_blk_addr,
495 data + msg->fmt2.offset1, msg->fmt2.count1))
496 return -EFAULT;
497 xcRB->reply_control_blk_length = msg->fmt2.count1;
498
499 /* Copy data buffer to user */
500 if (msg->fmt2.count2)
501 if (copy_to_user(xcRB->reply_data_addr,
502 data + msg->fmt2.offset2, msg->fmt2.count2))
503 return -EFAULT;
504 xcRB->reply_data_length = msg->fmt2.count2;
505 return 0;
506}
507
366static int convert_response_ica(struct zcrypt_device *zdev, 508static int convert_response_ica(struct zcrypt_device *zdev,
367 struct ap_message *reply, 509 struct ap_message *reply,
368 char __user *outputdata, 510 char __user *outputdata,
@@ -391,6 +533,36 @@ static int convert_response_ica(struct zcrypt_device *zdev,
391 } 533 }
392} 534}
393 535
536static int convert_response_xcrb(struct zcrypt_device *zdev,
537 struct ap_message *reply,
538 struct ica_xcRB *xcRB)
539{
540 struct type86x_reply *msg = reply->message;
541
542 /* Response type byte is the second byte in the response. */
543 switch (((unsigned char *) reply->message)[1]) {
544 case TYPE82_RSP_CODE:
545 case TYPE88_RSP_CODE:
546 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
547 return convert_error(zdev, reply);
548 case TYPE86_RSP_CODE:
549 if (msg->hdr.reply_code) {
550 memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
551 return convert_error(zdev, reply);
552 }
553 if (msg->cprbx.cprb_ver_id == 0x02)
554 return convert_type86_xcrb(zdev, reply, xcRB);
555 /* no break, incorrect cprb version is an unknown response */
556 default: /* Unknown response type, this should NEVER EVER happen */
557 PRINTK("Unrecognized Message Header: %08x%08x\n",
558 *(unsigned int *) reply->message,
559 *(unsigned int *) (reply->message+4));
560 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
561 zdev->online = 0;
562 return -EAGAIN; /* repeat the request on a different device. */
563 }
564}
565
394/** 566/**
395 * This function is called from the AP bus code after a crypto request 567 * This function is called from the AP bus code after a crypto request
396 * "msg" has finished with the reply message "reply". 568 * "msg" has finished with the reply message "reply".
@@ -407,6 +579,8 @@ static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
407 .type = TYPE82_RSP_CODE, 579 .type = TYPE82_RSP_CODE,
408 .reply_code = REP82_ERROR_MACHINE_FAILURE, 580 .reply_code = REP82_ERROR_MACHINE_FAILURE,
409 }; 581 };
582 struct response_type *resp_type =
583 (struct response_type *) msg->private;
410 struct type86x_reply *t86r = reply->message; 584 struct type86x_reply *t86r = reply->message;
411 int length; 585 int length;
412 586
@@ -415,12 +589,27 @@ static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
415 memcpy(msg->message, &error_reply, sizeof(error_reply)); 589 memcpy(msg->message, &error_reply, sizeof(error_reply));
416 else if (t86r->hdr.type == TYPE86_RSP_CODE && 590 else if (t86r->hdr.type == TYPE86_RSP_CODE &&
417 t86r->cprbx.cprb_ver_id == 0x02) { 591 t86r->cprbx.cprb_ver_id == 0x02) {
418 length = sizeof(struct type86x_reply) + t86r->length - 2; 592 switch (resp_type->type) {
419 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length); 593 case PCIXCC_RESPONSE_TYPE_ICA:
420 memcpy(msg->message, reply->message, length); 594 length = sizeof(struct type86x_reply)
595 + t86r->length - 2;
596 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
597 memcpy(msg->message, reply->message, length);
598 break;
599 case PCIXCC_RESPONSE_TYPE_XCRB:
600 length = t86r->fmt2.offset2 + t86r->fmt2.count2;
601 length = min(PCIXCC_MAX_XCRB_RESPONSE_SIZE, length);
602 memcpy(msg->message, reply->message, length);
603 break;
604 default:
605 PRINTK("Invalid internal response type: %i\n",
606 resp_type->type);
607 memcpy(msg->message, &error_reply,
608 sizeof error_reply);
609 }
421 } else 610 } else
422 memcpy(msg->message, reply->message, sizeof error_reply); 611 memcpy(msg->message, reply->message, sizeof error_reply);
423 complete((struct completion *) msg->private); 612 complete(&(resp_type->work));
424} 613}
425 614
426static atomic_t zcrypt_step = ATOMIC_INIT(0); 615static atomic_t zcrypt_step = ATOMIC_INIT(0);
@@ -436,7 +625,9 @@ static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
436 struct ica_rsa_modexpo *mex) 625 struct ica_rsa_modexpo *mex)
437{ 626{
438 struct ap_message ap_msg; 627 struct ap_message ap_msg;
439 struct completion work; 628 struct response_type resp_type = {
629 .type = PCIXCC_RESPONSE_TYPE_ICA,
630 };
440 int rc; 631 int rc;
441 632
442 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); 633 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
@@ -444,14 +635,14 @@ static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
444 return -ENOMEM; 635 return -ENOMEM;
445 ap_msg.psmid = (((unsigned long long) current->pid) << 32) + 636 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
446 atomic_inc_return(&zcrypt_step); 637 atomic_inc_return(&zcrypt_step);
447 ap_msg.private = &work; 638 ap_msg.private = &resp_type;
448 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex); 639 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
449 if (rc) 640 if (rc)
450 goto out_free; 641 goto out_free;
451 init_completion(&work); 642 init_completion(&resp_type.work);
452 ap_queue_message(zdev->ap_dev, &ap_msg); 643 ap_queue_message(zdev->ap_dev, &ap_msg);
453 rc = wait_for_completion_interruptible_timeout( 644 rc = wait_for_completion_interruptible_timeout(
454 &work, PCIXCC_CLEANUP_TIME); 645 &resp_type.work, PCIXCC_CLEANUP_TIME);
455 if (rc > 0) 646 if (rc > 0)
456 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata, 647 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
457 mex->outputdatalength); 648 mex->outputdatalength);
@@ -478,7 +669,9 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
478 struct ica_rsa_modexpo_crt *crt) 669 struct ica_rsa_modexpo_crt *crt)
479{ 670{
480 struct ap_message ap_msg; 671 struct ap_message ap_msg;
481 struct completion work; 672 struct response_type resp_type = {
673 .type = PCIXCC_RESPONSE_TYPE_ICA,
674 };
482 int rc; 675 int rc;
483 676
484 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); 677 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
@@ -486,14 +679,14 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
486 return -ENOMEM; 679 return -ENOMEM;
487 ap_msg.psmid = (((unsigned long long) current->pid) << 32) + 680 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
488 atomic_inc_return(&zcrypt_step); 681 atomic_inc_return(&zcrypt_step);
489 ap_msg.private = &work; 682 ap_msg.private = &resp_type;
490 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt); 683 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
491 if (rc) 684 if (rc)
492 goto out_free; 685 goto out_free;
493 init_completion(&work); 686 init_completion(&resp_type.work);
494 ap_queue_message(zdev->ap_dev, &ap_msg); 687 ap_queue_message(zdev->ap_dev, &ap_msg);
495 rc = wait_for_completion_interruptible_timeout( 688 rc = wait_for_completion_interruptible_timeout(
496 &work, PCIXCC_CLEANUP_TIME); 689 &resp_type.work, PCIXCC_CLEANUP_TIME);
497 if (rc > 0) 690 if (rc > 0)
498 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata, 691 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
499 crt->outputdatalength); 692 crt->outputdatalength);
@@ -510,11 +703,55 @@ out_free:
510} 703}
511 704
512/** 705/**
706 * The request distributor calls this function if it picked the PCIXCC/CEX2C
707 * device to handle a send_cprb request.
708 * @zdev: pointer to zcrypt_device structure that identifies the
709 * PCIXCC/CEX2C device to the request distributor
710 * @xcRB: pointer to the send_cprb request buffer
711 */
712long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, struct ica_xcRB *xcRB)
713{
714 struct ap_message ap_msg;
715 struct response_type resp_type = {
716 .type = PCIXCC_RESPONSE_TYPE_XCRB,
717 };
718 int rc;
719
720 ap_msg.message = (void *) kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
721 if (!ap_msg.message)
722 return -ENOMEM;
723 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
724 atomic_inc_return(&zcrypt_step);
725 ap_msg.private = &resp_type;
726 rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB);
727 if (rc)
728 goto out_free;
729 init_completion(&resp_type.work);
730 ap_queue_message(zdev->ap_dev, &ap_msg);
731 rc = wait_for_completion_interruptible_timeout(
732 &resp_type.work, PCIXCC_CLEANUP_TIME);
733 if (rc > 0)
734 rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
735 else {
736 /* Signal pending or message timed out. */
737 ap_cancel_message(zdev->ap_dev, &ap_msg);
738 if (rc == 0)
739 /* Message timed out. */
740 rc = -ETIME;
741 }
742out_free:
743 memset(ap_msg.message, 0x0, ap_msg.length);
744 kfree(ap_msg.message);
745 return rc;
746}
747
748/**
513 * The crypto operations for a PCIXCC/CEX2C card. 749 * The crypto operations for a PCIXCC/CEX2C card.
514 */ 750 */
515static struct zcrypt_ops zcrypt_pcixcc_ops = { 751static struct zcrypt_ops zcrypt_pcixcc_ops = {
516 .rsa_modexpo = zcrypt_pcixcc_modexpo, 752 .rsa_modexpo = zcrypt_pcixcc_modexpo,
517 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt, 753 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
754 .send_cprb = zcrypt_pcixcc_send_cprb,
518}; 755};
519 756
520/** 757/**
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.h b/drivers/s390/crypto/zcrypt_pcixcc.h
index d4c44c4d7ad0..a78ff307fd19 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.h
+++ b/drivers/s390/crypto/zcrypt_pcixcc.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_pcixcc.h 2 * linux/drivers/s390/crypto/zcrypt_pcixcc.h
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs