diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/s390/crypto | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
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 |