aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/crypto/zcrypt_pcixcc.c
diff options
context:
space:
mode:
authorHolger Dengler <hd@linux.vnet.ibm.com>2012-08-28 10:45:36 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-09-26 09:44:55 -0400
commit5e55a488c87aa6cc269b04bfec99e835f03b2c2d (patch)
tree59d848f6cf6a67a520a3bd482a853b2955cf97d2 /drivers/s390/crypto/zcrypt_pcixcc.c
parentb26bd9413c8359bd9f5c9bd1b789a10ebd2bb484 (diff)
s390/zcrypt: Separate msgtype implementation from card modules.
Msgtype implementations are now separated from card specific modules and can be dynamically registered. Existing msgtype implementations are restructured in modules. Signed-off-by: Holger Dengler <hd@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/crypto/zcrypt_pcixcc.c')
-rw-r--r--drivers/s390/crypto/zcrypt_pcixcc.c781
1 files changed, 13 insertions, 768 deletions
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index ccb4f8b60c75..c7275e303a0d 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -1,13 +1,14 @@
1/* 1/*
2 * zcrypt 2.1.0 2 * zcrypt 2.1.0
3 * 3 *
4 * Copyright IBM Corp. 2001, 2006 4 * Copyright IBM Corp. 2001, 2012
5 * Author(s): Robert Burroughs 5 * Author(s): Robert Burroughs
6 * Eric Rossman (edrossma@us.ibm.com) 6 * Eric Rossman (edrossma@us.ibm.com)
7 * 7 *
8 * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com) 8 * Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
9 * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com> 9 * Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
10 * Ralph Wuerthner <rwuerthn@de.ibm.com> 10 * Ralph Wuerthner <rwuerthn@de.ibm.com>
11 * 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
@@ -35,9 +36,10 @@
35#include "ap_bus.h" 36#include "ap_bus.h"
36#include "zcrypt_api.h" 37#include "zcrypt_api.h"
37#include "zcrypt_error.h" 38#include "zcrypt_error.h"
38#include "zcrypt_pcicc.h" 39#include "zcrypt_msgtype6.h"
39#include "zcrypt_pcixcc.h" 40#include "zcrypt_pcixcc.h"
40#include "zcrypt_cca_key.h" 41#include "zcrypt_cca_key.h"
42#include "zcrypt_msgtype6.h"
41 43
42#define PCIXCC_MIN_MOD_SIZE 16 /* 128 bits */ 44#define PCIXCC_MIN_MOD_SIZE 16 /* 128 bits */
43#define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */ 45#define PCIXCC_MIN_MOD_SIZE_OLD 64 /* 512 bits */
@@ -75,14 +77,12 @@ static struct ap_device_id zcrypt_pcixcc_ids[] = {
75 77
76MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids); 78MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids);
77MODULE_AUTHOR("IBM Corporation"); 79MODULE_AUTHOR("IBM Corporation");
78MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, " 80MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, " \
79 "Copyright IBM Corp. 2001, 2006"); 81 "Copyright IBM Corp. 2001, 2012");
80MODULE_LICENSE("GPL"); 82MODULE_LICENSE("GPL");
81 83
82static int zcrypt_pcixcc_probe(struct ap_device *ap_dev); 84static int zcrypt_pcixcc_probe(struct ap_device *ap_dev);
83static void zcrypt_pcixcc_remove(struct ap_device *ap_dev); 85static void zcrypt_pcixcc_remove(struct ap_device *ap_dev);
84static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *,
85 struct ap_message *);
86 86
87static struct ap_driver zcrypt_pcixcc_driver = { 87static struct ap_driver zcrypt_pcixcc_driver = {
88 .probe = zcrypt_pcixcc_probe, 88 .probe = zcrypt_pcixcc_probe,
@@ -92,766 +92,6 @@ static struct ap_driver zcrypt_pcixcc_driver = {
92}; 92};
93 93
94/** 94/**
95 * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C
96 * card in a type6 message. The 3 fields that must be filled in at execution
97 * time are req_parml, rpl_parml and usage_domain.
98 * Everything about this interface is ascii/big-endian, since the
99 * device does *not* have 'Intel inside'.
100 *
101 * The CPRBX is followed immediately by the parm block.
102 * The parm block contains:
103 * - function code ('PD' 0x5044 or 'PK' 0x504B)
104 * - rule block (one of:)
105 * + 0x000A 'PKCS-1.2' (MCL2 'PD')
106 * + 0x000A 'ZERO-PAD' (MCL2 'PK')
107 * + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD')
108 * + 0x000A 'MRP ' (MCL3 'PK' or CEX2C 'PK')
109 * - VUD block
110 */
111static struct CPRBX static_cprbx = {
112 .cprb_len = 0x00DC,
113 .cprb_ver_id = 0x02,
114 .func_id = {0x54,0x32},
115};
116
117/**
118 * Convert a ICAMEX message to a type6 MEX message.
119 *
120 * @zdev: crypto device pointer
121 * @ap_msg: pointer to AP message
122 * @mex: pointer to user input data
123 *
124 * Returns 0 on success or -EFAULT.
125 */
126static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev,
127 struct ap_message *ap_msg,
128 struct ica_rsa_modexpo *mex)
129{
130 static struct type6_hdr static_type6_hdrX = {
131 .type = 0x06,
132 .offset1 = 0x00000058,
133 .agent_id = {'C','A',},
134 .function_code = {'P','K'},
135 };
136 static struct function_and_rules_block static_pke_fnr = {
137 .function_code = {'P','K'},
138 .ulen = 10,
139 .only_rule = {'M','R','P',' ',' ',' ',' ',' '}
140 };
141 static struct function_and_rules_block static_pke_fnr_MCL2 = {
142 .function_code = {'P','K'},
143 .ulen = 10,
144 .only_rule = {'Z','E','R','O','-','P','A','D'}
145 };
146 struct {
147 struct type6_hdr hdr;
148 struct CPRBX cprbx;
149 struct function_and_rules_block fr;
150 unsigned short length;
151 char text[0];
152 } __attribute__((packed)) *msg = ap_msg->message;
153 int size;
154
155 /* VUD.ciphertext */
156 msg->length = mex->inputdatalength + 2;
157 if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
158 return -EFAULT;
159
160 /* Set up key which is located after the variable length text. */
161 size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1);
162 if (size < 0)
163 return size;
164 size += sizeof(*msg) + mex->inputdatalength;
165
166 /* message header, cprbx and f&r */
167 msg->hdr = static_type6_hdrX;
168 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
169 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
170
171 msg->cprbx = static_cprbx;
172 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
173 msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1;
174
175 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
176 static_pke_fnr_MCL2 : static_pke_fnr;
177
178 msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx);
179
180 ap_msg->length = size;
181 return 0;
182}
183
184/**
185 * Convert a ICACRT message to a type6 CRT message.
186 *
187 * @zdev: crypto device pointer
188 * @ap_msg: pointer to AP message
189 * @crt: pointer to user input data
190 *
191 * Returns 0 on success or -EFAULT.
192 */
193static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,
194 struct ap_message *ap_msg,
195 struct ica_rsa_modexpo_crt *crt)
196{
197 static struct type6_hdr static_type6_hdrX = {
198 .type = 0x06,
199 .offset1 = 0x00000058,
200 .agent_id = {'C','A',},
201 .function_code = {'P','D'},
202 };
203 static struct function_and_rules_block static_pkd_fnr = {
204 .function_code = {'P','D'},
205 .ulen = 10,
206 .only_rule = {'Z','E','R','O','-','P','A','D'}
207 };
208
209 static struct function_and_rules_block static_pkd_fnr_MCL2 = {
210 .function_code = {'P','D'},
211 .ulen = 10,
212 .only_rule = {'P','K','C','S','-','1','.','2'}
213 };
214 struct {
215 struct type6_hdr hdr;
216 struct CPRBX cprbx;
217 struct function_and_rules_block fr;
218 unsigned short length;
219 char text[0];
220 } __attribute__((packed)) *msg = ap_msg->message;
221 int size;
222
223 /* VUD.ciphertext */
224 msg->length = crt->inputdatalength + 2;
225 if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
226 return -EFAULT;
227
228 /* Set up key which is located after the variable length text. */
229 size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1);
230 if (size < 0)
231 return size;
232 size += sizeof(*msg) + crt->inputdatalength; /* total size of msg */
233
234 /* message header, cprbx and f&r */
235 msg->hdr = static_type6_hdrX;
236 msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
237 msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
238
239 msg->cprbx = static_cprbx;
240 msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
241 msg->cprbx.req_parml = msg->cprbx.rpl_msgbl =
242 size - sizeof(msg->hdr) - sizeof(msg->cprbx);
243
244 msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
245 static_pkd_fnr_MCL2 : static_pkd_fnr;
246
247 ap_msg->length = size;
248 return 0;
249}
250
251/**
252 * Convert a XCRB message to a type6 CPRB message.
253 *
254 * @zdev: crypto device pointer
255 * @ap_msg: pointer to AP message
256 * @xcRB: pointer to user input data
257 *
258 * Returns 0 on success or -EFAULT, -EINVAL.
259 */
260struct type86_fmt2_msg {
261 struct type86_hdr hdr;
262 struct type86_fmt2_ext fmt2;
263} __attribute__((packed));
264
265static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
266 struct ap_message *ap_msg,
267 struct ica_xcRB *xcRB)
268{
269 static struct type6_hdr static_type6_hdrX = {
270 .type = 0x06,
271 .offset1 = 0x00000058,
272 };
273 struct {
274 struct type6_hdr hdr;
275 struct CPRBX cprbx;
276 } __attribute__((packed)) *msg = ap_msg->message;
277
278 int rcblen = CEIL4(xcRB->request_control_blk_length);
279 int replylen;
280 char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
281 char *function_code;
282
283 /* length checks */
284 ap_msg->length = sizeof(struct type6_hdr) +
285 CEIL4(xcRB->request_control_blk_length) +
286 xcRB->request_data_length;
287 if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE)
288 return -EINVAL;
289 replylen = sizeof(struct type86_fmt2_msg) +
290 CEIL4(xcRB->reply_control_blk_length) +
291 xcRB->reply_data_length;
292 if (replylen > PCIXCC_MAX_XCRB_MESSAGE_SIZE)
293 return -EINVAL;
294
295 /* prepare type6 header */
296 msg->hdr = static_type6_hdrX;
297 memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
298 msg->hdr.ToCardLen1 = xcRB->request_control_blk_length;
299 if (xcRB->request_data_length) {
300 msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
301 msg->hdr.ToCardLen2 = xcRB->request_data_length;
302 }
303 msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
304 msg->hdr.FromCardLen2 = xcRB->reply_data_length;
305
306 /* prepare CPRB */
307 if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
308 xcRB->request_control_blk_length))
309 return -EFAULT;
310 if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
311 xcRB->request_control_blk_length)
312 return -EINVAL;
313 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
314 memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code));
315
316 if (memcmp(function_code, "US", 2) == 0)
317 ap_msg->special = 1;
318 else
319 ap_msg->special = 0;
320
321 /* copy data block */
322 if (xcRB->request_data_length &&
323 copy_from_user(req_data, xcRB->request_data_address,
324 xcRB->request_data_length))
325 return -EFAULT;
326 return 0;
327}
328
329/**
330 * Prepare a type6 CPRB message for random number generation
331 *
332 * @ap_dev: AP device pointer
333 * @ap_msg: pointer to AP message
334 */
335static void rng_type6CPRB_msgX(struct ap_device *ap_dev,
336 struct ap_message *ap_msg,
337 unsigned random_number_length)
338{
339 struct {
340 struct type6_hdr hdr;
341 struct CPRBX cprbx;
342 char function_code[2];
343 short int rule_length;
344 char rule[8];
345 short int verb_length;
346 short int key_length;
347 } __attribute__((packed)) *msg = ap_msg->message;
348 static struct type6_hdr static_type6_hdrX = {
349 .type = 0x06,
350 .offset1 = 0x00000058,
351 .agent_id = {'C', 'A'},
352 .function_code = {'R', 'L'},
353 .ToCardLen1 = sizeof *msg - sizeof(msg->hdr),
354 .FromCardLen1 = sizeof *msg - sizeof(msg->hdr),
355 };
356 static struct CPRBX local_cprbx = {
357 .cprb_len = 0x00dc,
358 .cprb_ver_id = 0x02,
359 .func_id = {0x54, 0x32},
360 .req_parml = sizeof *msg - sizeof(msg->hdr) -
361 sizeof(msg->cprbx),
362 .rpl_msgbl = sizeof *msg - sizeof(msg->hdr),
363 };
364
365 msg->hdr = static_type6_hdrX;
366 msg->hdr.FromCardLen2 = random_number_length,
367 msg->cprbx = local_cprbx;
368 msg->cprbx.rpl_datal = random_number_length,
369 msg->cprbx.domain = AP_QID_QUEUE(ap_dev->qid);
370 memcpy(msg->function_code, msg->hdr.function_code, 0x02);
371 msg->rule_length = 0x0a;
372 memcpy(msg->rule, "RANDOM ", 8);
373 msg->verb_length = 0x02;
374 msg->key_length = 0x02;
375 ap_msg->length = sizeof *msg;
376}
377
378/**
379 * Copy results from a type 86 ICA reply message back to user space.
380 *
381 * @zdev: crypto device pointer
382 * @reply: reply AP message.
383 * @data: pointer to user output data
384 * @length: size of user output data
385 *
386 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
387 */
388struct type86x_reply {
389 struct type86_hdr hdr;
390 struct type86_fmt2_ext fmt2;
391 struct CPRBX cprbx;
392 unsigned char pad[4]; /* 4 byte function code/rules block ? */
393 unsigned short length;
394 char text[0];
395} __attribute__((packed));
396
397static int convert_type86_ica(struct zcrypt_device *zdev,
398 struct ap_message *reply,
399 char __user *outputdata,
400 unsigned int outputdatalength)
401{
402 static unsigned char static_pad[] = {
403 0x00,0x02,
404 0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,
405 0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57,
406 0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,
407 0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39,
408 0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,
409 0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D,
410 0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,
411 0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F,
412 0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,
413 0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45,
414 0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,
415 0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F,
416 0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,
417 0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D,
418 0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,
419 0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9,
420 0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,
421 0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B,
422 0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,
423 0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD,
424 0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,
425 0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1,
426 0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,
427 0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23,
428 0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,
429 0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43,
430 0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,
431 0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F,
432 0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,
433 0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD,
434 0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,
435 0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09
436 };
437 struct type86x_reply *msg = reply->message;
438 unsigned short service_rc, service_rs;
439 unsigned int reply_len, pad_len;
440 char *data;
441
442 service_rc = msg->cprbx.ccp_rtcode;
443 if (unlikely(service_rc != 0)) {
444 service_rs = msg->cprbx.ccp_rscode;
445 if (service_rc == 8 && service_rs == 66)
446 return -EINVAL;
447 if (service_rc == 8 && service_rs == 65)
448 return -EINVAL;
449 if (service_rc == 8 && service_rs == 770)
450 return -EINVAL;
451 if (service_rc == 8 && service_rs == 783) {
452 zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
453 return -EAGAIN;
454 }
455 if (service_rc == 12 && service_rs == 769)
456 return -EINVAL;
457 if (service_rc == 8 && service_rs == 72)
458 return -EINVAL;
459 zdev->online = 0;
460 return -EAGAIN; /* repeat the request on a different device. */
461 }
462 data = msg->text;
463 reply_len = msg->length - 2;
464 if (reply_len > outputdatalength)
465 return -EINVAL;
466 /*
467 * For all encipher requests, the length of the ciphertext (reply_len)
468 * will always equal the modulus length. For MEX decipher requests
469 * the output needs to get padded. Minimum pad size is 10.
470 *
471 * Currently, the cases where padding will be added is for:
472 * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
473 * ZERO-PAD and CRT is only supported for PKD requests)
474 * - PCICC, always
475 */
476 pad_len = outputdatalength - reply_len;
477 if (pad_len > 0) {
478 if (pad_len < 10)
479 return -EINVAL;
480 /* 'restore' padding left in the PCICC/PCIXCC card. */
481 if (copy_to_user(outputdata, static_pad, pad_len - 1))
482 return -EFAULT;
483 if (put_user(0, outputdata + pad_len - 1))
484 return -EFAULT;
485 }
486 /* Copy the crypto response to user space. */
487 if (copy_to_user(outputdata + pad_len, data, reply_len))
488 return -EFAULT;
489 return 0;
490}
491
492/**
493 * Copy results from a type 86 XCRB reply message back to user space.
494 *
495 * @zdev: crypto device pointer
496 * @reply: reply AP message.
497 * @xcRB: pointer to XCRB
498 *
499 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
500 */
501static int convert_type86_xcrb(struct zcrypt_device *zdev,
502 struct ap_message *reply,
503 struct ica_xcRB *xcRB)
504{
505 struct type86_fmt2_msg *msg = reply->message;
506 char *data = reply->message;
507
508 /* Copy CPRB to user */
509 if (copy_to_user(xcRB->reply_control_blk_addr,
510 data + msg->fmt2.offset1, msg->fmt2.count1))
511 return -EFAULT;
512 xcRB->reply_control_blk_length = msg->fmt2.count1;
513
514 /* Copy data buffer to user */
515 if (msg->fmt2.count2)
516 if (copy_to_user(xcRB->reply_data_addr,
517 data + msg->fmt2.offset2, msg->fmt2.count2))
518 return -EFAULT;
519 xcRB->reply_data_length = msg->fmt2.count2;
520 return 0;
521}
522
523static int convert_type86_rng(struct zcrypt_device *zdev,
524 struct ap_message *reply,
525 char *buffer)
526{
527 struct {
528 struct type86_hdr hdr;
529 struct type86_fmt2_ext fmt2;
530 struct CPRBX cprbx;
531 } __attribute__((packed)) *msg = reply->message;
532 char *data = reply->message;
533
534 if (msg->cprbx.ccp_rtcode != 0 || msg->cprbx.ccp_rscode != 0)
535 return -EINVAL;
536 memcpy(buffer, data + msg->fmt2.offset2, msg->fmt2.count2);
537 return msg->fmt2.count2;
538}
539
540static int convert_response_ica(struct zcrypt_device *zdev,
541 struct ap_message *reply,
542 char __user *outputdata,
543 unsigned int outputdatalength)
544{
545 struct type86x_reply *msg = reply->message;
546
547 /* Response type byte is the second byte in the response. */
548 switch (((unsigned char *) reply->message)[1]) {
549 case TYPE82_RSP_CODE:
550 case TYPE88_RSP_CODE:
551 return convert_error(zdev, reply);
552 case TYPE86_RSP_CODE:
553 if (msg->cprbx.ccp_rtcode &&
554 (msg->cprbx.ccp_rscode == 0x14f) &&
555 (outputdatalength > 256)) {
556 if (zdev->max_exp_bit_length <= 17) {
557 zdev->max_exp_bit_length = 17;
558 return -EAGAIN;
559 } else
560 return -EINVAL;
561 }
562 if (msg->hdr.reply_code)
563 return convert_error(zdev, reply);
564 if (msg->cprbx.cprb_ver_id == 0x02)
565 return convert_type86_ica(zdev, reply,
566 outputdata, outputdatalength);
567 /* Fall through, no break, incorrect cprb version is an unknown
568 * response */
569 default: /* Unknown response type, this should NEVER EVER happen */
570 zdev->online = 0;
571 return -EAGAIN; /* repeat the request on a different device. */
572 }
573}
574
575static int convert_response_xcrb(struct zcrypt_device *zdev,
576 struct ap_message *reply,
577 struct ica_xcRB *xcRB)
578{
579 struct type86x_reply *msg = reply->message;
580
581 /* Response type byte is the second byte in the response. */
582 switch (((unsigned char *) reply->message)[1]) {
583 case TYPE82_RSP_CODE:
584 case TYPE88_RSP_CODE:
585 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
586 return convert_error(zdev, reply);
587 case TYPE86_RSP_CODE:
588 if (msg->hdr.reply_code) {
589 memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
590 return convert_error(zdev, reply);
591 }
592 if (msg->cprbx.cprb_ver_id == 0x02)
593 return convert_type86_xcrb(zdev, reply, xcRB);
594 /* Fall through, no break, incorrect cprb version is an unknown
595 * response */
596 default: /* Unknown response type, this should NEVER EVER happen */
597 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
598 zdev->online = 0;
599 return -EAGAIN; /* repeat the request on a different device. */
600 }
601}
602
603static int convert_response_rng(struct zcrypt_device *zdev,
604 struct ap_message *reply,
605 char *data)
606{
607 struct type86x_reply *msg = reply->message;
608
609 switch (msg->hdr.type) {
610 case TYPE82_RSP_CODE:
611 case TYPE88_RSP_CODE:
612 return -EINVAL;
613 case TYPE86_RSP_CODE:
614 if (msg->hdr.reply_code)
615 return -EINVAL;
616 if (msg->cprbx.cprb_ver_id == 0x02)
617 return convert_type86_rng(zdev, reply, data);
618 /* Fall through, no break, incorrect cprb version is an unknown
619 * response */
620 default: /* Unknown response type, this should NEVER EVER happen */
621 zdev->online = 0;
622 return -EAGAIN; /* repeat the request on a different device. */
623 }
624}
625
626/**
627 * This function is called from the AP bus code after a crypto request
628 * "msg" has finished with the reply message "reply".
629 * It is called from tasklet context.
630 * @ap_dev: pointer to the AP device
631 * @msg: pointer to the AP message
632 * @reply: pointer to the AP reply message
633 */
634static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
635 struct ap_message *msg,
636 struct ap_message *reply)
637{
638 static struct error_hdr error_reply = {
639 .type = TYPE82_RSP_CODE,
640 .reply_code = REP82_ERROR_MACHINE_FAILURE,
641 };
642 struct response_type *resp_type =
643 (struct response_type *) msg->private;
644 struct type86x_reply *t86r;
645 int length;
646
647 /* Copy the reply message to the request message buffer. */
648 if (IS_ERR(reply)) {
649 memcpy(msg->message, &error_reply, sizeof(error_reply));
650 goto out;
651 }
652 t86r = reply->message;
653 if (t86r->hdr.type == TYPE86_RSP_CODE &&
654 t86r->cprbx.cprb_ver_id == 0x02) {
655 switch (resp_type->type) {
656 case PCIXCC_RESPONSE_TYPE_ICA:
657 length = sizeof(struct type86x_reply)
658 + t86r->length - 2;
659 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
660 memcpy(msg->message, reply->message, length);
661 break;
662 case PCIXCC_RESPONSE_TYPE_XCRB:
663 length = t86r->fmt2.offset2 + t86r->fmt2.count2;
664 length = min(PCIXCC_MAX_XCRB_MESSAGE_SIZE, length);
665 memcpy(msg->message, reply->message, length);
666 break;
667 default:
668 memcpy(msg->message, &error_reply, sizeof error_reply);
669 }
670 } else
671 memcpy(msg->message, reply->message, sizeof error_reply);
672out:
673 complete(&(resp_type->work));
674}
675
676static atomic_t zcrypt_step = ATOMIC_INIT(0);
677
678/**
679 * The request distributor calls this function if it picked the PCIXCC/CEX2C
680 * device to handle a modexpo request.
681 * @zdev: pointer to zcrypt_device structure that identifies the
682 * PCIXCC/CEX2C device to the request distributor
683 * @mex: pointer to the modexpo request buffer
684 */
685static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
686 struct ica_rsa_modexpo *mex)
687{
688 struct ap_message ap_msg;
689 struct response_type resp_type = {
690 .type = PCIXCC_RESPONSE_TYPE_ICA,
691 };
692 int rc;
693
694 ap_init_message(&ap_msg);
695 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
696 if (!ap_msg.message)
697 return -ENOMEM;
698 ap_msg.receive = zcrypt_pcixcc_receive;
699 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
700 atomic_inc_return(&zcrypt_step);
701 ap_msg.private = &resp_type;
702 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
703 if (rc)
704 goto out_free;
705 init_completion(&resp_type.work);
706 ap_queue_message(zdev->ap_dev, &ap_msg);
707 rc = wait_for_completion_interruptible(&resp_type.work);
708 if (rc == 0)
709 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
710 mex->outputdatalength);
711 else
712 /* Signal pending. */
713 ap_cancel_message(zdev->ap_dev, &ap_msg);
714out_free:
715 free_page((unsigned long) ap_msg.message);
716 return rc;
717}
718
719/**
720 * The request distributor calls this function if it picked the PCIXCC/CEX2C
721 * device to handle a modexpo_crt request.
722 * @zdev: pointer to zcrypt_device structure that identifies the
723 * PCIXCC/CEX2C device to the request distributor
724 * @crt: pointer to the modexpoc_crt request buffer
725 */
726static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
727 struct ica_rsa_modexpo_crt *crt)
728{
729 struct ap_message ap_msg;
730 struct response_type resp_type = {
731 .type = PCIXCC_RESPONSE_TYPE_ICA,
732 };
733 int rc;
734
735 ap_init_message(&ap_msg);
736 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
737 if (!ap_msg.message)
738 return -ENOMEM;
739 ap_msg.receive = zcrypt_pcixcc_receive;
740 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
741 atomic_inc_return(&zcrypt_step);
742 ap_msg.private = &resp_type;
743 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
744 if (rc)
745 goto out_free;
746 init_completion(&resp_type.work);
747 ap_queue_message(zdev->ap_dev, &ap_msg);
748 rc = wait_for_completion_interruptible(&resp_type.work);
749 if (rc == 0)
750 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
751 crt->outputdatalength);
752 else
753 /* Signal pending. */
754 ap_cancel_message(zdev->ap_dev, &ap_msg);
755out_free:
756 free_page((unsigned long) ap_msg.message);
757 return rc;
758}
759
760/**
761 * The request distributor calls this function if it picked the PCIXCC/CEX2C
762 * device to handle a send_cprb request.
763 * @zdev: pointer to zcrypt_device structure that identifies the
764 * PCIXCC/CEX2C device to the request distributor
765 * @xcRB: pointer to the send_cprb request buffer
766 */
767static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
768 struct ica_xcRB *xcRB)
769{
770 struct ap_message ap_msg;
771 struct response_type resp_type = {
772 .type = PCIXCC_RESPONSE_TYPE_XCRB,
773 };
774 int rc;
775
776 ap_init_message(&ap_msg);
777 ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
778 if (!ap_msg.message)
779 return -ENOMEM;
780 ap_msg.receive = zcrypt_pcixcc_receive;
781 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
782 atomic_inc_return(&zcrypt_step);
783 ap_msg.private = &resp_type;
784 rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB);
785 if (rc)
786 goto out_free;
787 init_completion(&resp_type.work);
788 ap_queue_message(zdev->ap_dev, &ap_msg);
789 rc = wait_for_completion_interruptible(&resp_type.work);
790 if (rc == 0)
791 rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
792 else
793 /* Signal pending. */
794 ap_cancel_message(zdev->ap_dev, &ap_msg);
795out_free:
796 kzfree(ap_msg.message);
797 return rc;
798}
799
800/**
801 * The request distributor calls this function if it picked the PCIXCC/CEX2C
802 * device to generate random data.
803 * @zdev: pointer to zcrypt_device structure that identifies the
804 * PCIXCC/CEX2C device to the request distributor
805 * @buffer: pointer to a memory page to return random data
806 */
807
808static long zcrypt_pcixcc_rng(struct zcrypt_device *zdev,
809 char *buffer)
810{
811 struct ap_message ap_msg;
812 struct response_type resp_type = {
813 .type = PCIXCC_RESPONSE_TYPE_XCRB,
814 };
815 int rc;
816
817 ap_init_message(&ap_msg);
818 ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
819 if (!ap_msg.message)
820 return -ENOMEM;
821 ap_msg.receive = zcrypt_pcixcc_receive;
822 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
823 atomic_inc_return(&zcrypt_step);
824 ap_msg.private = &resp_type;
825 rng_type6CPRB_msgX(zdev->ap_dev, &ap_msg, ZCRYPT_RNG_BUFFER_SIZE);
826 init_completion(&resp_type.work);
827 ap_queue_message(zdev->ap_dev, &ap_msg);
828 rc = wait_for_completion_interruptible(&resp_type.work);
829 if (rc == 0)
830 rc = convert_response_rng(zdev, &ap_msg, buffer);
831 else
832 /* Signal pending. */
833 ap_cancel_message(zdev->ap_dev, &ap_msg);
834 kfree(ap_msg.message);
835 return rc;
836}
837
838/**
839 * The crypto operations for a PCIXCC/CEX2C card.
840 */
841static struct zcrypt_ops zcrypt_pcixcc_ops = {
842 .rsa_modexpo = zcrypt_pcixcc_modexpo,
843 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
844 .send_cprb = zcrypt_pcixcc_send_cprb,
845};
846
847static struct zcrypt_ops zcrypt_pcixcc_with_rng_ops = {
848 .rsa_modexpo = zcrypt_pcixcc_modexpo,
849 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
850 .send_cprb = zcrypt_pcixcc_send_cprb,
851 .rng = zcrypt_pcixcc_rng,
852};
853
854/**
855 * Micro-code detection function. Its sends a message to a pcixcc card 95 * Micro-code detection function. Its sends a message to a pcixcc card
856 * to find out the microcode level. 96 * to find out the microcode level.
857 * @ap_dev: pointer to the AP device. 97 * @ap_dev: pointer to the AP device.
@@ -1083,9 +323,11 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
1083 return rc; 323 return rc;
1084 } 324 }
1085 if (rc) 325 if (rc)
1086 zdev->ops = &zcrypt_pcixcc_with_rng_ops; 326 zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME,
327 MSGTYPE06_VARIANT_DEFAULT);
1087 else 328 else
1088 zdev->ops = &zcrypt_pcixcc_ops; 329 zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME,
330 MSGTYPE06_VARIANT_NORNG);
1089 ap_dev->reply = &zdev->reply; 331 ap_dev->reply = &zdev->reply;
1090 ap_dev->private = zdev; 332 ap_dev->private = zdev;
1091 rc = zcrypt_device_register(zdev); 333 rc = zcrypt_device_register(zdev);
@@ -1095,6 +337,7 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
1095 337
1096 out_free: 338 out_free:
1097 ap_dev->private = NULL; 339 ap_dev->private = NULL;
340 zcrypt_msgtype_release(zdev->ops);
1098 zcrypt_device_free(zdev); 341 zcrypt_device_free(zdev);
1099 return rc; 342 return rc;
1100} 343}
@@ -1106,8 +349,10 @@ static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
1106static void zcrypt_pcixcc_remove(struct ap_device *ap_dev) 349static void zcrypt_pcixcc_remove(struct ap_device *ap_dev)
1107{ 350{
1108 struct zcrypt_device *zdev = ap_dev->private; 351 struct zcrypt_device *zdev = ap_dev->private;
352 struct zcrypt_ops *zops = zdev->ops;
1109 353
1110 zcrypt_device_unregister(zdev); 354 zcrypt_device_unregister(zdev);
355 zcrypt_msgtype_release(zops);
1111} 356}
1112 357
1113int __init zcrypt_pcixcc_init(void) 358int __init zcrypt_pcixcc_init(void)