Commit | Line | Data |
---|---|---|
812141a9 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
5e55a488 | 2 | /* |
5e55a488 HD |
3 | * Copyright IBM Corp. 2001, 2012 |
4 | * Author(s): Robert Burroughs | |
5 | * Eric Rossman (edrossma@us.ibm.com) | |
6 | * | |
7 | * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) | |
8 | * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> | |
9 | * Ralph Wuerthner <rwuerthn@de.ibm.com> | |
10 | * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com> | |
5e55a488 HD |
11 | */ |
12 | ||
91f3e3ea IT |
13 | #define KMSG_COMPONENT "zcrypt" |
14 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | |
15 | ||
5e55a488 HD |
16 | #include <linux/module.h> |
17 | #include <linux/slab.h> | |
18 | #include <linux/init.h> | |
19 | #include <linux/err.h> | |
20 | #include <linux/atomic.h> | |
21 | #include <linux/uaccess.h> | |
22 | ||
23 | #include "ap_bus.h" | |
24 | #include "zcrypt_api.h" | |
25 | #include "zcrypt_error.h" | |
26 | #include "zcrypt_msgtype50.h" | |
27 | ||
ee410de8 | 28 | /* >= CEX3A: 4096 bits */ |
ac2b96f3 | 29 | #define CEX3A_MAX_MOD_SIZE 512 |
5e55a488 | 30 | |
ee410de8 | 31 | /* CEX2A: max outputdatalength + type80_hdr */ |
ac2b96f3 | 32 | #define CEX2A_MAX_RESPONSE_SIZE 0x110 |
5e55a488 | 33 | |
ee410de8 | 34 | /* >= CEX3A: 512 bit modulus, (max outputdatalength) + type80_hdr */ |
ac2b96f3 | 35 | #define CEX3A_MAX_RESPONSE_SIZE 0x210 |
5e55a488 HD |
36 | |
37 | MODULE_AUTHOR("IBM Corporation"); | |
38 | MODULE_DESCRIPTION("Cryptographic Accelerator (message type 50), " \ | |
39 | "Copyright IBM Corp. 2001, 2012"); | |
40 | MODULE_LICENSE("GPL"); | |
41 | ||
5e55a488 | 42 | /** |
ee410de8 | 43 | * The type 50 message family is associated with a CEXxA cards. |
5e55a488 HD |
44 | * |
45 | * The four members of the family are described below. | |
46 | * | |
47 | * Note that all unsigned char arrays are right-justified and left-padded | |
48 | * with zeroes. | |
49 | * | |
50 | * Note that all reserved fields must be zeroes. | |
51 | */ | |
52 | struct type50_hdr { | |
53 | unsigned char reserved1; | |
54 | unsigned char msg_type_code; /* 0x50 */ | |
55 | unsigned short msg_len; | |
56 | unsigned char reserved2; | |
57 | unsigned char ignored; | |
58 | unsigned short reserved3; | |
59 | } __packed; | |
60 | ||
61 | #define TYPE50_TYPE_CODE 0x50 | |
62 | ||
63 | #define TYPE50_MEB1_FMT 0x0001 | |
64 | #define TYPE50_MEB2_FMT 0x0002 | |
65 | #define TYPE50_MEB3_FMT 0x0003 | |
66 | #define TYPE50_CRB1_FMT 0x0011 | |
67 | #define TYPE50_CRB2_FMT 0x0012 | |
68 | #define TYPE50_CRB3_FMT 0x0013 | |
69 | ||
70 | /* Mod-Exp, with a small modulus */ | |
71 | struct type50_meb1_msg { | |
72 | struct type50_hdr header; | |
73 | unsigned short keyblock_type; /* 0x0001 */ | |
74 | unsigned char reserved[6]; | |
75 | unsigned char exponent[128]; | |
76 | unsigned char modulus[128]; | |
77 | unsigned char message[128]; | |
78 | } __packed; | |
79 | ||
80 | /* Mod-Exp, with a large modulus */ | |
81 | struct type50_meb2_msg { | |
82 | struct type50_hdr header; | |
83 | unsigned short keyblock_type; /* 0x0002 */ | |
84 | unsigned char reserved[6]; | |
85 | unsigned char exponent[256]; | |
86 | unsigned char modulus[256]; | |
87 | unsigned char message[256]; | |
88 | } __packed; | |
89 | ||
90 | /* Mod-Exp, with a larger modulus */ | |
91 | struct type50_meb3_msg { | |
92 | struct type50_hdr header; | |
93 | unsigned short keyblock_type; /* 0x0003 */ | |
94 | unsigned char reserved[6]; | |
95 | unsigned char exponent[512]; | |
96 | unsigned char modulus[512]; | |
97 | unsigned char message[512]; | |
98 | } __packed; | |
99 | ||
100 | /* CRT, with a small modulus */ | |
101 | struct type50_crb1_msg { | |
102 | struct type50_hdr header; | |
103 | unsigned short keyblock_type; /* 0x0011 */ | |
104 | unsigned char reserved[6]; | |
105 | unsigned char p[64]; | |
106 | unsigned char q[64]; | |
107 | unsigned char dp[64]; | |
108 | unsigned char dq[64]; | |
109 | unsigned char u[64]; | |
110 | unsigned char message[128]; | |
111 | } __packed; | |
112 | ||
113 | /* CRT, with a large modulus */ | |
114 | struct type50_crb2_msg { | |
115 | struct type50_hdr header; | |
116 | unsigned short keyblock_type; /* 0x0012 */ | |
117 | unsigned char reserved[6]; | |
118 | unsigned char p[128]; | |
119 | unsigned char q[128]; | |
120 | unsigned char dp[128]; | |
121 | unsigned char dq[128]; | |
122 | unsigned char u[128]; | |
123 | unsigned char message[256]; | |
124 | } __packed; | |
125 | ||
126 | /* CRT, with a larger modulus */ | |
127 | struct type50_crb3_msg { | |
128 | struct type50_hdr header; | |
129 | unsigned short keyblock_type; /* 0x0013 */ | |
130 | unsigned char reserved[6]; | |
131 | unsigned char p[256]; | |
132 | unsigned char q[256]; | |
133 | unsigned char dp[256]; | |
134 | unsigned char dq[256]; | |
135 | unsigned char u[256]; | |
136 | unsigned char message[512]; | |
137 | } __packed; | |
138 | ||
139 | /** | |
ee410de8 | 140 | * The type 80 response family is associated with a CEXxA cards. |
5e55a488 HD |
141 | * |
142 | * Note that all unsigned char arrays are right-justified and left-padded | |
143 | * with zeroes. | |
144 | * | |
145 | * Note that all reserved fields must be zeroes. | |
146 | */ | |
147 | ||
148 | #define TYPE80_RSP_CODE 0x80 | |
149 | ||
150 | struct type80_hdr { | |
151 | unsigned char reserved1; | |
152 | unsigned char type; /* 0x80 */ | |
153 | unsigned short len; | |
154 | unsigned char code; /* 0x00 */ | |
155 | unsigned char reserved2[3]; | |
156 | unsigned char reserved3[8]; | |
157 | } __packed; | |
158 | ||
34a15167 IT |
159 | unsigned int get_rsa_modex_fc(struct ica_rsa_modexpo *mex, int *fcode) |
160 | { | |
161 | ||
162 | if (!mex->inputdatalength) | |
163 | return -EINVAL; | |
164 | ||
165 | if (mex->inputdatalength <= 128) /* 1024 bit */ | |
166 | *fcode = MEX_1K; | |
167 | else if (mex->inputdatalength <= 256) /* 2048 bit */ | |
168 | *fcode = MEX_2K; | |
169 | else /* 4096 bit */ | |
170 | *fcode = MEX_4K; | |
171 | ||
172 | return 0; | |
173 | } | |
174 | ||
175 | unsigned int get_rsa_crt_fc(struct ica_rsa_modexpo_crt *crt, int *fcode) | |
176 | { | |
177 | ||
178 | if (!crt->inputdatalength) | |
179 | return -EINVAL; | |
180 | ||
181 | if (crt->inputdatalength <= 128) /* 1024 bit */ | |
182 | *fcode = CRT_1K; | |
183 | else if (crt->inputdatalength <= 256) /* 2048 bit */ | |
184 | *fcode = CRT_2K; | |
185 | else /* 4096 bit */ | |
186 | *fcode = CRT_4K; | |
187 | ||
188 | return 0; | |
189 | } | |
190 | ||
5e55a488 HD |
191 | /** |
192 | * Convert a ICAMEX message to a type50 MEX message. | |
193 | * | |
e28d2af4 IT |
194 | * @zq: crypto queue pointer |
195 | * @ap_msg: crypto request pointer | |
5e55a488 HD |
196 | * @mex: pointer to user input data |
197 | * | |
198 | * Returns 0 on success or -EFAULT. | |
199 | */ | |
e28d2af4 | 200 | static int ICAMEX_msg_to_type50MEX_msg(struct zcrypt_queue *zq, |
5e55a488 HD |
201 | struct ap_message *ap_msg, |
202 | struct ica_rsa_modexpo *mex) | |
203 | { | |
204 | unsigned char *mod, *exp, *inp; | |
205 | int mod_len; | |
206 | ||
207 | mod_len = mex->inputdatalength; | |
208 | ||
209 | if (mod_len <= 128) { | |
210 | struct type50_meb1_msg *meb1 = ap_msg->message; | |
ac2b96f3 | 211 | |
5e55a488 HD |
212 | memset(meb1, 0, sizeof(*meb1)); |
213 | ap_msg->length = sizeof(*meb1); | |
214 | meb1->header.msg_type_code = TYPE50_TYPE_CODE; | |
215 | meb1->header.msg_len = sizeof(*meb1); | |
216 | meb1->keyblock_type = TYPE50_MEB1_FMT; | |
217 | mod = meb1->modulus + sizeof(meb1->modulus) - mod_len; | |
218 | exp = meb1->exponent + sizeof(meb1->exponent) - mod_len; | |
219 | inp = meb1->message + sizeof(meb1->message) - mod_len; | |
220 | } else if (mod_len <= 256) { | |
221 | struct type50_meb2_msg *meb2 = ap_msg->message; | |
ac2b96f3 | 222 | |
5e55a488 HD |
223 | memset(meb2, 0, sizeof(*meb2)); |
224 | ap_msg->length = sizeof(*meb2); | |
225 | meb2->header.msg_type_code = TYPE50_TYPE_CODE; | |
226 | meb2->header.msg_len = sizeof(*meb2); | |
227 | meb2->keyblock_type = TYPE50_MEB2_FMT; | |
228 | mod = meb2->modulus + sizeof(meb2->modulus) - mod_len; | |
229 | exp = meb2->exponent + sizeof(meb2->exponent) - mod_len; | |
230 | inp = meb2->message + sizeof(meb2->message) - mod_len; | |
76b31381 | 231 | } else if (mod_len <= 512) { |
5e55a488 | 232 | struct type50_meb3_msg *meb3 = ap_msg->message; |
ac2b96f3 | 233 | |
5e55a488 HD |
234 | memset(meb3, 0, sizeof(*meb3)); |
235 | ap_msg->length = sizeof(*meb3); | |
236 | meb3->header.msg_type_code = TYPE50_TYPE_CODE; | |
237 | meb3->header.msg_len = sizeof(*meb3); | |
238 | meb3->keyblock_type = TYPE50_MEB3_FMT; | |
239 | mod = meb3->modulus + sizeof(meb3->modulus) - mod_len; | |
240 | exp = meb3->exponent + sizeof(meb3->exponent) - mod_len; | |
241 | inp = meb3->message + sizeof(meb3->message) - mod_len; | |
76b31381 HF |
242 | } else |
243 | return -EINVAL; | |
5e55a488 HD |
244 | |
245 | if (copy_from_user(mod, mex->n_modulus, mod_len) || | |
246 | copy_from_user(exp, mex->b_key, mod_len) || | |
247 | copy_from_user(inp, mex->inputdata, mod_len)) | |
248 | return -EFAULT; | |
249 | return 0; | |
250 | } | |
251 | ||
252 | /** | |
253 | * Convert a ICACRT message to a type50 CRT message. | |
254 | * | |
e28d2af4 IT |
255 | * @zq: crypto queue pointer |
256 | * @ap_msg: crypto request pointer | |
5e55a488 HD |
257 | * @crt: pointer to user input data |
258 | * | |
259 | * Returns 0 on success or -EFAULT. | |
260 | */ | |
e28d2af4 | 261 | static int ICACRT_msg_to_type50CRT_msg(struct zcrypt_queue *zq, |
5e55a488 HD |
262 | struct ap_message *ap_msg, |
263 | struct ica_rsa_modexpo_crt *crt) | |
264 | { | |
1e466fcf | 265 | int mod_len, short_len; |
5e55a488 HD |
266 | unsigned char *p, *q, *dp, *dq, *u, *inp; |
267 | ||
268 | mod_len = crt->inputdatalength; | |
1330a125 | 269 | short_len = (mod_len + 1) / 2; |
5e55a488 HD |
270 | |
271 | /* | |
1e466fcf IT |
272 | * CEX2A and CEX3A w/o FW update can handle requests up to |
273 | * 256 byte modulus (2k keys). | |
ee410de8 | 274 | * CEX3A with FW update and newer CEXxA cards are able to handle |
1e466fcf | 275 | * 512 byte modulus (4k keys). |
5e55a488 | 276 | */ |
1e466fcf | 277 | if (mod_len <= 128) { /* up to 1024 bit key size */ |
5e55a488 | 278 | struct type50_crb1_msg *crb1 = ap_msg->message; |
ac2b96f3 | 279 | |
5e55a488 HD |
280 | memset(crb1, 0, sizeof(*crb1)); |
281 | ap_msg->length = sizeof(*crb1); | |
282 | crb1->header.msg_type_code = TYPE50_TYPE_CODE; | |
283 | crb1->header.msg_len = sizeof(*crb1); | |
284 | crb1->keyblock_type = TYPE50_CRB1_FMT; | |
1e466fcf | 285 | p = crb1->p + sizeof(crb1->p) - short_len; |
5e55a488 | 286 | q = crb1->q + sizeof(crb1->q) - short_len; |
1e466fcf | 287 | dp = crb1->dp + sizeof(crb1->dp) - short_len; |
5e55a488 | 288 | dq = crb1->dq + sizeof(crb1->dq) - short_len; |
1e466fcf | 289 | u = crb1->u + sizeof(crb1->u) - short_len; |
5e55a488 | 290 | inp = crb1->message + sizeof(crb1->message) - mod_len; |
1e466fcf | 291 | } else if (mod_len <= 256) { /* up to 2048 bit key size */ |
5e55a488 | 292 | struct type50_crb2_msg *crb2 = ap_msg->message; |
ac2b96f3 | 293 | |
5e55a488 HD |
294 | memset(crb2, 0, sizeof(*crb2)); |
295 | ap_msg->length = sizeof(*crb2); | |
296 | crb2->header.msg_type_code = TYPE50_TYPE_CODE; | |
297 | crb2->header.msg_len = sizeof(*crb2); | |
298 | crb2->keyblock_type = TYPE50_CRB2_FMT; | |
1e466fcf | 299 | p = crb2->p + sizeof(crb2->p) - short_len; |
5e55a488 | 300 | q = crb2->q + sizeof(crb2->q) - short_len; |
1e466fcf | 301 | dp = crb2->dp + sizeof(crb2->dp) - short_len; |
5e55a488 | 302 | dq = crb2->dq + sizeof(crb2->dq) - short_len; |
1e466fcf | 303 | u = crb2->u + sizeof(crb2->u) - short_len; |
5e55a488 | 304 | inp = crb2->message + sizeof(crb2->message) - mod_len; |
1e466fcf | 305 | } else if ((mod_len <= 512) && /* up to 4096 bit key size */ |
e28d2af4 | 306 | (zq->zcard->max_mod_size == CEX3A_MAX_MOD_SIZE)) { |
5e55a488 | 307 | struct type50_crb3_msg *crb3 = ap_msg->message; |
ac2b96f3 | 308 | |
5e55a488 HD |
309 | memset(crb3, 0, sizeof(*crb3)); |
310 | ap_msg->length = sizeof(*crb3); | |
311 | crb3->header.msg_type_code = TYPE50_TYPE_CODE; | |
312 | crb3->header.msg_len = sizeof(*crb3); | |
313 | crb3->keyblock_type = TYPE50_CRB3_FMT; | |
1e466fcf | 314 | p = crb3->p + sizeof(crb3->p) - short_len; |
5e55a488 | 315 | q = crb3->q + sizeof(crb3->q) - short_len; |
1e466fcf | 316 | dp = crb3->dp + sizeof(crb3->dp) - short_len; |
5e55a488 | 317 | dq = crb3->dq + sizeof(crb3->dq) - short_len; |
1e466fcf | 318 | u = crb3->u + sizeof(crb3->u) - short_len; |
5e55a488 | 319 | inp = crb3->message + sizeof(crb3->message) - mod_len; |
1e466fcf IT |
320 | } else |
321 | return -EINVAL; | |
5e55a488 | 322 | |
1e466fcf IT |
323 | /* |
324 | * correct the offset of p, bp and mult_inv according zcrypt.h | |
325 | * block size right aligned (skip the first byte) | |
326 | */ | |
327 | if (copy_from_user(p, crt->np_prime + MSGTYPE_ADJUSTMENT, short_len) || | |
5e55a488 | 328 | copy_from_user(q, crt->nq_prime, short_len) || |
1e466fcf | 329 | copy_from_user(dp, crt->bp_key + MSGTYPE_ADJUSTMENT, short_len) || |
5e55a488 | 330 | copy_from_user(dq, crt->bq_key, short_len) || |
1e466fcf | 331 | copy_from_user(u, crt->u_mult_inv + MSGTYPE_ADJUSTMENT, short_len) || |
5e55a488 HD |
332 | copy_from_user(inp, crt->inputdata, mod_len)) |
333 | return -EFAULT; | |
334 | ||
335 | return 0; | |
336 | } | |
337 | ||
338 | /** | |
339 | * Copy results from a type 80 reply message back to user space. | |
340 | * | |
e28d2af4 | 341 | * @zq: crypto device pointer |
5e55a488 HD |
342 | * @reply: reply AP message. |
343 | * @data: pointer to user output data | |
344 | * @length: size of user output data | |
345 | * | |
346 | * Returns 0 on success or -EFAULT. | |
347 | */ | |
e28d2af4 | 348 | static int convert_type80(struct zcrypt_queue *zq, |
5e55a488 HD |
349 | struct ap_message *reply, |
350 | char __user *outputdata, | |
351 | unsigned int outputdatalength) | |
352 | { | |
353 | struct type80_hdr *t80h = reply->message; | |
354 | unsigned char *data; | |
355 | ||
356 | if (t80h->len < sizeof(*t80h) + outputdatalength) { | |
ee410de8 | 357 | /* The result is too short, the CEXxA card may not do that.. */ |
e28d2af4 IT |
358 | zq->online = 0; |
359 | pr_err("Cryptographic device %02x.%04x failed and was set offline\n", | |
360 | AP_QID_CARD(zq->queue->qid), | |
361 | AP_QID_QUEUE(zq->queue->qid)); | |
cccd85bf HF |
362 | ZCRYPT_DBF(DBF_ERR, |
363 | "device=%02x.%04x code=0x%02x => online=0 rc=EAGAIN\n", | |
364 | AP_QID_CARD(zq->queue->qid), | |
365 | AP_QID_QUEUE(zq->queue->qid), | |
366 | t80h->code); | |
5e55a488 HD |
367 | return -EAGAIN; /* repeat the request on a different device. */ |
368 | } | |
e28d2af4 | 369 | if (zq->zcard->user_space_type == ZCRYPT_CEX2A) |
5e55a488 HD |
370 | BUG_ON(t80h->len > CEX2A_MAX_RESPONSE_SIZE); |
371 | else | |
372 | BUG_ON(t80h->len > CEX3A_MAX_RESPONSE_SIZE); | |
373 | data = reply->message + t80h->len - outputdatalength; | |
374 | if (copy_to_user(outputdata, data, outputdatalength)) | |
375 | return -EFAULT; | |
376 | return 0; | |
377 | } | |
378 | ||
e28d2af4 | 379 | static int convert_response(struct zcrypt_queue *zq, |
5e55a488 HD |
380 | struct ap_message *reply, |
381 | char __user *outputdata, | |
382 | unsigned int outputdatalength) | |
383 | { | |
384 | /* Response type byte is the second byte in the response. */ | |
cccd85bf HF |
385 | unsigned char rtype = ((unsigned char *) reply->message)[1]; |
386 | ||
387 | switch (rtype) { | |
5e55a488 HD |
388 | case TYPE82_RSP_CODE: |
389 | case TYPE88_RSP_CODE: | |
e28d2af4 | 390 | return convert_error(zq, reply); |
5e55a488 | 391 | case TYPE80_RSP_CODE: |
e28d2af4 | 392 | return convert_type80(zq, reply, |
5e55a488 HD |
393 | outputdata, outputdatalength); |
394 | default: /* Unknown response type, this should NEVER EVER happen */ | |
e28d2af4 IT |
395 | zq->online = 0; |
396 | pr_err("Cryptographic device %02x.%04x failed and was set offline\n", | |
397 | AP_QID_CARD(zq->queue->qid), | |
398 | AP_QID_QUEUE(zq->queue->qid)); | |
cccd85bf HF |
399 | ZCRYPT_DBF(DBF_ERR, |
400 | "device=%02x.%04x rtype=0x%02x => online=0 rc=EAGAIN\n", | |
401 | AP_QID_CARD(zq->queue->qid), | |
402 | AP_QID_QUEUE(zq->queue->qid), | |
403 | (unsigned int) rtype); | |
5e55a488 HD |
404 | return -EAGAIN; /* repeat the request on a different device. */ |
405 | } | |
406 | } | |
407 | ||
408 | /** | |
409 | * This function is called from the AP bus code after a crypto request | |
410 | * "msg" has finished with the reply message "reply". | |
411 | * It is called from tasklet context. | |
e28d2af4 | 412 | * @aq: pointer to the AP device |
5e55a488 HD |
413 | * @msg: pointer to the AP message |
414 | * @reply: pointer to the AP reply message | |
415 | */ | |
e28d2af4 | 416 | static void zcrypt_cex2a_receive(struct ap_queue *aq, |
5e55a488 HD |
417 | struct ap_message *msg, |
418 | struct ap_message *reply) | |
419 | { | |
420 | static struct error_hdr error_reply = { | |
421 | .type = TYPE82_RSP_CODE, | |
422 | .reply_code = REP82_ERROR_MACHINE_FAILURE, | |
423 | }; | |
424 | struct type80_hdr *t80h; | |
425 | int length; | |
426 | ||
427 | /* Copy the reply message to the request message buffer. */ | |
f58fe336 MS |
428 | if (!reply) |
429 | goto out; /* ap_msg->rc indicates the error */ | |
5e55a488 HD |
430 | t80h = reply->message; |
431 | if (t80h->type == TYPE80_RSP_CODE) { | |
e28d2af4 | 432 | if (aq->ap_dev.device_type == AP_DEVICE_TYPE_CEX2A) |
5e55a488 HD |
433 | length = min_t(int, |
434 | CEX2A_MAX_RESPONSE_SIZE, t80h->len); | |
435 | else | |
436 | length = min_t(int, | |
437 | CEX3A_MAX_RESPONSE_SIZE, t80h->len); | |
438 | memcpy(msg->message, reply->message, length); | |
439 | } else | |
440 | memcpy(msg->message, reply->message, sizeof(error_reply)); | |
441 | out: | |
442 | complete((struct completion *) msg->private); | |
443 | } | |
444 | ||
445 | static atomic_t zcrypt_step = ATOMIC_INIT(0); | |
446 | ||
447 | /** | |
ee410de8 | 448 | * The request distributor calls this function if it picked the CEXxA |
5e55a488 | 449 | * device to handle a modexpo request. |
e28d2af4 | 450 | * @zq: pointer to zcrypt_queue structure that identifies the |
ee410de8 | 451 | * CEXxA device to the request distributor |
5e55a488 HD |
452 | * @mex: pointer to the modexpo request buffer |
453 | */ | |
e28d2af4 | 454 | static long zcrypt_cex2a_modexpo(struct zcrypt_queue *zq, |
5e55a488 HD |
455 | struct ica_rsa_modexpo *mex) |
456 | { | |
457 | struct ap_message ap_msg; | |
458 | struct completion work; | |
459 | int rc; | |
460 | ||
461 | ap_init_message(&ap_msg); | |
e28d2af4 | 462 | if (zq->zcard->user_space_type == ZCRYPT_CEX2A) |
5e55a488 HD |
463 | ap_msg.message = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, |
464 | GFP_KERNEL); | |
465 | else | |
466 | ap_msg.message = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, | |
467 | GFP_KERNEL); | |
468 | if (!ap_msg.message) | |
469 | return -ENOMEM; | |
470 | ap_msg.receive = zcrypt_cex2a_receive; | |
471 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | |
472 | atomic_inc_return(&zcrypt_step); | |
473 | ap_msg.private = &work; | |
e28d2af4 | 474 | rc = ICAMEX_msg_to_type50MEX_msg(zq, &ap_msg, mex); |
5e55a488 HD |
475 | if (rc) |
476 | goto out_free; | |
477 | init_completion(&work); | |
e28d2af4 | 478 | ap_queue_message(zq->queue, &ap_msg); |
5e55a488 | 479 | rc = wait_for_completion_interruptible(&work); |
f58fe336 MS |
480 | if (rc == 0) { |
481 | rc = ap_msg.rc; | |
482 | if (rc == 0) | |
e28d2af4 | 483 | rc = convert_response(zq, &ap_msg, mex->outputdata, |
f58fe336 MS |
484 | mex->outputdatalength); |
485 | } else | |
5e55a488 | 486 | /* Signal pending. */ |
e28d2af4 | 487 | ap_cancel_message(zq->queue, &ap_msg); |
5e55a488 HD |
488 | out_free: |
489 | kfree(ap_msg.message); | |
490 | return rc; | |
491 | } | |
492 | ||
493 | /** | |
ee410de8 | 494 | * The request distributor calls this function if it picked the CEXxA |
5e55a488 | 495 | * device to handle a modexpo_crt request. |
e28d2af4 | 496 | * @zq: pointer to zcrypt_queue structure that identifies the |
ee410de8 | 497 | * CEXxA device to the request distributor |
5e55a488 HD |
498 | * @crt: pointer to the modexpoc_crt request buffer |
499 | */ | |
e28d2af4 | 500 | static long zcrypt_cex2a_modexpo_crt(struct zcrypt_queue *zq, |
5e55a488 HD |
501 | struct ica_rsa_modexpo_crt *crt) |
502 | { | |
503 | struct ap_message ap_msg; | |
504 | struct completion work; | |
505 | int rc; | |
506 | ||
507 | ap_init_message(&ap_msg); | |
e28d2af4 | 508 | if (zq->zcard->user_space_type == ZCRYPT_CEX2A) |
5e55a488 HD |
509 | ap_msg.message = kmalloc(MSGTYPE50_CRB2_MAX_MSG_SIZE, |
510 | GFP_KERNEL); | |
511 | else | |
512 | ap_msg.message = kmalloc(MSGTYPE50_CRB3_MAX_MSG_SIZE, | |
513 | GFP_KERNEL); | |
514 | if (!ap_msg.message) | |
515 | return -ENOMEM; | |
516 | ap_msg.receive = zcrypt_cex2a_receive; | |
517 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | |
518 | atomic_inc_return(&zcrypt_step); | |
519 | ap_msg.private = &work; | |
e28d2af4 | 520 | rc = ICACRT_msg_to_type50CRT_msg(zq, &ap_msg, crt); |
5e55a488 HD |
521 | if (rc) |
522 | goto out_free; | |
523 | init_completion(&work); | |
e28d2af4 | 524 | ap_queue_message(zq->queue, &ap_msg); |
5e55a488 | 525 | rc = wait_for_completion_interruptible(&work); |
f58fe336 MS |
526 | if (rc == 0) { |
527 | rc = ap_msg.rc; | |
528 | if (rc == 0) | |
e28d2af4 | 529 | rc = convert_response(zq, &ap_msg, crt->outputdata, |
f58fe336 MS |
530 | crt->outputdatalength); |
531 | } else | |
5e55a488 | 532 | /* Signal pending. */ |
e28d2af4 | 533 | ap_cancel_message(zq->queue, &ap_msg); |
5e55a488 HD |
534 | out_free: |
535 | kfree(ap_msg.message); | |
536 | return rc; | |
537 | } | |
538 | ||
539 | /** | |
540 | * The crypto operations for message type 50. | |
541 | */ | |
542 | static struct zcrypt_ops zcrypt_msgtype50_ops = { | |
543 | .rsa_modexpo = zcrypt_cex2a_modexpo, | |
544 | .rsa_modexpo_crt = zcrypt_cex2a_modexpo_crt, | |
545 | .owner = THIS_MODULE, | |
121a868d | 546 | .name = MSGTYPE50_NAME, |
5e55a488 HD |
547 | .variant = MSGTYPE50_VARIANT_DEFAULT, |
548 | }; | |
549 | ||
fc1d3f02 | 550 | void __init zcrypt_msgtype50_init(void) |
5e55a488 HD |
551 | { |
552 | zcrypt_msgtype_register(&zcrypt_msgtype50_ops); | |
5e55a488 HD |
553 | } |
554 | ||
555 | void __exit zcrypt_msgtype50_exit(void) | |
556 | { | |
557 | zcrypt_msgtype_unregister(&zcrypt_msgtype50_ops); | |
558 | } |