diff options
author | Ralph Wuerthner <rwuerthn@de.ibm.com> | 2006-09-20 09:58:36 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-09-20 09:58:36 -0400 |
commit | 5432114baf0300286a6ca1b0aea549492a379432 (patch) | |
tree | 6a9cf64c86e4ee4d439f91e9bd4485688d28ddd7 /drivers/s390/crypto/zcrypt_api.c | |
parent | fe3a1be59c851aba2330387596c6134bc5ec8397 (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/crypto/zcrypt_api.c')
-rw-r--r-- | drivers/s390/crypto/zcrypt_api.c | 112 |
1 files changed, 111 insertions, 1 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 | ||
395 | static 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 | |||
395 | static void zcrypt_status_mask(char status[AP_DEVICES]) | 430 | static 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 | ||
733 | struct 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 | |||
753 | static 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 | |||
686 | long zcrypt_compat_ioctl(struct file *filp, unsigned int cmd, | 794 | long 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 |