diff options
Diffstat (limited to 'drivers/s390/crypto')
22 files changed, 1280 insertions, 2301 deletions
diff --git a/drivers/s390/crypto/Makefile b/drivers/s390/crypto/Makefile index 771faf7094d..f0a12d2eb78 100644 --- a/drivers/s390/crypto/Makefile +++ b/drivers/s390/crypto/Makefile | |||
| @@ -2,7 +2,16 @@ | |||
| 2 | # S/390 crypto devices | 2 | # S/390 crypto devices |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | ifdef CONFIG_ZCRYPT_MONOLITHIC | ||
| 6 | |||
| 7 | z90crypt-objs := zcrypt_mono.o ap_bus.o zcrypt_api.o \ | ||
| 8 | zcrypt_pcica.o zcrypt_pcicc.o zcrypt_pcixcc.o zcrypt_cex2a.o | ||
| 9 | obj-$(CONFIG_ZCRYPT) += z90crypt.o | ||
| 10 | |||
| 11 | else | ||
| 12 | |||
| 5 | ap-objs := ap_bus.o | 13 | ap-objs := ap_bus.o |
| 6 | obj-$(CONFIG_ZCRYPT) += ap.o zcrypt_api.o zcrypt_pcicc.o zcrypt_pcixcc.o | 14 | obj-$(CONFIG_ZCRYPT) += ap.o zcrypt_api.o zcrypt_pcicc.o zcrypt_pcixcc.o |
| 7 | obj-$(CONFIG_ZCRYPT) += zcrypt_pcica.o zcrypt_cex2a.o zcrypt_cex4.o | 15 | obj-$(CONFIG_ZCRYPT) += zcrypt_pcica.o zcrypt_cex2a.o |
| 8 | obj-$(CONFIG_ZCRYPT) += zcrypt_msgtype6.o zcrypt_msgtype50.o | 16 | |
| 17 | endif | ||
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index b8b340ac533..b77ae519d79 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright IBM Corp. 2006, 2012 | 2 | * linux/drivers/s390/crypto/ap_bus.c |
| 3 | * | ||
| 4 | * Copyright (C) 2006 IBM Corporation | ||
| 3 | * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> | 5 | * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> |
| 4 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 6 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
| 5 | * Ralph Wuerthner <rwuerthn@de.ibm.com> | 7 | * Ralph Wuerthner <rwuerthn@de.ibm.com> |
| @@ -40,10 +42,10 @@ | |||
| 40 | #include <asm/reset.h> | 42 | #include <asm/reset.h> |
| 41 | #include <asm/airq.h> | 43 | #include <asm/airq.h> |
| 42 | #include <linux/atomic.h> | 44 | #include <linux/atomic.h> |
| 45 | #include <asm/system.h> | ||
| 43 | #include <asm/isc.h> | 46 | #include <asm/isc.h> |
| 44 | #include <linux/hrtimer.h> | 47 | #include <linux/hrtimer.h> |
| 45 | #include <linux/ktime.h> | 48 | #include <linux/ktime.h> |
| 46 | #include <asm/facility.h> | ||
| 47 | 49 | ||
| 48 | #include "ap_bus.h" | 50 | #include "ap_bus.h" |
| 49 | 51 | ||
| @@ -62,14 +64,13 @@ static void ap_interrupt_handler(void *unused1, void *unused2); | |||
| 62 | static void ap_reset(struct ap_device *ap_dev); | 64 | static void ap_reset(struct ap_device *ap_dev); |
| 63 | static void ap_config_timeout(unsigned long ptr); | 65 | static void ap_config_timeout(unsigned long ptr); |
| 64 | static int ap_select_domain(void); | 66 | static int ap_select_domain(void); |
| 65 | static void ap_query_configuration(void); | ||
| 66 | 67 | ||
| 67 | /* | 68 | /* |
| 68 | * Module description. | 69 | * Module description. |
| 69 | */ | 70 | */ |
| 70 | MODULE_AUTHOR("IBM Corporation"); | 71 | MODULE_AUTHOR("IBM Corporation"); |
| 71 | MODULE_DESCRIPTION("Adjunct Processor Bus driver, " \ | 72 | MODULE_DESCRIPTION("Adjunct Processor Bus driver, " |
| 72 | "Copyright IBM Corp. 2006, 2012"); | 73 | "Copyright 2006 IBM Corporation"); |
| 73 | MODULE_LICENSE("GPL"); | 74 | MODULE_LICENSE("GPL"); |
| 74 | 75 | ||
| 75 | /* | 76 | /* |
| @@ -85,7 +86,6 @@ module_param_named(poll_thread, ap_thread_flag, int, 0000); | |||
| 85 | MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off)."); | 86 | MODULE_PARM_DESC(poll_thread, "Turn on/off poll thread, default is 0 (off)."); |
| 86 | 87 | ||
| 87 | static struct device *ap_root_device = NULL; | 88 | static struct device *ap_root_device = NULL; |
| 88 | static struct ap_config_info *ap_configuration; | ||
| 89 | static DEFINE_SPINLOCK(ap_device_list_lock); | 89 | static DEFINE_SPINLOCK(ap_device_list_lock); |
| 90 | static LIST_HEAD(ap_device_list); | 90 | static LIST_HEAD(ap_device_list); |
| 91 | 91 | ||
| @@ -160,19 +160,6 @@ static int ap_interrupts_available(void) | |||
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | /** | 162 | /** |
| 163 | * ap_configuration_available(): Test if AP configuration | ||
| 164 | * information is available. | ||
| 165 | * | ||
| 166 | * Returns 1 if AP configuration information is available. | ||
| 167 | */ | ||
| 168 | #ifdef CONFIG_64BIT | ||
| 169 | static int ap_configuration_available(void) | ||
| 170 | { | ||
| 171 | return test_facility(2) && test_facility(12); | ||
| 172 | } | ||
| 173 | #endif | ||
| 174 | |||
| 175 | /** | ||
| 176 | * ap_test_queue(): Test adjunct processor queue. | 163 | * ap_test_queue(): Test adjunct processor queue. |
| 177 | * @qid: The AP queue number | 164 | * @qid: The AP queue number |
| 178 | * @queue_depth: Pointer to queue depth value | 165 | * @queue_depth: Pointer to queue depth value |
| @@ -228,7 +215,7 @@ ap_queue_interruption_control(ap_qid_t qid, void *ind) | |||
| 228 | register struct ap_queue_status reg1_out asm ("1"); | 215 | register struct ap_queue_status reg1_out asm ("1"); |
| 229 | register void *reg2 asm ("2") = ind; | 216 | register void *reg2 asm ("2") = ind; |
| 230 | asm volatile( | 217 | asm volatile( |
| 231 | ".long 0xb2af0000" /* PQAP(AQIC) */ | 218 | ".long 0xb2af0000" /* PQAP(RAPQ) */ |
| 232 | : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2) | 219 | : "+d" (reg0), "+d" (reg1_in), "=d" (reg1_out), "+d" (reg2) |
| 233 | : | 220 | : |
| 234 | : "cc" ); | 221 | : "cc" ); |
| @@ -245,7 +232,7 @@ __ap_query_functions(ap_qid_t qid, unsigned int *functions) | |||
| 245 | register unsigned long reg2 asm ("2"); | 232 | register unsigned long reg2 asm ("2"); |
| 246 | 233 | ||
| 247 | asm volatile( | 234 | asm volatile( |
| 248 | ".long 0xb2af0000\n" /* PQAP(TAPQ) */ | 235 | ".long 0xb2af0000\n" |
| 249 | "0:\n" | 236 | "0:\n" |
| 250 | EX_TABLE(0b, 0b) | 237 | EX_TABLE(0b, 0b) |
| 251 | : "+d" (reg0), "+d" (reg1), "=d" (reg2) | 238 | : "+d" (reg0), "+d" (reg1), "=d" (reg2) |
| @@ -257,26 +244,6 @@ __ap_query_functions(ap_qid_t qid, unsigned int *functions) | |||
| 257 | } | 244 | } |
| 258 | #endif | 245 | #endif |
| 259 | 246 | ||
| 260 | #ifdef CONFIG_64BIT | ||
| 261 | static inline int __ap_query_configuration(struct ap_config_info *config) | ||
| 262 | { | ||
| 263 | register unsigned long reg0 asm ("0") = 0x04000000UL; | ||
| 264 | register unsigned long reg1 asm ("1") = -EINVAL; | ||
| 265 | register unsigned char *reg2 asm ("2") = (unsigned char *)config; | ||
| 266 | |||
| 267 | asm volatile( | ||
| 268 | ".long 0xb2af0000\n" /* PQAP(QCI) */ | ||
| 269 | "0: la %1,0\n" | ||
| 270 | "1:\n" | ||
| 271 | EX_TABLE(0b, 1b) | ||
| 272 | : "+d" (reg0), "+d" (reg1), "+d" (reg2) | ||
| 273 | : | ||
| 274 | : "cc"); | ||
| 275 | |||
| 276 | return reg1; | ||
| 277 | } | ||
| 278 | #endif | ||
| 279 | |||
| 280 | /** | 247 | /** |
| 281 | * ap_query_functions(): Query supported functions. | 248 | * ap_query_functions(): Query supported functions. |
| 282 | * @qid: The AP queue number | 249 | * @qid: The AP queue number |
| @@ -327,6 +294,25 @@ static int ap_query_functions(ap_qid_t qid, unsigned int *functions) | |||
| 327 | } | 294 | } |
| 328 | 295 | ||
| 329 | /** | 296 | /** |
| 297 | * ap_4096_commands_availablen(): Check for availability of 4096 bit RSA | ||
| 298 | * support. | ||
| 299 | * @qid: The AP queue number | ||
| 300 | * | ||
| 301 | * Returns 1 if 4096 bit RSA keys are support fo the AP, returns 0 if not. | ||
| 302 | */ | ||
| 303 | int ap_4096_commands_available(ap_qid_t qid) | ||
| 304 | { | ||
| 305 | unsigned int functions; | ||
| 306 | |||
| 307 | if (ap_query_functions(qid, &functions)) | ||
| 308 | return 0; | ||
| 309 | |||
| 310 | return test_ap_facility(functions, 1) && | ||
| 311 | test_ap_facility(functions, 2); | ||
| 312 | } | ||
| 313 | EXPORT_SYMBOL(ap_4096_commands_available); | ||
| 314 | |||
| 315 | /** | ||
| 330 | * ap_queue_enable_interruption(): Enable interruption on an AP. | 316 | * ap_queue_enable_interruption(): Enable interruption on an AP. |
| 331 | * @qid: The AP queue number | 317 | * @qid: The AP queue number |
| 332 | * @ind: the notification indicator byte | 318 | * @ind: the notification indicator byte |
| @@ -352,12 +338,6 @@ static int ap_queue_enable_interruption(ap_qid_t qid, void *ind) | |||
| 352 | break; | 338 | break; |
| 353 | case AP_RESPONSE_RESET_IN_PROGRESS: | 339 | case AP_RESPONSE_RESET_IN_PROGRESS: |
| 354 | case AP_RESPONSE_BUSY: | 340 | case AP_RESPONSE_BUSY: |
| 355 | if (i < AP_MAX_RESET - 1) { | ||
| 356 | udelay(5); | ||
| 357 | status = ap_queue_interruption_control(qid, | ||
| 358 | ind); | ||
| 359 | continue; | ||
| 360 | } | ||
| 361 | break; | 341 | break; |
| 362 | case AP_RESPONSE_Q_NOT_AVAIL: | 342 | case AP_RESPONSE_Q_NOT_AVAIL: |
| 363 | case AP_RESPONSE_DECONFIGURED: | 343 | case AP_RESPONSE_DECONFIGURED: |
| @@ -411,7 +391,7 @@ __ap_send(ap_qid_t qid, unsigned long long psmid, void *msg, size_t length, | |||
| 411 | reg0 |= 0x400000UL; | 391 | reg0 |= 0x400000UL; |
| 412 | 392 | ||
| 413 | asm volatile ( | 393 | asm volatile ( |
| 414 | "0: .long 0xb2ad0042\n" /* NQAP */ | 394 | "0: .long 0xb2ad0042\n" /* DQAP */ |
| 415 | " brc 2,0b" | 395 | " brc 2,0b" |
| 416 | : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3) | 396 | : "+d" (reg0), "=d" (reg1), "+d" (reg2), "+d" (reg3) |
| 417 | : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg) | 397 | : "d" (reg4), "d" (reg5), "m" (*(msgblock *) msg) |
| @@ -470,7 +450,7 @@ __ap_recv(ap_qid_t qid, unsigned long long *psmid, void *msg, size_t length) | |||
| 470 | 450 | ||
| 471 | 451 | ||
| 472 | asm volatile( | 452 | asm volatile( |
| 473 | "0: .long 0xb2ae0064\n" /* DQAP */ | 453 | "0: .long 0xb2ae0064\n" |
| 474 | " brc 6,0b\n" | 454 | " brc 6,0b\n" |
| 475 | : "+d" (reg0), "=d" (reg1), "+d" (reg2), | 455 | : "+d" (reg0), "=d" (reg1), "+d" (reg2), |
| 476 | "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7), | 456 | "+d" (reg4), "+d" (reg5), "+d" (reg6), "+d" (reg7), |
| @@ -673,34 +653,6 @@ static ssize_t ap_request_count_show(struct device *dev, | |||
| 673 | 653 | ||
| 674 | static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL); | 654 | static DEVICE_ATTR(request_count, 0444, ap_request_count_show, NULL); |
| 675 | 655 | ||
| 676 | static ssize_t ap_requestq_count_show(struct device *dev, | ||
| 677 | struct device_attribute *attr, char *buf) | ||
| 678 | { | ||
| 679 | struct ap_device *ap_dev = to_ap_dev(dev); | ||
| 680 | int rc; | ||
| 681 | |||
| 682 | spin_lock_bh(&ap_dev->lock); | ||
| 683 | rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->requestq_count); | ||
| 684 | spin_unlock_bh(&ap_dev->lock); | ||
| 685 | return rc; | ||
| 686 | } | ||
| 687 | |||
| 688 | static DEVICE_ATTR(requestq_count, 0444, ap_requestq_count_show, NULL); | ||
| 689 | |||
| 690 | static ssize_t ap_pendingq_count_show(struct device *dev, | ||
| 691 | struct device_attribute *attr, char *buf) | ||
| 692 | { | ||
| 693 | struct ap_device *ap_dev = to_ap_dev(dev); | ||
| 694 | int rc; | ||
| 695 | |||
| 696 | spin_lock_bh(&ap_dev->lock); | ||
| 697 | rc = snprintf(buf, PAGE_SIZE, "%d\n", ap_dev->pendingq_count); | ||
| 698 | spin_unlock_bh(&ap_dev->lock); | ||
| 699 | return rc; | ||
| 700 | } | ||
| 701 | |||
| 702 | static DEVICE_ATTR(pendingq_count, 0444, ap_pendingq_count_show, NULL); | ||
| 703 | |||
| 704 | static ssize_t ap_modalias_show(struct device *dev, | 656 | static ssize_t ap_modalias_show(struct device *dev, |
| 705 | struct device_attribute *attr, char *buf) | 657 | struct device_attribute *attr, char *buf) |
| 706 | { | 658 | { |
| @@ -709,23 +661,11 @@ static ssize_t ap_modalias_show(struct device *dev, | |||
| 709 | 661 | ||
| 710 | static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL); | 662 | static DEVICE_ATTR(modalias, 0444, ap_modalias_show, NULL); |
| 711 | 663 | ||
| 712 | static ssize_t ap_functions_show(struct device *dev, | ||
| 713 | struct device_attribute *attr, char *buf) | ||
| 714 | { | ||
| 715 | struct ap_device *ap_dev = to_ap_dev(dev); | ||
| 716 | return snprintf(buf, PAGE_SIZE, "0x%08X\n", ap_dev->functions); | ||
| 717 | } | ||
| 718 | |||
| 719 | static DEVICE_ATTR(ap_functions, 0444, ap_functions_show, NULL); | ||
| 720 | |||
| 721 | static struct attribute *ap_dev_attrs[] = { | 664 | static struct attribute *ap_dev_attrs[] = { |
| 722 | &dev_attr_hwtype.attr, | 665 | &dev_attr_hwtype.attr, |
| 723 | &dev_attr_depth.attr, | 666 | &dev_attr_depth.attr, |
| 724 | &dev_attr_request_count.attr, | 667 | &dev_attr_request_count.attr, |
| 725 | &dev_attr_requestq_count.attr, | ||
| 726 | &dev_attr_pendingq_count.attr, | ||
| 727 | &dev_attr_modalias.attr, | 668 | &dev_attr_modalias.attr, |
| 728 | &dev_attr_ap_functions.attr, | ||
| 729 | NULL | 669 | NULL |
| 730 | }; | 670 | }; |
| 731 | static struct attribute_group ap_dev_attr_group = { | 671 | static struct attribute_group ap_dev_attr_group = { |
| @@ -828,7 +768,6 @@ static int ap_bus_resume(struct device *dev) | |||
| 828 | ap_suspend_flag = 0; | 768 | ap_suspend_flag = 0; |
| 829 | if (!ap_interrupts_available()) | 769 | if (!ap_interrupts_available()) |
| 830 | ap_interrupt_indicator = NULL; | 770 | ap_interrupt_indicator = NULL; |
| 831 | ap_query_configuration(); | ||
| 832 | if (!user_set_domain) { | 771 | if (!user_set_domain) { |
| 833 | ap_domain_index = -1; | 772 | ap_domain_index = -1; |
| 834 | ap_select_domain(); | 773 | ap_select_domain(); |
| @@ -897,12 +836,12 @@ static void __ap_flush_queue(struct ap_device *ap_dev) | |||
| 897 | list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) { | 836 | list_for_each_entry_safe(ap_msg, next, &ap_dev->pendingq, list) { |
| 898 | list_del_init(&ap_msg->list); | 837 | list_del_init(&ap_msg->list); |
| 899 | ap_dev->pendingq_count--; | 838 | ap_dev->pendingq_count--; |
| 900 | ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); | 839 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); |
| 901 | } | 840 | } |
| 902 | list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) { | 841 | list_for_each_entry_safe(ap_msg, next, &ap_dev->requestq, list) { |
| 903 | list_del_init(&ap_msg->list); | 842 | list_del_init(&ap_msg->list); |
| 904 | ap_dev->requestq_count--; | 843 | ap_dev->requestq_count--; |
| 905 | ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); | 844 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); |
| 906 | } | 845 | } |
| 907 | } | 846 | } |
| 908 | 847 | ||
| @@ -952,20 +891,6 @@ void ap_driver_unregister(struct ap_driver *ap_drv) | |||
| 952 | } | 891 | } |
| 953 | EXPORT_SYMBOL(ap_driver_unregister); | 892 | EXPORT_SYMBOL(ap_driver_unregister); |
| 954 | 893 | ||
| 955 | void ap_bus_force_rescan(void) | ||
| 956 | { | ||
| 957 | /* Delete the AP bus rescan timer. */ | ||
| 958 | del_timer(&ap_config_timer); | ||
| 959 | |||
| 960 | /* processing a synchonuous bus rescan */ | ||
| 961 | ap_scan_bus(NULL); | ||
| 962 | |||
| 963 | /* Setup the AP bus rescan timer again. */ | ||
| 964 | ap_config_timer.expires = jiffies + ap_config_time * HZ; | ||
| 965 | add_timer(&ap_config_timer); | ||
| 966 | } | ||
| 967 | EXPORT_SYMBOL(ap_bus_force_rescan); | ||
| 968 | |||
| 969 | /* | 894 | /* |
| 970 | * AP bus attributes. | 895 | * AP bus attributes. |
| 971 | */ | 896 | */ |
| @@ -1068,65 +993,6 @@ static struct bus_attribute *const ap_bus_attrs[] = { | |||
| 1068 | NULL, | 993 | NULL, |
| 1069 | }; | 994 | }; |
| 1070 | 995 | ||
| 1071 | static inline int ap_test_config(unsigned int *field, unsigned int nr) | ||
| 1072 | { | ||
| 1073 | if (nr > 0xFFu) | ||
| 1074 | return 0; | ||
| 1075 | return ap_test_bit((field + (nr >> 5)), (nr & 0x1f)); | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | /* | ||
| 1079 | * ap_test_config_card_id(): Test, whether an AP card ID is configured. | ||
| 1080 | * @id AP card ID | ||
| 1081 | * | ||
| 1082 | * Returns 0 if the card is not configured | ||
| 1083 | * 1 if the card is configured or | ||
| 1084 | * if the configuration information is not available | ||
| 1085 | */ | ||
| 1086 | static inline int ap_test_config_card_id(unsigned int id) | ||
| 1087 | { | ||
| 1088 | if (!ap_configuration) | ||
| 1089 | return 1; | ||
| 1090 | return ap_test_config(ap_configuration->apm, id); | ||
| 1091 | } | ||
| 1092 | |||
| 1093 | /* | ||
| 1094 | * ap_test_config_domain(): Test, whether an AP usage domain is configured. | ||
| 1095 | * @domain AP usage domain ID | ||
| 1096 | * | ||
| 1097 | * Returns 0 if the usage domain is not configured | ||
| 1098 | * 1 if the usage domain is configured or | ||
| 1099 | * if the configuration information is not available | ||
| 1100 | */ | ||
| 1101 | static inline int ap_test_config_domain(unsigned int domain) | ||
| 1102 | { | ||
| 1103 | if (!ap_configuration) | ||
| 1104 | return 1; | ||
| 1105 | return ap_test_config(ap_configuration->aqm, domain); | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | /** | ||
| 1109 | * ap_query_configuration(): Query AP configuration information. | ||
| 1110 | * | ||
| 1111 | * Query information of installed cards and configured domains from AP. | ||
| 1112 | */ | ||
| 1113 | static void ap_query_configuration(void) | ||
| 1114 | { | ||
| 1115 | #ifdef CONFIG_64BIT | ||
| 1116 | if (ap_configuration_available()) { | ||
| 1117 | if (!ap_configuration) | ||
| 1118 | ap_configuration = | ||
| 1119 | kzalloc(sizeof(struct ap_config_info), | ||
| 1120 | GFP_KERNEL); | ||
| 1121 | if (ap_configuration) | ||
| 1122 | __ap_query_configuration(ap_configuration); | ||
| 1123 | } else | ||
| 1124 | ap_configuration = NULL; | ||
| 1125 | #else | ||
| 1126 | ap_configuration = NULL; | ||
| 1127 | #endif | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | /** | 996 | /** |
| 1131 | * ap_select_domain(): Select an AP domain. | 997 | * ap_select_domain(): Select an AP domain. |
| 1132 | * | 998 | * |
| @@ -1135,7 +1001,6 @@ static void ap_query_configuration(void) | |||
| 1135 | static int ap_select_domain(void) | 1001 | static int ap_select_domain(void) |
| 1136 | { | 1002 | { |
| 1137 | int queue_depth, device_type, count, max_count, best_domain; | 1003 | int queue_depth, device_type, count, max_count, best_domain; |
| 1138 | ap_qid_t qid; | ||
| 1139 | int rc, i, j; | 1004 | int rc, i, j; |
| 1140 | 1005 | ||
| 1141 | /* | 1006 | /* |
| @@ -1149,13 +1014,9 @@ static int ap_select_domain(void) | |||
| 1149 | best_domain = -1; | 1014 | best_domain = -1; |
| 1150 | max_count = 0; | 1015 | max_count = 0; |
| 1151 | for (i = 0; i < AP_DOMAINS; i++) { | 1016 | for (i = 0; i < AP_DOMAINS; i++) { |
| 1152 | if (!ap_test_config_domain(i)) | ||
| 1153 | continue; | ||
| 1154 | count = 0; | 1017 | count = 0; |
| 1155 | for (j = 0; j < AP_DEVICES; j++) { | 1018 | for (j = 0; j < AP_DEVICES; j++) { |
| 1156 | if (!ap_test_config_card_id(j)) | 1019 | ap_qid_t qid = AP_MKQID(j, i); |
| 1157 | continue; | ||
| 1158 | qid = AP_MKQID(j, i); | ||
| 1159 | rc = ap_query_queue(qid, &queue_depth, &device_type); | 1020 | rc = ap_query_queue(qid, &queue_depth, &device_type); |
| 1160 | if (rc) | 1021 | if (rc) |
| 1161 | continue; | 1022 | continue; |
| @@ -1272,7 +1133,7 @@ out: | |||
| 1272 | 1133 | ||
| 1273 | static void ap_interrupt_handler(void *unused1, void *unused2) | 1134 | static void ap_interrupt_handler(void *unused1, void *unused2) |
| 1274 | { | 1135 | { |
| 1275 | inc_irq_stat(IRQIO_APB); | 1136 | kstat_cpu(smp_processor_id()).irqs[IOINT_APB]++; |
| 1276 | tasklet_schedule(&ap_tasklet); | 1137 | tasklet_schedule(&ap_tasklet); |
| 1277 | } | 1138 | } |
| 1278 | 1139 | ||
| @@ -1304,7 +1165,6 @@ static void ap_scan_bus(struct work_struct *unused) | |||
| 1304 | unsigned int device_functions; | 1165 | unsigned int device_functions; |
| 1305 | int rc, i; | 1166 | int rc, i; |
| 1306 | 1167 | ||
| 1307 | ap_query_configuration(); | ||
| 1308 | if (ap_select_domain() != 0) | 1168 | if (ap_select_domain() != 0) |
| 1309 | return; | 1169 | return; |
| 1310 | for (i = 0; i < AP_DEVICES; i++) { | 1170 | for (i = 0; i < AP_DEVICES; i++) { |
| @@ -1312,10 +1172,7 @@ static void ap_scan_bus(struct work_struct *unused) | |||
| 1312 | dev = bus_find_device(&ap_bus_type, NULL, | 1172 | dev = bus_find_device(&ap_bus_type, NULL, |
| 1313 | (void *)(unsigned long)qid, | 1173 | (void *)(unsigned long)qid, |
| 1314 | __ap_scan_bus); | 1174 | __ap_scan_bus); |
| 1315 | if (ap_test_config_card_id(i)) | 1175 | rc = ap_query_queue(qid, &queue_depth, &device_type); |
| 1316 | rc = ap_query_queue(qid, &queue_depth, &device_type); | ||
| 1317 | else | ||
| 1318 | rc = -ENODEV; | ||
| 1319 | if (dev) { | 1176 | if (dev) { |
| 1320 | if (rc == -EBUSY) { | 1177 | if (rc == -EBUSY) { |
| 1321 | set_current_state(TASK_UNINTERRUPTIBLE); | 1178 | set_current_state(TASK_UNINTERRUPTIBLE); |
| @@ -1356,22 +1213,29 @@ static void ap_scan_bus(struct work_struct *unused) | |||
| 1356 | (unsigned long) ap_dev); | 1213 | (unsigned long) ap_dev); |
| 1357 | switch (device_type) { | 1214 | switch (device_type) { |
| 1358 | case 0: | 1215 | case 0: |
| 1359 | /* device type probing for old cards */ | ||
| 1360 | if (ap_probe_device_type(ap_dev)) { | 1216 | if (ap_probe_device_type(ap_dev)) { |
| 1361 | kfree(ap_dev); | 1217 | kfree(ap_dev); |
| 1362 | continue; | 1218 | continue; |
| 1363 | } | 1219 | } |
| 1364 | break; | 1220 | break; |
| 1221 | case 10: | ||
| 1222 | if (ap_query_functions(qid, &device_functions)) { | ||
| 1223 | kfree(ap_dev); | ||
| 1224 | continue; | ||
| 1225 | } | ||
| 1226 | if (test_ap_facility(device_functions, 3)) | ||
| 1227 | ap_dev->device_type = AP_DEVICE_TYPE_CEX3C; | ||
| 1228 | else if (test_ap_facility(device_functions, 4)) | ||
| 1229 | ap_dev->device_type = AP_DEVICE_TYPE_CEX3A; | ||
| 1230 | else { | ||
| 1231 | kfree(ap_dev); | ||
| 1232 | continue; | ||
| 1233 | } | ||
| 1234 | break; | ||
| 1365 | default: | 1235 | default: |
| 1366 | ap_dev->device_type = device_type; | 1236 | ap_dev->device_type = device_type; |
| 1367 | } | 1237 | } |
| 1368 | 1238 | ||
| 1369 | rc = ap_query_functions(qid, &device_functions); | ||
| 1370 | if (!rc) | ||
| 1371 | ap_dev->functions = device_functions; | ||
| 1372 | else | ||
| 1373 | ap_dev->functions = 0u; | ||
| 1374 | |||
| 1375 | ap_dev->device.bus = &ap_bus_type; | 1239 | ap_dev->device.bus = &ap_bus_type; |
| 1376 | ap_dev->device.parent = ap_root_device; | 1240 | ap_dev->device.parent = ap_root_device; |
| 1377 | if (dev_set_name(&ap_dev->device, "card%02x", | 1241 | if (dev_set_name(&ap_dev->device, "card%02x", |
| @@ -1407,16 +1271,18 @@ ap_config_timeout(unsigned long ptr) | |||
| 1407 | } | 1271 | } |
| 1408 | 1272 | ||
| 1409 | /** | 1273 | /** |
| 1410 | * __ap_schedule_poll_timer(): Schedule poll timer. | 1274 | * ap_schedule_poll_timer(): Schedule poll timer. |
| 1411 | * | 1275 | * |
| 1412 | * Set up the timer to run the poll tasklet | 1276 | * Set up the timer to run the poll tasklet |
| 1413 | */ | 1277 | */ |
| 1414 | static inline void __ap_schedule_poll_timer(void) | 1278 | static inline void ap_schedule_poll_timer(void) |
| 1415 | { | 1279 | { |
| 1416 | ktime_t hr_time; | 1280 | ktime_t hr_time; |
| 1417 | 1281 | ||
| 1418 | spin_lock_bh(&ap_poll_timer_lock); | 1282 | spin_lock_bh(&ap_poll_timer_lock); |
| 1419 | if (hrtimer_is_queued(&ap_poll_timer) || ap_suspend_flag) | 1283 | if (ap_using_interrupts() || ap_suspend_flag) |
| 1284 | goto out; | ||
| 1285 | if (hrtimer_is_queued(&ap_poll_timer)) | ||
| 1420 | goto out; | 1286 | goto out; |
| 1421 | if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) { | 1287 | if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) { |
| 1422 | hr_time = ktime_set(0, poll_timeout); | 1288 | hr_time = ktime_set(0, poll_timeout); |
| @@ -1428,18 +1294,6 @@ out: | |||
| 1428 | } | 1294 | } |
| 1429 | 1295 | ||
| 1430 | /** | 1296 | /** |
| 1431 | * ap_schedule_poll_timer(): Schedule poll timer. | ||
| 1432 | * | ||
| 1433 | * Set up the timer to run the poll tasklet | ||
| 1434 | */ | ||
| 1435 | static inline void ap_schedule_poll_timer(void) | ||
| 1436 | { | ||
| 1437 | if (ap_using_interrupts()) | ||
| 1438 | return; | ||
| 1439 | __ap_schedule_poll_timer(); | ||
| 1440 | } | ||
| 1441 | |||
| 1442 | /** | ||
| 1443 | * ap_poll_read(): Receive pending reply messages from an AP device. | 1297 | * ap_poll_read(): Receive pending reply messages from an AP device. |
| 1444 | * @ap_dev: pointer to the AP device | 1298 | * @ap_dev: pointer to the AP device |
| 1445 | * @flags: pointer to control flags, bit 2^0 is set if another poll is | 1299 | * @flags: pointer to control flags, bit 2^0 is set if another poll is |
| @@ -1465,7 +1319,7 @@ static int ap_poll_read(struct ap_device *ap_dev, unsigned long *flags) | |||
| 1465 | continue; | 1319 | continue; |
| 1466 | list_del_init(&ap_msg->list); | 1320 | list_del_init(&ap_msg->list); |
| 1467 | ap_dev->pendingq_count--; | 1321 | ap_dev->pendingq_count--; |
| 1468 | ap_msg->receive(ap_dev, ap_msg, ap_dev->reply); | 1322 | ap_dev->drv->receive(ap_dev, ap_msg, ap_dev->reply); |
| 1469 | break; | 1323 | break; |
| 1470 | } | 1324 | } |
| 1471 | if (ap_dev->queue_count > 0) | 1325 | if (ap_dev->queue_count > 0) |
| @@ -1520,9 +1374,8 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags) | |||
| 1520 | *flags |= 1; | 1374 | *flags |= 1; |
| 1521 | *flags |= 2; | 1375 | *flags |= 2; |
| 1522 | break; | 1376 | break; |
| 1523 | case AP_RESPONSE_RESET_IN_PROGRESS: | ||
| 1524 | __ap_schedule_poll_timer(); | ||
| 1525 | case AP_RESPONSE_Q_FULL: | 1377 | case AP_RESPONSE_Q_FULL: |
| 1378 | case AP_RESPONSE_RESET_IN_PROGRESS: | ||
| 1526 | *flags |= 2; | 1379 | *flags |= 2; |
| 1527 | break; | 1380 | break; |
| 1528 | case AP_RESPONSE_MESSAGE_TOO_BIG: | 1381 | case AP_RESPONSE_MESSAGE_TOO_BIG: |
| @@ -1586,10 +1439,10 @@ static int __ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_ms | |||
| 1586 | return -EBUSY; | 1439 | return -EBUSY; |
| 1587 | case AP_RESPONSE_REQ_FAC_NOT_INST: | 1440 | case AP_RESPONSE_REQ_FAC_NOT_INST: |
| 1588 | case AP_RESPONSE_MESSAGE_TOO_BIG: | 1441 | case AP_RESPONSE_MESSAGE_TOO_BIG: |
| 1589 | ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL)); | 1442 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-EINVAL)); |
| 1590 | return -EINVAL; | 1443 | return -EINVAL; |
| 1591 | default: /* Device is gone. */ | 1444 | default: /* Device is gone. */ |
| 1592 | ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); | 1445 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); |
| 1593 | return -ENODEV; | 1446 | return -ENODEV; |
| 1594 | } | 1447 | } |
| 1595 | } else { | 1448 | } else { |
| @@ -1607,10 +1460,6 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg) | |||
| 1607 | unsigned long flags; | 1460 | unsigned long flags; |
| 1608 | int rc; | 1461 | int rc; |
| 1609 | 1462 | ||
| 1610 | /* For asynchronous message handling a valid receive-callback | ||
| 1611 | * is required. */ | ||
| 1612 | BUG_ON(!ap_msg->receive); | ||
| 1613 | |||
| 1614 | spin_lock_bh(&ap_dev->lock); | 1463 | spin_lock_bh(&ap_dev->lock); |
| 1615 | if (!ap_dev->unregistered) { | 1464 | if (!ap_dev->unregistered) { |
| 1616 | /* Make room on the queue by polling for finished requests. */ | 1465 | /* Make room on the queue by polling for finished requests. */ |
| @@ -1622,7 +1471,7 @@ void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg) | |||
| 1622 | if (rc == -ENODEV) | 1471 | if (rc == -ENODEV) |
| 1623 | ap_dev->unregistered = 1; | 1472 | ap_dev->unregistered = 1; |
| 1624 | } else { | 1473 | } else { |
| 1625 | ap_msg->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); | 1474 | ap_dev->drv->receive(ap_dev, ap_msg, ERR_PTR(-ENODEV)); |
| 1626 | rc = -ENODEV; | 1475 | rc = -ENODEV; |
| 1627 | } | 1476 | } |
| 1628 | spin_unlock_bh(&ap_dev->lock); | 1477 | spin_unlock_bh(&ap_dev->lock); |
| @@ -1692,8 +1541,6 @@ static void ap_reset(struct ap_device *ap_dev) | |||
| 1692 | rc = ap_init_queue(ap_dev->qid); | 1541 | rc = ap_init_queue(ap_dev->qid); |
| 1693 | if (rc == -ENODEV) | 1542 | if (rc == -ENODEV) |
| 1694 | ap_dev->unregistered = 1; | 1543 | ap_dev->unregistered = 1; |
| 1695 | else | ||
| 1696 | __ap_schedule_poll_timer(); | ||
| 1697 | } | 1544 | } |
| 1698 | 1545 | ||
| 1699 | static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags) | 1546 | static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags) |
| @@ -1917,7 +1764,6 @@ int __init ap_module_init(void) | |||
| 1917 | goto out_root; | 1764 | goto out_root; |
| 1918 | } | 1765 | } |
| 1919 | 1766 | ||
| 1920 | ap_query_configuration(); | ||
| 1921 | if (ap_select_domain() == 0) | 1767 | if (ap_select_domain() == 0) |
| 1922 | ap_scan_bus(NULL); | 1768 | ap_scan_bus(NULL); |
| 1923 | 1769 | ||
| @@ -2003,5 +1849,7 @@ void ap_module_exit(void) | |||
| 2003 | } | 1849 | } |
| 2004 | } | 1850 | } |
| 2005 | 1851 | ||
| 1852 | #ifndef CONFIG_ZCRYPT_MONOLITHIC | ||
| 2006 | module_init(ap_module_init); | 1853 | module_init(ap_module_init); |
| 2007 | module_exit(ap_module_exit); | 1854 | module_exit(ap_module_exit); |
| 1855 | #endif | ||
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 685f6cc022f..d960a6309ee 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright IBM Corp. 2006, 2012 | 2 | * linux/drivers/s390/crypto/ap_bus.h |
| 3 | * | ||
| 4 | * Copyright (C) 2006 IBM Corporation | ||
| 3 | * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> | 5 | * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> |
| 4 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 6 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
| 5 | * Ralph Wuerthner <rwuerthn@de.ibm.com> | 7 | * Ralph Wuerthner <rwuerthn@de.ibm.com> |
| @@ -83,12 +85,13 @@ int ap_queue_status_invalid_test(struct ap_queue_status *status) | |||
| 83 | return !(memcmp(status, &invalid, sizeof(struct ap_queue_status))); | 85 | return !(memcmp(status, &invalid, sizeof(struct ap_queue_status))); |
| 84 | } | 86 | } |
| 85 | 87 | ||
| 86 | #define AP_MAX_BITS 31 | 88 | #define MAX_AP_FACILITY 31 |
| 87 | static inline int ap_test_bit(unsigned int *ptr, unsigned int nr) | 89 | |
| 90 | static inline int test_ap_facility(unsigned int function, unsigned int nr) | ||
| 88 | { | 91 | { |
| 89 | if (nr > AP_MAX_BITS) | 92 | if (nr > MAX_AP_FACILITY) |
| 90 | return 0; | 93 | return 0; |
| 91 | return (*ptr & (0x80000000u >> nr)) != 0; | 94 | return function & (unsigned int)(0x80000000 >> nr); |
| 92 | } | 95 | } |
| 93 | 96 | ||
| 94 | #define AP_RESPONSE_NORMAL 0x00 | 97 | #define AP_RESPONSE_NORMAL 0x00 |
| @@ -116,15 +119,6 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr) | |||
| 116 | #define AP_DEVICE_TYPE_CEX2C 7 | 119 | #define AP_DEVICE_TYPE_CEX2C 7 |
| 117 | #define AP_DEVICE_TYPE_CEX3A 8 | 120 | #define AP_DEVICE_TYPE_CEX3A 8 |
| 118 | #define AP_DEVICE_TYPE_CEX3C 9 | 121 | #define AP_DEVICE_TYPE_CEX3C 9 |
| 119 | #define AP_DEVICE_TYPE_CEX4 10 | ||
| 120 | |||
| 121 | /* | ||
| 122 | * Known function facilities | ||
| 123 | */ | ||
| 124 | #define AP_FUNC_MEX4K 1 | ||
| 125 | #define AP_FUNC_CRT4K 2 | ||
| 126 | #define AP_FUNC_COPRO 3 | ||
| 127 | #define AP_FUNC_ACCEL 4 | ||
| 128 | 122 | ||
| 129 | /* | 123 | /* |
| 130 | * AP reset flag states | 124 | * AP reset flag states |
| @@ -142,6 +136,9 @@ struct ap_driver { | |||
| 142 | 136 | ||
| 143 | int (*probe)(struct ap_device *); | 137 | int (*probe)(struct ap_device *); |
| 144 | void (*remove)(struct ap_device *); | 138 | void (*remove)(struct ap_device *); |
| 139 | /* receive is called from tasklet context */ | ||
| 140 | void (*receive)(struct ap_device *, struct ap_message *, | ||
| 141 | struct ap_message *); | ||
| 145 | int request_timeout; /* request timeout in jiffies */ | 142 | int request_timeout; /* request timeout in jiffies */ |
| 146 | }; | 143 | }; |
| 147 | 144 | ||
| @@ -159,7 +156,6 @@ struct ap_device { | |||
| 159 | ap_qid_t qid; /* AP queue id. */ | 156 | ap_qid_t qid; /* AP queue id. */ |
| 160 | int queue_depth; /* AP queue depth.*/ | 157 | int queue_depth; /* AP queue depth.*/ |
| 161 | int device_type; /* AP device type. */ | 158 | int device_type; /* AP device type. */ |
| 162 | unsigned int functions; /* AP device function bitfield. */ | ||
| 163 | int unregistered; /* marks AP device as unregistered */ | 159 | int unregistered; /* marks AP device as unregistered */ |
| 164 | struct timer_list timeout; /* Timer for request timeouts. */ | 160 | struct timer_list timeout; /* Timer for request timeouts. */ |
| 165 | int reset; /* Reset required after req. timeout. */ | 161 | int reset; /* Reset required after req. timeout. */ |
| @@ -187,22 +183,8 @@ struct ap_message { | |||
| 187 | 183 | ||
| 188 | void *private; /* ap driver private pointer. */ | 184 | void *private; /* ap driver private pointer. */ |
| 189 | unsigned int special:1; /* Used for special commands. */ | 185 | unsigned int special:1; /* Used for special commands. */ |
| 190 | /* receive is called from tasklet context */ | ||
| 191 | void (*receive)(struct ap_device *, struct ap_message *, | ||
| 192 | struct ap_message *); | ||
| 193 | }; | 186 | }; |
| 194 | 187 | ||
| 195 | struct ap_config_info { | ||
| 196 | unsigned int special_command:1; | ||
| 197 | unsigned int ap_extended:1; | ||
| 198 | unsigned char reserved1:6; | ||
| 199 | unsigned char reserved2[15]; | ||
| 200 | unsigned int apm[8]; /* AP ID mask */ | ||
| 201 | unsigned int aqm[8]; /* AP queue mask */ | ||
| 202 | unsigned int adm[8]; /* AP domain mask */ | ||
| 203 | unsigned char reserved4[16]; | ||
| 204 | } __packed; | ||
| 205 | |||
| 206 | #define AP_DEVICE(dt) \ | 188 | #define AP_DEVICE(dt) \ |
| 207 | .dev_type=(dt), \ | 189 | .dev_type=(dt), \ |
| 208 | .match_flags=AP_DEVICE_ID_MATCH_DEVICE_TYPE, | 190 | .match_flags=AP_DEVICE_ID_MATCH_DEVICE_TYPE, |
| @@ -217,7 +199,6 @@ static inline void ap_init_message(struct ap_message *ap_msg) | |||
| 217 | ap_msg->psmid = 0; | 199 | ap_msg->psmid = 0; |
| 218 | ap_msg->length = 0; | 200 | ap_msg->length = 0; |
| 219 | ap_msg->special = 0; | 201 | ap_msg->special = 0; |
| 220 | ap_msg->receive = NULL; | ||
| 221 | } | 202 | } |
| 222 | 203 | ||
| 223 | /* | 204 | /* |
| @@ -231,9 +212,10 @@ int ap_recv(ap_qid_t, unsigned long long *, void *, size_t); | |||
| 231 | void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg); | 212 | void ap_queue_message(struct ap_device *ap_dev, struct ap_message *ap_msg); |
| 232 | void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg); | 213 | void ap_cancel_message(struct ap_device *ap_dev, struct ap_message *ap_msg); |
| 233 | void ap_flush_queue(struct ap_device *ap_dev); | 214 | void ap_flush_queue(struct ap_device *ap_dev); |
| 234 | void ap_bus_force_rescan(void); | ||
| 235 | 215 | ||
| 236 | int ap_module_init(void); | 216 | int ap_module_init(void); |
| 237 | void ap_module_exit(void); | 217 | void ap_module_exit(void); |
| 238 | 218 | ||
| 219 | int ap_4096_commands_available(ap_qid_t qid); | ||
| 220 | |||
| 239 | #endif /* _AP_BUS_H_ */ | 221 | #endif /* _AP_BUS_H_ */ |
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 31cfaa55607..88ad33ed5d3 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/drivers/s390/crypto/zcrypt_api.c | ||
| 3 | * | ||
| 2 | * zcrypt 2.1.0 | 4 | * zcrypt 2.1.0 |
| 3 | * | 5 | * |
| 4 | * Copyright IBM Corp. 2001, 2012 | 6 | * Copyright (C) 2001, 2006 IBM Corporation |
| 5 | * Author(s): Robert Burroughs | 7 | * Author(s): Robert Burroughs |
| 6 | * Eric Rossman (edrossma@us.ibm.com) | 8 | * Eric Rossman (edrossma@us.ibm.com) |
| 7 | * Cornelia Huck <cornelia.huck@de.ibm.com> | 9 | * Cornelia Huck <cornelia.huck@de.ibm.com> |
| @@ -9,7 +11,6 @@ | |||
| 9 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) | 11 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) |
| 10 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> | 12 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> |
| 11 | * Ralph Wuerthner <rwuerthn@de.ibm.com> | 13 | * Ralph Wuerthner <rwuerthn@de.ibm.com> |
| 12 | * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com> | ||
| 13 | * | 14 | * |
| 14 | * This program is free software; you can redistribute it and/or modify | 15 | * 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 | * it under the terms of the GNU General Public License as published by |
| @@ -38,39 +39,25 @@ | |||
| 38 | #include <linux/atomic.h> | 39 | #include <linux/atomic.h> |
| 39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
| 40 | #include <linux/hw_random.h> | 41 | #include <linux/hw_random.h> |
| 41 | #include <linux/debugfs.h> | ||
| 42 | #include <asm/debug.h> | ||
| 43 | 42 | ||
| 44 | #include "zcrypt_debug.h" | ||
| 45 | #include "zcrypt_api.h" | 43 | #include "zcrypt_api.h" |
| 46 | 44 | ||
| 47 | /* | 45 | /* |
| 48 | * Module description. | 46 | * Module description. |
| 49 | */ | 47 | */ |
| 50 | MODULE_AUTHOR("IBM Corporation"); | 48 | MODULE_AUTHOR("IBM Corporation"); |
| 51 | MODULE_DESCRIPTION("Cryptographic Coprocessor interface, " \ | 49 | MODULE_DESCRIPTION("Cryptographic Coprocessor interface, " |
| 52 | "Copyright IBM Corp. 2001, 2012"); | 50 | "Copyright 2001, 2006 IBM Corporation"); |
| 53 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
| 54 | 52 | ||
| 55 | static DEFINE_SPINLOCK(zcrypt_device_lock); | 53 | static DEFINE_SPINLOCK(zcrypt_device_lock); |
| 56 | static LIST_HEAD(zcrypt_device_list); | 54 | static LIST_HEAD(zcrypt_device_list); |
| 57 | static int zcrypt_device_count = 0; | 55 | static int zcrypt_device_count = 0; |
| 58 | static atomic_t zcrypt_open_count = ATOMIC_INIT(0); | 56 | static atomic_t zcrypt_open_count = ATOMIC_INIT(0); |
| 59 | static atomic_t zcrypt_rescan_count = ATOMIC_INIT(0); | ||
| 60 | |||
| 61 | atomic_t zcrypt_rescan_req = ATOMIC_INIT(0); | ||
| 62 | EXPORT_SYMBOL(zcrypt_rescan_req); | ||
| 63 | 57 | ||
| 64 | static int zcrypt_rng_device_add(void); | 58 | static int zcrypt_rng_device_add(void); |
| 65 | static void zcrypt_rng_device_remove(void); | 59 | static void zcrypt_rng_device_remove(void); |
| 66 | 60 | ||
| 67 | static DEFINE_SPINLOCK(zcrypt_ops_list_lock); | ||
| 68 | static LIST_HEAD(zcrypt_ops_list); | ||
| 69 | |||
| 70 | static debug_info_t *zcrypt_dbf_common; | ||
| 71 | static debug_info_t *zcrypt_dbf_devices; | ||
| 72 | static struct dentry *debugfs_root; | ||
| 73 | |||
| 74 | /* | 61 | /* |
| 75 | * Device attributes common for all crypto devices. | 62 | * Device attributes common for all crypto devices. |
| 76 | */ | 63 | */ |
| @@ -100,8 +87,6 @@ static ssize_t zcrypt_online_store(struct device *dev, | |||
| 100 | if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1) | 87 | if (sscanf(buf, "%d\n", &online) != 1 || online < 0 || online > 1) |
| 101 | return -EINVAL; | 88 | return -EINVAL; |
| 102 | zdev->online = online; | 89 | zdev->online = online; |
| 103 | ZCRYPT_DBF_DEV(DBF_INFO, zdev, "dev%04xo%dman", zdev->ap_dev->qid, | ||
| 104 | zdev->online); | ||
| 105 | if (!online) | 90 | if (!online) |
| 106 | ap_flush_queue(zdev->ap_dev); | 91 | ap_flush_queue(zdev->ap_dev); |
| 107 | return count; | 92 | return count; |
| @@ -120,24 +105,6 @@ static struct attribute_group zcrypt_device_attr_group = { | |||
| 120 | }; | 105 | }; |
| 121 | 106 | ||
| 122 | /** | 107 | /** |
| 123 | * Process a rescan of the transport layer. | ||
| 124 | * | ||
| 125 | * Returns 1, if the rescan has been processed, otherwise 0. | ||
| 126 | */ | ||
| 127 | static inline int zcrypt_process_rescan(void) | ||
| 128 | { | ||
| 129 | if (atomic_read(&zcrypt_rescan_req)) { | ||
| 130 | atomic_set(&zcrypt_rescan_req, 0); | ||
| 131 | atomic_inc(&zcrypt_rescan_count); | ||
| 132 | ap_bus_force_rescan(); | ||
| 133 | ZCRYPT_DBF_COMMON(DBF_INFO, "rescan%07d", | ||
| 134 | atomic_inc_return(&zcrypt_rescan_count)); | ||
| 135 | return 1; | ||
| 136 | } | ||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | /** | ||
| 141 | * __zcrypt_increase_preference(): Increase preference of a crypto device. | 108 | * __zcrypt_increase_preference(): Increase preference of a crypto device. |
| 142 | * @zdev: Pointer the crypto device | 109 | * @zdev: Pointer the crypto device |
| 143 | * | 110 | * |
| @@ -225,7 +192,6 @@ struct zcrypt_device *zcrypt_device_alloc(size_t max_response_size) | |||
| 225 | zdev->reply.length = max_response_size; | 192 | zdev->reply.length = max_response_size; |
| 226 | spin_lock_init(&zdev->lock); | 193 | spin_lock_init(&zdev->lock); |
| 227 | INIT_LIST_HEAD(&zdev->list); | 194 | INIT_LIST_HEAD(&zdev->list); |
| 228 | zdev->dbf_area = zcrypt_dbf_devices; | ||
| 229 | return zdev; | 195 | return zdev; |
| 230 | 196 | ||
| 231 | out_free: | 197 | out_free: |
| @@ -251,8 +217,6 @@ int zcrypt_device_register(struct zcrypt_device *zdev) | |||
| 251 | { | 217 | { |
| 252 | int rc; | 218 | int rc; |
| 253 | 219 | ||
| 254 | if (!zdev->ops) | ||
| 255 | return -ENODEV; | ||
| 256 | rc = sysfs_create_group(&zdev->ap_dev->device.kobj, | 220 | rc = sysfs_create_group(&zdev->ap_dev->device.kobj, |
| 257 | &zcrypt_device_attr_group); | 221 | &zcrypt_device_attr_group); |
| 258 | if (rc) | 222 | if (rc) |
| @@ -261,8 +225,6 @@ int zcrypt_device_register(struct zcrypt_device *zdev) | |||
| 261 | kref_init(&zdev->refcount); | 225 | kref_init(&zdev->refcount); |
| 262 | spin_lock_bh(&zcrypt_device_lock); | 226 | spin_lock_bh(&zcrypt_device_lock); |
| 263 | zdev->online = 1; /* New devices are online by default. */ | 227 | zdev->online = 1; /* New devices are online by default. */ |
| 264 | ZCRYPT_DBF_DEV(DBF_INFO, zdev, "dev%04xo%dreg", zdev->ap_dev->qid, | ||
| 265 | zdev->online); | ||
| 266 | list_add_tail(&zdev->list, &zcrypt_device_list); | 228 | list_add_tail(&zdev->list, &zcrypt_device_list); |
| 267 | __zcrypt_increase_preference(zdev); | 229 | __zcrypt_increase_preference(zdev); |
| 268 | zcrypt_device_count++; | 230 | zcrypt_device_count++; |
| @@ -309,67 +271,6 @@ void zcrypt_device_unregister(struct zcrypt_device *zdev) | |||
| 309 | } | 271 | } |
| 310 | EXPORT_SYMBOL(zcrypt_device_unregister); | 272 | EXPORT_SYMBOL(zcrypt_device_unregister); |
| 311 | 273 | ||
| 312 | void zcrypt_msgtype_register(struct zcrypt_ops *zops) | ||
| 313 | { | ||
| 314 | if (zops->owner) { | ||
| 315 | spin_lock_bh(&zcrypt_ops_list_lock); | ||
| 316 | list_add_tail(&zops->list, &zcrypt_ops_list); | ||
| 317 | spin_unlock_bh(&zcrypt_ops_list_lock); | ||
| 318 | } | ||
| 319 | } | ||
| 320 | EXPORT_SYMBOL(zcrypt_msgtype_register); | ||
| 321 | |||
| 322 | void zcrypt_msgtype_unregister(struct zcrypt_ops *zops) | ||
| 323 | { | ||
| 324 | spin_lock_bh(&zcrypt_ops_list_lock); | ||
| 325 | list_del_init(&zops->list); | ||
| 326 | spin_unlock_bh(&zcrypt_ops_list_lock); | ||
| 327 | } | ||
| 328 | EXPORT_SYMBOL(zcrypt_msgtype_unregister); | ||
| 329 | |||
| 330 | static inline | ||
| 331 | struct zcrypt_ops *__ops_lookup(unsigned char *name, int variant) | ||
| 332 | { | ||
| 333 | struct zcrypt_ops *zops; | ||
| 334 | int found = 0; | ||
| 335 | |||
| 336 | spin_lock_bh(&zcrypt_ops_list_lock); | ||
| 337 | list_for_each_entry(zops, &zcrypt_ops_list, list) { | ||
| 338 | if ((zops->variant == variant) && | ||
| 339 | (!strncmp(zops->owner->name, name, MODULE_NAME_LEN))) { | ||
| 340 | found = 1; | ||
| 341 | break; | ||
| 342 | } | ||
| 343 | } | ||
| 344 | spin_unlock_bh(&zcrypt_ops_list_lock); | ||
| 345 | |||
| 346 | if (!found) | ||
| 347 | return NULL; | ||
| 348 | return zops; | ||
| 349 | } | ||
| 350 | |||
| 351 | struct zcrypt_ops *zcrypt_msgtype_request(unsigned char *name, int variant) | ||
| 352 | { | ||
| 353 | struct zcrypt_ops *zops = NULL; | ||
| 354 | |||
| 355 | zops = __ops_lookup(name, variant); | ||
| 356 | if (!zops) { | ||
| 357 | request_module(name); | ||
| 358 | zops = __ops_lookup(name, variant); | ||
| 359 | } | ||
| 360 | if ((!zops) || (!try_module_get(zops->owner))) | ||
| 361 | return NULL; | ||
| 362 | return zops; | ||
| 363 | } | ||
| 364 | EXPORT_SYMBOL(zcrypt_msgtype_request); | ||
| 365 | |||
| 366 | void zcrypt_msgtype_release(struct zcrypt_ops *zops) | ||
| 367 | { | ||
| 368 | if (zops) | ||
| 369 | module_put(zops->owner); | ||
| 370 | } | ||
| 371 | EXPORT_SYMBOL(zcrypt_msgtype_release); | ||
| 372 | |||
| 373 | /** | 274 | /** |
| 374 | * zcrypt_read (): Not supported beyond zcrypt 1.3.1. | 275 | * zcrypt_read (): Not supported beyond zcrypt 1.3.1. |
| 375 | * | 276 | * |
| @@ -741,11 +642,6 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, | |||
| 741 | do { | 642 | do { |
| 742 | rc = zcrypt_rsa_modexpo(&mex); | 643 | rc = zcrypt_rsa_modexpo(&mex); |
| 743 | } while (rc == -EAGAIN); | 644 | } while (rc == -EAGAIN); |
| 744 | /* on failure: retry once again after a requested rescan */ | ||
| 745 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | ||
| 746 | do { | ||
| 747 | rc = zcrypt_rsa_modexpo(&mex); | ||
| 748 | } while (rc == -EAGAIN); | ||
| 749 | if (rc) | 645 | if (rc) |
| 750 | return rc; | 646 | return rc; |
| 751 | return put_user(mex.outputdatalength, &umex->outputdatalength); | 647 | return put_user(mex.outputdatalength, &umex->outputdatalength); |
| @@ -758,11 +654,6 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, | |||
| 758 | do { | 654 | do { |
| 759 | rc = zcrypt_rsa_crt(&crt); | 655 | rc = zcrypt_rsa_crt(&crt); |
| 760 | } while (rc == -EAGAIN); | 656 | } while (rc == -EAGAIN); |
| 761 | /* on failure: retry once again after a requested rescan */ | ||
| 762 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | ||
| 763 | do { | ||
| 764 | rc = zcrypt_rsa_crt(&crt); | ||
| 765 | } while (rc == -EAGAIN); | ||
| 766 | if (rc) | 657 | if (rc) |
| 767 | return rc; | 658 | return rc; |
| 768 | return put_user(crt.outputdatalength, &ucrt->outputdatalength); | 659 | return put_user(crt.outputdatalength, &ucrt->outputdatalength); |
| @@ -775,11 +666,6 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, | |||
| 775 | do { | 666 | do { |
| 776 | rc = zcrypt_send_cprb(&xcRB); | 667 | rc = zcrypt_send_cprb(&xcRB); |
| 777 | } while (rc == -EAGAIN); | 668 | } while (rc == -EAGAIN); |
| 778 | /* on failure: retry once again after a requested rescan */ | ||
| 779 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | ||
| 780 | do { | ||
| 781 | rc = zcrypt_send_cprb(&xcRB); | ||
| 782 | } while (rc == -EAGAIN); | ||
| 783 | if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB))) | 669 | if (copy_to_user(uxcRB, &xcRB, sizeof(xcRB))) |
| 784 | return -EFAULT; | 670 | return -EFAULT; |
| 785 | return rc; | 671 | return rc; |
| @@ -886,15 +772,10 @@ static long trans_modexpo32(struct file *filp, unsigned int cmd, | |||
| 886 | do { | 772 | do { |
| 887 | rc = zcrypt_rsa_modexpo(&mex64); | 773 | rc = zcrypt_rsa_modexpo(&mex64); |
| 888 | } while (rc == -EAGAIN); | 774 | } while (rc == -EAGAIN); |
| 889 | /* on failure: retry once again after a requested rescan */ | 775 | if (!rc) |
| 890 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | 776 | rc = put_user(mex64.outputdatalength, |
| 891 | do { | 777 | &umex32->outputdatalength); |
| 892 | rc = zcrypt_rsa_modexpo(&mex64); | 778 | return rc; |
| 893 | } while (rc == -EAGAIN); | ||
| 894 | if (rc) | ||
| 895 | return rc; | ||
| 896 | return put_user(mex64.outputdatalength, | ||
| 897 | &umex32->outputdatalength); | ||
| 898 | } | 779 | } |
| 899 | 780 | ||
| 900 | struct compat_ica_rsa_modexpo_crt { | 781 | struct compat_ica_rsa_modexpo_crt { |
| @@ -931,15 +812,10 @@ static long trans_modexpo_crt32(struct file *filp, unsigned int cmd, | |||
| 931 | do { | 812 | do { |
| 932 | rc = zcrypt_rsa_crt(&crt64); | 813 | rc = zcrypt_rsa_crt(&crt64); |
| 933 | } while (rc == -EAGAIN); | 814 | } while (rc == -EAGAIN); |
| 934 | /* on failure: retry once again after a requested rescan */ | 815 | if (!rc) |
| 935 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | 816 | rc = put_user(crt64.outputdatalength, |
| 936 | do { | 817 | &ucrt32->outputdatalength); |
| 937 | rc = zcrypt_rsa_crt(&crt64); | 818 | return rc; |
| 938 | } while (rc == -EAGAIN); | ||
| 939 | if (rc) | ||
| 940 | return rc; | ||
| 941 | return put_user(crt64.outputdatalength, | ||
| 942 | &ucrt32->outputdatalength); | ||
| 943 | } | 819 | } |
| 944 | 820 | ||
| 945 | struct compat_ica_xcRB { | 821 | struct compat_ica_xcRB { |
| @@ -995,11 +871,6 @@ static long trans_xcRB32(struct file *filp, unsigned int cmd, | |||
| 995 | do { | 871 | do { |
| 996 | rc = zcrypt_send_cprb(&xcRB64); | 872 | rc = zcrypt_send_cprb(&xcRB64); |
| 997 | } while (rc == -EAGAIN); | 873 | } while (rc == -EAGAIN); |
| 998 | /* on failure: retry once again after a requested rescan */ | ||
| 999 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | ||
| 1000 | do { | ||
| 1001 | rc = zcrypt_send_cprb(&xcRB64); | ||
| 1002 | } while (rc == -EAGAIN); | ||
| 1003 | xcRB32.reply_control_blk_length = xcRB64.reply_control_blk_length; | 874 | xcRB32.reply_control_blk_length = xcRB64.reply_control_blk_length; |
| 1004 | xcRB32.reply_data_length = xcRB64.reply_data_length; | 875 | xcRB32.reply_data_length = xcRB64.reply_data_length; |
| 1005 | xcRB32.status = xcRB64.status; | 876 | xcRB32.status = xcRB64.status; |
| @@ -1257,9 +1128,6 @@ static int zcrypt_rng_data_read(struct hwrng *rng, u32 *data) | |||
| 1257 | */ | 1128 | */ |
| 1258 | if (zcrypt_rng_buffer_index == 0) { | 1129 | if (zcrypt_rng_buffer_index == 0) { |
| 1259 | rc = zcrypt_rng((char *) zcrypt_rng_buffer); | 1130 | rc = zcrypt_rng((char *) zcrypt_rng_buffer); |
| 1260 | /* on failure: retry once again after a requested rescan */ | ||
| 1261 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | ||
| 1262 | rc = zcrypt_rng((char *) zcrypt_rng_buffer); | ||
| 1263 | if (rc < 0) | 1131 | if (rc < 0) |
| 1264 | return -EIO; | 1132 | return -EIO; |
| 1265 | zcrypt_rng_buffer_index = rc / sizeof *data; | 1133 | zcrypt_rng_buffer_index = rc / sizeof *data; |
| @@ -1312,30 +1180,6 @@ static void zcrypt_rng_device_remove(void) | |||
| 1312 | mutex_unlock(&zcrypt_rng_mutex); | 1180 | mutex_unlock(&zcrypt_rng_mutex); |
| 1313 | } | 1181 | } |
| 1314 | 1182 | ||
| 1315 | int __init zcrypt_debug_init(void) | ||
| 1316 | { | ||
| 1317 | debugfs_root = debugfs_create_dir("zcrypt", NULL); | ||
| 1318 | |||
| 1319 | zcrypt_dbf_common = debug_register("zcrypt_common", 1, 1, 16); | ||
| 1320 | debug_register_view(zcrypt_dbf_common, &debug_hex_ascii_view); | ||
| 1321 | debug_set_level(zcrypt_dbf_common, DBF_ERR); | ||
| 1322 | |||
| 1323 | zcrypt_dbf_devices = debug_register("zcrypt_devices", 1, 1, 16); | ||
| 1324 | debug_register_view(zcrypt_dbf_devices, &debug_hex_ascii_view); | ||
| 1325 | debug_set_level(zcrypt_dbf_devices, DBF_ERR); | ||
| 1326 | |||
| 1327 | return 0; | ||
| 1328 | } | ||
| 1329 | |||
| 1330 | void zcrypt_debug_exit(void) | ||
| 1331 | { | ||
| 1332 | debugfs_remove(debugfs_root); | ||
| 1333 | if (zcrypt_dbf_common) | ||
| 1334 | debug_unregister(zcrypt_dbf_common); | ||
| 1335 | if (zcrypt_dbf_devices) | ||
| 1336 | debug_unregister(zcrypt_dbf_devices); | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | /** | 1183 | /** |
| 1340 | * zcrypt_api_init(): Module initialization. | 1184 | * zcrypt_api_init(): Module initialization. |
| 1341 | * | 1185 | * |
| @@ -1345,12 +1189,6 @@ int __init zcrypt_api_init(void) | |||
| 1345 | { | 1189 | { |
| 1346 | int rc; | 1190 | int rc; |
| 1347 | 1191 | ||
| 1348 | rc = zcrypt_debug_init(); | ||
| 1349 | if (rc) | ||
| 1350 | goto out; | ||
| 1351 | |||
| 1352 | atomic_set(&zcrypt_rescan_req, 0); | ||
| 1353 | |||
| 1354 | /* Register the request sprayer. */ | 1192 | /* Register the request sprayer. */ |
| 1355 | rc = misc_register(&zcrypt_misc_device); | 1193 | rc = misc_register(&zcrypt_misc_device); |
| 1356 | if (rc < 0) | 1194 | if (rc < 0) |
| @@ -1380,8 +1218,9 @@ void zcrypt_api_exit(void) | |||
| 1380 | { | 1218 | { |
| 1381 | remove_proc_entry("driver/z90crypt", NULL); | 1219 | remove_proc_entry("driver/z90crypt", NULL); |
| 1382 | misc_deregister(&zcrypt_misc_device); | 1220 | misc_deregister(&zcrypt_misc_device); |
| 1383 | zcrypt_debug_exit(); | ||
| 1384 | } | 1221 | } |
| 1385 | 1222 | ||
| 1223 | #ifndef CONFIG_ZCRYPT_MONOLITHIC | ||
| 1386 | module_init(zcrypt_api_init); | 1224 | module_init(zcrypt_api_init); |
| 1387 | module_exit(zcrypt_api_exit); | 1225 | module_exit(zcrypt_api_exit); |
| 1226 | #endif | ||
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index 89632919c99..9688f3985b0 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/drivers/s390/crypto/zcrypt_api.h | ||
| 3 | * | ||
| 2 | * zcrypt 2.1.0 | 4 | * zcrypt 2.1.0 |
| 3 | * | 5 | * |
| 4 | * Copyright IBM Corp. 2001, 2012 | 6 | * Copyright (C) 2001, 2006 IBM Corporation |
| 5 | * Author(s): Robert Burroughs | 7 | * Author(s): Robert Burroughs |
| 6 | * Eric Rossman (edrossma@us.ibm.com) | 8 | * Eric Rossman (edrossma@us.ibm.com) |
| 7 | * Cornelia Huck <cornelia.huck@de.ibm.com> | 9 | * Cornelia Huck <cornelia.huck@de.ibm.com> |
| @@ -9,7 +11,6 @@ | |||
| 9 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) | 11 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) |
| 10 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> | 12 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> |
| 11 | * Ralph Wuerthner <rwuerthn@de.ibm.com> | 13 | * Ralph Wuerthner <rwuerthn@de.ibm.com> |
| 12 | * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com> | ||
| 13 | * | 14 | * |
| 14 | * This program is free software; you can redistribute it and/or modify | 15 | * 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 | * it under the terms of the GNU General Public License as published by |
| @@ -29,10 +30,8 @@ | |||
| 29 | #ifndef _ZCRYPT_API_H_ | 30 | #ifndef _ZCRYPT_API_H_ |
| 30 | #define _ZCRYPT_API_H_ | 31 | #define _ZCRYPT_API_H_ |
| 31 | 32 | ||
| 32 | #include <linux/atomic.h> | ||
| 33 | #include <asm/debug.h> | ||
| 34 | #include <asm/zcrypt.h> | ||
| 35 | #include "ap_bus.h" | 33 | #include "ap_bus.h" |
| 34 | #include <asm/zcrypt.h> | ||
| 36 | 35 | ||
| 37 | /* deprecated status calls */ | 36 | /* deprecated status calls */ |
| 38 | #define ICAZ90STATUS _IOR(ZCRYPT_IOCTL_MAGIC, 0x10, struct ica_z90_status) | 37 | #define ICAZ90STATUS _IOR(ZCRYPT_IOCTL_MAGIC, 0x10, struct ica_z90_status) |
| @@ -90,9 +89,6 @@ struct zcrypt_ops { | |||
| 90 | struct ica_rsa_modexpo_crt *); | 89 | struct ica_rsa_modexpo_crt *); |
| 91 | long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *); | 90 | long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *); |
| 92 | long (*rng)(struct zcrypt_device *, char *); | 91 | long (*rng)(struct zcrypt_device *, char *); |
| 93 | struct list_head list; /* zcrypt ops list. */ | ||
| 94 | struct module *owner; | ||
| 95 | int variant; | ||
| 96 | }; | 92 | }; |
| 97 | 93 | ||
| 98 | struct zcrypt_device { | 94 | struct zcrypt_device { |
| @@ -114,23 +110,14 @@ struct zcrypt_device { | |||
| 114 | 110 | ||
| 115 | struct ap_message reply; /* Per-device reply structure. */ | 111 | struct ap_message reply; /* Per-device reply structure. */ |
| 116 | int max_exp_bit_length; | 112 | int max_exp_bit_length; |
| 117 | |||
| 118 | debug_info_t *dbf_area; /* debugging */ | ||
| 119 | }; | 113 | }; |
| 120 | 114 | ||
| 121 | /* transport layer rescanning */ | ||
| 122 | extern atomic_t zcrypt_rescan_req; | ||
| 123 | |||
| 124 | struct zcrypt_device *zcrypt_device_alloc(size_t); | 115 | struct zcrypt_device *zcrypt_device_alloc(size_t); |
| 125 | void zcrypt_device_free(struct zcrypt_device *); | 116 | void zcrypt_device_free(struct zcrypt_device *); |
| 126 | void zcrypt_device_get(struct zcrypt_device *); | 117 | void zcrypt_device_get(struct zcrypt_device *); |
| 127 | int zcrypt_device_put(struct zcrypt_device *); | 118 | int zcrypt_device_put(struct zcrypt_device *); |
| 128 | int zcrypt_device_register(struct zcrypt_device *); | 119 | int zcrypt_device_register(struct zcrypt_device *); |
| 129 | void zcrypt_device_unregister(struct zcrypt_device *); | 120 | void zcrypt_device_unregister(struct zcrypt_device *); |
| 130 | void zcrypt_msgtype_register(struct zcrypt_ops *); | ||
| 131 | void zcrypt_msgtype_unregister(struct zcrypt_ops *); | ||
| 132 | struct zcrypt_ops *zcrypt_msgtype_request(unsigned char *, int); | ||
| 133 | void zcrypt_msgtype_release(struct zcrypt_ops *); | ||
| 134 | int zcrypt_api_init(void); | 121 | int zcrypt_api_init(void); |
| 135 | void zcrypt_api_exit(void); | 122 | void zcrypt_api_exit(void); |
| 136 | 123 | ||
diff --git a/drivers/s390/crypto/zcrypt_cca_key.h b/drivers/s390/crypto/zcrypt_cca_key.h index 1f42f103c76..ed82f2f59b1 100644 --- a/drivers/s390/crypto/zcrypt_cca_key.h +++ b/drivers/s390/crypto/zcrypt_cca_key.h | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/drivers/s390/crypto/zcrypt_cca_key.h | ||
| 3 | * | ||
| 2 | * zcrypt 2.1.0 | 4 | * zcrypt 2.1.0 |
| 3 | * | 5 | * |
| 4 | * Copyright IBM Corp. 2001, 2006 | 6 | * Copyright (C) 2001, 2006 IBM Corporation |
| 5 | * Author(s): Robert Burroughs | 7 | * Author(s): Robert Burroughs |
| 6 | * Eric Rossman (edrossma@us.ibm.com) | 8 | * Eric Rossman (edrossma@us.ibm.com) |
| 7 | * | 9 | * |
diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c index 1e849d6e1df..da171b5f399 100644 --- a/drivers/s390/crypto/zcrypt_cex2a.c +++ b/drivers/s390/crypto/zcrypt_cex2a.c | |||
| @@ -1,14 +1,15 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/drivers/s390/crypto/zcrypt_cex2a.c | ||
| 3 | * | ||
| 2 | * zcrypt 2.1.0 | 4 | * zcrypt 2.1.0 |
| 3 | * | 5 | * |
| 4 | * Copyright IBM Corp. 2001, 2012 | 6 | * Copyright (C) 2001, 2006 IBM Corporation |
| 5 | * Author(s): Robert Burroughs | 7 | * Author(s): Robert Burroughs |
| 6 | * Eric Rossman (edrossma@us.ibm.com) | 8 | * Eric Rossman (edrossma@us.ibm.com) |
| 7 | * | 9 | * |
| 8 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) | 10 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) |
| 9 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> | 11 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> |
| 10 | * Ralph Wuerthner <rwuerthn@de.ibm.com> | 12 | * Ralph Wuerthner <rwuerthn@de.ibm.com> |
| 11 | * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com> | ||
| 12 | * | 13 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 14 | * 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 | * it under the terms of the GNU General Public License as published by |
| @@ -36,7 +37,6 @@ | |||
| 36 | #include "zcrypt_api.h" | 37 | #include "zcrypt_api.h" |
| 37 | #include "zcrypt_error.h" | 38 | #include "zcrypt_error.h" |
| 38 | #include "zcrypt_cex2a.h" | 39 | #include "zcrypt_cex2a.h" |
| 39 | #include "zcrypt_msgtype50.h" | ||
| 40 | 40 | ||
| 41 | #define CEX2A_MIN_MOD_SIZE 1 /* 8 bits */ | 41 | #define CEX2A_MIN_MOD_SIZE 1 /* 8 bits */ |
| 42 | #define CEX2A_MAX_MOD_SIZE 256 /* 2048 bits */ | 42 | #define CEX2A_MAX_MOD_SIZE 256 /* 2048 bits */ |
| @@ -63,23 +63,364 @@ static struct ap_device_id zcrypt_cex2a_ids[] = { | |||
| 63 | { /* end of list */ }, | 63 | { /* end of list */ }, |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
| 66 | #ifndef CONFIG_ZCRYPT_MONOLITHIC | ||
| 66 | MODULE_DEVICE_TABLE(ap, zcrypt_cex2a_ids); | 67 | MODULE_DEVICE_TABLE(ap, zcrypt_cex2a_ids); |
| 67 | MODULE_AUTHOR("IBM Corporation"); | 68 | MODULE_AUTHOR("IBM Corporation"); |
| 68 | MODULE_DESCRIPTION("CEX2A Cryptographic Coprocessor device driver, " \ | 69 | MODULE_DESCRIPTION("CEX2A Cryptographic Coprocessor device driver, " |
| 69 | "Copyright IBM Corp. 2001, 2012"); | 70 | "Copyright 2001, 2006 IBM Corporation"); |
| 70 | MODULE_LICENSE("GPL"); | 71 | MODULE_LICENSE("GPL"); |
| 72 | #endif | ||
| 71 | 73 | ||
| 72 | static int zcrypt_cex2a_probe(struct ap_device *ap_dev); | 74 | static int zcrypt_cex2a_probe(struct ap_device *ap_dev); |
| 73 | static void zcrypt_cex2a_remove(struct ap_device *ap_dev); | 75 | static void zcrypt_cex2a_remove(struct ap_device *ap_dev); |
| 76 | static void zcrypt_cex2a_receive(struct ap_device *, struct ap_message *, | ||
| 77 | struct ap_message *); | ||
| 74 | 78 | ||
| 75 | static struct ap_driver zcrypt_cex2a_driver = { | 79 | static struct ap_driver zcrypt_cex2a_driver = { |
| 76 | .probe = zcrypt_cex2a_probe, | 80 | .probe = zcrypt_cex2a_probe, |
| 77 | .remove = zcrypt_cex2a_remove, | 81 | .remove = zcrypt_cex2a_remove, |
| 82 | .receive = zcrypt_cex2a_receive, | ||
| 78 | .ids = zcrypt_cex2a_ids, | 83 | .ids = zcrypt_cex2a_ids, |
| 79 | .request_timeout = CEX2A_CLEANUP_TIME, | 84 | .request_timeout = CEX2A_CLEANUP_TIME, |
| 80 | }; | 85 | }; |
| 81 | 86 | ||
| 82 | /** | 87 | /** |
| 88 | * Convert a ICAMEX message to a type50 MEX message. | ||
| 89 | * | ||
| 90 | * @zdev: crypto device pointer | ||
| 91 | * @zreq: crypto request pointer | ||
| 92 | * @mex: pointer to user input data | ||
| 93 | * | ||
| 94 | * Returns 0 on success or -EFAULT. | ||
| 95 | */ | ||
| 96 | static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_device *zdev, | ||
| 97 | struct ap_message *ap_msg, | ||
| 98 | struct ica_rsa_modexpo *mex) | ||
| 99 | { | ||
| 100 | unsigned char *mod, *exp, *inp; | ||
| 101 | int mod_len; | ||
| 102 | |||
| 103 | mod_len = mex->inputdatalength; | ||
| 104 | |||
| 105 | if (mod_len <= 128) { | ||
| 106 | struct type50_meb1_msg *meb1 = ap_msg->message; | ||
| 107 | memset(meb1, 0, sizeof(*meb1)); | ||
| 108 | ap_msg->length = sizeof(*meb1); | ||
| 109 | meb1->header.msg_type_code = TYPE50_TYPE_CODE; | ||
| 110 | meb1->header.msg_len = sizeof(*meb1); | ||
| 111 | meb1->keyblock_type = TYPE50_MEB1_FMT; | ||
| 112 | mod = meb1->modulus + sizeof(meb1->modulus) - mod_len; | ||
| 113 | exp = meb1->exponent + sizeof(meb1->exponent) - mod_len; | ||
| 114 | inp = meb1->message + sizeof(meb1->message) - mod_len; | ||
| 115 | } else if (mod_len <= 256) { | ||
| 116 | struct type50_meb2_msg *meb2 = ap_msg->message; | ||
| 117 | memset(meb2, 0, sizeof(*meb2)); | ||
| 118 | ap_msg->length = sizeof(*meb2); | ||
| 119 | meb2->header.msg_type_code = TYPE50_TYPE_CODE; | ||
| 120 | meb2->header.msg_len = sizeof(*meb2); | ||
| 121 | meb2->keyblock_type = TYPE50_MEB2_FMT; | ||
| 122 | mod = meb2->modulus + sizeof(meb2->modulus) - mod_len; | ||
| 123 | exp = meb2->exponent + sizeof(meb2->exponent) - mod_len; | ||
| 124 | inp = meb2->message + sizeof(meb2->message) - mod_len; | ||
| 125 | } else { | ||
| 126 | /* mod_len > 256 = 4096 bit RSA Key */ | ||
| 127 | struct type50_meb3_msg *meb3 = ap_msg->message; | ||
| 128 | memset(meb3, 0, sizeof(*meb3)); | ||
| 129 | ap_msg->length = sizeof(*meb3); | ||
| 130 | meb3->header.msg_type_code = TYPE50_TYPE_CODE; | ||
| 131 | meb3->header.msg_len = sizeof(*meb3); | ||
| 132 | meb3->keyblock_type = TYPE50_MEB3_FMT; | ||
| 133 | mod = meb3->modulus + sizeof(meb3->modulus) - mod_len; | ||
| 134 | exp = meb3->exponent + sizeof(meb3->exponent) - mod_len; | ||
| 135 | inp = meb3->message + sizeof(meb3->message) - mod_len; | ||
| 136 | } | ||
| 137 | |||
| 138 | if (copy_from_user(mod, mex->n_modulus, mod_len) || | ||
| 139 | copy_from_user(exp, mex->b_key, mod_len) || | ||
| 140 | copy_from_user(inp, mex->inputdata, mod_len)) | ||
| 141 | return -EFAULT; | ||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | /** | ||
| 146 | * Convert a ICACRT message to a type50 CRT message. | ||
| 147 | * | ||
| 148 | * @zdev: crypto device pointer | ||
| 149 | * @zreq: crypto request pointer | ||
| 150 | * @crt: pointer to user input data | ||
| 151 | * | ||
| 152 | * Returns 0 on success or -EFAULT. | ||
| 153 | */ | ||
| 154 | static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_device *zdev, | ||
| 155 | struct ap_message *ap_msg, | ||
| 156 | struct ica_rsa_modexpo_crt *crt) | ||
| 157 | { | ||
| 158 | int mod_len, short_len, long_len, long_offset, limit; | ||
| 159 | unsigned char *p, *q, *dp, *dq, *u, *inp; | ||
| 160 | |||
| 161 | mod_len = crt->inputdatalength; | ||
| 162 | short_len = mod_len / 2; | ||
| 163 | long_len = mod_len / 2 + 8; | ||
| 164 | |||
| 165 | /* | ||
| 166 | * CEX2A cannot handle p, dp, or U > 128 bytes. | ||
| 167 | * If we have one of these, we need to do extra checking. | ||
| 168 | * For CEX3A the limit is 256 bytes. | ||
| 169 | */ | ||
| 170 | if (zdev->max_mod_size == CEX3A_MAX_MOD_SIZE) | ||
| 171 | limit = 256; | ||
| 172 | else | ||
| 173 | limit = 128; | ||
| 174 | |||
| 175 | if (long_len > limit) { | ||
| 176 | /* | ||
| 177 | * zcrypt_rsa_crt already checked for the leading | ||
| 178 | * zeroes of np_prime, bp_key and u_mult_inc. | ||
| 179 | */ | ||
| 180 | long_offset = long_len - limit; | ||
| 181 | long_len = limit; | ||
| 182 | } else | ||
| 183 | long_offset = 0; | ||
| 184 | |||
| 185 | /* | ||
| 186 | * Instead of doing extra work for p, dp, U > 64 bytes, we'll just use | ||
| 187 | * the larger message structure. | ||
| 188 | */ | ||
| 189 | if (long_len <= 64) { | ||
| 190 | struct type50_crb1_msg *crb1 = ap_msg->message; | ||
| 191 | memset(crb1, 0, sizeof(*crb1)); | ||
| 192 | ap_msg->length = sizeof(*crb1); | ||
| 193 | crb1->header.msg_type_code = TYPE50_TYPE_CODE; | ||
| 194 | crb1->header.msg_len = sizeof(*crb1); | ||
| 195 | crb1->keyblock_type = TYPE50_CRB1_FMT; | ||
| 196 | p = crb1->p + sizeof(crb1->p) - long_len; | ||
| 197 | q = crb1->q + sizeof(crb1->q) - short_len; | ||
| 198 | dp = crb1->dp + sizeof(crb1->dp) - long_len; | ||
| 199 | dq = crb1->dq + sizeof(crb1->dq) - short_len; | ||
| 200 | u = crb1->u + sizeof(crb1->u) - long_len; | ||
| 201 | inp = crb1->message + sizeof(crb1->message) - mod_len; | ||
| 202 | } else if (long_len <= 128) { | ||
| 203 | struct type50_crb2_msg *crb2 = ap_msg->message; | ||
| 204 | memset(crb2, 0, sizeof(*crb2)); | ||
| 205 | ap_msg->length = sizeof(*crb2); | ||
| 206 | crb2->header.msg_type_code = TYPE50_TYPE_CODE; | ||
| 207 | crb2->header.msg_len = sizeof(*crb2); | ||
| 208 | crb2->keyblock_type = TYPE50_CRB2_FMT; | ||
| 209 | p = crb2->p + sizeof(crb2->p) - long_len; | ||
| 210 | q = crb2->q + sizeof(crb2->q) - short_len; | ||
| 211 | dp = crb2->dp + sizeof(crb2->dp) - long_len; | ||
| 212 | dq = crb2->dq + sizeof(crb2->dq) - short_len; | ||
| 213 | u = crb2->u + sizeof(crb2->u) - long_len; | ||
| 214 | inp = crb2->message + sizeof(crb2->message) - mod_len; | ||
| 215 | } else { | ||
| 216 | /* long_len >= 256 */ | ||
| 217 | struct type50_crb3_msg *crb3 = ap_msg->message; | ||
| 218 | memset(crb3, 0, sizeof(*crb3)); | ||
| 219 | ap_msg->length = sizeof(*crb3); | ||
| 220 | crb3->header.msg_type_code = TYPE50_TYPE_CODE; | ||
| 221 | crb3->header.msg_len = sizeof(*crb3); | ||
| 222 | crb3->keyblock_type = TYPE50_CRB3_FMT; | ||
| 223 | p = crb3->p + sizeof(crb3->p) - long_len; | ||
| 224 | q = crb3->q + sizeof(crb3->q) - short_len; | ||
| 225 | dp = crb3->dp + sizeof(crb3->dp) - long_len; | ||
| 226 | dq = crb3->dq + sizeof(crb3->dq) - short_len; | ||
| 227 | u = crb3->u + sizeof(crb3->u) - long_len; | ||
| 228 | inp = crb3->message + sizeof(crb3->message) - mod_len; | ||
| 229 | } | ||
| 230 | |||
| 231 | if (copy_from_user(p, crt->np_prime + long_offset, long_len) || | ||
| 232 | copy_from_user(q, crt->nq_prime, short_len) || | ||
| 233 | copy_from_user(dp, crt->bp_key + long_offset, long_len) || | ||
| 234 | copy_from_user(dq, crt->bq_key, short_len) || | ||
| 235 | copy_from_user(u, crt->u_mult_inv + long_offset, long_len) || | ||
| 236 | copy_from_user(inp, crt->inputdata, mod_len)) | ||
| 237 | return -EFAULT; | ||
| 238 | |||
| 239 | return 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | /** | ||
| 243 | * Copy results from a type 80 reply message back to user space. | ||
| 244 | * | ||
| 245 | * @zdev: crypto device pointer | ||
| 246 | * @reply: reply AP message. | ||
| 247 | * @data: pointer to user output data | ||
| 248 | * @length: size of user output data | ||
| 249 | * | ||
| 250 | * Returns 0 on success or -EFAULT. | ||
| 251 | */ | ||
| 252 | static int convert_type80(struct zcrypt_device *zdev, | ||
| 253 | struct ap_message *reply, | ||
| 254 | char __user *outputdata, | ||
| 255 | unsigned int outputdatalength) | ||
| 256 | { | ||
| 257 | struct type80_hdr *t80h = reply->message; | ||
| 258 | unsigned char *data; | ||
| 259 | |||
| 260 | if (t80h->len < sizeof(*t80h) + outputdatalength) { | ||
| 261 | /* The result is too short, the CEX2A card may not do that.. */ | ||
| 262 | zdev->online = 0; | ||
| 263 | return -EAGAIN; /* repeat the request on a different device. */ | ||
| 264 | } | ||
| 265 | if (zdev->user_space_type == ZCRYPT_CEX2A) | ||
| 266 | BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE); | ||
| 267 | else | ||
| 268 | BUG_ON(t80h->len > CEX3A_MAX_RESPONSE_SIZE); | ||
| 269 | data = reply->message + t80h->len - outputdatalength; | ||
| 270 | if (copy_to_user(outputdata, data, outputdatalength)) | ||
| 271 | return -EFAULT; | ||
| 272 | return 0; | ||
| 273 | } | ||
| 274 | |||
| 275 | static int convert_response(struct zcrypt_device *zdev, | ||
| 276 | struct ap_message *reply, | ||
| 277 | char __user *outputdata, | ||
| 278 | unsigned int outputdatalength) | ||
| 279 | { | ||
| 280 | /* Response type byte is the second byte in the response. */ | ||
| 281 | switch (((unsigned char *) reply->message)[1]) { | ||
| 282 | case TYPE82_RSP_CODE: | ||
| 283 | case TYPE88_RSP_CODE: | ||
| 284 | return convert_error(zdev, reply); | ||
| 285 | case TYPE80_RSP_CODE: | ||
| 286 | return convert_type80(zdev, reply, | ||
| 287 | outputdata, outputdatalength); | ||
| 288 | default: /* Unknown response type, this should NEVER EVER happen */ | ||
| 289 | zdev->online = 0; | ||
| 290 | return -EAGAIN; /* repeat the request on a different device. */ | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | /** | ||
| 295 | * This function is called from the AP bus code after a crypto request | ||
| 296 | * "msg" has finished with the reply message "reply". | ||
| 297 | * It is called from tasklet context. | ||
| 298 | * @ap_dev: pointer to the AP device | ||
| 299 | * @msg: pointer to the AP message | ||
| 300 | * @reply: pointer to the AP reply message | ||
| 301 | */ | ||
| 302 | static void zcrypt_cex2a_receive(struct ap_device *ap_dev, | ||
| 303 | struct ap_message *msg, | ||
| 304 | struct ap_message *reply) | ||
| 305 | { | ||
| 306 | static struct error_hdr error_reply = { | ||
| 307 | .type = TYPE82_RSP_CODE, | ||
| 308 | .reply_code = REP82_ERROR_MACHINE_FAILURE, | ||
| 309 | }; | ||
| 310 | struct type80_hdr *t80h; | ||
| 311 | int length; | ||
| 312 | |||
| 313 | /* Copy the reply message to the request message buffer. */ | ||
| 314 | if (IS_ERR(reply)) { | ||
| 315 | memcpy(msg->message, &error_reply, sizeof(error_reply)); | ||
| 316 | goto out; | ||
| 317 | } | ||
| 318 | t80h = reply->message; | ||
| 319 | if (t80h->type == TYPE80_RSP_CODE) { | ||
| 320 | if (ap_dev->device_type == AP_DEVICE_TYPE_CEX2A) | ||
| 321 | length = min(CEX2A_MAX_RESPONSE_SIZE, (int) t80h->len); | ||
| 322 | else | ||
| 323 | length = min(CEX3A_MAX_RESPONSE_SIZE, (int) t80h->len); | ||
| 324 | memcpy(msg->message, reply->message, length); | ||
| 325 | } else | ||
| 326 | memcpy(msg->message, reply->message, sizeof error_reply); | ||
| 327 | out: | ||
| 328 | complete((struct completion *) msg->private); | ||
| 329 | } | ||
| 330 | |||
| 331 | static atomic_t zcrypt_step = ATOMIC_INIT(0); | ||
| 332 | |||
| 333 | /** | ||
| 334 | * The request distributor calls this function if it picked the CEX2A | ||
| 335 | * device to handle a modexpo request. | ||
| 336 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
| 337 | * CEX2A device to the request distributor | ||
| 338 | * @mex: pointer to the modexpo request buffer | ||
| 339 | */ | ||
| 340 | static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev, | ||
| 341 | struct ica_rsa_modexpo *mex) | ||
| 342 | { | ||
| 343 | struct ap_message ap_msg; | ||
| 344 | struct completion work; | ||
| 345 | int rc; | ||
| 346 | |||
| 347 | ap_init_message(&ap_msg); | ||
| 348 | if (zdev->user_space_type == ZCRYPT_CEX2A) | ||
| 349 | ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL); | ||
| 350 | else | ||
| 351 | ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL); | ||
| 352 | if (!ap_msg.message) | ||
| 353 | return -ENOMEM; | ||
| 354 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
| 355 | atomic_inc_return(&zcrypt_step); | ||
| 356 | ap_msg.private = &work; | ||
| 357 | rc = ICAMEX_msg_to_type50MEX_msg(zdev, &ap_msg, mex); | ||
| 358 | if (rc) | ||
| 359 | goto out_free; | ||
| 360 | init_completion(&work); | ||
| 361 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
| 362 | rc = wait_for_completion_interruptible(&work); | ||
| 363 | if (rc == 0) | ||
| 364 | rc = convert_response(zdev, &ap_msg, mex->outputdata, | ||
| 365 | mex->outputdatalength); | ||
| 366 | else | ||
| 367 | /* Signal pending. */ | ||
| 368 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
| 369 | out_free: | ||
| 370 | kfree(ap_msg.message); | ||
| 371 | return rc; | ||
| 372 | } | ||
| 373 | |||
| 374 | /** | ||
| 375 | * The request distributor calls this function if it picked the CEX2A | ||
| 376 | * device to handle a modexpo_crt request. | ||
| 377 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
| 378 | * CEX2A device to the request distributor | ||
| 379 | * @crt: pointer to the modexpoc_crt request buffer | ||
| 380 | */ | ||
| 381 | static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev, | ||
| 382 | struct ica_rsa_modexpo_crt *crt) | ||
| 383 | { | ||
| 384 | struct ap_message ap_msg; | ||
| 385 | struct completion work; | ||
| 386 | int rc; | ||
| 387 | |||
| 388 | ap_init_message(&ap_msg); | ||
| 389 | if (zdev->user_space_type == ZCRYPT_CEX2A) | ||
| 390 | ap_msg.message = kmalloc(CEX2A_MAX_MESSAGE_SIZE, GFP_KERNEL); | ||
| 391 | else | ||
| 392 | ap_msg.message = kmalloc(CEX3A_MAX_MESSAGE_SIZE, GFP_KERNEL); | ||
| 393 | if (!ap_msg.message) | ||
| 394 | return -ENOMEM; | ||
| 395 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
| 396 | atomic_inc_return(&zcrypt_step); | ||
| 397 | ap_msg.private = &work; | ||
| 398 | rc = ICACRT_msg_to_type50CRT_msg(zdev, &ap_msg, crt); | ||
| 399 | if (rc) | ||
| 400 | goto out_free; | ||
| 401 | init_completion(&work); | ||
| 402 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
| 403 | rc = wait_for_completion_interruptible(&work); | ||
| 404 | if (rc == 0) | ||
| 405 | rc = convert_response(zdev, &ap_msg, crt->outputdata, | ||
| 406 | crt->outputdatalength); | ||
| 407 | else | ||
| 408 | /* Signal pending. */ | ||
| 409 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
| 410 | out_free: | ||
| 411 | kfree(ap_msg.message); | ||
| 412 | return rc; | ||
| 413 | } | ||
| 414 | |||
| 415 | /** | ||
| 416 | * The crypto operations for a CEX2A card. | ||
| 417 | */ | ||
| 418 | static struct zcrypt_ops zcrypt_cex2a_ops = { | ||
| 419 | .rsa_modexpo = zcrypt_cex2a_modexpo, | ||
| 420 | .rsa_modexpo_crt = zcrypt_cex2a_modexpo_crt, | ||
| 421 | }; | ||
| 422 | |||
| 423 | /** | ||
| 83 | * Probe function for CEX2A cards. It always accepts the AP device | 424 | * Probe function for CEX2A cards. It always accepts the AP device |
| 84 | * since the bus_match already checked the hardware type. | 425 | * since the bus_match already checked the hardware type. |
| 85 | * @ap_dev: pointer to the AP device. | 426 | * @ap_dev: pointer to the AP device. |
| @@ -111,8 +452,7 @@ static int zcrypt_cex2a_probe(struct ap_device *ap_dev) | |||
| 111 | zdev->min_mod_size = CEX2A_MIN_MOD_SIZE; | 452 | zdev->min_mod_size = CEX2A_MIN_MOD_SIZE; |
| 112 | zdev->max_mod_size = CEX2A_MAX_MOD_SIZE; | 453 | zdev->max_mod_size = CEX2A_MAX_MOD_SIZE; |
| 113 | zdev->max_exp_bit_length = CEX2A_MAX_MOD_SIZE; | 454 | zdev->max_exp_bit_length = CEX2A_MAX_MOD_SIZE; |
| 114 | if (ap_test_bit(&ap_dev->functions, AP_FUNC_MEX4K) && | 455 | if (ap_4096_commands_available(ap_dev->qid)) { |
| 115 | ap_test_bit(&ap_dev->functions, AP_FUNC_CRT4K)) { | ||
| 116 | zdev->max_mod_size = CEX3A_MAX_MOD_SIZE; | 456 | zdev->max_mod_size = CEX3A_MAX_MOD_SIZE; |
| 117 | zdev->max_exp_bit_length = CEX3A_MAX_MOD_SIZE; | 457 | zdev->max_exp_bit_length = CEX3A_MAX_MOD_SIZE; |
| 118 | } | 458 | } |
| @@ -120,18 +460,16 @@ static int zcrypt_cex2a_probe(struct ap_device *ap_dev) | |||
| 120 | zdev->speed_rating = CEX3A_SPEED_RATING; | 460 | zdev->speed_rating = CEX3A_SPEED_RATING; |
| 121 | break; | 461 | break; |
| 122 | } | 462 | } |
| 123 | if (!zdev) | 463 | if (zdev != NULL) { |
| 124 | return -ENODEV; | 464 | zdev->ap_dev = ap_dev; |
| 125 | zdev->ops = zcrypt_msgtype_request(MSGTYPE50_NAME, | 465 | zdev->ops = &zcrypt_cex2a_ops; |
| 126 | MSGTYPE50_VARIANT_DEFAULT); | 466 | zdev->online = 1; |
| 127 | zdev->ap_dev = ap_dev; | 467 | ap_dev->reply = &zdev->reply; |
| 128 | zdev->online = 1; | 468 | ap_dev->private = zdev; |
| 129 | ap_dev->reply = &zdev->reply; | 469 | rc = zcrypt_device_register(zdev); |
| 130 | ap_dev->private = zdev; | 470 | } |
| 131 | rc = zcrypt_device_register(zdev); | ||
| 132 | if (rc) { | 471 | if (rc) { |
| 133 | ap_dev->private = NULL; | 472 | ap_dev->private = NULL; |
| 134 | zcrypt_msgtype_release(zdev->ops); | ||
| 135 | zcrypt_device_free(zdev); | 473 | zcrypt_device_free(zdev); |
| 136 | } | 474 | } |
| 137 | return rc; | 475 | return rc; |
| @@ -144,10 +482,8 @@ static int zcrypt_cex2a_probe(struct ap_device *ap_dev) | |||
| 144 | static void zcrypt_cex2a_remove(struct ap_device *ap_dev) | 482 | static void zcrypt_cex2a_remove(struct ap_device *ap_dev) |
| 145 | { | 483 | { |
| 146 | struct zcrypt_device *zdev = ap_dev->private; | 484 | struct zcrypt_device *zdev = ap_dev->private; |
| 147 | struct zcrypt_ops *zops = zdev->ops; | ||
| 148 | 485 | ||
| 149 | zcrypt_device_unregister(zdev); | 486 | zcrypt_device_unregister(zdev); |
| 150 | zcrypt_msgtype_release(zops); | ||
| 151 | } | 487 | } |
| 152 | 488 | ||
| 153 | int __init zcrypt_cex2a_init(void) | 489 | int __init zcrypt_cex2a_init(void) |
| @@ -160,5 +496,7 @@ void __exit zcrypt_cex2a_exit(void) | |||
| 160 | ap_driver_unregister(&zcrypt_cex2a_driver); | 496 | ap_driver_unregister(&zcrypt_cex2a_driver); |
| 161 | } | 497 | } |
| 162 | 498 | ||
| 499 | #ifndef CONFIG_ZCRYPT_MONOLITHIC | ||
| 163 | module_init(zcrypt_cex2a_init); | 500 | module_init(zcrypt_cex2a_init); |
| 164 | module_exit(zcrypt_cex2a_exit); | 501 | module_exit(zcrypt_cex2a_exit); |
| 502 | #endif | ||
diff --git a/drivers/s390/crypto/zcrypt_cex2a.h b/drivers/s390/crypto/zcrypt_cex2a.h index 0dce4b9af18..0350665810c 100644 --- a/drivers/s390/crypto/zcrypt_cex2a.h +++ b/drivers/s390/crypto/zcrypt_cex2a.h | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/drivers/s390/crypto/zcrypt_cex2a.h | ||
| 3 | * | ||
| 2 | * zcrypt 2.1.0 | 4 | * zcrypt 2.1.0 |
| 3 | * | 5 | * |
| 4 | * Copyright IBM Corp. 2001, 2006 | 6 | * Copyright (C) 2001, 2006 IBM Corporation |
| 5 | * Author(s): Robert Burroughs | 7 | * Author(s): Robert Burroughs |
| 6 | * Eric Rossman (edrossma@us.ibm.com) | 8 | * Eric Rossman (edrossma@us.ibm.com) |
| 7 | * | 9 | * |
diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c deleted file mode 100644 index ce1226398ac..00000000000 --- a/drivers/s390/crypto/zcrypt_cex4.c +++ /dev/null | |||
| @@ -1,149 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright IBM Corp. 2012 | ||
| 3 | * Author(s): Holger Dengler <hd@linux.vnet.ibm.com> | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/module.h> | ||
| 7 | #include <linux/slab.h> | ||
| 8 | #include <linux/init.h> | ||
| 9 | #include <linux/err.h> | ||
| 10 | #include <linux/atomic.h> | ||
| 11 | #include <linux/uaccess.h> | ||
| 12 | |||
| 13 | #include "ap_bus.h" | ||
| 14 | #include "zcrypt_api.h" | ||
| 15 | #include "zcrypt_msgtype6.h" | ||
| 16 | #include "zcrypt_msgtype50.h" | ||
| 17 | #include "zcrypt_error.h" | ||
| 18 | #include "zcrypt_cex4.h" | ||
| 19 | |||
| 20 | #define CEX4A_MIN_MOD_SIZE 1 /* 8 bits */ | ||
| 21 | #define CEX4A_MAX_MOD_SIZE_2K 256 /* 2048 bits */ | ||
| 22 | #define CEX4A_MAX_MOD_SIZE_4K 512 /* 4096 bits */ | ||
| 23 | |||
| 24 | #define CEX4C_MIN_MOD_SIZE 16 /* 256 bits */ | ||
| 25 | #define CEX4C_MAX_MOD_SIZE 512 /* 4096 bits */ | ||
| 26 | |||
| 27 | #define CEX4A_SPEED_RATING 900 /* TODO new card, new speed rating */ | ||
| 28 | #define CEX4C_SPEED_RATING 6500 /* TODO new card, new speed rating */ | ||
| 29 | |||
| 30 | #define CEX4A_MAX_MESSAGE_SIZE MSGTYPE50_CRB3_MAX_MSG_SIZE | ||
| 31 | #define CEX4C_MAX_MESSAGE_SIZE MSGTYPE06_MAX_MSG_SIZE | ||
| 32 | |||
| 33 | #define CEX4_CLEANUP_TIME (15*HZ) | ||
| 34 | |||
| 35 | static struct ap_device_id zcrypt_cex4_ids[] = { | ||
| 36 | { AP_DEVICE(AP_DEVICE_TYPE_CEX4) }, | ||
| 37 | { /* end of list */ }, | ||
| 38 | }; | ||
| 39 | |||
| 40 | MODULE_DEVICE_TABLE(ap, zcrypt_cex4_ids); | ||
| 41 | MODULE_AUTHOR("IBM Corporation"); | ||
| 42 | MODULE_DESCRIPTION("CEX4 Cryptographic Card device driver, " \ | ||
| 43 | "Copyright IBM Corp. 2012"); | ||
| 44 | MODULE_LICENSE("GPL"); | ||
| 45 | |||
| 46 | static int zcrypt_cex4_probe(struct ap_device *ap_dev); | ||
| 47 | static void zcrypt_cex4_remove(struct ap_device *ap_dev); | ||
| 48 | |||
| 49 | static struct ap_driver zcrypt_cex4_driver = { | ||
| 50 | .probe = zcrypt_cex4_probe, | ||
| 51 | .remove = zcrypt_cex4_remove, | ||
| 52 | .ids = zcrypt_cex4_ids, | ||
| 53 | .request_timeout = CEX4_CLEANUP_TIME, | ||
| 54 | }; | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Probe function for CEX4 cards. It always accepts the AP device | ||
| 58 | * since the bus_match already checked the hardware type. | ||
| 59 | * @ap_dev: pointer to the AP device. | ||
| 60 | */ | ||
| 61 | static int zcrypt_cex4_probe(struct ap_device *ap_dev) | ||
| 62 | { | ||
| 63 | struct zcrypt_device *zdev = NULL; | ||
| 64 | int rc = 0; | ||
| 65 | |||
| 66 | switch (ap_dev->device_type) { | ||
| 67 | case AP_DEVICE_TYPE_CEX4: | ||
| 68 | if (ap_test_bit(&ap_dev->functions, AP_FUNC_ACCEL)) { | ||
| 69 | zdev = zcrypt_device_alloc(CEX4A_MAX_MESSAGE_SIZE); | ||
| 70 | if (!zdev) | ||
| 71 | return -ENOMEM; | ||
| 72 | zdev->type_string = "CEX4A"; | ||
| 73 | zdev->user_space_type = ZCRYPT_CEX3A; | ||
| 74 | zdev->min_mod_size = CEX4A_MIN_MOD_SIZE; | ||
| 75 | if (ap_test_bit(&ap_dev->functions, AP_FUNC_MEX4K) && | ||
| 76 | ap_test_bit(&ap_dev->functions, AP_FUNC_CRT4K)) { | ||
| 77 | zdev->max_mod_size = | ||
| 78 | CEX4A_MAX_MOD_SIZE_4K; | ||
| 79 | zdev->max_exp_bit_length = | ||
| 80 | CEX4A_MAX_MOD_SIZE_4K; | ||
| 81 | } else { | ||
| 82 | zdev->max_mod_size = | ||
| 83 | CEX4A_MAX_MOD_SIZE_2K; | ||
| 84 | zdev->max_exp_bit_length = | ||
| 85 | CEX4A_MAX_MOD_SIZE_2K; | ||
| 86 | } | ||
| 87 | zdev->short_crt = 1; | ||
| 88 | zdev->speed_rating = CEX4A_SPEED_RATING; | ||
| 89 | zdev->ops = zcrypt_msgtype_request(MSGTYPE50_NAME, | ||
| 90 | MSGTYPE50_VARIANT_DEFAULT); | ||
| 91 | } else if (ap_test_bit(&ap_dev->functions, AP_FUNC_COPRO)) { | ||
| 92 | zdev = zcrypt_device_alloc(CEX4C_MAX_MESSAGE_SIZE); | ||
| 93 | if (!zdev) | ||
| 94 | return -ENOMEM; | ||
| 95 | zdev->type_string = "CEX4C"; | ||
| 96 | zdev->user_space_type = ZCRYPT_CEX3C; | ||
| 97 | zdev->min_mod_size = CEX4C_MIN_MOD_SIZE; | ||
| 98 | zdev->max_mod_size = CEX4C_MAX_MOD_SIZE; | ||
| 99 | zdev->max_exp_bit_length = CEX4C_MAX_MOD_SIZE; | ||
| 100 | zdev->short_crt = 0; | ||
| 101 | zdev->speed_rating = CEX4C_SPEED_RATING; | ||
| 102 | zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, | ||
| 103 | MSGTYPE06_VARIANT_DEFAULT); | ||
| 104 | } | ||
| 105 | break; | ||
| 106 | } | ||
| 107 | if (!zdev) | ||
| 108 | return -ENODEV; | ||
| 109 | zdev->ap_dev = ap_dev; | ||
| 110 | zdev->online = 1; | ||
| 111 | ap_dev->reply = &zdev->reply; | ||
| 112 | ap_dev->private = zdev; | ||
| 113 | rc = zcrypt_device_register(zdev); | ||
| 114 | if (rc) { | ||
| 115 | zcrypt_msgtype_release(zdev->ops); | ||
| 116 | ap_dev->private = NULL; | ||
| 117 | zcrypt_device_free(zdev); | ||
| 118 | } | ||
| 119 | return rc; | ||
| 120 | } | ||
| 121 | |||
| 122 | /** | ||
| 123 | * This is called to remove the extended CEX4 driver information | ||
| 124 | * if an AP device is removed. | ||
| 125 | */ | ||
| 126 | static void zcrypt_cex4_remove(struct ap_device *ap_dev) | ||
| 127 | { | ||
| 128 | struct zcrypt_device *zdev = ap_dev->private; | ||
| 129 | struct zcrypt_ops *zops; | ||
| 130 | |||
| 131 | if (zdev) { | ||
| 132 | zops = zdev->ops; | ||
| 133 | zcrypt_device_unregister(zdev); | ||
| 134 | zcrypt_msgtype_release(zops); | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | int __init zcrypt_cex4_init(void) | ||
| 139 | { | ||
| 140 | return ap_driver_register(&zcrypt_cex4_driver, THIS_MODULE, "cex4"); | ||
| 141 | } | ||
| 142 | |||
| 143 | void __exit zcrypt_cex4_exit(void) | ||
| 144 | { | ||
| 145 | ap_driver_unregister(&zcrypt_cex4_driver); | ||
| 146 | } | ||
| 147 | |||
| 148 | module_init(zcrypt_cex4_init); | ||
| 149 | module_exit(zcrypt_cex4_exit); | ||
diff --git a/drivers/s390/crypto/zcrypt_cex4.h b/drivers/s390/crypto/zcrypt_cex4.h deleted file mode 100644 index 719571375cc..00000000000 --- a/drivers/s390/crypto/zcrypt_cex4.h +++ /dev/null | |||
| @@ -1,12 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright IBM Corp. 2012 | ||
| 3 | * Author(s): Holger Dengler <hd@linux.vnet.ibm.com> | ||
| 4 | */ | ||
| 5 | |||
| 6 | #ifndef _ZCRYPT_CEX4_H_ | ||
| 7 | #define _ZCRYPT_CEX4_H_ | ||
| 8 | |||
| 9 | int zcrypt_cex4_init(void); | ||
| 10 | void zcrypt_cex4_exit(void); | ||
| 11 | |||
| 12 | #endif /* _ZCRYPT_CEX4_H_ */ | ||
diff --git a/drivers/s390/crypto/zcrypt_debug.h b/drivers/s390/crypto/zcrypt_debug.h deleted file mode 100644 index 841ea72e4a4..00000000000 --- a/drivers/s390/crypto/zcrypt_debug.h +++ /dev/null | |||
| @@ -1,59 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright IBM Corp. 2012 | ||
| 3 | * Author(s): Holger Dengler (hd@linux.vnet.ibm.com) | ||
| 4 | */ | ||
| 5 | #ifndef ZCRYPT_DEBUG_H | ||
| 6 | #define ZCRYPT_DEBUG_H | ||
| 7 | |||
| 8 | #include <asm/debug.h> | ||
| 9 | #include "zcrypt_api.h" | ||
| 10 | |||
| 11 | /* that gives us 15 characters in the text event views */ | ||
| 12 | #define ZCRYPT_DBF_LEN 16 | ||
| 13 | |||
| 14 | /* sort out low debug levels early to avoid wasted sprints */ | ||
| 15 | static inline int zcrypt_dbf_passes(debug_info_t *dbf_grp, int level) | ||
| 16 | { | ||
| 17 | return (level <= dbf_grp->level); | ||
| 18 | } | ||
| 19 | |||
| 20 | #define DBF_ERR 3 /* error conditions */ | ||
| 21 | #define DBF_WARN 4 /* warning conditions */ | ||
| 22 | #define DBF_INFO 6 /* informational */ | ||
| 23 | |||
| 24 | #define RC2WARN(rc) ((rc) ? DBF_WARN : DBF_INFO) | ||
| 25 | |||
| 26 | #define ZCRYPT_DBF_COMMON(level, text...) \ | ||
| 27 | do { \ | ||
| 28 | if (zcrypt_dbf_passes(zcrypt_dbf_common, level)) { \ | ||
| 29 | char debug_buffer[ZCRYPT_DBF_LEN]; \ | ||
| 30 | snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \ | ||
| 31 | debug_text_event(zcrypt_dbf_common, level, \ | ||
| 32 | debug_buffer); \ | ||
| 33 | } \ | ||
| 34 | } while (0) | ||
| 35 | |||
| 36 | #define ZCRYPT_DBF_DEVICES(level, text...) \ | ||
| 37 | do { \ | ||
| 38 | if (zcrypt_dbf_passes(zcrypt_dbf_devices, level)) { \ | ||
| 39 | char debug_buffer[ZCRYPT_DBF_LEN]; \ | ||
| 40 | snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \ | ||
| 41 | debug_text_event(zcrypt_dbf_devices, level, \ | ||
| 42 | debug_buffer); \ | ||
| 43 | } \ | ||
| 44 | } while (0) | ||
| 45 | |||
| 46 | #define ZCRYPT_DBF_DEV(level, device, text...) \ | ||
| 47 | do { \ | ||
| 48 | if (zcrypt_dbf_passes(device->dbf_area, level)) { \ | ||
| 49 | char debug_buffer[ZCRYPT_DBF_LEN]; \ | ||
| 50 | snprintf(debug_buffer, ZCRYPT_DBF_LEN, text); \ | ||
| 51 | debug_text_event(device->dbf_area, level, \ | ||
| 52 | debug_buffer); \ | ||
| 53 | } \ | ||
| 54 | } while (0) | ||
| 55 | |||
| 56 | int zcrypt_debug_init(void); | ||
| 57 | void zcrypt_debug_exit(void); | ||
| 58 | |||
| 59 | #endif /* ZCRYPT_DEBUG_H */ | ||
diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h index 0079b661721..03ba27f05f9 100644 --- a/drivers/s390/crypto/zcrypt_error.h +++ b/drivers/s390/crypto/zcrypt_error.h | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/drivers/s390/crypto/zcrypt_error.h | ||
| 3 | * | ||
| 2 | * zcrypt 2.1.0 | 4 | * zcrypt 2.1.0 |
| 3 | * | 5 | * |
| 4 | * Copyright IBM Corp. 2001, 2006 | 6 | * Copyright (C) 2001, 2006 IBM Corporation |
| 5 | * Author(s): Robert Burroughs | 7 | * Author(s): Robert Burroughs |
| 6 | * Eric Rossman (edrossma@us.ibm.com) | 8 | * Eric Rossman (edrossma@us.ibm.com) |
| 7 | * | 9 | * |
| @@ -26,8 +28,6 @@ | |||
| 26 | #ifndef _ZCRYPT_ERROR_H_ | 28 | #ifndef _ZCRYPT_ERROR_H_ |
| 27 | #define _ZCRYPT_ERROR_H_ | 29 | #define _ZCRYPT_ERROR_H_ |
| 28 | 30 | ||
| 29 | #include <linux/atomic.h> | ||
| 30 | #include "zcrypt_debug.h" | ||
| 31 | #include "zcrypt_api.h" | 31 | #include "zcrypt_api.h" |
| 32 | 32 | ||
| 33 | /** | 33 | /** |
| @@ -110,27 +110,16 @@ static inline int convert_error(struct zcrypt_device *zdev, | |||
| 110 | * and then repeat the request. | 110 | * and then repeat the request. |
| 111 | */ | 111 | */ |
| 112 | WARN_ON(1); | 112 | WARN_ON(1); |
| 113 | atomic_set(&zcrypt_rescan_req, 1); | ||
| 114 | zdev->online = 0; | 113 | zdev->online = 0; |
| 115 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | ||
| 116 | zdev->ap_dev->qid, | ||
| 117 | zdev->online, ehdr->reply_code); | ||
| 118 | return -EAGAIN; | 114 | return -EAGAIN; |
| 119 | case REP82_ERROR_TRANSPORT_FAIL: | 115 | case REP82_ERROR_TRANSPORT_FAIL: |
| 120 | case REP82_ERROR_MACHINE_FAILURE: | 116 | case REP82_ERROR_MACHINE_FAILURE: |
| 121 | // REP88_ERROR_MODULE_FAILURE // '10' CEX2A | 117 | // REP88_ERROR_MODULE_FAILURE // '10' CEX2A |
| 122 | /* If a card fails disable it and repeat the request. */ | 118 | /* If a card fails disable it and repeat the request. */ |
| 123 | atomic_set(&zcrypt_rescan_req, 1); | ||
| 124 | zdev->online = 0; | 119 | zdev->online = 0; |
| 125 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | ||
| 126 | zdev->ap_dev->qid, | ||
| 127 | zdev->online, ehdr->reply_code); | ||
| 128 | return -EAGAIN; | 120 | return -EAGAIN; |
| 129 | default: | 121 | default: |
| 130 | zdev->online = 0; | 122 | zdev->online = 0; |
| 131 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | ||
| 132 | zdev->ap_dev->qid, | ||
| 133 | zdev->online, ehdr->reply_code); | ||
| 134 | return -EAGAIN; /* repeat the request on a different device. */ | 123 | return -EAGAIN; /* repeat the request on a different device. */ |
| 135 | } | 124 | } |
| 136 | } | 125 | } |
diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c deleted file mode 100644 index 7c522f338bd..00000000000 --- a/drivers/s390/crypto/zcrypt_msgtype50.c +++ /dev/null | |||
| @@ -1,517 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * zcrypt 2.1.0 | ||
| 3 | * | ||
| 4 | * Copyright IBM Corp. 2001, 2012 | ||
| 5 | * Author(s): Robert Burroughs | ||
| 6 | * Eric Rossman (edrossma@us.ibm.com) | ||
| 7 | * | ||
| 8 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) | ||
| 9 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
| 10 | * Ralph Wuerthner <rwuerthn@de.ibm.com> | ||
| 11 | * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.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 | #include <linux/module.h> | ||
| 29 | #include <linux/slab.h> | ||
| 30 | #include <linux/init.h> | ||
| 31 | #include <linux/err.h> | ||
| 32 | #include <linux/atomic.h> | ||
| 33 | #include <linux/uaccess.h> | ||
| 34 | |||
| 35 | #include "ap_bus.h" | ||
| 36 | #include "zcrypt_api.h" | ||
| 37 | #include "zcrypt_error.h" | ||
| 38 | #include "zcrypt_msgtype50.h" | ||
| 39 | |||
| 40 | #define CEX3A_MAX_MOD_SIZE 512 /* 4096 bits */ | ||
| 41 | |||
| 42 | #define CEX2A_MAX_RESPONSE_SIZE 0x110 /* max outputdatalength + type80_hdr */ | ||
| 43 | |||
| 44 | #define CEX3A_MAX_RESPONSE_SIZE 0x210 /* 512 bit modulus | ||
| 45 | * (max outputdatalength) + | ||
| 46 | * type80_hdr*/ | ||
| 47 | |||
| 48 | MODULE_AUTHOR("IBM Corporation"); | ||
| 49 | MODULE_DESCRIPTION("Cryptographic Accelerator (message type 50), " \ | ||
| 50 | "Copyright IBM Corp. 2001, 2012"); | ||
| 51 | MODULE_LICENSE("GPL"); | ||
| 52 | |||
| 53 | static void zcrypt_cex2a_receive(struct ap_device *, struct ap_message *, | ||
| 54 | struct ap_message *); | ||
| 55 | |||
| 56 | /** | ||
| 57 | * The type 50 message family is associated with a CEX2A card. | ||
| 58 | * | ||
| 59 | * The four members of the family are described below. | ||
| 60 | * | ||
| 61 | * Note that all unsigned char arrays are right-justified and left-padded | ||
| 62 | * with zeroes. | ||
| 63 | * | ||
| 64 | * Note that all reserved fields must be zeroes. | ||
| 65 | */ | ||
| 66 | struct type50_hdr { | ||
| 67 | unsigned char reserved1; | ||
| 68 | unsigned char msg_type_code; /* 0x50 */ | ||
| 69 | unsigned short msg_len; | ||
| 70 | unsigned char reserved2; | ||
| 71 | unsigned char ignored; | ||
| 72 | unsigned short reserved3; | ||
| 73 | } __packed; | ||
| 74 | |||
| 75 | #define TYPE50_TYPE_CODE 0x50 | ||
| 76 | |||
| 77 | #define TYPE50_MEB1_FMT 0x0001 | ||
| 78 | #define TYPE50_MEB2_FMT 0x0002 | ||
| 79 | #define TYPE50_MEB3_FMT 0x0003 | ||
| 80 | #define TYPE50_CRB1_FMT 0x0011 | ||
| 81 | #define TYPE50_CRB2_FMT 0x0012 | ||
| 82 | #define TYPE50_CRB3_FMT 0x0013 | ||
| 83 | |||
| 84 | /* Mod-Exp, with a small modulus */ | ||
| 85 | struct type50_meb1_msg { | ||
| 86 | struct type50_hdr header; | ||
| 87 | unsigned short keyblock_type; /* 0x0001 */ | ||
| 88 | unsigned char reserved[6]; | ||
| 89 | unsigned char exponent[128]; | ||
| 90 | unsigned char modulus[128]; | ||
| 91 | unsigned char message[128]; | ||
| 92 | } __packed; | ||
| 93 | |||
| 94 | /* Mod-Exp, with a large modulus */ | ||
| 95 | struct type50_meb2_msg { | ||
| 96 | struct type50_hdr header; | ||
| 97 | unsigned short keyblock_type; /* 0x0002 */ | ||
| 98 | unsigned char reserved[6]; | ||
| 99 | unsigned char exponent[256]; | ||
| 100 | unsigned char modulus[256]; | ||
| 101 | unsigned char message[256]; | ||
| 102 | } __packed; | ||
| 103 | |||
| 104 | /* Mod-Exp, with a larger modulus */ | ||
| 105 | struct type50_meb3_msg { | ||
| 106 | struct type50_hdr header; | ||
| 107 | unsigned short keyblock_type; /* 0x0003 */ | ||
| 108 | unsigned char reserved[6]; | ||
| 109 | unsigned char exponent[512]; | ||
| 110 | unsigned char modulus[512]; | ||
| 111 | unsigned char message[512]; | ||
| 112 | } __packed; | ||
| 113 | |||
| 114 | /* CRT, with a small modulus */ | ||
| 115 | struct type50_crb1_msg { | ||
| 116 | struct type50_hdr header; | ||
| 117 | unsigned short keyblock_type; /* 0x0011 */ | ||
| 118 | unsigned char reserved[6]; | ||
| 119 | unsigned char p[64]; | ||
| 120 | unsigned char q[64]; | ||
| 121 | unsigned char dp[64]; | ||
| 122 | unsigned char dq[64]; | ||
| 123 | unsigned char u[64]; | ||
| 124 | unsigned char message[128]; | ||
| 125 | } __packed; | ||
| 126 | |||
| 127 | /* CRT, with a large modulus */ | ||
| 128 | struct type50_crb2_msg { | ||
| 129 | struct type50_hdr header; | ||
| 130 | unsigned short keyblock_type; /* 0x0012 */ | ||
| 131 | unsigned char reserved[6]; | ||
| 132 | unsigned char p[128]; | ||
| 133 | unsigned char q[128]; | ||
| 134 | unsigned char dp[128]; | ||
| 135 | unsigned char dq[128]; | ||
| 136 | unsigned char u[128]; | ||
| 137 | unsigned char message[256]; | ||
| 138 | } __packed; | ||
| 139 | |||
| 140 | /* CRT, with a larger modulus */ | ||
| 141 | struct type50_crb3_msg { | ||
| 142 | struct type50_hdr header; | ||
| 143 | unsigned short keyblock_type; /* 0x0013 */ | ||
| 144 | unsigned char reserved[6]; | ||
| 145 | unsigned char p[256]; | ||
| 146 | unsigned char q[256]; | ||
| 147 | unsigned char dp[256]; | ||
| 148 | unsigned char dq[256]; | ||
| 149 | unsigned char u[256]; | ||
| 150 | unsigned char message[512]; | ||
| 151 | } __packed; | ||
| 152 | |||
| 153 | /** | ||
| 154 | * The type 80 response family is associated with a CEX2A card. | ||
| 155 | * | ||
| 156 | * Note that all unsigned char arrays are right-justified and left-padded | ||
| 157 | * with zeroes. | ||
| 158 | * | ||
| 159 | * Note that all reserved fields must be zeroes. | ||
| 160 | */ | ||
| 161 | |||
| 162 | #define TYPE80_RSP_CODE 0x80 | ||
| 163 | |||
| 164 | struct type80_hdr { | ||
| 165 | unsigned char reserved1; | ||
| 166 | unsigned char type; /* 0x80 */ | ||
| 167 | unsigned short len; | ||
| 168 | unsigned char code; /* 0x00 */ | ||
| 169 | unsigned char reserved2[3]; | ||
| 170 | unsigned char reserved3[8]; | ||
| 171 | } __packed; | ||
| 172 | |||
| 173 | /** | ||
| 174 | * Convert a ICAMEX message to a type50 MEX message. | ||
| 175 | * | ||
| 176 | * @zdev: crypto device pointer | ||
| 177 | * @zreq: crypto request pointer | ||
| 178 | * @mex: pointer to user input data | ||
| 179 | * | ||
| 180 | * Returns 0 on success or -EFAULT. | ||
| 181 | */ | ||
| 182 | static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_device *zdev, | ||
| 183 | struct ap_message *ap_msg, | ||
| 184 | struct ica_rsa_modexpo *mex) | ||
| 185 | { | ||
| 186 | unsigned char *mod, *exp, *inp; | ||
| 187 | int mod_len; | ||
| 188 | |||
| 189 | mod_len = mex->inputdatalength; | ||
| 190 | |||
| 191 | if (mod_len <= 128) { | ||
| 192 | struct type50_meb1_msg *meb1 = ap_msg->message; | ||
| 193 | memset(meb1, 0, sizeof(*meb1)); | ||
| 194 | ap_msg->length = sizeof(*meb1); | ||
| 195 | meb1->header.msg_type_code = TYPE50_TYPE_CODE; | ||
| 196 | meb1->header.msg_len = sizeof(*meb1); | ||
| 197 | meb1->keyblock_type = TYPE50_MEB1_FMT; | ||
| 198 | mod = meb1->modulus + sizeof(meb1->modulus) - mod_len; | ||
| 199 | exp = meb1->exponent + sizeof(meb1->exponent) - mod_len; | ||
| 200 | inp = meb1->message + sizeof(meb1->message) - mod_len; | ||
| 201 | } else if (mod_len <= 256) { | ||
| 202 | struct type50_meb2_msg *meb2 = ap_msg->message; | ||
| 203 | memset(meb2, 0, sizeof(*meb2)); | ||
| 204 | ap_msg->length = sizeof(*meb2); | ||
| 205 | meb2->header.msg_type_code = TYPE50_TYPE_CODE; | ||
| 206 | meb2->header.msg_len = sizeof(*meb2); | ||
| 207 | meb2->keyblock_type = TYPE50_MEB2_FMT; | ||
| 208 | mod = meb2->modulus + sizeof(meb2->modulus) - mod_len; | ||
| 209 | exp = meb2->exponent + sizeof(meb2->exponent) - mod_len; | ||
| 210 | inp = meb2->message + sizeof(meb2->message) - mod_len; | ||
| 211 | } else { | ||
| 212 | /* mod_len > 256 = 4096 bit RSA Key */ | ||
| 213 | struct type50_meb3_msg *meb3 = ap_msg->message; | ||
| 214 | memset(meb3, 0, sizeof(*meb3)); | ||
| 215 | ap_msg->length = sizeof(*meb3); | ||
| 216 | meb3->header.msg_type_code = TYPE50_TYPE_CODE; | ||
| 217 | meb3->header.msg_len = sizeof(*meb3); | ||
| 218 | meb3->keyblock_type = TYPE50_MEB3_FMT; | ||
| 219 | mod = meb3->modulus + sizeof(meb3->modulus) - mod_len; | ||
| 220 | exp = meb3->exponent + sizeof(meb3->exponent) - mod_len; | ||
| 221 | inp = meb3->message + sizeof(meb3->message) - mod_len; | ||
| 222 | } | ||
| 223 | |||
| 224 | if (copy_from_user(mod, mex->n_modulus, mod_len) || | ||
| 225 | copy_from_user(exp, mex->b_key, mod_len) || | ||
| 226 | copy_from_user(inp, mex->inputdata, mod_len)) | ||
| 227 | return -EFAULT; | ||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | /** | ||
| 232 | * Convert a ICACRT message to a type50 CRT message. | ||
| 233 | * | ||
| 234 | * @zdev: crypto device pointer | ||
| 235 | * @zreq: crypto request pointer | ||
| 236 | * @crt: pointer to user input data | ||
| 237 | * | ||
| 238 | * Returns 0 on success or -EFAULT. | ||
| 239 | */ | ||
| 240 | static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_device *zdev, | ||
| 241 | struct ap_message *ap_msg, | ||
| 242 | struct ica_rsa_modexpo_crt *crt) | ||
| 243 | { | ||
| 244 | int mod_len, short_len; | ||
| 245 | unsigned char *p, *q, *dp, *dq, *u, *inp; | ||
| 246 | |||
| 247 | mod_len = crt->inputdatalength; | ||
| 248 | short_len = mod_len / 2; | ||
| 249 | |||
| 250 | /* | ||
| 251 | * CEX2A and CEX3A w/o FW update can handle requests up to | ||
| 252 | * 256 byte modulus (2k keys). | ||
| 253 | * CEX3A with FW update and CEX4A cards are able to handle | ||
| 254 | * 512 byte modulus (4k keys). | ||
| 255 | */ | ||
| 256 | if (mod_len <= 128) { /* up to 1024 bit key size */ | ||
| 257 | struct type50_crb1_msg *crb1 = ap_msg->message; | ||
| 258 | memset(crb1, 0, sizeof(*crb1)); | ||
| 259 | ap_msg->length = sizeof(*crb1); | ||
| 260 | crb1->header.msg_type_code = TYPE50_TYPE_CODE; | ||
| 261 | crb1->header.msg_len = sizeof(*crb1); | ||
| 262 | crb1->keyblock_type = TYPE50_CRB1_FMT; | ||
| 263 | p = crb1->p + sizeof(crb1->p) - short_len; | ||
| 264 | q = crb1->q + sizeof(crb1->q) - short_len; | ||
| 265 | dp = crb1->dp + sizeof(crb1->dp) - short_len; | ||
| 266 | dq = crb1->dq + sizeof(crb1->dq) - short_len; | ||
| 267 | u = crb1->u + sizeof(crb1->u) - short_len; | ||
| 268 | inp = crb1->message + sizeof(crb1->message) - mod_len; | ||
| 269 | } else if (mod_len <= 256) { /* up to 2048 bit key size */ | ||
| 270 | struct type50_crb2_msg *crb2 = ap_msg->message; | ||
| 271 | memset(crb2, 0, sizeof(*crb2)); | ||
| 272 | ap_msg->length = sizeof(*crb2); | ||
| 273 | crb2->header.msg_type_code = TYPE50_TYPE_CODE; | ||
| 274 | crb2->header.msg_len = sizeof(*crb2); | ||
| 275 | crb2->keyblock_type = TYPE50_CRB2_FMT; | ||
| 276 | p = crb2->p + sizeof(crb2->p) - short_len; | ||
| 277 | q = crb2->q + sizeof(crb2->q) - short_len; | ||
| 278 | dp = crb2->dp + sizeof(crb2->dp) - short_len; | ||
| 279 | dq = crb2->dq + sizeof(crb2->dq) - short_len; | ||
| 280 | u = crb2->u + sizeof(crb2->u) - short_len; | ||
| 281 | inp = crb2->message + sizeof(crb2->message) - mod_len; | ||
| 282 | } else if ((mod_len <= 512) && /* up to 4096 bit key size */ | ||
| 283 | (zdev->max_mod_size == CEX3A_MAX_MOD_SIZE)) { /* >= CEX3A */ | ||
| 284 | struct type50_crb3_msg *crb3 = ap_msg->message; | ||
| 285 | memset(crb3, 0, sizeof(*crb3)); | ||
| 286 | ap_msg->length = sizeof(*crb3); | ||
| 287 | crb3->header.msg_type_code = TYPE50_TYPE_CODE; | ||
| 288 | crb3->header.msg_len = sizeof(*crb3); | ||
| 289 | crb3->keyblock_type = TYPE50_CRB3_FMT; | ||
| 290 | p = crb3->p + sizeof(crb3->p) - short_len; | ||
| 291 | q = crb3->q + sizeof(crb3->q) - short_len; | ||
| 292 | dp = crb3->dp + sizeof(crb3->dp) - short_len; | ||
| 293 | dq = crb3->dq + sizeof(crb3->dq) - short_len; | ||
| 294 | u = crb3->u + sizeof(crb3->u) - short_len; | ||
| 295 | inp = crb3->message + sizeof(crb3->message) - mod_len; | ||
| 296 | } else | ||
| 297 | return -EINVAL; | ||
| 298 | |||
| 299 | /* | ||
| 300 | * correct the offset of p, bp and mult_inv according zcrypt.h | ||
| 301 | * block size right aligned (skip the first byte) | ||
| 302 | */ | ||
| 303 | if (copy_from_user(p, crt->np_prime + MSGTYPE_ADJUSTMENT, short_len) || | ||
| 304 | copy_from_user(q, crt->nq_prime, short_len) || | ||
| 305 | copy_from_user(dp, crt->bp_key + MSGTYPE_ADJUSTMENT, short_len) || | ||
| 306 | copy_from_user(dq, crt->bq_key, short_len) || | ||
| 307 | copy_from_user(u, crt->u_mult_inv + MSGTYPE_ADJUSTMENT, short_len) || | ||
| 308 | copy_from_user(inp, crt->inputdata, mod_len)) | ||
| 309 | return -EFAULT; | ||
| 310 | |||
| 311 | return 0; | ||
| 312 | } | ||
| 313 | |||
| 314 | /** | ||
| 315 | * Copy results from a type 80 reply message back to user space. | ||
| 316 | * | ||
| 317 | * @zdev: crypto device pointer | ||
| 318 | * @reply: reply AP message. | ||
| 319 | * @data: pointer to user output data | ||
| 320 | * @length: size of user output data | ||
| 321 | * | ||
| 322 | * Returns 0 on success or -EFAULT. | ||
| 323 | */ | ||
| 324 | static int convert_type80(struct zcrypt_device *zdev, | ||
| 325 | struct ap_message *reply, | ||
| 326 | char __user *outputdata, | ||
| 327 | unsigned int outputdatalength) | ||
| 328 | { | ||
| 329 | struct type80_hdr *t80h = reply->message; | ||
| 330 | unsigned char *data; | ||
| 331 | |||
| 332 | if (t80h->len < sizeof(*t80h) + outputdatalength) { | ||
| 333 | /* The result is too short, the CEX2A card may not do that.. */ | ||
| 334 | zdev->online = 0; | ||
| 335 | return -EAGAIN; /* repeat the request on a different device. */ | ||
| 336 | } | ||
| 337 | if (zdev->user_space_type == ZCRYPT_CEX2A) | ||
| 338 | BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE); | ||
| 339 | else | ||
| 340 | BUG_ON(t80h->len > CEX3A_MAX_RESPONSE_SIZE); | ||
| 341 | data = reply->message + t80h->len - outputdatalength; | ||
| 342 | if (copy_to_user(outputdata, data, outputdatalength)) | ||
| 343 | return -EFAULT; | ||
| 344 | return 0; | ||
| 345 | } | ||
| 346 | |||
| 347 | static int convert_response(struct zcrypt_device *zdev, | ||
| 348 | struct ap_message *reply, | ||
| 349 | char __user *outputdata, | ||
| 350 | unsigned int outputdatalength) | ||
| 351 | { | ||
| 352 | /* Response type byte is the second byte in the response. */ | ||
| 353 | switch (((unsigned char *) reply->message)[1]) { | ||
| 354 | case TYPE82_RSP_CODE: | ||
| 355 | case TYPE88_RSP_CODE: | ||
| 356 | return convert_error(zdev, reply); | ||
| 357 | case TYPE80_RSP_CODE: | ||
| 358 | return convert_type80(zdev, reply, | ||
| 359 | outputdata, outputdatalength); | ||
| 360 | default: /* Unknown response type, this should NEVER EVER happen */ | ||
| 361 | zdev->online = 0; | ||
| 362 | return -EAGAIN; /* repeat the request on a different device. */ | ||
| 363 | } | ||
| 364 | } | ||
| 365 | |||
| 366 | /** | ||
| 367 | * This function is called from the AP bus code after a crypto request | ||
| 368 | * "msg" has finished with the reply message "reply". | ||
| 369 | * It is called from tasklet context. | ||
| 370 | * @ap_dev: pointer to the AP device | ||
| 371 | * @msg: pointer to the AP message | ||
| 372 | * @reply: pointer to the AP reply message | ||
| 373 | */ | ||
| 374 | static void zcrypt_cex2a_receive(struct ap_device *ap_dev, | ||
| 375 | struct ap_message *msg, | ||
| 376 | struct ap_message *reply) | ||
| 377 | { | ||
| 378 | static struct error_hdr error_reply = { | ||
| 379 | .type = TYPE82_RSP_CODE, | ||
| 380 | .reply_code = REP82_ERROR_MACHINE_FAILURE, | ||
| 381 | }; | ||
| 382 | struct type80_hdr *t80h; | ||
| 383 | int length; | ||
| 384 | |||
| 385 | /* Copy the reply message to the request message buffer. */ | ||
| 386 | if (IS_ERR(reply)) { | ||
| 387 | memcpy(msg->message, &error_reply, sizeof(error_reply)); | ||
| 388 | goto out; | ||
| 389 | } | ||
| 390 | t80h = reply->message; | ||
| 391 | if (t80h->type == TYPE80_RSP_CODE) { | ||
| 392 | if (ap_dev->device_type == AP_DEVICE_TYPE_CEX2A) | ||
| 393 | length = min_t(int, | ||
| 394 | CEX2A_MAX_RESPONSE_SIZE, t80h->len); | ||
| 395 | else | ||
| 396 | length = min_t(int, | ||
| 397 | CEX3A_MAX_RESPONSE_SIZE, t80h->len); | ||
| 398 | memcpy(msg->message, reply->message, length); | ||
| 399 | } else | ||
| 400 | memcpy(msg->message, reply->message, sizeof(error_reply)); | ||
| 401 | out: | ||
| 402 | complete((struct completion *) msg->private); | ||
| 403 | } | ||
| 404 | |||
| 405 | static atomic_t zcrypt_step = ATOMIC_INIT(0); | ||
| 406 | |||
| 407 | /** | ||
| 408 | * The request distributor calls this function if it picked the CEX2A | ||
| 409 | * device to handle a modexpo request. | ||
| 410 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
| 411 | * CEX2A device to the request distributor | ||
| 412 | * @mex: pointer to the modexpo request buffer | ||
| 413 | */ | ||
| 414 | static long zcrypt_cex2a_modexpo(struct zcrypt_device *zdev, | ||
| 415 | struct ica_rsa_modexpo *mex) | ||
| 416 | { | ||
| 417 | struct ap_message ap_msg; | ||
| 418 | struct completion work; | ||
| 419 | int rc; | ||
| 420 | |||
| 421 | ap_init_message(&ap_msg); | ||
| 422 | if (zdev->user_space_type == ZCRYPT_CEX2A) | ||
| 423 | ap_msg.message = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, | ||
| 424 | GFP_KERNEL); | ||
| 425 | else | ||
| 426 | ap_msg.message = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, | ||
| 427 | GFP_KERNEL); | ||
| 428 | if (!ap_msg.message) | ||
| 429 | return -ENOMEM; | ||
| 430 | ap_msg.receive = zcrypt_cex2a_receive; | ||
| 431 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
| 432 | atomic_inc_return(&zcrypt_step); | ||
| 433 | ap_msg.private = &work; | ||
| 434 | rc = ICAMEX_msg_to_type50MEX_msg(zdev, &ap_msg, mex); | ||
| 435 | if (rc) | ||
| 436 | goto out_free; | ||
| 437 | init_completion(&work); | ||
| 438 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
| 439 | rc = wait_for_completion_interruptible(&work); | ||
| 440 | if (rc == 0) | ||
| 441 | rc = convert_response(zdev, &ap_msg, mex->outputdata, | ||
| 442 | mex->outputdatalength); | ||
| 443 | else | ||
| 444 | /* Signal pending. */ | ||
| 445 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
| 446 | out_free: | ||
| 447 | kfree(ap_msg.message); | ||
| 448 | return rc; | ||
| 449 | } | ||
| 450 | |||
| 451 | /** | ||
| 452 | * The request distributor calls this function if it picked the CEX2A | ||
| 453 | * device to handle a modexpo_crt request. | ||
| 454 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
| 455 | * CEX2A device to the request distributor | ||
| 456 | * @crt: pointer to the modexpoc_crt request buffer | ||
| 457 | */ | ||
| 458 | static long zcrypt_cex2a_modexpo_crt(struct zcrypt_device *zdev, | ||
| 459 | struct ica_rsa_modexpo_crt *crt) | ||
| 460 | { | ||
| 461 | struct ap_message ap_msg; | ||
| 462 | struct completion work; | ||
| 463 | int rc; | ||
| 464 | |||
| 465 | ap_init_message(&ap_msg); | ||
| 466 | if (zdev->user_space_type == ZCRYPT_CEX2A) | ||
| 467 | ap_msg.message = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, | ||
| 468 | GFP_KERNEL); | ||
| 469 | else | ||
| 470 | ap_msg.message = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, | ||
| 471 | GFP_KERNEL); | ||
| 472 | if (!ap_msg.message) | ||
| 473 | return -ENOMEM; | ||
| 474 | ap_msg.receive = zcrypt_cex2a_receive; | ||
| 475 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
| 476 | atomic_inc_return(&zcrypt_step); | ||
| 477 | ap_msg.private = &work; | ||
| 478 | rc = ICACRT_msg_to_type50CRT_msg(zdev, &ap_msg, crt); | ||
| 479 | if (rc) | ||
| 480 | goto out_free; | ||
| 481 | init_completion(&work); | ||
| 482 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
| 483 | rc = wait_for_completion_interruptible(&work); | ||
| 484 | if (rc == 0) | ||
| 485 | rc = convert_response(zdev, &ap_msg, crt->outputdata, | ||
| 486 | crt->outputdatalength); | ||
| 487 | else | ||
| 488 | /* Signal pending. */ | ||
| 489 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
| 490 | out_free: | ||
| 491 | kfree(ap_msg.message); | ||
| 492 | return rc; | ||
| 493 | } | ||
| 494 | |||
| 495 | /** | ||
| 496 | * The crypto operations for message type 50. | ||
| 497 | */ | ||
| 498 | static struct zcrypt_ops zcrypt_msgtype50_ops = { | ||
| 499 | .rsa_modexpo = zcrypt_cex2a_modexpo, | ||
| 500 | .rsa_modexpo_crt = zcrypt_cex2a_modexpo_crt, | ||
| 501 | .owner = THIS_MODULE, | ||
| 502 | .variant = MSGTYPE50_VARIANT_DEFAULT, | ||
| 503 | }; | ||
| 504 | |||
| 505 | int __init zcrypt_msgtype50_init(void) | ||
| 506 | { | ||
| 507 | zcrypt_msgtype_register(&zcrypt_msgtype50_ops); | ||
| 508 | return 0; | ||
| 509 | } | ||
| 510 | |||
| 511 | void __exit zcrypt_msgtype50_exit(void) | ||
| 512 | { | ||
| 513 | zcrypt_msgtype_unregister(&zcrypt_msgtype50_ops); | ||
| 514 | } | ||
| 515 | |||
| 516 | module_init(zcrypt_msgtype50_init); | ||
| 517 | module_exit(zcrypt_msgtype50_exit); | ||
diff --git a/drivers/s390/crypto/zcrypt_msgtype50.h b/drivers/s390/crypto/zcrypt_msgtype50.h deleted file mode 100644 index 0a66e4aeeb5..00000000000 --- a/drivers/s390/crypto/zcrypt_msgtype50.h +++ /dev/null | |||
| @@ -1,41 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * zcrypt 2.1.0 | ||
| 3 | * | ||
| 4 | * Copyright IBM Corp. 2001, 2012 | ||
| 5 | * Author(s): Robert Burroughs | ||
| 6 | * Eric Rossman (edrossma@us.ibm.com) | ||
| 7 | * | ||
| 8 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) | ||
| 9 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
| 10 | * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU General Public License as published by | ||
| 14 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 15 | * any later version. | ||
| 16 | * | ||
| 17 | * This program is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU General Public License for more details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License | ||
| 23 | * along with this program; if not, write to the Free Software | ||
| 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 25 | */ | ||
| 26 | |||
| 27 | #ifndef _ZCRYPT_MSGTYPE50_H_ | ||
| 28 | #define _ZCRYPT_MSGTYPE50_H_ | ||
| 29 | |||
| 30 | #define MSGTYPE50_NAME "zcrypt_msgtype50" | ||
| 31 | #define MSGTYPE50_VARIANT_DEFAULT 0 | ||
| 32 | |||
| 33 | #define MSGTYPE50_CRB2_MAX_MSG_SIZE 0x390 /*sizeof(struct type50_crb2_msg)*/ | ||
| 34 | #define MSGTYPE50_CRB3_MAX_MSG_SIZE 0x710 /*sizeof(struct type50_crb3_msg)*/ | ||
| 35 | |||
| 36 | #define MSGTYPE_ADJUSTMENT 0x08 /*type04 extension (not needed in type50)*/ | ||
| 37 | |||
| 38 | int zcrypt_msgtype50_init(void); | ||
| 39 | void zcrypt_msgtype50_exit(void); | ||
| 40 | |||
| 41 | #endif /* _ZCRYPT_MSGTYPE50_H_ */ | ||
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c deleted file mode 100644 index 7d97fa5a26d..00000000000 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ /dev/null | |||
| @@ -1,856 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * zcrypt 2.1.0 | ||
| 3 | * | ||
| 4 | * Copyright IBM Corp. 2001, 2012 | ||
| 5 | * Author(s): Robert Burroughs | ||
| 6 | * Eric Rossman (edrossma@us.ibm.com) | ||
| 7 | * | ||
| 8 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) | ||
| 9 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
| 10 | * Ralph Wuerthner <rwuerthn@de.ibm.com> | ||
| 11 | * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.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 | #include <linux/module.h> | ||
| 29 | #include <linux/init.h> | ||
| 30 | #include <linux/err.h> | ||
| 31 | #include <linux/delay.h> | ||
| 32 | #include <linux/slab.h> | ||
| 33 | #include <linux/atomic.h> | ||
| 34 | #include <linux/uaccess.h> | ||
| 35 | |||
| 36 | #include "ap_bus.h" | ||
| 37 | #include "zcrypt_api.h" | ||
| 38 | #include "zcrypt_error.h" | ||
| 39 | #include "zcrypt_msgtype6.h" | ||
| 40 | #include "zcrypt_cca_key.h" | ||
| 41 | |||
| 42 | #define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */ | ||
| 43 | #define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */ | ||
| 44 | |||
| 45 | #define CEIL4(x) ((((x)+3)/4)*4) | ||
| 46 | |||
| 47 | struct response_type { | ||
| 48 | struct completion work; | ||
| 49 | int type; | ||
| 50 | }; | ||
| 51 | #define PCIXCC_RESPONSE_TYPE_ICA 0 | ||
| 52 | #define PCIXCC_RESPONSE_TYPE_XCRB 1 | ||
| 53 | |||
| 54 | MODULE_AUTHOR("IBM Corporation"); | ||
| 55 | MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \ | ||
| 56 | "Copyright IBM Corp. 2001, 2012"); | ||
| 57 | MODULE_LICENSE("GPL"); | ||
| 58 | |||
| 59 | static void zcrypt_msgtype6_receive(struct ap_device *, struct ap_message *, | ||
| 60 | struct ap_message *); | ||
| 61 | |||
| 62 | /** | ||
| 63 | * CPRB | ||
| 64 | * Note that all shorts, ints and longs are little-endian. | ||
| 65 | * All pointer fields are 32-bits long, and mean nothing | ||
| 66 | * | ||
| 67 | * A request CPRB is followed by a request_parameter_block. | ||
| 68 | * | ||
| 69 | * The request (or reply) parameter block is organized thus: | ||
| 70 | * function code | ||
| 71 | * VUD block | ||
| 72 | * key block | ||
| 73 | */ | ||
| 74 | struct CPRB { | ||
| 75 | unsigned short cprb_len; /* CPRB length */ | ||
| 76 | unsigned char cprb_ver_id; /* CPRB version id. */ | ||
| 77 | unsigned char pad_000; /* Alignment pad byte. */ | ||
| 78 | unsigned char srpi_rtcode[4]; /* SRPI return code LELONG */ | ||
| 79 | unsigned char srpi_verb; /* SRPI verb type */ | ||
| 80 | unsigned char flags; /* flags */ | ||
| 81 | unsigned char func_id[2]; /* function id */ | ||
| 82 | unsigned char checkpoint_flag; /* */ | ||
| 83 | unsigned char resv2; /* reserved */ | ||
| 84 | unsigned short req_parml; /* request parameter buffer */ | ||
| 85 | /* length 16-bit little endian */ | ||
| 86 | unsigned char req_parmp[4]; /* request parameter buffer * | ||
| 87 | * pointer (means nothing: the * | ||
| 88 | * parameter buffer follows * | ||
| 89 | * the CPRB). */ | ||
| 90 | unsigned char req_datal[4]; /* request data buffer */ | ||
| 91 | /* length ULELONG */ | ||
| 92 | unsigned char req_datap[4]; /* request data buffer */ | ||
| 93 | /* pointer */ | ||
| 94 | unsigned short rpl_parml; /* reply parameter buffer */ | ||
| 95 | /* length 16-bit little endian */ | ||
| 96 | unsigned char pad_001[2]; /* Alignment pad bytes. ULESHORT */ | ||
| 97 | unsigned char rpl_parmp[4]; /* reply parameter buffer * | ||
| 98 | * pointer (means nothing: the * | ||
| 99 | * parameter buffer follows * | ||
| 100 | * the CPRB). */ | ||
| 101 | unsigned char rpl_datal[4]; /* reply data buffer len ULELONG */ | ||
| 102 | unsigned char rpl_datap[4]; /* reply data buffer */ | ||
| 103 | /* pointer */ | ||
| 104 | unsigned short ccp_rscode; /* server reason code ULESHORT */ | ||
| 105 | unsigned short ccp_rtcode; /* server return code ULESHORT */ | ||
| 106 | unsigned char repd_parml[2]; /* replied parameter len ULESHORT*/ | ||
| 107 | unsigned char mac_data_len[2]; /* Mac Data Length ULESHORT */ | ||
| 108 | unsigned char repd_datal[4]; /* replied data length ULELONG */ | ||
| 109 | unsigned char req_pc[2]; /* PC identifier */ | ||
| 110 | unsigned char res_origin[8]; /* resource origin */ | ||
| 111 | unsigned char mac_value[8]; /* Mac Value */ | ||
| 112 | unsigned char logon_id[8]; /* Logon Identifier */ | ||
| 113 | unsigned char usage_domain[2]; /* cdx */ | ||
| 114 | unsigned char resv3[18]; /* reserved for requestor */ | ||
| 115 | unsigned short svr_namel; /* server name length ULESHORT */ | ||
| 116 | unsigned char svr_name[8]; /* server name */ | ||
| 117 | } __packed; | ||
| 118 | |||
| 119 | struct function_and_rules_block { | ||
| 120 | unsigned char function_code[2]; | ||
| 121 | unsigned short ulen; | ||
| 122 | unsigned char only_rule[8]; | ||
| 123 | } __packed; | ||
| 124 | |||
| 125 | /** | ||
| 126 | * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C | ||
| 127 | * card in a type6 message. The 3 fields that must be filled in at execution | ||
| 128 | * time are req_parml, rpl_parml and usage_domain. | ||
| 129 | * Everything about this interface is ascii/big-endian, since the | ||
| 130 | * device does *not* have 'Intel inside'. | ||
| 131 | * | ||
| 132 | * The CPRBX is followed immediately by the parm block. | ||
| 133 | * The parm block contains: | ||
| 134 | * - function code ('PD' 0x5044 or 'PK' 0x504B) | ||
| 135 | * - rule block (one of:) | ||
| 136 | * + 0x000A 'PKCS-1.2' (MCL2 'PD') | ||
| 137 | * + 0x000A 'ZERO-PAD' (MCL2 'PK') | ||
| 138 | * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD') | ||
| 139 | * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK') | ||
| 140 | * - VUD block | ||
| 141 | */ | ||
| 142 | static struct CPRBX static_cprbx = { | ||
| 143 | .cprb_len = 0x00DC, | ||
| 144 | .cprb_ver_id = 0x02, | ||
| 145 | .func_id = {0x54, 0x32}, | ||
| 146 | }; | ||
| 147 | |||
| 148 | /** | ||
| 149 | * Convert a ICAMEX message to a type6 MEX message. | ||
| 150 | * | ||
| 151 | * @zdev: crypto device pointer | ||
| 152 | * @ap_msg: pointer to AP message | ||
| 153 | * @mex: pointer to user input data | ||
| 154 | * | ||
| 155 | * Returns 0 on success or -EFAULT. | ||
| 156 | */ | ||
| 157 | static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev, | ||
| 158 | struct ap_message *ap_msg, | ||
| 159 | struct ica_rsa_modexpo *mex) | ||
| 160 | { | ||
| 161 | static struct type6_hdr static_type6_hdrX = { | ||
| 162 | .type = 0x06, | ||
| 163 | .offset1 = 0x00000058, | ||
| 164 | .agent_id = {'C', 'A',}, | ||
| 165 | .function_code = {'P', 'K'}, | ||
| 166 | }; | ||
| 167 | static struct function_and_rules_block static_pke_fnr = { | ||
| 168 | .function_code = {'P', 'K'}, | ||
| 169 | .ulen = 10, | ||
| 170 | .only_rule = {'M', 'R', 'P', ' ', ' ', ' ', ' ', ' '} | ||
| 171 | }; | ||
| 172 | static struct function_and_rules_block static_pke_fnr_MCL2 = { | ||
| 173 | .function_code = {'P', 'K'}, | ||
| 174 | .ulen = 10, | ||
| 175 | .only_rule = {'Z', 'E', 'R', 'O', '-', 'P', 'A', 'D'} | ||
| 176 | }; | ||
| 177 | struct { | ||
| 178 | struct type6_hdr hdr; | ||
| 179 | struct CPRBX cprbx; | ||
| 180 | struct function_and_rules_block fr; | ||
| 181 | unsigned short length; | ||
| 182 | char text[0]; | ||
| 183 | } __packed * msg = ap_msg->message; | ||
| 184 | int size; | ||
| 185 | |||
| 186 | /* VUD.ciphertext */ | ||
| 187 | msg->length = mex->inputdatalength + 2; | ||
| 188 | if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength)) | ||
| 189 | return -EFAULT; | ||
| 190 | |||
| 191 | /* Set up key which is located after the variable length text. */ | ||
| 192 | size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1); | ||
| 193 | if (size < 0) | ||
| 194 | return size; | ||
| 195 | size += sizeof(*msg) + mex->inputdatalength; | ||
| 196 | |||
| 197 | /* message header, cprbx and f&r */ | ||
| 198 | msg->hdr = static_type6_hdrX; | ||
| 199 | msg->hdr.ToCardLen1 = size - sizeof(msg->hdr); | ||
| 200 | msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr); | ||
| 201 | |||
| 202 | msg->cprbx = static_cprbx; | ||
| 203 | msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid); | ||
| 204 | msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1; | ||
| 205 | |||
| 206 | msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ? | ||
| 207 | static_pke_fnr_MCL2 : static_pke_fnr; | ||
| 208 | |||
| 209 | msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx); | ||
| 210 | |||
| 211 | ap_msg->length = size; | ||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | |||
| 215 | /** | ||
| 216 | * Convert a ICACRT message to a type6 CRT message. | ||
| 217 | * | ||
| 218 | * @zdev: crypto device pointer | ||
| 219 | * @ap_msg: pointer to AP message | ||
| 220 | * @crt: pointer to user input data | ||
| 221 | * | ||
| 222 | * Returns 0 on success or -EFAULT. | ||
| 223 | */ | ||
| 224 | static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev, | ||
| 225 | struct ap_message *ap_msg, | ||
| 226 | struct ica_rsa_modexpo_crt *crt) | ||
| 227 | { | ||
| 228 | static struct type6_hdr static_type6_hdrX = { | ||
| 229 | .type = 0x06, | ||
| 230 | .offset1 = 0x00000058, | ||
| 231 | .agent_id = {'C', 'A',}, | ||
| 232 | .function_code = {'P', 'D'}, | ||
| 233 | }; | ||
| 234 | static struct function_and_rules_block static_pkd_fnr = { | ||
| 235 | .function_code = {'P', 'D'}, | ||
| 236 | .ulen = 10, | ||
| 237 | .only_rule = {'Z', 'E', 'R', 'O', '-', 'P', 'A', 'D'} | ||
| 238 | }; | ||
| 239 | |||
| 240 | static struct function_and_rules_block static_pkd_fnr_MCL2 = { | ||
| 241 | .function_code = {'P', 'D'}, | ||
| 242 | .ulen = 10, | ||
| 243 | .only_rule = {'P', 'K', 'C', 'S', '-', '1', '.', '2'} | ||
| 244 | }; | ||
| 245 | struct { | ||
| 246 | struct type6_hdr hdr; | ||
| 247 | struct CPRBX cprbx; | ||
| 248 | struct function_and_rules_block fr; | ||
| 249 | unsigned short length; | ||
| 250 | char text[0]; | ||
| 251 | } __packed * msg = ap_msg->message; | ||
| 252 | int size; | ||
| 253 | |||
| 254 | /* VUD.ciphertext */ | ||
| 255 | msg->length = crt->inputdatalength + 2; | ||
| 256 | if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength)) | ||
| 257 | return -EFAULT; | ||
| 258 | |||
| 259 | /* Set up key which is located after the variable length text. */ | ||
| 260 | size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1); | ||
| 261 | if (size < 0) | ||
| 262 | return size; | ||
| 263 | size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */ | ||
| 264 | |||
| 265 | /* message header, cprbx and f&r */ | ||
| 266 | msg->hdr = static_type6_hdrX; | ||
| 267 | msg->hdr.ToCardLen1 = size - sizeof(msg->hdr); | ||
| 268 | msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr); | ||
| 269 | |||
| 270 | msg->cprbx = static_cprbx; | ||
| 271 | msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid); | ||
| 272 | msg->cprbx.req_parml = msg->cprbx.rpl_msgbl = | ||
| 273 | size - sizeof(msg->hdr) - sizeof(msg->cprbx); | ||
| 274 | |||
| 275 | msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ? | ||
| 276 | static_pkd_fnr_MCL2 : static_pkd_fnr; | ||
| 277 | |||
| 278 | ap_msg->length = size; | ||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | /** | ||
| 283 | * Convert a XCRB message to a type6 CPRB message. | ||
| 284 | * | ||
| 285 | * @zdev: crypto device pointer | ||
| 286 | * @ap_msg: pointer to AP message | ||
| 287 | * @xcRB: pointer to user input data | ||
| 288 | * | ||
| 289 | * Returns 0 on success or -EFAULT, -EINVAL. | ||
| 290 | */ | ||
| 291 | struct type86_fmt2_msg { | ||
| 292 | struct type86_hdr hdr; | ||
| 293 | struct type86_fmt2_ext fmt2; | ||
| 294 | } __packed; | ||
| 295 | |||
| 296 | static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, | ||
| 297 | struct ap_message *ap_msg, | ||
| 298 | struct ica_xcRB *xcRB) | ||
| 299 | { | ||
| 300 | static struct type6_hdr static_type6_hdrX = { | ||
| 301 | .type = 0x06, | ||
| 302 | .offset1 = 0x00000058, | ||
| 303 | }; | ||
| 304 | struct { | ||
| 305 | struct type6_hdr hdr; | ||
| 306 | struct CPRBX cprbx; | ||
| 307 | } __packed * msg = ap_msg->message; | ||
| 308 | |||
| 309 | int rcblen = CEIL4(xcRB->request_control_blk_length); | ||
| 310 | int replylen; | ||
| 311 | char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen; | ||
| 312 | char *function_code; | ||
| 313 | |||
| 314 | /* length checks */ | ||
| 315 | ap_msg->length = sizeof(struct type6_hdr) + | ||
| 316 | CEIL4(xcRB->request_control_blk_length) + | ||
| 317 | xcRB->request_data_length; | ||
| 318 | if (ap_msg->length > MSGTYPE06_MAX_MSG_SIZE) | ||
| 319 | return -EINVAL; | ||
| 320 | replylen = sizeof(struct type86_fmt2_msg) + | ||
| 321 | CEIL4(xcRB->reply_control_blk_length) + | ||
| 322 | xcRB->reply_data_length; | ||
| 323 | if (replylen > MSGTYPE06_MAX_MSG_SIZE) | ||
| 324 | return -EINVAL; | ||
| 325 | |||
| 326 | /* prepare type6 header */ | ||
| 327 | msg->hdr = static_type6_hdrX; | ||
| 328 | memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID)); | ||
| 329 | msg->hdr.ToCardLen1 = xcRB->request_control_blk_length; | ||
| 330 | if (xcRB->request_data_length) { | ||
| 331 | msg->hdr.offset2 = msg->hdr.offset1 + rcblen; | ||
| 332 | msg->hdr.ToCardLen2 = xcRB->request_data_length; | ||
| 333 | } | ||
| 334 | msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length; | ||
| 335 | msg->hdr.FromCardLen2 = xcRB->reply_data_length; | ||
| 336 | |||
| 337 | /* prepare CPRB */ | ||
| 338 | if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr, | ||
| 339 | xcRB->request_control_blk_length)) | ||
| 340 | return -EFAULT; | ||
| 341 | if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) > | ||
| 342 | xcRB->request_control_blk_length) | ||
| 343 | return -EINVAL; | ||
| 344 | function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len; | ||
| 345 | memcpy(msg->hdr.function_code, function_code, | ||
| 346 | sizeof(msg->hdr.function_code)); | ||
| 347 | |||
| 348 | if (memcmp(function_code, "US", 2) == 0) | ||
| 349 | ap_msg->special = 1; | ||
| 350 | else | ||
| 351 | ap_msg->special = 0; | ||
| 352 | |||
| 353 | /* copy data block */ | ||
| 354 | if (xcRB->request_data_length && | ||
| 355 | copy_from_user(req_data, xcRB->request_data_address, | ||
| 356 | xcRB->request_data_length)) | ||
| 357 | return -EFAULT; | ||
| 358 | return 0; | ||
| 359 | } | ||
| 360 | |||
| 361 | /** | ||
| 362 | * Copy results from a type 86 ICA reply message back to user space. | ||
| 363 | * | ||
| 364 | * @zdev: crypto device pointer | ||
| 365 | * @reply: reply AP message. | ||
| 366 | * @data: pointer to user output data | ||
| 367 | * @length: size of user output data | ||
| 368 | * | ||
| 369 | * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error. | ||
| 370 | */ | ||
| 371 | struct type86x_reply { | ||
| 372 | struct type86_hdr hdr; | ||
| 373 | struct type86_fmt2_ext fmt2; | ||
| 374 | struct CPRBX cprbx; | ||
| 375 | unsigned char pad[4]; /* 4 byte function code/rules block ? */ | ||
| 376 | unsigned short length; | ||
| 377 | char text[0]; | ||
| 378 | } __packed; | ||
| 379 | |||
| 380 | static int convert_type86_ica(struct zcrypt_device *zdev, | ||
| 381 | struct ap_message *reply, | ||
| 382 | char __user *outputdata, | ||
| 383 | unsigned int outputdatalength) | ||
| 384 | { | ||
| 385 | static unsigned char static_pad[] = { | ||
| 386 | 0x00, 0x02, | ||
| 387 | 0x1B, 0x7B, 0x5D, 0xB5, 0x75, 0x01, 0x3D, 0xFD, | ||
| 388 | 0x8D, 0xD1, 0xC7, 0x03, 0x2D, 0x09, 0x23, 0x57, | ||
| 389 | 0x89, 0x49, 0xB9, 0x3F, 0xBB, 0x99, 0x41, 0x5B, | ||
| 390 | 0x75, 0x21, 0x7B, 0x9D, 0x3B, 0x6B, 0x51, 0x39, | ||
| 391 | 0xBB, 0x0D, 0x35, 0xB9, 0x89, 0x0F, 0x93, 0xA5, | ||
| 392 | 0x0B, 0x47, 0xF1, 0xD3, 0xBB, 0xCB, 0xF1, 0x9D, | ||
| 393 | 0x23, 0x73, 0x71, 0xFF, 0xF3, 0xF5, 0x45, 0xFB, | ||
| 394 | 0x61, 0x29, 0x23, 0xFD, 0xF1, 0x29, 0x3F, 0x7F, | ||
| 395 | 0x17, 0xB7, 0x1B, 0xA9, 0x19, 0xBD, 0x57, 0xA9, | ||
| 396 | 0xD7, 0x95, 0xA3, 0xCB, 0xED, 0x1D, 0xDB, 0x45, | ||
| 397 | 0x7D, 0x11, 0xD1, 0x51, 0x1B, 0xED, 0x71, 0xE9, | ||
| 398 | 0xB1, 0xD1, 0xAB, 0xAB, 0x21, 0x2B, 0x1B, 0x9F, | ||
| 399 | 0x3B, 0x9F, 0xF7, 0xF7, 0xBD, 0x63, 0xEB, 0xAD, | ||
| 400 | 0xDF, 0xB3, 0x6F, 0x5B, 0xDB, 0x8D, 0xA9, 0x5D, | ||
| 401 | 0xE3, 0x7D, 0x77, 0x49, 0x47, 0xF5, 0xA7, 0xFD, | ||
| 402 | 0xAB, 0x2F, 0x27, 0x35, 0x77, 0xD3, 0x49, 0xC9, | ||
| 403 | 0x09, 0xEB, 0xB1, 0xF9, 0xBF, 0x4B, 0xCB, 0x2B, | ||
| 404 | 0xEB, 0xEB, 0x05, 0xFF, 0x7D, 0xC7, 0x91, 0x8B, | ||
| 405 | 0x09, 0x83, 0xB9, 0xB9, 0x69, 0x33, 0x39, 0x6B, | ||
| 406 | 0x79, 0x75, 0x19, 0xBF, 0xBB, 0x07, 0x1D, 0xBD, | ||
| 407 | 0x29, 0xBF, 0x39, 0x95, 0x93, 0x1D, 0x35, 0xC7, | ||
| 408 | 0xC9, 0x4D, 0xE5, 0x97, 0x0B, 0x43, 0x9B, 0xF1, | ||
| 409 | 0x16, 0x93, 0x03, 0x1F, 0xA5, 0xFB, 0xDB, 0xF3, | ||
| 410 | 0x27, 0x4F, 0x27, 0x61, 0x05, 0x1F, 0xB9, 0x23, | ||
| 411 | 0x2F, 0xC3, 0x81, 0xA9, 0x23, 0x71, 0x55, 0x55, | ||
| 412 | 0xEB, 0xED, 0x41, 0xE5, 0xF3, 0x11, 0xF1, 0x43, | ||
| 413 | 0x69, 0x03, 0xBD, 0x0B, 0x37, 0x0F, 0x51, 0x8F, | ||
| 414 | 0x0B, 0xB5, 0x89, 0x5B, 0x67, 0xA9, 0xD9, 0x4F, | ||
| 415 | 0x01, 0xF9, 0x21, 0x77, 0x37, 0x73, 0x79, 0xC5, | ||
| 416 | 0x7F, 0x51, 0xC1, 0xCF, 0x97, 0xA1, 0x75, 0xAD, | ||
| 417 | 0x35, 0x9D, 0xD3, 0xD3, 0xA7, 0x9D, 0x5D, 0x41, | ||
| 418 | 0x6F, 0x65, 0x1B, 0xCF, 0xA9, 0x87, 0x91, 0x09 | ||
| 419 | }; | ||
| 420 | struct type86x_reply *msg = reply->message; | ||
| 421 | unsigned short service_rc, service_rs; | ||
| 422 | unsigned int reply_len, pad_len; | ||
| 423 | char *data; | ||
| 424 | |||
| 425 | service_rc = msg->cprbx.ccp_rtcode; | ||
| 426 | if (unlikely(service_rc != 0)) { | ||
| 427 | service_rs = msg->cprbx.ccp_rscode; | ||
| 428 | if (service_rc == 8 && service_rs == 66) | ||
| 429 | return -EINVAL; | ||
| 430 | if (service_rc == 8 && service_rs == 65) | ||
| 431 | return -EINVAL; | ||
| 432 | if (service_rc == 8 && service_rs == 770) | ||
| 433 | return -EINVAL; | ||
| 434 | if (service_rc == 8 && service_rs == 783) { | ||
| 435 | zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; | ||
| 436 | return -EAGAIN; | ||
| 437 | } | ||
| 438 | if (service_rc == 12 && service_rs == 769) | ||
| 439 | return -EINVAL; | ||
| 440 | if (service_rc == 8 && service_rs == 72) | ||
| 441 | return -EINVAL; | ||
| 442 | zdev->online = 0; | ||
| 443 | return -EAGAIN; /* repeat the request on a different device. */ | ||
| 444 | } | ||
| 445 | data = msg->text; | ||
| 446 | reply_len = msg->length - 2; | ||
| 447 | if (reply_len > outputdatalength) | ||
| 448 | return -EINVAL; | ||
| 449 | /* | ||
| 450 | * For all encipher requests, the length of the ciphertext (reply_len) | ||
| 451 | * will always equal the modulus length. For MEX decipher requests | ||
| 452 | * the output needs to get padded. Minimum pad size is 10. | ||
| 453 | * | ||
| 454 | * Currently, the cases where padding will be added is for: | ||
| 455 | * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support | ||
| 456 | * ZERO-PAD and CRT is only supported for PKD requests) | ||
| 457 | * - PCICC, always | ||
| 458 | */ | ||
| 459 | pad_len = outputdatalength - reply_len; | ||
| 460 | if (pad_len > 0) { | ||
| 461 | if (pad_len < 10) | ||
| 462 | return -EINVAL; | ||
| 463 | /* 'restore' padding left in the PCICC/PCIXCC card. */ | ||
| 464 | if (copy_to_user(outputdata, static_pad, pad_len - 1)) | ||
| 465 | return -EFAULT; | ||
| 466 | if (put_user(0, outputdata + pad_len - 1)) | ||
| 467 | return -EFAULT; | ||
| 468 | } | ||
| 469 | /* Copy the crypto response to user space. */ | ||
| 470 | if (copy_to_user(outputdata + pad_len, data, reply_len)) | ||
| 471 | return -EFAULT; | ||
| 472 | return 0; | ||
| 473 | } | ||
| 474 | |||
| 475 | /** | ||
| 476 | * Copy results from a type 86 XCRB reply message back to user space. | ||
| 477 | * | ||
| 478 | * @zdev: crypto device pointer | ||
| 479 | * @reply: reply AP message. | ||
| 480 | * @xcRB: pointer to XCRB | ||
| 481 | * | ||
| 482 | * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error. | ||
| 483 | */ | ||
| 484 | static int convert_type86_xcrb(struct zcrypt_device *zdev, | ||
| 485 | struct ap_message *reply, | ||
| 486 | struct ica_xcRB *xcRB) | ||
| 487 | { | ||
| 488 | struct type86_fmt2_msg *msg = reply->message; | ||
| 489 | char *data = reply->message; | ||
| 490 | |||
| 491 | /* Copy CPRB to user */ | ||
| 492 | if (copy_to_user(xcRB->reply_control_blk_addr, | ||
| 493 | data + msg->fmt2.offset1, msg->fmt2.count1)) | ||
| 494 | return -EFAULT; | ||
| 495 | xcRB->reply_control_blk_length = msg->fmt2.count1; | ||
| 496 | |||
| 497 | /* Copy data buffer to user */ | ||
| 498 | if (msg->fmt2.count2) | ||
| 499 | if (copy_to_user(xcRB->reply_data_addr, | ||
| 500 | data + msg->fmt2.offset2, msg->fmt2.count2)) | ||
| 501 | return -EFAULT; | ||
| 502 | xcRB->reply_data_length = msg->fmt2.count2; | ||
| 503 | return 0; | ||
| 504 | } | ||
| 505 | |||
| 506 | static int convert_type86_rng(struct zcrypt_device *zdev, | ||
| 507 | struct ap_message *reply, | ||
| 508 | char *buffer) | ||
| 509 | { | ||
| 510 | struct { | ||
| 511 | struct type86_hdr hdr; | ||
| 512 | struct type86_fmt2_ext fmt2; | ||
| 513 | struct CPRBX cprbx; | ||
| 514 | } __packed * msg = reply->message; | ||
| 515 | char *data = reply->message; | ||
| 516 | |||
| 517 | if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0) | ||
| 518 | return -EINVAL; | ||
| 519 | memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2); | ||
| 520 | return msg->fmt2.count2; | ||
| 521 | } | ||
| 522 | |||
| 523 | static int convert_response_ica(struct zcrypt_device *zdev, | ||
| 524 | struct ap_message *reply, | ||
| 525 | char __user *outputdata, | ||
| 526 | unsigned int outputdatalength) | ||
| 527 | { | ||
| 528 | struct type86x_reply *msg = reply->message; | ||
| 529 | |||
| 530 | /* Response type byte is the second byte in the response. */ | ||
| 531 | switch (((unsigned char *) reply->message)[1]) { | ||
| 532 | case TYPE82_RSP_CODE: | ||
| 533 | case TYPE88_RSP_CODE: | ||
| 534 | return convert_error(zdev, reply); | ||
| 535 | case TYPE86_RSP_CODE: | ||
| 536 | if (msg->cprbx.ccp_rtcode && | ||
| 537 | (msg->cprbx.ccp_rscode == 0x14f) && | ||
| 538 | (outputdatalength > 256)) { | ||
| 539 | if (zdev->max_exp_bit_length <= 17) { | ||
| 540 | zdev->max_exp_bit_length = 17; | ||
| 541 | return -EAGAIN; | ||
| 542 | } else | ||
| 543 | return -EINVAL; | ||
| 544 | } | ||
| 545 | if (msg->hdr.reply_code) | ||
| 546 | return convert_error(zdev, reply); | ||
| 547 | if (msg->cprbx.cprb_ver_id == 0x02) | ||
| 548 | return convert_type86_ica(zdev, reply, | ||
| 549 | outputdata, outputdatalength); | ||
| 550 | /* Fall through, no break, incorrect cprb version is an unknown | ||
| 551 | * response */ | ||
| 552 | default: /* Unknown response type, this should NEVER EVER happen */ | ||
| 553 | zdev->online = 0; | ||
| 554 | return -EAGAIN; /* repeat the request on a different device. */ | ||
| 555 | } | ||
| 556 | } | ||
| 557 | |||
| 558 | static int convert_response_xcrb(struct zcrypt_device *zdev, | ||
| 559 | struct ap_message *reply, | ||
| 560 | struct ica_xcRB *xcRB) | ||
| 561 | { | ||
| 562 | struct type86x_reply *msg = reply->message; | ||
| 563 | |||
| 564 | /* Response type byte is the second byte in the response. */ | ||
| 565 | switch (((unsigned char *) reply->message)[1]) { | ||
| 566 | case TYPE82_RSP_CODE: | ||
| 567 | case TYPE88_RSP_CODE: | ||
| 568 | xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ | ||
| 569 | return convert_error(zdev, reply); | ||
| 570 | case TYPE86_RSP_CODE: | ||
| 571 | if (msg->hdr.reply_code) { | ||
| 572 | memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32)); | ||
| 573 | return convert_error(zdev, reply); | ||
| 574 | } | ||
| 575 | if (msg->cprbx.cprb_ver_id == 0x02) | ||
| 576 | return convert_type86_xcrb(zdev, reply, xcRB); | ||
| 577 | /* Fall through, no break, incorrect cprb version is an unknown | ||
| 578 | * response */ | ||
| 579 | default: /* Unknown response type, this should NEVER EVER happen */ | ||
| 580 | xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ | ||
| 581 | zdev->online = 0; | ||
| 582 | return -EAGAIN; /* repeat the request on a different device. */ | ||
| 583 | } | ||
| 584 | } | ||
| 585 | |||
| 586 | static int convert_response_rng(struct zcrypt_device *zdev, | ||
| 587 | struct ap_message *reply, | ||
| 588 | char *data) | ||
| 589 | { | ||
| 590 | struct type86x_reply *msg = reply->message; | ||
| 591 | |||
| 592 | switch (msg->hdr.type) { | ||
| 593 | case TYPE82_RSP_CODE: | ||
| 594 | case TYPE88_RSP_CODE: | ||
| 595 | return -EINVAL; | ||
| 596 | case TYPE86_RSP_CODE: | ||
| 597 | if (msg->hdr.reply_code) | ||
| 598 | return -EINVAL; | ||
| 599 | if (msg->cprbx.cprb_ver_id == 0x02) | ||
| 600 | return convert_type86_rng(zdev, reply, data); | ||
| 601 | /* Fall through, no break, incorrect cprb version is an unknown | ||
| 602 | * response */ | ||
| 603 | default: /* Unknown response type, this should NEVER EVER happen */ | ||
| 604 | zdev->online = 0; | ||
| 605 | return -EAGAIN; /* repeat the request on a different device. */ | ||
| 606 | } | ||
| 607 | } | ||
| 608 | |||
| 609 | /** | ||
| 610 | * This function is called from the AP bus code after a crypto request | ||
| 611 | * "msg" has finished with the reply message "reply". | ||
| 612 | * It is called from tasklet context. | ||
| 613 | * @ap_dev: pointer to the AP device | ||
| 614 | * @msg: pointer to the AP message | ||
| 615 | * @reply: pointer to the AP reply message | ||
| 616 | */ | ||
| 617 | static void zcrypt_msgtype6_receive(struct ap_device *ap_dev, | ||
| 618 | struct ap_message *msg, | ||
| 619 | struct ap_message *reply) | ||
| 620 | { | ||
| 621 | static struct error_hdr error_reply = { | ||
| 622 | .type = TYPE82_RSP_CODE, | ||
| 623 | .reply_code = REP82_ERROR_MACHINE_FAILURE, | ||
| 624 | }; | ||
| 625 | struct response_type *resp_type = | ||
| 626 | (struct response_type *) msg->private; | ||
| 627 | struct type86x_reply *t86r; | ||
| 628 | int length; | ||
| 629 | |||
| 630 | /* Copy the reply message to the request message buffer. */ | ||
| 631 | if (IS_ERR(reply)) { | ||
| 632 | memcpy(msg->message, &error_reply, sizeof(error_reply)); | ||
| 633 | goto out; | ||
| 634 | } | ||
| 635 | t86r = reply->message; | ||
| 636 | if (t86r->hdr.type == TYPE86_RSP_CODE && | ||
| 637 | t86r->cprbx.cprb_ver_id == 0x02) { | ||
| 638 | switch (resp_type->type) { | ||
| 639 | case PCIXCC_RESPONSE_TYPE_ICA: | ||
| 640 | length = sizeof(struct type86x_reply) | ||
| 641 | + t86r->length - 2; | ||
| 642 | length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length); | ||
| 643 | memcpy(msg->message, reply->message, length); | ||
| 644 | break; | ||
| 645 | case PCIXCC_RESPONSE_TYPE_XCRB: | ||
| 646 | length = t86r->fmt2.offset2 + t86r->fmt2.count2; | ||
| 647 | length = min(MSGTYPE06_MAX_MSG_SIZE, length); | ||
| 648 | memcpy(msg->message, reply->message, length); | ||
| 649 | break; | ||
| 650 | default: | ||
| 651 | memcpy(msg->message, &error_reply, | ||
| 652 | sizeof(error_reply)); | ||
| 653 | } | ||
| 654 | } else | ||
| 655 | memcpy(msg->message, reply->message, sizeof(error_reply)); | ||
| 656 | out: | ||
| 657 | complete(&(resp_type->work)); | ||
| 658 | } | ||
| 659 | |||
| 660 | static atomic_t zcrypt_step = ATOMIC_INIT(0); | ||
| 661 | |||
| 662 | /** | ||
| 663 | * The request distributor calls this function if it picked the PCIXCC/CEX2C | ||
| 664 | * device to handle a modexpo request. | ||
| 665 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
| 666 | * PCIXCC/CEX2C device to the request distributor | ||
| 667 | * @mex: pointer to the modexpo request buffer | ||
| 668 | */ | ||
| 669 | static long zcrypt_msgtype6_modexpo(struct zcrypt_device *zdev, | ||
| 670 | struct ica_rsa_modexpo *mex) | ||
| 671 | { | ||
| 672 | struct ap_message ap_msg; | ||
| 673 | struct response_type resp_type = { | ||
| 674 | .type = PCIXCC_RESPONSE_TYPE_ICA, | ||
| 675 | }; | ||
| 676 | int rc; | ||
| 677 | |||
| 678 | ap_init_message(&ap_msg); | ||
| 679 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | ||
| 680 | if (!ap_msg.message) | ||
| 681 | return -ENOMEM; | ||
| 682 | ap_msg.receive = zcrypt_msgtype6_receive; | ||
| 683 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
| 684 | atomic_inc_return(&zcrypt_step); | ||
| 685 | ap_msg.private = &resp_type; | ||
| 686 | rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex); | ||
| 687 | if (rc) | ||
| 688 | goto out_free; | ||
| 689 | init_completion(&resp_type.work); | ||
| 690 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
| 691 | rc = wait_for_completion_interruptible(&resp_type.work); | ||
| 692 | if (rc == 0) | ||
| 693 | rc = convert_response_ica(zdev, &ap_msg, mex->outputdata, | ||
| 694 | mex->outputdatalength); | ||
| 695 | else | ||
| 696 | /* Signal pending. */ | ||
| 697 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
| 698 | out_free: | ||
| 699 | free_page((unsigned long) ap_msg.message); | ||
| 700 | return rc; | ||
| 701 | } | ||
| 702 | |||
| 703 | /** | ||
| 704 | * The request distributor calls this function if it picked the PCIXCC/CEX2C | ||
| 705 | * device to handle a modexpo_crt request. | ||
| 706 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
| 707 | * PCIXCC/CEX2C device to the request distributor | ||
| 708 | * @crt: pointer to the modexpoc_crt request buffer | ||
| 709 | */ | ||
| 710 | static long zcrypt_msgtype6_modexpo_crt(struct zcrypt_device *zdev, | ||
| 711 | struct ica_rsa_modexpo_crt *crt) | ||
| 712 | { | ||
| 713 | struct ap_message ap_msg; | ||
| 714 | struct response_type resp_type = { | ||
| 715 | .type = PCIXCC_RESPONSE_TYPE_ICA, | ||
| 716 | }; | ||
| 717 | int rc; | ||
| 718 | |||
| 719 | ap_init_message(&ap_msg); | ||
| 720 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | ||
| 721 | if (!ap_msg.message) | ||
| 722 | return -ENOMEM; | ||
| 723 | ap_msg.receive = zcrypt_msgtype6_receive; | ||
| 724 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
| 725 | atomic_inc_return(&zcrypt_step); | ||
| 726 | ap_msg.private = &resp_type; | ||
| 727 | rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt); | ||
| 728 | if (rc) | ||
| 729 | goto out_free; | ||
| 730 | init_completion(&resp_type.work); | ||
| 731 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
| 732 | rc = wait_for_completion_interruptible(&resp_type.work); | ||
| 733 | if (rc == 0) | ||
| 734 | rc = convert_response_ica(zdev, &ap_msg, crt->outputdata, | ||
| 735 | crt->outputdatalength); | ||
| 736 | else | ||
| 737 | /* Signal pending. */ | ||
| 738 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
| 739 | out_free: | ||
| 740 | free_page((unsigned long) ap_msg.message); | ||
| 741 | return rc; | ||
| 742 | } | ||
| 743 | |||
| 744 | /** | ||
| 745 | * The request distributor calls this function if it picked the PCIXCC/CEX2C | ||
| 746 | * device to handle a send_cprb request. | ||
| 747 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
| 748 | * PCIXCC/CEX2C device to the request distributor | ||
| 749 | * @xcRB: pointer to the send_cprb request buffer | ||
| 750 | */ | ||
| 751 | static long zcrypt_msgtype6_send_cprb(struct zcrypt_device *zdev, | ||
| 752 | struct ica_xcRB *xcRB) | ||
| 753 | { | ||
| 754 | struct ap_message ap_msg; | ||
| 755 | struct response_type resp_type = { | ||
| 756 | .type = PCIXCC_RESPONSE_TYPE_XCRB, | ||
| 757 | }; | ||
| 758 | int rc; | ||
| 759 | |||
| 760 | ap_init_message(&ap_msg); | ||
| 761 | ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); | ||
| 762 | if (!ap_msg.message) | ||
| 763 | return -ENOMEM; | ||
| 764 | ap_msg.receive = zcrypt_msgtype6_receive; | ||
| 765 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
| 766 | atomic_inc_return(&zcrypt_step); | ||
| 767 | ap_msg.private = &resp_type; | ||
| 768 | rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB); | ||
| 769 | if (rc) | ||
| 770 | goto out_free; | ||
| 771 | init_completion(&resp_type.work); | ||
| 772 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
| 773 | rc = wait_for_completion_interruptible(&resp_type.work); | ||
| 774 | if (rc == 0) | ||
| 775 | rc = convert_response_xcrb(zdev, &ap_msg, xcRB); | ||
| 776 | else | ||
| 777 | /* Signal pending. */ | ||
| 778 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
| 779 | out_free: | ||
| 780 | kzfree(ap_msg.message); | ||
| 781 | return rc; | ||
| 782 | } | ||
| 783 | |||
| 784 | /** | ||
| 785 | * The request distributor calls this function if it picked the PCIXCC/CEX2C | ||
| 786 | * device to generate random data. | ||
| 787 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
| 788 | * PCIXCC/CEX2C device to the request distributor | ||
| 789 | * @buffer: pointer to a memory page to return random data | ||
| 790 | */ | ||
| 791 | |||
| 792 | static long zcrypt_msgtype6_rng(struct zcrypt_device *zdev, | ||
| 793 | char *buffer) | ||
| 794 | { | ||
| 795 | struct ap_message ap_msg; | ||
| 796 | struct response_type resp_type = { | ||
| 797 | .type = PCIXCC_RESPONSE_TYPE_XCRB, | ||
| 798 | }; | ||
| 799 | int rc; | ||
| 800 | |||
| 801 | ap_init_message(&ap_msg); | ||
| 802 | ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); | ||
| 803 | if (!ap_msg.message) | ||
| 804 | return -ENOMEM; | ||
| 805 | ap_msg.receive = zcrypt_msgtype6_receive; | ||
| 806 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
| 807 | atomic_inc_return(&zcrypt_step); | ||
| 808 | ap_msg.private = &resp_type; | ||
| 809 | rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE); | ||
| 810 | init_completion(&resp_type.work); | ||
| 811 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
| 812 | rc = wait_for_completion_interruptible(&resp_type.work); | ||
| 813 | if (rc == 0) | ||
| 814 | rc = convert_response_rng(zdev, &ap_msg, buffer); | ||
| 815 | else | ||
| 816 | /* Signal pending. */ | ||
| 817 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
| 818 | kfree(ap_msg.message); | ||
| 819 | return rc; | ||
| 820 | } | ||
| 821 | |||
| 822 | /** | ||
| 823 | * The crypto operations for a PCIXCC/CEX2C card. | ||
| 824 | */ | ||
| 825 | static struct zcrypt_ops zcrypt_msgtype6_norng_ops = { | ||
| 826 | .owner = THIS_MODULE, | ||
| 827 | .variant = MSGTYPE06_VARIANT_NORNG, | ||
| 828 | .rsa_modexpo = zcrypt_msgtype6_modexpo, | ||
| 829 | .rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt, | ||
| 830 | .send_cprb = zcrypt_msgtype6_send_cprb, | ||
| 831 | }; | ||
| 832 | |||
| 833 | static struct zcrypt_ops zcrypt_msgtype6_ops = { | ||
| 834 | .owner = THIS_MODULE, | ||
| 835 | .variant = MSGTYPE06_VARIANT_DEFAULT, | ||
| 836 | .rsa_modexpo = zcrypt_msgtype6_modexpo, | ||
| 837 | .rsa_modexpo_crt = zcrypt_msgtype6_modexpo_crt, | ||
| 838 | .send_cprb = zcrypt_msgtype6_send_cprb, | ||
| 839 | .rng = zcrypt_msgtype6_rng, | ||
| 840 | }; | ||
| 841 | |||
| 842 | int __init zcrypt_msgtype6_init(void) | ||
| 843 | { | ||
| 844 | zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops); | ||
| 845 | zcrypt_msgtype_register(&zcrypt_msgtype6_ops); | ||
| 846 | return 0; | ||
| 847 | } | ||
| 848 | |||
| 849 | void __exit zcrypt_msgtype6_exit(void) | ||
| 850 | { | ||
| 851 | zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops); | ||
| 852 | zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops); | ||
| 853 | } | ||
| 854 | |||
| 855 | module_init(zcrypt_msgtype6_init); | ||
| 856 | module_exit(zcrypt_msgtype6_exit); | ||
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.h b/drivers/s390/crypto/zcrypt_msgtype6.h deleted file mode 100644 index 1e500d3c073..00000000000 --- a/drivers/s390/crypto/zcrypt_msgtype6.h +++ /dev/null | |||
| @@ -1,169 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * zcrypt 2.1.0 | ||
| 3 | * | ||
| 4 | * Copyright IBM Corp. 2001, 2012 | ||
| 5 | * Author(s): Robert Burroughs | ||
| 6 | * Eric Rossman (edrossma@us.ibm.com) | ||
| 7 | * | ||
| 8 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) | ||
| 9 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> | ||
| 10 | * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com> | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify | ||
| 13 | * it under the terms of the GNU General Public License as published by | ||
| 14 | * the Free Software Foundation; either version 2, or (at your option) | ||
| 15 | * any later version. | ||
| 16 | * | ||
| 17 | * This program is distributed in the hope that it will be useful, | ||
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | * GNU General Public License for more details. | ||
| 21 | * | ||
| 22 | * You should have received a copy of the GNU General Public License | ||
| 23 | * along with this program; if not, write to the Free Software | ||
| 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 25 | */ | ||
| 26 | |||
| 27 | #ifndef _ZCRYPT_MSGTYPE6_H_ | ||
| 28 | #define _ZCRYPT_MSGTYPE6_H_ | ||
| 29 | |||
| 30 | #include <asm/zcrypt.h> | ||
| 31 | |||
| 32 | #define MSGTYPE06_NAME "zcrypt_msgtype6" | ||
| 33 | #define MSGTYPE06_VARIANT_DEFAULT 0 | ||
| 34 | #define MSGTYPE06_VARIANT_NORNG 1 | ||
| 35 | |||
| 36 | #define MSGTYPE06_MAX_MSG_SIZE (12*1024) | ||
| 37 | |||
| 38 | /** | ||
| 39 | * The type 6 message family is associated with PCICC or PCIXCC cards. | ||
| 40 | * | ||
| 41 | * It contains a message header followed by a CPRB, both of which | ||
| 42 | * are described below. | ||
| 43 | * | ||
| 44 | * Note that all reserved fields must be zeroes. | ||
| 45 | */ | ||
| 46 | struct type6_hdr { | ||
| 47 | unsigned char reserved1; /* 0x00 */ | ||
| 48 | unsigned char type; /* 0x06 */ | ||
| 49 | unsigned char reserved2[2]; /* 0x0000 */ | ||
| 50 | unsigned char right[4]; /* 0x00000000 */ | ||
| 51 | unsigned char reserved3[2]; /* 0x0000 */ | ||
| 52 | unsigned char reserved4[2]; /* 0x0000 */ | ||
| 53 | unsigned char apfs[4]; /* 0x00000000 */ | ||
| 54 | unsigned int offset1; /* 0x00000058 (offset to CPRB) */ | ||
| 55 | unsigned int offset2; /* 0x00000000 */ | ||
| 56 | unsigned int offset3; /* 0x00000000 */ | ||
| 57 | unsigned int offset4; /* 0x00000000 */ | ||
| 58 | unsigned char agent_id[16]; /* PCICC: */ | ||
| 59 | /* 0x0100 */ | ||
| 60 | /* 0x4343412d4150504c202020 */ | ||
| 61 | /* 0x010101 */ | ||
| 62 | /* PCIXCC: */ | ||
| 63 | /* 0x4341000000000000 */ | ||
| 64 | /* 0x0000000000000000 */ | ||
| 65 | unsigned char rqid[2]; /* rqid. internal to 603 */ | ||
| 66 | unsigned char reserved5[2]; /* 0x0000 */ | ||
| 67 | unsigned char function_code[2]; /* for PKD, 0x5044 (ascii 'PD') */ | ||
| 68 | unsigned char reserved6[2]; /* 0x0000 */ | ||
| 69 | unsigned int ToCardLen1; /* (request CPRB len + 3) & -4 */ | ||
| 70 | unsigned int ToCardLen2; /* db len 0x00000000 for PKD */ | ||
| 71 | unsigned int ToCardLen3; /* 0x00000000 */ | ||
| 72 | unsigned int ToCardLen4; /* 0x00000000 */ | ||
| 73 | unsigned int FromCardLen1; /* response buffer length */ | ||
| 74 | unsigned int FromCardLen2; /* db len 0x00000000 for PKD */ | ||
| 75 | unsigned int FromCardLen3; /* 0x00000000 */ | ||
| 76 | unsigned int FromCardLen4; /* 0x00000000 */ | ||
| 77 | } __packed; | ||
| 78 | |||
| 79 | /** | ||
| 80 | * The type 86 message family is associated with PCICC and PCIXCC cards. | ||
| 81 | * | ||
| 82 | * It contains a message header followed by a CPRB. The CPRB is | ||
| 83 | * the same as the request CPRB, which is described above. | ||
| 84 | * | ||
| 85 | * If format is 1, an error condition exists and no data beyond | ||
| 86 | * the 8-byte message header is of interest. | ||
| 87 | * | ||
| 88 | * The non-error message is shown below. | ||
| 89 | * | ||
| 90 | * Note that all reserved fields must be zeroes. | ||
| 91 | */ | ||
| 92 | struct type86_hdr { | ||
| 93 | unsigned char reserved1; /* 0x00 */ | ||
| 94 | unsigned char type; /* 0x86 */ | ||
| 95 | unsigned char format; /* 0x01 (error) or 0x02 (ok) */ | ||
| 96 | unsigned char reserved2; /* 0x00 */ | ||
| 97 | unsigned char reply_code; /* reply code (see above) */ | ||
| 98 | unsigned char reserved3[3]; /* 0x000000 */ | ||
| 99 | } __packed; | ||
| 100 | |||
| 101 | #define TYPE86_RSP_CODE 0x86 | ||
| 102 | #define TYPE86_FMT2 0x02 | ||
| 103 | |||
| 104 | struct type86_fmt2_ext { | ||
| 105 | unsigned char reserved[4]; /* 0x00000000 */ | ||
| 106 | unsigned char apfs[4]; /* final status */ | ||
| 107 | unsigned int count1; /* length of CPRB + parameters */ | ||
| 108 | unsigned int offset1; /* offset to CPRB */ | ||
| 109 | unsigned int count2; /* 0x00000000 */ | ||
| 110 | unsigned int offset2; /* db offset 0x00000000 for PKD */ | ||
| 111 | unsigned int count3; /* 0x00000000 */ | ||
| 112 | unsigned int offset3; /* 0x00000000 */ | ||
| 113 | unsigned int count4; /* 0x00000000 */ | ||
| 114 | unsigned int offset4; /* 0x00000000 */ | ||
| 115 | } __packed; | ||
| 116 | |||
| 117 | /** | ||
| 118 | * Prepare a type6 CPRB message for random number generation | ||
| 119 | * | ||
| 120 | * @ap_dev: AP device pointer | ||
| 121 | * @ap_msg: pointer to AP message | ||
| 122 | */ | ||
| 123 | static inline void rng_type6CPRB_msgX(struct ap_device *ap_dev, | ||
| 124 | struct ap_message *ap_msg, | ||
| 125 | unsigned random_number_length) | ||
| 126 | { | ||
| 127 | struct { | ||
| 128 | struct type6_hdr hdr; | ||
| 129 | struct CPRBX cprbx; | ||
| 130 | char function_code[2]; | ||
| 131 | short int rule_length; | ||
| 132 | char rule[8]; | ||
| 133 | short int verb_length; | ||
| 134 | short int key_length; | ||
| 135 | } __packed * msg = ap_msg->message; | ||
| 136 | static struct type6_hdr static_type6_hdrX = { | ||
| 137 | .type = 0x06, | ||
| 138 | .offset1 = 0x00000058, | ||
| 139 | .agent_id = {'C', 'A'}, | ||
| 140 | .function_code = {'R', 'L'}, | ||
| 141 | .ToCardLen1 = sizeof(*msg) - sizeof(msg->hdr), | ||
| 142 | .FromCardLen1 = sizeof(*msg) - sizeof(msg->hdr), | ||
| 143 | }; | ||
| 144 | static struct CPRBX local_cprbx = { | ||
| 145 | .cprb_len = 0x00dc, | ||
| 146 | .cprb_ver_id = 0x02, | ||
| 147 | .func_id = {0x54, 0x32}, | ||
| 148 | .req_parml = sizeof(*msg) - sizeof(msg->hdr) - | ||
| 149 | sizeof(msg->cprbx), | ||
| 150 | .rpl_msgbl = sizeof(*msg) - sizeof(msg->hdr), | ||
| 151 | }; | ||
| 152 | |||
| 153 | msg->hdr = static_type6_hdrX; | ||
| 154 | msg->hdr.FromCardLen2 = random_number_length, | ||
| 155 | msg->cprbx = local_cprbx; | ||
| 156 | msg->cprbx.rpl_datal = random_number_length, | ||
| 157 | msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid); | ||
| 158 | memcpy(msg->function_code, msg->hdr.function_code, 0x02); | ||
| 159 | msg->rule_length = 0x0a; | ||
| 160 | memcpy(msg->rule, "RANDOM ", 8); | ||
| 161 | msg->verb_length = 0x02; | ||
| 162 | msg->key_length = 0x02; | ||
| 163 | ap_msg->length = sizeof(*msg); | ||
| 164 | } | ||
| 165 | |||
| 166 | int zcrypt_msgtype6_init(void); | ||
| 167 | void zcrypt_msgtype6_exit(void); | ||
| 168 | |||
| 169 | #endif /* _ZCRYPT_MSGTYPE6_H_ */ | ||
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c index f2b71d8df01..d84816f144d 100644 --- a/drivers/s390/crypto/zcrypt_pcica.c +++ b/drivers/s390/crypto/zcrypt_pcica.c | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/drivers/s390/crypto/zcrypt_pcica.c | ||
| 3 | * | ||
| 2 | * zcrypt 2.1.0 | 4 | * zcrypt 2.1.0 |
| 3 | * | 5 | * |
| 4 | * Copyright IBM Corp. 2001, 2006 | 6 | * Copyright (C) 2001, 2006 IBM Corporation |
| 5 | * Author(s): Robert Burroughs | 7 | * Author(s): Robert Burroughs |
| 6 | * Eric Rossman (edrossma@us.ibm.com) | 8 | * Eric Rossman (edrossma@us.ibm.com) |
| 7 | * | 9 | * |
| @@ -51,11 +53,13 @@ static struct ap_device_id zcrypt_pcica_ids[] = { | |||
| 51 | { /* end of list */ }, | 53 | { /* end of list */ }, |
| 52 | }; | 54 | }; |
| 53 | 55 | ||
| 56 | #ifndef CONFIG_ZCRYPT_MONOLITHIC | ||
| 54 | MODULE_DEVICE_TABLE(ap, zcrypt_pcica_ids); | 57 | MODULE_DEVICE_TABLE(ap, zcrypt_pcica_ids); |
| 55 | MODULE_AUTHOR("IBM Corporation"); | 58 | MODULE_AUTHOR("IBM Corporation"); |
| 56 | MODULE_DESCRIPTION("PCICA Cryptographic Coprocessor device driver, " | 59 | MODULE_DESCRIPTION("PCICA Cryptographic Coprocessor device driver, " |
| 57 | "Copyright IBM Corp. 2001, 2006"); | 60 | "Copyright 2001, 2006 IBM Corporation"); |
| 58 | MODULE_LICENSE("GPL"); | 61 | MODULE_LICENSE("GPL"); |
| 62 | #endif | ||
| 59 | 63 | ||
| 60 | static int zcrypt_pcica_probe(struct ap_device *ap_dev); | 64 | static int zcrypt_pcica_probe(struct ap_device *ap_dev); |
| 61 | static void zcrypt_pcica_remove(struct ap_device *ap_dev); | 65 | static void zcrypt_pcica_remove(struct ap_device *ap_dev); |
| @@ -65,6 +69,7 @@ static void zcrypt_pcica_receive(struct ap_device *, struct ap_message *, | |||
| 65 | static struct ap_driver zcrypt_pcica_driver = { | 69 | static struct ap_driver zcrypt_pcica_driver = { |
| 66 | .probe = zcrypt_pcica_probe, | 70 | .probe = zcrypt_pcica_probe, |
| 67 | .remove = zcrypt_pcica_remove, | 71 | .remove = zcrypt_pcica_remove, |
| 72 | .receive = zcrypt_pcica_receive, | ||
| 68 | .ids = zcrypt_pcica_ids, | 73 | .ids = zcrypt_pcica_ids, |
| 69 | .request_timeout = PCICA_CLEANUP_TIME, | 74 | .request_timeout = PCICA_CLEANUP_TIME, |
| 70 | }; | 75 | }; |
| @@ -281,7 +286,6 @@ static long zcrypt_pcica_modexpo(struct zcrypt_device *zdev, | |||
| 281 | ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); | 286 | ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); |
| 282 | if (!ap_msg.message) | 287 | if (!ap_msg.message) |
| 283 | return -ENOMEM; | 288 | return -ENOMEM; |
| 284 | ap_msg.receive = zcrypt_pcica_receive; | ||
| 285 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 289 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
| 286 | atomic_inc_return(&zcrypt_step); | 290 | atomic_inc_return(&zcrypt_step); |
| 287 | ap_msg.private = &work; | 291 | ap_msg.private = &work; |
| @@ -320,7 +324,6 @@ static long zcrypt_pcica_modexpo_crt(struct zcrypt_device *zdev, | |||
| 320 | ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); | 324 | ap_msg.message = kmalloc(PCICA_MAX_MESSAGE_SIZE, GFP_KERNEL); |
| 321 | if (!ap_msg.message) | 325 | if (!ap_msg.message) |
| 322 | return -ENOMEM; | 326 | return -ENOMEM; |
| 323 | ap_msg.receive = zcrypt_pcica_receive; | ||
| 324 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 327 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
| 325 | atomic_inc_return(&zcrypt_step); | 328 | atomic_inc_return(&zcrypt_step); |
| 326 | ap_msg.private = &work; | 329 | ap_msg.private = &work; |
| @@ -405,5 +408,7 @@ void zcrypt_pcica_exit(void) | |||
| 405 | ap_driver_unregister(&zcrypt_pcica_driver); | 408 | ap_driver_unregister(&zcrypt_pcica_driver); |
| 406 | } | 409 | } |
| 407 | 410 | ||
| 411 | #ifndef CONFIG_ZCRYPT_MONOLITHIC | ||
| 408 | module_init(zcrypt_pcica_init); | 412 | module_init(zcrypt_pcica_init); |
| 409 | module_exit(zcrypt_pcica_exit); | 413 | module_exit(zcrypt_pcica_exit); |
| 414 | #endif | ||
diff --git a/drivers/s390/crypto/zcrypt_pcica.h b/drivers/s390/crypto/zcrypt_pcica.h index 9a59155cad5..3be11187f6d 100644 --- a/drivers/s390/crypto/zcrypt_pcica.h +++ b/drivers/s390/crypto/zcrypt_pcica.h | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/drivers/s390/crypto/zcrypt_pcica.h | ||
| 3 | * | ||
| 2 | * zcrypt 2.1.0 | 4 | * zcrypt 2.1.0 |
| 3 | * | 5 | * |
| 4 | * Copyright IBM Corp. 2001, 2006 | 6 | * Copyright (C) 2001, 2006 IBM Corporation |
| 5 | * Author(s): Robert Burroughs | 7 | * Author(s): Robert Burroughs |
| 6 | * Eric Rossman (edrossma@us.ibm.com) | 8 | * Eric Rossman (edrossma@us.ibm.com) |
| 7 | * | 9 | * |
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c index 0d90a433405..bdbdbe19299 100644 --- a/drivers/s390/crypto/zcrypt_pcicc.c +++ b/drivers/s390/crypto/zcrypt_pcicc.c | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/drivers/s390/crypto/zcrypt_pcicc.c | ||
| 3 | * | ||
| 2 | * zcrypt 2.1.0 | 4 | * zcrypt 2.1.0 |
| 3 | * | 5 | * |
| 4 | * Copyright IBM Corp. 2001, 2006 | 6 | * Copyright (C) 2001, 2006 IBM Corporation |
| 5 | * Author(s): Robert Burroughs | 7 | * Author(s): Robert Burroughs |
| 6 | * Eric Rossman (edrossma@us.ibm.com) | 8 | * Eric Rossman (edrossma@us.ibm.com) |
| 7 | * | 9 | * |
| @@ -63,11 +65,13 @@ static struct ap_device_id zcrypt_pcicc_ids[] = { | |||
| 63 | { /* end of list */ }, | 65 | { /* end of list */ }, |
| 64 | }; | 66 | }; |
| 65 | 67 | ||
| 68 | #ifndef CONFIG_ZCRYPT_MONOLITHIC | ||
| 66 | MODULE_DEVICE_TABLE(ap, zcrypt_pcicc_ids); | 69 | MODULE_DEVICE_TABLE(ap, zcrypt_pcicc_ids); |
| 67 | MODULE_AUTHOR("IBM Corporation"); | 70 | MODULE_AUTHOR("IBM Corporation"); |
| 68 | MODULE_DESCRIPTION("PCICC Cryptographic Coprocessor device driver, " | 71 | MODULE_DESCRIPTION("PCICC Cryptographic Coprocessor device driver, " |
| 69 | "Copyright IBM Corp. 2001, 2006"); | 72 | "Copyright 2001, 2006 IBM Corporation"); |
| 70 | MODULE_LICENSE("GPL"); | 73 | MODULE_LICENSE("GPL"); |
| 74 | #endif | ||
| 71 | 75 | ||
| 72 | static int zcrypt_pcicc_probe(struct ap_device *ap_dev); | 76 | static int zcrypt_pcicc_probe(struct ap_device *ap_dev); |
| 73 | static void zcrypt_pcicc_remove(struct ap_device *ap_dev); | 77 | static void zcrypt_pcicc_remove(struct ap_device *ap_dev); |
| @@ -77,6 +81,7 @@ static void zcrypt_pcicc_receive(struct ap_device *, struct ap_message *, | |||
| 77 | static struct ap_driver zcrypt_pcicc_driver = { | 81 | static struct ap_driver zcrypt_pcicc_driver = { |
| 78 | .probe = zcrypt_pcicc_probe, | 82 | .probe = zcrypt_pcicc_probe, |
| 79 | .remove = zcrypt_pcicc_remove, | 83 | .remove = zcrypt_pcicc_remove, |
| 84 | .receive = zcrypt_pcicc_receive, | ||
| 80 | .ids = zcrypt_pcicc_ids, | 85 | .ids = zcrypt_pcicc_ids, |
| 81 | .request_timeout = PCICC_CLEANUP_TIME, | 86 | .request_timeout = PCICC_CLEANUP_TIME, |
| 82 | }; | 87 | }; |
| @@ -485,7 +490,6 @@ static long zcrypt_pcicc_modexpo(struct zcrypt_device *zdev, | |||
| 485 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | 490 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); |
| 486 | if (!ap_msg.message) | 491 | if (!ap_msg.message) |
| 487 | return -ENOMEM; | 492 | return -ENOMEM; |
| 488 | ap_msg.receive = zcrypt_pcicc_receive; | ||
| 489 | ap_msg.length = PAGE_SIZE; | 493 | ap_msg.length = PAGE_SIZE; |
| 490 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 494 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
| 491 | atomic_inc_return(&zcrypt_step); | 495 | atomic_inc_return(&zcrypt_step); |
| @@ -525,7 +529,6 @@ static long zcrypt_pcicc_modexpo_crt(struct zcrypt_device *zdev, | |||
| 525 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | 529 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); |
| 526 | if (!ap_msg.message) | 530 | if (!ap_msg.message) |
| 527 | return -ENOMEM; | 531 | return -ENOMEM; |
| 528 | ap_msg.receive = zcrypt_pcicc_receive; | ||
| 529 | ap_msg.length = PAGE_SIZE; | 532 | ap_msg.length = PAGE_SIZE; |
| 530 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | 533 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + |
| 531 | atomic_inc_return(&zcrypt_step); | 534 | atomic_inc_return(&zcrypt_step); |
| @@ -611,5 +614,7 @@ void zcrypt_pcicc_exit(void) | |||
| 611 | ap_driver_unregister(&zcrypt_pcicc_driver); | 614 | ap_driver_unregister(&zcrypt_pcicc_driver); |
| 612 | } | 615 | } |
| 613 | 616 | ||
| 617 | #ifndef CONFIG_ZCRYPT_MONOLITHIC | ||
| 614 | module_init(zcrypt_pcicc_init); | 618 | module_init(zcrypt_pcicc_init); |
| 615 | module_exit(zcrypt_pcicc_exit); | 619 | module_exit(zcrypt_pcicc_exit); |
| 620 | #endif | ||
diff --git a/drivers/s390/crypto/zcrypt_pcicc.h b/drivers/s390/crypto/zcrypt_pcicc.h index 7fe27e15075..6d4454846c8 100644 --- a/drivers/s390/crypto/zcrypt_pcicc.h +++ b/drivers/s390/crypto/zcrypt_pcicc.h | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/drivers/s390/crypto/zcrypt_pcicc.h | ||
| 3 | * | ||
| 2 | * zcrypt 2.1.0 | 4 | * zcrypt 2.1.0 |
| 3 | * | 5 | * |
| 4 | * Copyright IBM Corp. 2001, 2006 | 6 | * Copyright (C) 2001, 2006 IBM Corporation |
| 5 | * Author(s): Robert Burroughs | 7 | * Author(s): Robert Burroughs |
| 6 | * Eric Rossman (edrossma@us.ibm.com) | 8 | * Eric Rossman (edrossma@us.ibm.com) |
| 7 | * | 9 | * |
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c index 899ffa19f5e..dd4737808e0 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/drivers/s390/crypto/zcrypt_pcixcc.c | |||
| @@ -1,14 +1,15 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/drivers/s390/crypto/zcrypt_pcixcc.c | ||
| 3 | * | ||
| 2 | * zcrypt 2.1.0 | 4 | * zcrypt 2.1.0 |
| 3 | * | 5 | * |
| 4 | * Copyright IBM Corp. 2001, 2012 | 6 | * Copyright (C) 2001, 2006 IBM Corporation |
| 5 | * Author(s): Robert Burroughs | 7 | * Author(s): Robert Burroughs |
| 6 | * Eric Rossman (edrossma@us.ibm.com) | 8 | * Eric Rossman (edrossma@us.ibm.com) |
| 7 | * | 9 | * |
| 8 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) | 10 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) |
| 9 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> | 11 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> |
| 10 | * Ralph Wuerthner <rwuerthn@de.ibm.com> | 12 | * Ralph Wuerthner <rwuerthn@de.ibm.com> |
| 11 | * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com> | ||
| 12 | * | 13 | * |
| 13 | * This program is free software; you can redistribute it and/or modify | 14 | * 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 | * it under the terms of the GNU General Public License as published by |
| @@ -36,7 +37,7 @@ | |||
| 36 | #include "ap_bus.h" | 37 | #include "ap_bus.h" |
| 37 | #include "zcrypt_api.h" | 38 | #include "zcrypt_api.h" |
| 38 | #include "zcrypt_error.h" | 39 | #include "zcrypt_error.h" |
| 39 | #include "zcrypt_msgtype6.h" | 40 | #include "zcrypt_pcicc.h" |
| 40 | #include "zcrypt_pcixcc.h" | 41 | #include "zcrypt_pcixcc.h" |
| 41 | #include "zcrypt_cca_key.h" | 42 | #include "zcrypt_cca_key.h" |
| 42 | 43 | ||
| @@ -55,6 +56,11 @@ | |||
| 55 | #define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */ | 56 | #define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply */ |
| 56 | 57 | ||
| 57 | #define PCIXCC_MAX_XCRB_MESSAGE_SIZE (12*1024) | 58 | #define PCIXCC_MAX_XCRB_MESSAGE_SIZE (12*1024) |
| 59 | #define PCIXCC_MAX_XCRB_RESPONSE_SIZE PCIXCC_MAX_XCRB_MESSAGE_SIZE | ||
| 60 | #define PCIXCC_MAX_XCRB_DATA_SIZE (11*1024) | ||
| 61 | #define PCIXCC_MAX_XCRB_REPLY_SIZE (5*1024) | ||
| 62 | |||
| 63 | #define PCIXCC_MAX_RESPONSE_SIZE PCIXCC_MAX_XCRB_RESPONSE_SIZE | ||
| 58 | 64 | ||
| 59 | #define PCIXCC_CLEANUP_TIME (15*HZ) | 65 | #define PCIXCC_CLEANUP_TIME (15*HZ) |
| 60 | 66 | ||
| @@ -74,23 +80,791 @@ static struct ap_device_id zcrypt_pcixcc_ids[] = { | |||
| 74 | { /* end of list */ }, | 80 | { /* end of list */ }, |
| 75 | }; | 81 | }; |
| 76 | 82 | ||
| 83 | #ifndef CONFIG_ZCRYPT_MONOLITHIC | ||
| 77 | MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids); | 84 | MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids); |
| 78 | MODULE_AUTHOR("IBM Corporation"); | 85 | MODULE_AUTHOR("IBM Corporation"); |
| 79 | MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, " \ | 86 | MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, " |
| 80 | "Copyright IBM Corp. 2001, 2012"); | 87 | "Copyright 2001, 2006 IBM Corporation"); |
| 81 | MODULE_LICENSE("GPL"); | 88 | MODULE_LICENSE("GPL"); |
| 89 | #endif | ||
| 82 | 90 | ||
| 83 | static int zcrypt_pcixcc_probe(struct ap_device *ap_dev); | 91 | static int zcrypt_pcixcc_probe(struct ap_device *ap_dev); |
| 84 | static void zcrypt_pcixcc_remove(struct ap_device *ap_dev); | 92 | static void zcrypt_pcixcc_remove(struct ap_device *ap_dev); |
| 93 | static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *, | ||
| 94 | struct ap_message *); | ||
| 85 | 95 | ||
| 86 | static struct ap_driver zcrypt_pcixcc_driver = { | 96 | static struct ap_driver zcrypt_pcixcc_driver = { |
| 87 | .probe = zcrypt_pcixcc_probe, | 97 | .probe = zcrypt_pcixcc_probe, |
| 88 | .remove = zcrypt_pcixcc_remove, | 98 | .remove = zcrypt_pcixcc_remove, |
| 99 | .receive = zcrypt_pcixcc_receive, | ||
| 89 | .ids = zcrypt_pcixcc_ids, | 100 | .ids = zcrypt_pcixcc_ids, |
| 90 | .request_timeout = PCIXCC_CLEANUP_TIME, | 101 | .request_timeout = PCIXCC_CLEANUP_TIME, |
| 91 | }; | 102 | }; |
| 92 | 103 | ||
| 93 | /** | 104 | /** |
| 105 | * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C | ||
| 106 | * card in a type6 message. The 3 fields that must be filled in at execution | ||
| 107 | * time are req_parml, rpl_parml and usage_domain. | ||
| 108 | * Everything about this interface is ascii/big-endian, since the | ||
| 109 | * device does *not* have 'Intel inside'. | ||
| 110 | * | ||
| 111 | * The CPRBX is followed immediately by the parm block. | ||
| 112 | * The parm block contains: | ||
| 113 | * - function code ('PD' 0x5044 or 'PK' 0x504B) | ||
| 114 | * - rule block (one of:) | ||
| 115 | * + 0x000A 'PKCS-1.2' (MCL2 'PD') | ||
| 116 | * + 0x000A 'ZERO-PAD' (MCL2 'PK') | ||
| 117 | * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD') | ||
| 118 | * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK') | ||
| 119 | * - VUD block | ||
| 120 | */ | ||
| 121 | static struct CPRBX static_cprbx = { | ||
| 122 | .cprb_len = 0x00DC, | ||
| 123 | .cprb_ver_id = 0x02, | ||
| 124 | .func_id = {0x54,0x32}, | ||
| 125 | }; | ||
| 126 | |||
| 127 | /** | ||
| 128 | * Convert a ICAMEX message to a type6 MEX message. | ||
| 129 | * | ||
| 130 | * @zdev: crypto device pointer | ||
| 131 | * @ap_msg: pointer to AP message | ||
| 132 | * @mex: pointer to user input data | ||
| 133 | * | ||
| 134 | * Returns 0 on success or -EFAULT. | ||
| 135 | */ | ||
| 136 | static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev, | ||
| 137 | struct ap_message *ap_msg, | ||
| 138 | struct ica_rsa_modexpo *mex) | ||
| 139 | { | ||
| 140 | static struct type6_hdr static_type6_hdrX = { | ||
| 141 | .type = 0x06, | ||
| 142 | .offset1 = 0x00000058, | ||
| 143 | .agent_id = {'C','A',}, | ||
| 144 | .function_code = {'P','K'}, | ||
| 145 | }; | ||
| 146 | static struct function_and_rules_block static_pke_fnr = { | ||
| 147 | .function_code = {'P','K'}, | ||
| 148 | .ulen = 10, | ||
| 149 | .only_rule = {'M','R','P',' ',' ',' ',' ',' '} | ||
| 150 | }; | ||
| 151 | static struct function_and_rules_block static_pke_fnr_MCL2 = { | ||
| 152 | .function_code = {'P','K'}, | ||
| 153 | .ulen = 10, | ||
| 154 | .only_rule = {'Z','E','R','O','-','P','A','D'} | ||
| 155 | }; | ||
| 156 | struct { | ||
| 157 | struct type6_hdr hdr; | ||
| 158 | struct CPRBX cprbx; | ||
| 159 | struct function_and_rules_block fr; | ||
| 160 | unsigned short length; | ||
| 161 | char text[0]; | ||
| 162 | } __attribute__((packed)) *msg = ap_msg->message; | ||
| 163 | int size; | ||
| 164 | |||
| 165 | /* VUD.ciphertext */ | ||
| 166 | msg->length = mex->inputdatalength + 2; | ||
| 167 | if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength)) | ||
| 168 | return -EFAULT; | ||
| 169 | |||
| 170 | /* Set up key which is located after the variable length text. */ | ||
| 171 | size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1); | ||
| 172 | if (size < 0) | ||
| 173 | return size; | ||
| 174 | size += sizeof(*msg) + mex->inputdatalength; | ||
| 175 | |||
| 176 | /* message header, cprbx and f&r */ | ||
| 177 | msg->hdr = static_type6_hdrX; | ||
| 178 | msg->hdr.ToCardLen1 = size - sizeof(msg->hdr); | ||
| 179 | msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr); | ||
| 180 | |||
| 181 | msg->cprbx = static_cprbx; | ||
| 182 | msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid); | ||
| 183 | msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1; | ||
| 184 | |||
| 185 | msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ? | ||
| 186 | static_pke_fnr_MCL2 : static_pke_fnr; | ||
| 187 | |||
| 188 | msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx); | ||
| 189 | |||
| 190 | ap_msg->length = size; | ||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | /** | ||
| 195 | * Convert a ICACRT message to a type6 CRT message. | ||
| 196 | * | ||
| 197 | * @zdev: crypto device pointer | ||
| 198 | * @ap_msg: pointer to AP message | ||
| 199 | * @crt: pointer to user input data | ||
| 200 | * | ||
| 201 | * Returns 0 on success or -EFAULT. | ||
| 202 | */ | ||
| 203 | static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev, | ||
| 204 | struct ap_message *ap_msg, | ||
| 205 | struct ica_rsa_modexpo_crt *crt) | ||
| 206 | { | ||
| 207 | static struct type6_hdr static_type6_hdrX = { | ||
| 208 | .type = 0x06, | ||
| 209 | .offset1 = 0x00000058, | ||
| 210 | .agent_id = {'C','A',}, | ||
| 211 | .function_code = {'P','D'}, | ||
| 212 | }; | ||
| 213 | static struct function_and_rules_block static_pkd_fnr = { | ||
| 214 | .function_code = {'P','D'}, | ||
| 215 | .ulen = 10, | ||
| 216 | .only_rule = {'Z','E','R','O','-','P','A','D'} | ||
| 217 | }; | ||
| 218 | |||
| 219 | static struct function_and_rules_block static_pkd_fnr_MCL2 = { | ||
| 220 | .function_code = {'P','D'}, | ||
| 221 | .ulen = 10, | ||
| 222 | .only_rule = {'P','K','C','S','-','1','.','2'} | ||
| 223 | }; | ||
| 224 | struct { | ||
| 225 | struct type6_hdr hdr; | ||
| 226 | struct CPRBX cprbx; | ||
| 227 | struct function_and_rules_block fr; | ||
| 228 | unsigned short length; | ||
| 229 | char text[0]; | ||
| 230 | } __attribute__((packed)) *msg = ap_msg->message; | ||
| 231 | int size; | ||
| 232 | |||
| 233 | /* VUD.ciphertext */ | ||
| 234 | msg->length = crt->inputdatalength + 2; | ||
| 235 | if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength)) | ||
| 236 | return -EFAULT; | ||
| 237 | |||
| 238 | /* Set up key which is located after the variable length text. */ | ||
| 239 | size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1); | ||
| 240 | if (size < 0) | ||
| 241 | return size; | ||
| 242 | size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */ | ||
| 243 | |||
| 244 | /* message header, cprbx and f&r */ | ||
| 245 | msg->hdr = static_type6_hdrX; | ||
| 246 | msg->hdr.ToCardLen1 = size - sizeof(msg->hdr); | ||
| 247 | msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr); | ||
| 248 | |||
| 249 | msg->cprbx = static_cprbx; | ||
| 250 | msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid); | ||
| 251 | msg->cprbx.req_parml = msg->cprbx.rpl_msgbl = | ||
| 252 | size - sizeof(msg->hdr) - sizeof(msg->cprbx); | ||
| 253 | |||
| 254 | msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ? | ||
| 255 | static_pkd_fnr_MCL2 : static_pkd_fnr; | ||
| 256 | |||
| 257 | ap_msg->length = size; | ||
| 258 | return 0; | ||
| 259 | } | ||
| 260 | |||
| 261 | /** | ||
| 262 | * Convert a XCRB message to a type6 CPRB message. | ||
| 263 | * | ||
| 264 | * @zdev: crypto device pointer | ||
| 265 | * @ap_msg: pointer to AP message | ||
| 266 | * @xcRB: pointer to user input data | ||
| 267 | * | ||
| 268 | * Returns 0 on success or -EFAULT. | ||
| 269 | */ | ||
| 270 | struct type86_fmt2_msg { | ||
| 271 | struct type86_hdr hdr; | ||
| 272 | struct type86_fmt2_ext fmt2; | ||
| 273 | } __attribute__((packed)); | ||
| 274 | |||
| 275 | static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, | ||
| 276 | struct ap_message *ap_msg, | ||
| 277 | struct ica_xcRB *xcRB) | ||
| 278 | { | ||
| 279 | static struct type6_hdr static_type6_hdrX = { | ||
| 280 | .type = 0x06, | ||
| 281 | .offset1 = 0x00000058, | ||
| 282 | }; | ||
| 283 | struct { | ||
| 284 | struct type6_hdr hdr; | ||
| 285 | struct CPRBX cprbx; | ||
| 286 | } __attribute__((packed)) *msg = ap_msg->message; | ||
| 287 | |||
| 288 | int rcblen = CEIL4(xcRB->request_control_blk_length); | ||
| 289 | int replylen; | ||
| 290 | char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen; | ||
| 291 | char *function_code; | ||
| 292 | |||
| 293 | /* length checks */ | ||
| 294 | ap_msg->length = sizeof(struct type6_hdr) + | ||
| 295 | CEIL4(xcRB->request_control_blk_length) + | ||
| 296 | xcRB->request_data_length; | ||
| 297 | if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE) | ||
| 298 | return -EFAULT; | ||
| 299 | if (CEIL4(xcRB->reply_control_blk_length) > PCIXCC_MAX_XCRB_REPLY_SIZE) | ||
| 300 | return -EFAULT; | ||
| 301 | if (CEIL4(xcRB->reply_data_length) > PCIXCC_MAX_XCRB_DATA_SIZE) | ||
| 302 | return -EFAULT; | ||
| 303 | replylen = CEIL4(xcRB->reply_control_blk_length) + | ||
| 304 | CEIL4(xcRB->reply_data_length) + | ||
| 305 | sizeof(struct type86_fmt2_msg); | ||
| 306 | if (replylen > PCIXCC_MAX_XCRB_RESPONSE_SIZE) { | ||
| 307 | xcRB->reply_control_blk_length = PCIXCC_MAX_XCRB_RESPONSE_SIZE - | ||
| 308 | (sizeof(struct type86_fmt2_msg) + | ||
| 309 | CEIL4(xcRB->reply_data_length)); | ||
| 310 | } | ||
| 311 | |||
| 312 | /* prepare type6 header */ | ||
| 313 | msg->hdr = static_type6_hdrX; | ||
| 314 | memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID)); | ||
| 315 | msg->hdr.ToCardLen1 = xcRB->request_control_blk_length; | ||
| 316 | if (xcRB->request_data_length) { | ||
| 317 | msg->hdr.offset2 = msg->hdr.offset1 + rcblen; | ||
| 318 | msg->hdr.ToCardLen2 = xcRB->request_data_length; | ||
| 319 | } | ||
| 320 | msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length; | ||
| 321 | msg->hdr.FromCardLen2 = xcRB->reply_data_length; | ||
| 322 | |||
| 323 | /* prepare CPRB */ | ||
| 324 | if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr, | ||
| 325 | xcRB->request_control_blk_length)) | ||
| 326 | return -EFAULT; | ||
| 327 | if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) > | ||
| 328 | xcRB->request_control_blk_length) | ||
| 329 | return -EFAULT; | ||
| 330 | function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len; | ||
| 331 | memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code)); | ||
| 332 | |||
| 333 | if (memcmp(function_code, "US", 2) == 0) | ||
| 334 | ap_msg->special = 1; | ||
| 335 | else | ||
| 336 | ap_msg->special = 0; | ||
| 337 | |||
| 338 | /* copy data block */ | ||
| 339 | if (xcRB->request_data_length && | ||
| 340 | copy_from_user(req_data, xcRB->request_data_address, | ||
| 341 | xcRB->request_data_length)) | ||
| 342 | return -EFAULT; | ||
| 343 | return 0; | ||
| 344 | } | ||
| 345 | |||
| 346 | /** | ||
| 347 | * Prepare a type6 CPRB message for random number generation | ||
| 348 | * | ||
| 349 | * @ap_dev: AP device pointer | ||
| 350 | * @ap_msg: pointer to AP message | ||
| 351 | */ | ||
| 352 | static void rng_type6CPRB_msgX(struct ap_device *ap_dev, | ||
| 353 | struct ap_message *ap_msg, | ||
| 354 | unsigned random_number_length) | ||
| 355 | { | ||
| 356 | struct { | ||
| 357 | struct type6_hdr hdr; | ||
| 358 | struct CPRBX cprbx; | ||
| 359 | char function_code[2]; | ||
| 360 | short int rule_length; | ||
| 361 | char rule[8]; | ||
| 362 | short int verb_length; | ||
| 363 | short int key_length; | ||
| 364 | } __attribute__((packed)) *msg = ap_msg->message; | ||
| 365 | static struct type6_hdr static_type6_hdrX = { | ||
| 366 | .type = 0x06, | ||
| 367 | .offset1 = 0x00000058, | ||
| 368 | .agent_id = {'C', 'A'}, | ||
| 369 | .function_code = {'R', 'L'}, | ||
| 370 | .ToCardLen1 = sizeof *msg - sizeof(msg->hdr), | ||
| 371 | .FromCardLen1 = sizeof *msg - sizeof(msg->hdr), | ||
| 372 | }; | ||
| 373 | static struct CPRBX local_cprbx = { | ||
| 374 | .cprb_len = 0x00dc, | ||
| 375 | .cprb_ver_id = 0x02, | ||
| 376 | .func_id = {0x54, 0x32}, | ||
| 377 | .req_parml = sizeof *msg - sizeof(msg->hdr) - | ||
| 378 | sizeof(msg->cprbx), | ||
| 379 | .rpl_msgbl = sizeof *msg - sizeof(msg->hdr), | ||
| 380 | }; | ||
| 381 | |||
| 382 | msg->hdr = static_type6_hdrX; | ||
| 383 | msg->hdr.FromCardLen2 = random_number_length, | ||
| 384 | msg->cprbx = local_cprbx; | ||
| 385 | msg->cprbx.rpl_datal = random_number_length, | ||
| 386 | msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid); | ||
| 387 | memcpy(msg->function_code, msg->hdr.function_code, 0x02); | ||
| 388 | msg->rule_length = 0x0a; | ||
| 389 | memcpy(msg->rule, "RANDOM ", 8); | ||
| 390 | msg->verb_length = 0x02; | ||
| 391 | msg->key_length = 0x02; | ||
| 392 | ap_msg->length = sizeof *msg; | ||
| 393 | } | ||
| 394 | |||
| 395 | /** | ||
| 396 | * Copy results from a type 86 ICA reply message back to user space. | ||
| 397 | * | ||
| 398 | * @zdev: crypto device pointer | ||
| 399 | * @reply: reply AP message. | ||
| 400 | * @data: pointer to user output data | ||
| 401 | * @length: size of user output data | ||
| 402 | * | ||
| 403 | * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error. | ||
| 404 | */ | ||
| 405 | struct type86x_reply { | ||
| 406 | struct type86_hdr hdr; | ||
| 407 | struct type86_fmt2_ext fmt2; | ||
| 408 | struct CPRBX cprbx; | ||
| 409 | unsigned char pad[4]; /* 4 byte function code/rules block ? */ | ||
| 410 | unsigned short length; | ||
| 411 | char text[0]; | ||
| 412 | } __attribute__((packed)); | ||
| 413 | |||
| 414 | static int convert_type86_ica(struct zcrypt_device *zdev, | ||
| 415 | struct ap_message *reply, | ||
| 416 | char __user *outputdata, | ||
| 417 | unsigned int outputdatalength) | ||
| 418 | { | ||
| 419 | static unsigned char static_pad[] = { | ||
| 420 | 0x00,0x02, | ||
| 421 | 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD, | ||
| 422 | 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57, | ||
| 423 | 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B, | ||
| 424 | 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39, | ||
| 425 | 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5, | ||
| 426 | 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D, | ||
| 427 | 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB, | ||
| 428 | 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F, | ||
| 429 | 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9, | ||
| 430 | 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45, | ||
| 431 | 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9, | ||
| 432 | 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F, | ||
| 433 | 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD, | ||
| 434 | 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D, | ||
| 435 | 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD, | ||
| 436 | 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9, | ||
| 437 | 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B, | ||
| 438 | 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B, | ||
| 439 | 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B, | ||
| 440 | 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD, | ||
| 441 | 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7, | ||
| 442 | 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1, | ||
| 443 | 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3, | ||
| 444 | 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23, | ||
| 445 | 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55, | ||
| 446 | 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43, | ||
| 447 | 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F, | ||
| 448 | 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F, | ||
| 449 | 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5, | ||
| 450 | 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD, | ||
| 451 | 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41, | ||
| 452 | 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09 | ||
| 453 | }; | ||
| 454 | struct type86x_reply *msg = reply->message; | ||
| 455 | unsigned short service_rc, service_rs; | ||
| 456 | unsigned int reply_len, pad_len; | ||
| 457 | char *data; | ||
| 458 | |||
| 459 | service_rc = msg->cprbx.ccp_rtcode; | ||
| 460 | if (unlikely(service_rc != 0)) { | ||
| 461 | service_rs = msg->cprbx.ccp_rscode; | ||
| 462 | if (service_rc == 8 && service_rs == 66) | ||
| 463 | return -EINVAL; | ||
| 464 | if (service_rc == 8 && service_rs == 65) | ||
| 465 | return -EINVAL; | ||
| 466 | if (service_rc == 8 && service_rs == 770) | ||
| 467 | return -EINVAL; | ||
| 468 | if (service_rc == 8 && service_rs == 783) { | ||
| 469 | zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; | ||
| 470 | return -EAGAIN; | ||
| 471 | } | ||
| 472 | if (service_rc == 12 && service_rs == 769) | ||
| 473 | return -EINVAL; | ||
| 474 | if (service_rc == 8 && service_rs == 72) | ||
| 475 | return -EINVAL; | ||
| 476 | zdev->online = 0; | ||
| 477 | return -EAGAIN; /* repeat the request on a different device. */ | ||
| 478 | } | ||
| 479 | data = msg->text; | ||
| 480 | reply_len = msg->length - 2; | ||
| 481 | if (reply_len > outputdatalength) | ||
| 482 | return -EINVAL; | ||
| 483 | /* | ||
| 484 | * For all encipher requests, the length of the ciphertext (reply_len) | ||
| 485 | * will always equal the modulus length. For MEX decipher requests | ||
| 486 | * the output needs to get padded. Minimum pad size is 10. | ||
| 487 | * | ||
| 488 | * Currently, the cases where padding will be added is for: | ||
| 489 | * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support | ||
| 490 | * ZERO-PAD and CRT is only supported for PKD requests) | ||
| 491 | * - PCICC, always | ||
| 492 | */ | ||
| 493 | pad_len = outputdatalength - reply_len; | ||
| 494 | if (pad_len > 0) { | ||
| 495 | if (pad_len < 10) | ||
| 496 | return -EINVAL; | ||
| 497 | /* 'restore' padding left in the PCICC/PCIXCC card. */ | ||
| 498 | if (copy_to_user(outputdata, static_pad, pad_len - 1)) | ||
| 499 | return -EFAULT; | ||
| 500 | if (put_user(0, outputdata + pad_len - 1)) | ||
| 501 | return -EFAULT; | ||
| 502 | } | ||
| 503 | /* Copy the crypto response to user space. */ | ||
| 504 | if (copy_to_user(outputdata + pad_len, data, reply_len)) | ||
| 505 | return -EFAULT; | ||
| 506 | return 0; | ||
| 507 | } | ||
| 508 | |||
| 509 | /** | ||
| 510 | * Copy results from a type 86 XCRB reply message back to user space. | ||
| 511 | * | ||
| 512 | * @zdev: crypto device pointer | ||
| 513 | * @reply: reply AP message. | ||
| 514 | * @xcRB: pointer to XCRB | ||
| 515 | * | ||
| 516 | * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error. | ||
| 517 | */ | ||
| 518 | static int convert_type86_xcrb(struct zcrypt_device *zdev, | ||
| 519 | struct ap_message *reply, | ||
| 520 | struct ica_xcRB *xcRB) | ||
| 521 | { | ||
| 522 | struct type86_fmt2_msg *msg = reply->message; | ||
| 523 | char *data = reply->message; | ||
| 524 | |||
| 525 | /* Copy CPRB to user */ | ||
| 526 | if (copy_to_user(xcRB->reply_control_blk_addr, | ||
| 527 | data + msg->fmt2.offset1, msg->fmt2.count1)) | ||
| 528 | return -EFAULT; | ||
| 529 | xcRB->reply_control_blk_length = msg->fmt2.count1; | ||
| 530 | |||
| 531 | /* Copy data buffer to user */ | ||
| 532 | if (msg->fmt2.count2) | ||
| 533 | if (copy_to_user(xcRB->reply_data_addr, | ||
| 534 | data + msg->fmt2.offset2, msg->fmt2.count2)) | ||
| 535 | return -EFAULT; | ||
| 536 | xcRB->reply_data_length = msg->fmt2.count2; | ||
| 537 | return 0; | ||
| 538 | } | ||
| 539 | |||
| 540 | static int convert_type86_rng(struct zcrypt_device *zdev, | ||
| 541 | struct ap_message *reply, | ||
| 542 | char *buffer) | ||
| 543 | { | ||
| 544 | struct { | ||
| 545 | struct type86_hdr hdr; | ||
| 546 | struct type86_fmt2_ext fmt2; | ||
| 547 | struct CPRBX cprbx; | ||
| 548 | } __attribute__((packed)) *msg = reply->message; | ||
| 549 | char *data = reply->message; | ||
| 550 | |||
| 551 | if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0) | ||
| 552 | return -EINVAL; | ||
| 553 | memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2); | ||
| 554 | return msg->fmt2.count2; | ||
| 555 | } | ||
| 556 | |||
| 557 | static int convert_response_ica(struct zcrypt_device *zdev, | ||
| 558 | struct ap_message *reply, | ||
| 559 | char __user *outputdata, | ||
| 560 | unsigned int outputdatalength) | ||
| 561 | { | ||
| 562 | struct type86x_reply *msg = reply->message; | ||
| 563 | |||
| 564 | /* Response type byte is the second byte in the response. */ | ||
| 565 | switch (((unsigned char *) reply->message)[1]) { | ||
| 566 | case TYPE82_RSP_CODE: | ||
| 567 | case TYPE88_RSP_CODE: | ||
| 568 | return convert_error(zdev, reply); | ||
| 569 | case TYPE86_RSP_CODE: | ||
| 570 | if (msg->cprbx.ccp_rtcode && | ||
| 571 | (msg->cprbx.ccp_rscode == 0x14f) && | ||
| 572 | (outputdatalength > 256)) { | ||
| 573 | if (zdev->max_exp_bit_length <= 17) { | ||
| 574 | zdev->max_exp_bit_length = 17; | ||
| 575 | return -EAGAIN; | ||
| 576 | } else | ||
| 577 | return -EINVAL; | ||
| 578 | } | ||
| 579 | if (msg->hdr.reply_code) | ||
| 580 | return convert_error(zdev, reply); | ||
| 581 | if (msg->cprbx.cprb_ver_id == 0x02) | ||
| 582 | return convert_type86_ica(zdev, reply, | ||
| 583 | outputdata, outputdatalength); | ||
| 584 | /* Fall through, no break, incorrect cprb version is an unknown | ||
| 585 | * response */ | ||
| 586 | default: /* Unknown response type, this should NEVER EVER happen */ | ||
| 587 | zdev->online = 0; | ||
| 588 | return -EAGAIN; /* repeat the request on a different device. */ | ||
| 589 | } | ||
| 590 | } | ||
| 591 | |||
| 592 | static int convert_response_xcrb(struct zcrypt_device *zdev, | ||
| 593 | struct ap_message *reply, | ||
| 594 | struct ica_xcRB *xcRB) | ||
| 595 | { | ||
| 596 | struct type86x_reply *msg = reply->message; | ||
| 597 | |||
| 598 | /* Response type byte is the second byte in the response. */ | ||
| 599 | switch (((unsigned char *) reply->message)[1]) { | ||
| 600 | case TYPE82_RSP_CODE: | ||
| 601 | case TYPE88_RSP_CODE: | ||
| 602 | xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ | ||
| 603 | return convert_error(zdev, reply); | ||
| 604 | case TYPE86_RSP_CODE: | ||
| 605 | if (msg->hdr.reply_code) { | ||
| 606 | memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32)); | ||
| 607 | return convert_error(zdev, reply); | ||
| 608 | } | ||
| 609 | if (msg->cprbx.cprb_ver_id == 0x02) | ||
| 610 | return convert_type86_xcrb(zdev, reply, xcRB); | ||
| 611 | /* Fall through, no break, incorrect cprb version is an unknown | ||
| 612 | * response */ | ||
| 613 | default: /* Unknown response type, this should NEVER EVER happen */ | ||
| 614 | xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ | ||
| 615 | zdev->online = 0; | ||
| 616 | return -EAGAIN; /* repeat the request on a different device. */ | ||
| 617 | } | ||
| 618 | } | ||
| 619 | |||
| 620 | static int convert_response_rng(struct zcrypt_device *zdev, | ||
| 621 | struct ap_message *reply, | ||
| 622 | char *data) | ||
| 623 | { | ||
| 624 | struct type86x_reply *msg = reply->message; | ||
| 625 | |||
| 626 | switch (msg->hdr.type) { | ||
| 627 | case TYPE82_RSP_CODE: | ||
| 628 | case TYPE88_RSP_CODE: | ||
| 629 | return -EINVAL; | ||
| 630 | case TYPE86_RSP_CODE: | ||
| 631 | if (msg->hdr.reply_code) | ||
| 632 | return -EINVAL; | ||
| 633 | if (msg->cprbx.cprb_ver_id == 0x02) | ||
| 634 | return convert_type86_rng(zdev, reply, data); | ||
| 635 | /* Fall through, no break, incorrect cprb version is an unknown | ||
| 636 | * response */ | ||
| 637 | default: /* Unknown response type, this should NEVER EVER happen */ | ||
| 638 | zdev->online = 0; | ||
| 639 | return -EAGAIN; /* repeat the request on a different device. */ | ||
| 640 | } | ||
| 641 | } | ||
| 642 | |||
| 643 | /** | ||
| 644 | * This function is called from the AP bus code after a crypto request | ||
| 645 | * "msg" has finished with the reply message "reply". | ||
| 646 | * It is called from tasklet context. | ||
| 647 | * @ap_dev: pointer to the AP device | ||
| 648 | * @msg: pointer to the AP message | ||
| 649 | * @reply: pointer to the AP reply message | ||
| 650 | */ | ||
| 651 | static void zcrypt_pcixcc_receive(struct ap_device *ap_dev, | ||
| 652 | struct ap_message *msg, | ||
| 653 | struct ap_message *reply) | ||
| 654 | { | ||
| 655 | static struct error_hdr error_reply = { | ||
| 656 | .type = TYPE82_RSP_CODE, | ||
| 657 | .reply_code = REP82_ERROR_MACHINE_FAILURE, | ||
| 658 | }; | ||
| 659 | struct response_type *resp_type = | ||
| 660 | (struct response_type *) msg->private; | ||
| 661 | struct type86x_reply *t86r; | ||
| 662 | int length; | ||
| 663 | |||
| 664 | /* Copy the reply message to the request message buffer. */ | ||
| 665 | if (IS_ERR(reply)) { | ||
| 666 | memcpy(msg->message, &error_reply, sizeof(error_reply)); | ||
| 667 | goto out; | ||
| 668 | } | ||
| 669 | t86r = reply->message; | ||
| 670 | if (t86r->hdr.type == TYPE86_RSP_CODE && | ||
| 671 | t86r->cprbx.cprb_ver_id == 0x02) { | ||
| 672 | switch (resp_type->type) { | ||
| 673 | case PCIXCC_RESPONSE_TYPE_ICA: | ||
| 674 | length = sizeof(struct type86x_reply) | ||
| 675 | + t86r->length - 2; | ||
| 676 | length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length); | ||
| 677 | memcpy(msg->message, reply->message, length); | ||
| 678 | break; | ||
| 679 | case PCIXCC_RESPONSE_TYPE_XCRB: | ||
| 680 | length = t86r->fmt2.offset2 + t86r->fmt2.count2; | ||
| 681 | length = min(PCIXCC_MAX_XCRB_RESPONSE_SIZE, length); | ||
| 682 | memcpy(msg->message, reply->message, length); | ||
| 683 | break; | ||
| 684 | default: | ||
| 685 | memcpy(msg->message, &error_reply, sizeof error_reply); | ||
| 686 | } | ||
| 687 | } else | ||
| 688 | memcpy(msg->message, reply->message, sizeof error_reply); | ||
| 689 | out: | ||
| 690 | complete(&(resp_type->work)); | ||
| 691 | } | ||
| 692 | |||
| 693 | static atomic_t zcrypt_step = ATOMIC_INIT(0); | ||
| 694 | |||
| 695 | /** | ||
| 696 | * The request distributor calls this function if it picked the PCIXCC/CEX2C | ||
| 697 | * device to handle a modexpo request. | ||
| 698 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
| 699 | * PCIXCC/CEX2C device to the request distributor | ||
| 700 | * @mex: pointer to the modexpo request buffer | ||
| 701 | */ | ||
| 702 | static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev, | ||
| 703 | struct ica_rsa_modexpo *mex) | ||
| 704 | { | ||
| 705 | struct ap_message ap_msg; | ||
| 706 | struct response_type resp_type = { | ||
| 707 | .type = PCIXCC_RESPONSE_TYPE_ICA, | ||
| 708 | }; | ||
| 709 | int rc; | ||
| 710 | |||
| 711 | ap_init_message(&ap_msg); | ||
| 712 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | ||
| 713 | if (!ap_msg.message) | ||
| 714 | return -ENOMEM; | ||
| 715 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
| 716 | atomic_inc_return(&zcrypt_step); | ||
| 717 | ap_msg.private = &resp_type; | ||
| 718 | rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex); | ||
| 719 | if (rc) | ||
| 720 | goto out_free; | ||
| 721 | init_completion(&resp_type.work); | ||
| 722 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
| 723 | rc = wait_for_completion_interruptible(&resp_type.work); | ||
| 724 | if (rc == 0) | ||
| 725 | rc = convert_response_ica(zdev, &ap_msg, mex->outputdata, | ||
| 726 | mex->outputdatalength); | ||
| 727 | else | ||
| 728 | /* Signal pending. */ | ||
| 729 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
| 730 | out_free: | ||
| 731 | free_page((unsigned long) ap_msg.message); | ||
| 732 | return rc; | ||
| 733 | } | ||
| 734 | |||
| 735 | /** | ||
| 736 | * The request distributor calls this function if it picked the PCIXCC/CEX2C | ||
| 737 | * device to handle a modexpo_crt request. | ||
| 738 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
| 739 | * PCIXCC/CEX2C device to the request distributor | ||
| 740 | * @crt: pointer to the modexpoc_crt request buffer | ||
| 741 | */ | ||
| 742 | static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev, | ||
| 743 | struct ica_rsa_modexpo_crt *crt) | ||
| 744 | { | ||
| 745 | struct ap_message ap_msg; | ||
| 746 | struct response_type resp_type = { | ||
| 747 | .type = PCIXCC_RESPONSE_TYPE_ICA, | ||
| 748 | }; | ||
| 749 | int rc; | ||
| 750 | |||
| 751 | ap_init_message(&ap_msg); | ||
| 752 | ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); | ||
| 753 | if (!ap_msg.message) | ||
| 754 | return -ENOMEM; | ||
| 755 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
| 756 | atomic_inc_return(&zcrypt_step); | ||
| 757 | ap_msg.private = &resp_type; | ||
| 758 | rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt); | ||
| 759 | if (rc) | ||
| 760 | goto out_free; | ||
| 761 | init_completion(&resp_type.work); | ||
| 762 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
| 763 | rc = wait_for_completion_interruptible(&resp_type.work); | ||
| 764 | if (rc == 0) | ||
| 765 | rc = convert_response_ica(zdev, &ap_msg, crt->outputdata, | ||
| 766 | crt->outputdatalength); | ||
| 767 | else | ||
| 768 | /* Signal pending. */ | ||
| 769 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
| 770 | out_free: | ||
| 771 | free_page((unsigned long) ap_msg.message); | ||
| 772 | return rc; | ||
| 773 | } | ||
| 774 | |||
| 775 | /** | ||
| 776 | * The request distributor calls this function if it picked the PCIXCC/CEX2C | ||
| 777 | * device to handle a send_cprb request. | ||
| 778 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
| 779 | * PCIXCC/CEX2C device to the request distributor | ||
| 780 | * @xcRB: pointer to the send_cprb request buffer | ||
| 781 | */ | ||
| 782 | static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, | ||
| 783 | struct ica_xcRB *xcRB) | ||
| 784 | { | ||
| 785 | struct ap_message ap_msg; | ||
| 786 | struct response_type resp_type = { | ||
| 787 | .type = PCIXCC_RESPONSE_TYPE_XCRB, | ||
| 788 | }; | ||
| 789 | int rc; | ||
| 790 | |||
| 791 | ap_init_message(&ap_msg); | ||
| 792 | ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL); | ||
| 793 | if (!ap_msg.message) | ||
| 794 | return -ENOMEM; | ||
| 795 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
| 796 | atomic_inc_return(&zcrypt_step); | ||
| 797 | ap_msg.private = &resp_type; | ||
| 798 | rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB); | ||
| 799 | if (rc) | ||
| 800 | goto out_free; | ||
| 801 | init_completion(&resp_type.work); | ||
| 802 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
| 803 | rc = wait_for_completion_interruptible(&resp_type.work); | ||
| 804 | if (rc == 0) | ||
| 805 | rc = convert_response_xcrb(zdev, &ap_msg, xcRB); | ||
| 806 | else | ||
| 807 | /* Signal pending. */ | ||
| 808 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
| 809 | out_free: | ||
| 810 | kzfree(ap_msg.message); | ||
| 811 | return rc; | ||
| 812 | } | ||
| 813 | |||
| 814 | /** | ||
| 815 | * The request distributor calls this function if it picked the PCIXCC/CEX2C | ||
| 816 | * device to generate random data. | ||
| 817 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
| 818 | * PCIXCC/CEX2C device to the request distributor | ||
| 819 | * @buffer: pointer to a memory page to return random data | ||
| 820 | */ | ||
| 821 | |||
| 822 | static long zcrypt_pcixcc_rng(struct zcrypt_device *zdev, | ||
| 823 | char *buffer) | ||
| 824 | { | ||
| 825 | struct ap_message ap_msg; | ||
| 826 | struct response_type resp_type = { | ||
| 827 | .type = PCIXCC_RESPONSE_TYPE_XCRB, | ||
| 828 | }; | ||
| 829 | int rc; | ||
| 830 | |||
| 831 | ap_init_message(&ap_msg); | ||
| 832 | ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL); | ||
| 833 | if (!ap_msg.message) | ||
| 834 | return -ENOMEM; | ||
| 835 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
| 836 | atomic_inc_return(&zcrypt_step); | ||
| 837 | ap_msg.private = &resp_type; | ||
| 838 | rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE); | ||
| 839 | init_completion(&resp_type.work); | ||
| 840 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
| 841 | rc = wait_for_completion_interruptible(&resp_type.work); | ||
| 842 | if (rc == 0) | ||
| 843 | rc = convert_response_rng(zdev, &ap_msg, buffer); | ||
| 844 | else | ||
| 845 | /* Signal pending. */ | ||
| 846 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
| 847 | kfree(ap_msg.message); | ||
| 848 | return rc; | ||
| 849 | } | ||
| 850 | |||
| 851 | /** | ||
| 852 | * The crypto operations for a PCIXCC/CEX2C card. | ||
| 853 | */ | ||
| 854 | static struct zcrypt_ops zcrypt_pcixcc_ops = { | ||
| 855 | .rsa_modexpo = zcrypt_pcixcc_modexpo, | ||
| 856 | .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt, | ||
| 857 | .send_cprb = zcrypt_pcixcc_send_cprb, | ||
| 858 | }; | ||
| 859 | |||
| 860 | static struct zcrypt_ops zcrypt_pcixcc_with_rng_ops = { | ||
| 861 | .rsa_modexpo = zcrypt_pcixcc_modexpo, | ||
| 862 | .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt, | ||
| 863 | .send_cprb = zcrypt_pcixcc_send_cprb, | ||
| 864 | .rng = zcrypt_pcixcc_rng, | ||
| 865 | }; | ||
| 866 | |||
| 867 | /** | ||
| 94 | * Micro-code detection function. Its sends a message to a pcixcc card | 868 | * Micro-code detection function. Its sends a message to a pcixcc card |
| 95 | * to find out the microcode level. | 869 | * to find out the microcode level. |
| 96 | * @ap_dev: pointer to the AP device. | 870 | * @ap_dev: pointer to the AP device. |
| @@ -269,7 +1043,7 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) | |||
| 269 | struct zcrypt_device *zdev; | 1043 | struct zcrypt_device *zdev; |
| 270 | int rc = 0; | 1044 | int rc = 0; |
| 271 | 1045 | ||
| 272 | zdev = zcrypt_device_alloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE); | 1046 | zdev = zcrypt_device_alloc(PCIXCC_MAX_RESPONSE_SIZE); |
| 273 | if (!zdev) | 1047 | if (!zdev) |
| 274 | return -ENOMEM; | 1048 | return -ENOMEM; |
| 275 | zdev->ap_dev = ap_dev; | 1049 | zdev->ap_dev = ap_dev; |
| @@ -322,11 +1096,9 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) | |||
| 322 | return rc; | 1096 | return rc; |
| 323 | } | 1097 | } |
| 324 | if (rc) | 1098 | if (rc) |
| 325 | zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, | 1099 | zdev->ops = &zcrypt_pcixcc_with_rng_ops; |
| 326 | MSGTYPE06_VARIANT_DEFAULT); | ||
| 327 | else | 1100 | else |
| 328 | zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, | 1101 | zdev->ops = &zcrypt_pcixcc_ops; |
| 329 | MSGTYPE06_VARIANT_NORNG); | ||
| 330 | ap_dev->reply = &zdev->reply; | 1102 | ap_dev->reply = &zdev->reply; |
| 331 | ap_dev->private = zdev; | 1103 | ap_dev->private = zdev; |
| 332 | rc = zcrypt_device_register(zdev); | 1104 | rc = zcrypt_device_register(zdev); |
| @@ -336,7 +1108,6 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) | |||
| 336 | 1108 | ||
| 337 | out_free: | 1109 | out_free: |
| 338 | ap_dev->private = NULL; | 1110 | ap_dev->private = NULL; |
| 339 | zcrypt_msgtype_release(zdev->ops); | ||
| 340 | zcrypt_device_free(zdev); | 1111 | zcrypt_device_free(zdev); |
| 341 | return rc; | 1112 | return rc; |
| 342 | } | 1113 | } |
| @@ -348,10 +1119,8 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev) | |||
| 348 | static void zcrypt_pcixcc_remove(struct ap_device *ap_dev) | 1119 | static void zcrypt_pcixcc_remove(struct ap_device *ap_dev) |
| 349 | { | 1120 | { |
| 350 | struct zcrypt_device *zdev = ap_dev->private; | 1121 | struct zcrypt_device *zdev = ap_dev->private; |
| 351 | struct zcrypt_ops *zops = zdev->ops; | ||
| 352 | 1122 | ||
| 353 | zcrypt_device_unregister(zdev); | 1123 | zcrypt_device_unregister(zdev); |
| 354 | zcrypt_msgtype_release(zops); | ||
| 355 | } | 1124 | } |
| 356 | 1125 | ||
| 357 | int __init zcrypt_pcixcc_init(void) | 1126 | int __init zcrypt_pcixcc_init(void) |
| @@ -364,5 +1133,7 @@ void zcrypt_pcixcc_exit(void) | |||
| 364 | ap_driver_unregister(&zcrypt_pcixcc_driver); | 1133 | ap_driver_unregister(&zcrypt_pcixcc_driver); |
| 365 | } | 1134 | } |
| 366 | 1135 | ||
| 1136 | #ifndef CONFIG_ZCRYPT_MONOLITHIC | ||
| 367 | module_init(zcrypt_pcixcc_init); | 1137 | module_init(zcrypt_pcixcc_init); |
| 368 | module_exit(zcrypt_pcixcc_exit); | 1138 | module_exit(zcrypt_pcixcc_exit); |
| 1139 | #endif | ||
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.h b/drivers/s390/crypto/zcrypt_pcixcc.h index eacafc8962f..8cb7d7a6973 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.h +++ b/drivers/s390/crypto/zcrypt_pcixcc.h | |||
| @@ -1,13 +1,14 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/drivers/s390/crypto/zcrypt_pcixcc.h | ||
| 3 | * | ||
| 2 | * zcrypt 2.1.0 | 4 | * zcrypt 2.1.0 |
| 3 | * | 5 | * |
| 4 | * Copyright IBM Corp. 2001, 2012 | 6 | * Copyright (C) 2001, 2006 IBM Corporation |
| 5 | * Author(s): Robert Burroughs | 7 | * Author(s): Robert Burroughs |
| 6 | * Eric Rossman (edrossma@us.ibm.com) | 8 | * Eric Rossman (edrossma@us.ibm.com) |
| 7 | * | 9 | * |
| 8 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) | 10 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) |
| 9 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> | 11 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> |
| 10 | * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com> | ||
| 11 | * | 12 | * |
| 12 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
| 13 | * it under the terms of the GNU General Public License as published by | 14 | * it under the terms of the GNU General Public License as published by |
