1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/err.h>
16#include <linux/delay.h>
17#include <linux/slab.h>
18#include <linux/atomic.h>
19#include <linux/uaccess.h>
20#include <linux/mod_devicetable.h>
21
22#include "ap_bus.h"
23#include "zcrypt_api.h"
24#include "zcrypt_error.h"
25#include "zcrypt_msgtype6.h"
26#include "zcrypt_cex2c.h"
27#include "zcrypt_cca_key.h"
28
29#define CEX2C_MIN_MOD_SIZE 16
30#define CEX2C_MAX_MOD_SIZE 256
31#define CEX3C_MIN_MOD_SIZE 16
32#define CEX3C_MAX_MOD_SIZE 512
33#define CEX2C_MAX_XCRB_MESSAGE_SIZE (12*1024)
34#define CEX2C_CLEANUP_TIME (15*HZ)
35
36MODULE_AUTHOR("IBM Corporation");
37MODULE_DESCRIPTION("CEX2C/CEX3C Cryptographic Coprocessor device driver, " \
38 "Copyright IBM Corp. 2001, 2018");
39MODULE_LICENSE("GPL");
40
41static struct ap_device_id zcrypt_cex2c_card_ids[] = {
42 { .dev_type = AP_DEVICE_TYPE_CEX2C,
43 .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
44 { .dev_type = AP_DEVICE_TYPE_CEX3C,
45 .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
46 { },
47};
48
49MODULE_DEVICE_TABLE(ap, zcrypt_cex2c_card_ids);
50
51static struct ap_device_id zcrypt_cex2c_queue_ids[] = {
52 { .dev_type = AP_DEVICE_TYPE_CEX2C,
53 .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
54 { .dev_type = AP_DEVICE_TYPE_CEX3C,
55 .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
56 { },
57};
58
59MODULE_DEVICE_TABLE(ap, zcrypt_cex2c_queue_ids);
60
61
62
63
64
65
66
67
68static int zcrypt_cex2c_rng_supported(struct ap_queue *aq)
69{
70 struct ap_message ap_msg;
71 unsigned long long psmid;
72 unsigned int domain;
73 struct {
74 struct type86_hdr hdr;
75 struct type86_fmt2_ext fmt2;
76 struct CPRBX cprbx;
77 } __packed *reply;
78 struct {
79 struct type6_hdr hdr;
80 struct CPRBX cprbx;
81 char function_code[2];
82 short int rule_length;
83 char rule[8];
84 short int verb_length;
85 short int key_length;
86 } __packed *msg;
87 int rc, i;
88
89 ap_init_message(&ap_msg);
90 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
91 if (!ap_msg.message)
92 return -ENOMEM;
93
94 rng_type6CPRB_msgX(&ap_msg, 4, &domain);
95
96 msg = ap_msg.message;
97 msg->cprbx.domain = AP_QID_QUEUE(aq->qid);
98
99 rc = ap_send(aq->qid, 0x0102030405060708ULL, ap_msg.message,
100 ap_msg.length);
101 if (rc)
102 goto out_free;
103
104
105 for (i = 0; i < 2 * HZ; i++) {
106 msleep(1000 / HZ);
107 rc = ap_recv(aq->qid, &psmid, ap_msg.message, 4096);
108 if (rc == 0 && psmid == 0x0102030405060708ULL)
109 break;
110 }
111
112 if (i >= 2 * HZ) {
113
114 rc = -ENODEV;
115 goto out_free;
116 }
117
118 reply = ap_msg.message;
119 if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0)
120 rc = 1;
121 else
122 rc = 0;
123out_free:
124 free_page((unsigned long) ap_msg.message);
125 return rc;
126}
127
128
129
130
131
132
133static int zcrypt_cex2c_card_probe(struct ap_device *ap_dev)
134{
135
136
137
138
139 static const int CEX2C_SPEED_IDX[] = {
140 1000, 1400, 2400, 1100, 1500, 2600, 100, 12};
141 static const int CEX3C_SPEED_IDX[] = {
142 500, 700, 1400, 550, 800, 1500, 80, 10};
143
144 struct ap_card *ac = to_ap_card(&ap_dev->device);
145 struct zcrypt_card *zc;
146 int rc = 0;
147
148 zc = zcrypt_card_alloc();
149 if (!zc)
150 return -ENOMEM;
151 zc->card = ac;
152 ac->private = zc;
153 switch (ac->ap_dev.device_type) {
154 case AP_DEVICE_TYPE_CEX2C:
155 zc->user_space_type = ZCRYPT_CEX2C;
156 zc->type_string = "CEX2C";
157 memcpy(zc->speed_rating, CEX2C_SPEED_IDX,
158 sizeof(CEX2C_SPEED_IDX));
159 zc->min_mod_size = CEX2C_MIN_MOD_SIZE;
160 zc->max_mod_size = CEX2C_MAX_MOD_SIZE;
161 zc->max_exp_bit_length = CEX2C_MAX_MOD_SIZE;
162 break;
163 case AP_DEVICE_TYPE_CEX3C:
164 zc->user_space_type = ZCRYPT_CEX3C;
165 zc->type_string = "CEX3C";
166 memcpy(zc->speed_rating, CEX3C_SPEED_IDX,
167 sizeof(CEX3C_SPEED_IDX));
168 zc->min_mod_size = CEX3C_MIN_MOD_SIZE;
169 zc->max_mod_size = CEX3C_MAX_MOD_SIZE;
170 zc->max_exp_bit_length = CEX3C_MAX_MOD_SIZE;
171 break;
172 default:
173 zcrypt_card_free(zc);
174 return -ENODEV;
175 }
176 zc->online = 1;
177
178 rc = zcrypt_card_register(zc);
179 if (rc) {
180 ac->private = NULL;
181 zcrypt_card_free(zc);
182 }
183
184 return rc;
185}
186
187
188
189
190
191static void zcrypt_cex2c_card_remove(struct ap_device *ap_dev)
192{
193 struct zcrypt_card *zc = to_ap_card(&ap_dev->device)->private;
194
195 if (zc)
196 zcrypt_card_unregister(zc);
197}
198
199static struct ap_driver zcrypt_cex2c_card_driver = {
200 .probe = zcrypt_cex2c_card_probe,
201 .remove = zcrypt_cex2c_card_remove,
202 .ids = zcrypt_cex2c_card_ids,
203 .flags = AP_DRIVER_FLAG_DEFAULT,
204};
205
206
207
208
209
210
211static int zcrypt_cex2c_queue_probe(struct ap_device *ap_dev)
212{
213 struct ap_queue *aq = to_ap_queue(&ap_dev->device);
214 struct zcrypt_queue *zq;
215 int rc;
216
217 zq = zcrypt_queue_alloc(CEX2C_MAX_XCRB_MESSAGE_SIZE);
218 if (!zq)
219 return -ENOMEM;
220 zq->queue = aq;
221 zq->online = 1;
222 atomic_set(&zq->load, 0);
223 ap_rapq(aq->qid);
224 rc = zcrypt_cex2c_rng_supported(aq);
225 if (rc < 0) {
226 zcrypt_queue_free(zq);
227 return rc;
228 }
229 if (rc)
230 zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
231 MSGTYPE06_VARIANT_DEFAULT);
232 else
233 zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
234 MSGTYPE06_VARIANT_NORNG);
235 ap_queue_init_state(aq);
236 ap_queue_init_reply(aq, &zq->reply);
237 aq->request_timeout = CEX2C_CLEANUP_TIME;
238 aq->private = zq;
239 rc = zcrypt_queue_register(zq);
240 if (rc) {
241 aq->private = NULL;
242 zcrypt_queue_free(zq);
243 }
244 return rc;
245}
246
247
248
249
250
251static void zcrypt_cex2c_queue_remove(struct ap_device *ap_dev)
252{
253 struct ap_queue *aq = to_ap_queue(&ap_dev->device);
254 struct zcrypt_queue *zq = aq->private;
255
256 if (zq)
257 zcrypt_queue_unregister(zq);
258}
259
260static struct ap_driver zcrypt_cex2c_queue_driver = {
261 .probe = zcrypt_cex2c_queue_probe,
262 .remove = zcrypt_cex2c_queue_remove,
263 .suspend = ap_queue_suspend,
264 .resume = ap_queue_resume,
265 .ids = zcrypt_cex2c_queue_ids,
266 .flags = AP_DRIVER_FLAG_DEFAULT,
267};
268
269int __init zcrypt_cex2c_init(void)
270{
271 int rc;
272
273 rc = ap_driver_register(&zcrypt_cex2c_card_driver,
274 THIS_MODULE, "cex2card");
275 if (rc)
276 return rc;
277
278 rc = ap_driver_register(&zcrypt_cex2c_queue_driver,
279 THIS_MODULE, "cex2cqueue");
280 if (rc)
281 ap_driver_unregister(&zcrypt_cex2c_card_driver);
282
283 return rc;
284}
285
286void zcrypt_cex2c_exit(void)
287{
288 ap_driver_unregister(&zcrypt_cex2c_queue_driver);
289 ap_driver_unregister(&zcrypt_cex2c_card_driver);
290}
291
292module_init(zcrypt_cex2c_init);
293module_exit(zcrypt_cex2c_exit);
294