aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/crypto/zcrypt_pcixcc.c
diff options
context:
space:
mode:
authorRalph Wuerthner <rwuerthn@de.ibm.com>2006-09-20 09:58:36 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-09-20 09:58:36 -0400
commit5432114baf0300286a6ca1b0aea549492a379432 (patch)
tree6a9cf64c86e4ee4d439f91e9bd4485688d28ddd7 /drivers/s390/crypto/zcrypt_pcixcc.c
parentfe3a1be59c851aba2330387596c6134bc5ec8397 (diff)
[S390] zcrypt secure key cryptography extension.
Allow the user space to send extended cprb messages directly to the PCIXCC / CEX2C cards. This allows the CCA library to construct special crypto requests that use "secure" keys that are stored on the card. Signed-off-by: Ralph Wuerthner <rwuerthn@de.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.c263
1 files changed, 250 insertions, 13 deletions
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c
index 6064cf58be43..2da8b9381407 100644
--- a/drivers/s390/crypto/zcrypt_pcixcc.c
+++ b/drivers/s390/crypto/zcrypt_pcixcc.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * linux/drivers/s390/crypto/zcrypt_pcixcc.c 2 * linux/drivers/s390/crypto/zcrypt_pcixcc.c
3 * 3 *
4 * zcrypt 2.0.0 4 * zcrypt 2.1.0
5 * 5 *
6 * Copyright (C) 2001, 2006 IBM Corporation 6 * Copyright (C) 2001, 2006 IBM Corporation
7 * Author(s): Robert Burroughs 7 * Author(s): Robert Burroughs
@@ -60,6 +60,15 @@
60 60
61#define PCIXCC_CLEANUP_TIME (15*HZ) 61#define PCIXCC_CLEANUP_TIME (15*HZ)
62 62
63#define CEIL4(x) ((((x)+3)/4)*4)
64
65struct response_type {
66 struct completion work;
67 int type;
68};
69#define PCIXCC_RESPONSE_TYPE_ICA 0
70#define PCIXCC_RESPONSE_TYPE_XCRB 1
71
63static struct ap_device_id zcrypt_pcixcc_ids[] = { 72static struct ap_device_id zcrypt_pcixcc_ids[] = {
64 { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) }, 73 { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) },
65 { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) }, 74 { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) },
@@ -244,6 +253,108 @@ static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,
244} 253}
245 254
246/** 255/**
256 * Convert a XCRB message to a type6 CPRB message.
257 *
258 * @zdev: crypto device pointer
259 * @ap_msg: pointer to AP message
260 * @xcRB: pointer to user input data
261 *
262 * Returns 0 on success or -EFAULT.
263 */
264struct type86_fmt2_msg {
265 struct type86_hdr hdr;
266 struct type86_fmt2_ext fmt2;
267} __attribute__((packed));
268
269static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
270 struct ap_message *ap_msg,
271 struct ica_xcRB *xcRB)
272{
273 static struct type6_hdr static_type6_hdrX = {
274 .type = 0x06,
275 .offset1 = 0x00000058,
276 };
277 struct {
278 struct type6_hdr hdr;
279 struct ica_CPRBX cprbx;
280 } __attribute__((packed)) *msg = ap_msg->message;
281
282 int rcblen = CEIL4(xcRB->request_control_blk_length);
283 int replylen;
284 char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
285 char *function_code;
286
287 /* length checks */
288 ap_msg->length = sizeof(struct type6_hdr) +
289 CEIL4(xcRB->request_control_blk_length) +
290 xcRB->request_data_length;
291 if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE) {
292 PRINTK("Combined message is too large (%ld/%d/%d).\n",
293 sizeof(struct type6_hdr),
294 xcRB->request_control_blk_length,
295 xcRB->request_data_length);
296 return -EFAULT;
297 }
298 if (CEIL4(xcRB->reply_control_blk_length) >
299 PCIXCC_MAX_XCRB_REPLY_SIZE) {
300 PDEBUG("Reply CPRB length is too large (%d).\n",
301 xcRB->request_control_blk_length);
302 return -EFAULT;
303 }
304 if (CEIL4(xcRB->reply_data_length) > PCIXCC_MAX_XCRB_DATA_SIZE) {
305 PDEBUG("Reply data block length is too large (%d).\n",
306 xcRB->reply_data_length);
307 return -EFAULT;
308 }
309 replylen = CEIL4(xcRB->reply_control_blk_length) +
310 CEIL4(xcRB->reply_data_length) +
311 sizeof(struct type86_fmt2_msg);
312 if (replylen > PCIXCC_MAX_XCRB_RESPONSE_SIZE) {
313 PDEBUG("Reply CPRB + data block > PCIXCC_MAX_XCRB_RESPONSE_SIZE"
314 " (%d/%d/%d).\n",
315 sizeof(struct type86_fmt2_msg),
316 xcRB->reply_control_blk_length,
317 xcRB->reply_data_length);
318 xcRB->reply_control_blk_length = PCIXCC_MAX_XCRB_RESPONSE_SIZE -
319 (sizeof(struct type86_fmt2_msg) +
320 CEIL4(xcRB->reply_data_length));
321 PDEBUG("Capping Reply CPRB length at %d\n",
322 xcRB->reply_control_blk_length);
323 }
324
325 /* prepare type6 header */
326 msg->hdr = static_type6_hdrX;
327 memcpy(msg->hdr.agent_id , &(xcRB->agent_ID), sizeof(xcRB->agent_ID));
328 msg->hdr.ToCardLen1 = xcRB->request_control_blk_length;
329 if (xcRB->request_data_length) {
330 msg->hdr.offset2 = msg->hdr.offset1 + rcblen;
331 msg->hdr.ToCardLen2 = xcRB->request_data_length;
332 }
333 msg->hdr.FromCardLen1 = xcRB->reply_control_blk_length;
334 msg->hdr.FromCardLen2 = xcRB->reply_data_length;
335
336 /* prepare CPRB */
337 if (copy_from_user(&(msg->cprbx), xcRB->request_control_blk_addr,
338 xcRB->request_control_blk_length))
339 return -EFAULT;
340 if (msg->cprbx.cprb_len + sizeof(msg->hdr.function_code) >
341 xcRB->request_control_blk_length) {
342 PDEBUG("cprb_len too large (%d/%d)\n", msg->cprbx.cprb_len,
343 xcRB->request_control_blk_length);
344 return -EFAULT;
345 }
346 function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
347 memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code));
348
349 /* copy data block */
350 if (xcRB->request_data_length &&
351 copy_from_user(req_data, xcRB->request_data_address,
352 xcRB->request_data_length))
353 return -EFAULT;
354 return 0;
355}
356
357/**
247 * Copy results from a type 86 ICA reply message back to user space. 358 * Copy results from a type 86 ICA reply message back to user space.
248 * 359 *
249 * @zdev: crypto device pointer 360 * @zdev: crypto device pointer
@@ -363,6 +474,37 @@ static int convert_type86_ica(struct zcrypt_device *zdev,
363 return 0; 474 return 0;
364} 475}
365 476
477/**
478 * Copy results from a type 86 XCRB reply message back to user space.
479 *
480 * @zdev: crypto device pointer
481 * @reply: reply AP message.
482 * @xcRB: pointer to XCRB
483 *
484 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
485 */
486static int convert_type86_xcrb(struct zcrypt_device *zdev,
487 struct ap_message *reply,
488 struct ica_xcRB *xcRB)
489{
490 struct type86_fmt2_msg *msg = reply->message;
491 char *data = reply->message;
492
493 /* Copy CPRB to user */
494 if (copy_to_user(xcRB->reply_control_blk_addr,
495 data + msg->fmt2.offset1, msg->fmt2.count1))
496 return -EFAULT;
497 xcRB->reply_control_blk_length = msg->fmt2.count1;
498
499 /* Copy data buffer to user */
500 if (msg->fmt2.count2)
501 if (copy_to_user(xcRB->reply_data_addr,
502 data + msg->fmt2.offset2, msg->fmt2.count2))
503 return -EFAULT;
504 xcRB->reply_data_length = msg->fmt2.count2;
505 return 0;
506}
507
366static int convert_response_ica(struct zcrypt_device *zdev, 508static int convert_response_ica(struct zcrypt_device *zdev,
367 struct ap_message *reply, 509 struct ap_message *reply,
368 char __user *outputdata, 510 char __user *outputdata,
@@ -391,6 +533,36 @@ static int convert_response_ica(struct zcrypt_device *zdev,
391 } 533 }
392} 534}
393 535
536static int convert_response_xcrb(struct zcrypt_device *zdev,
537 struct ap_message *reply,
538 struct ica_xcRB *xcRB)
539{
540 struct type86x_reply *msg = reply->message;
541
542 /* Response type byte is the second byte in the response. */
543 switch (((unsigned char *) reply->message)[1]) {
544 case TYPE82_RSP_CODE:
545 case TYPE88_RSP_CODE:
546 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
547 return convert_error(zdev, reply);
548 case TYPE86_RSP_CODE:
549 if (msg->hdr.reply_code) {
550 memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
551 return convert_error(zdev, reply);
552 }
553 if (msg->cprbx.cprb_ver_id == 0x02)
554 return convert_type86_xcrb(zdev, reply, xcRB);
555 /* no break, incorrect cprb version is an unknown response */
556 default: /* Unknown response type, this should NEVER EVER happen */
557 PRINTK("Unrecognized Message Header: %08x%08x\n",
558 *(unsigned int *) reply->message,
559 *(unsigned int *) (reply->message+4));
560 xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
561 zdev->online = 0;
562 return -EAGAIN; /* repeat the request on a different device. */
563 }
564}
565
394/** 566/**
395 * This function is called from the AP bus code after a crypto request 567 * This function is called from the AP bus code after a crypto request
396 * "msg" has finished with the reply message "reply". 568 * "msg" has finished with the reply message "reply".
@@ -407,6 +579,8 @@ static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
407 .type = TYPE82_RSP_CODE, 579 .type = TYPE82_RSP_CODE,
408 .reply_code = REP82_ERROR_MACHINE_FAILURE, 580 .reply_code = REP82_ERROR_MACHINE_FAILURE,
409 }; 581 };
582 struct response_type *resp_type =
583 (struct response_type *) msg->private;
410 struct type86x_reply *t86r = reply->message; 584 struct type86x_reply *t86r = reply->message;
411 int length; 585 int length;
412 586
@@ -415,12 +589,27 @@ static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
415 memcpy(msg->message, &error_reply, sizeof(error_reply)); 589 memcpy(msg->message, &error_reply, sizeof(error_reply));
416 else if (t86r->hdr.type == TYPE86_RSP_CODE && 590 else if (t86r->hdr.type == TYPE86_RSP_CODE &&
417 t86r->cprbx.cprb_ver_id == 0x02) { 591 t86r->cprbx.cprb_ver_id == 0x02) {
418 length = sizeof(struct type86x_reply) + t86r->length - 2; 592 switch (resp_type->type) {
419 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length); 593 case PCIXCC_RESPONSE_TYPE_ICA:
420 memcpy(msg->message, reply->message, length); 594 length = sizeof(struct type86x_reply)
595 + t86r->length - 2;
596 length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
597 memcpy(msg->message, reply->message, length);
598 break;
599 case PCIXCC_RESPONSE_TYPE_XCRB:
600 length = t86r->fmt2.offset2 + t86r->fmt2.count2;
601 length = min(PCIXCC_MAX_XCRB_RESPONSE_SIZE, length);
602 memcpy(msg->message, reply->message, length);
603 break;
604 default:
605 PRINTK("Invalid internal response type: %i\n",
606 resp_type->type);
607 memcpy(msg->message, &error_reply,
608 sizeof error_reply);
609 }
421 } else 610 } else
422 memcpy(msg->message, reply->message, sizeof error_reply); 611 memcpy(msg->message, reply->message, sizeof error_reply);
423 complete((struct completion *) msg->private); 612 complete(&(resp_type->work));
424} 613}
425 614
426static atomic_t zcrypt_step = ATOMIC_INIT(0); 615static atomic_t zcrypt_step = ATOMIC_INIT(0);
@@ -436,7 +625,9 @@ static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
436 struct ica_rsa_modexpo *mex) 625 struct ica_rsa_modexpo *mex)
437{ 626{
438 struct ap_message ap_msg; 627 struct ap_message ap_msg;
439 struct completion work; 628 struct response_type resp_type = {
629 .type = PCIXCC_RESPONSE_TYPE_ICA,
630 };
440 int rc; 631 int rc;
441 632
442 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); 633 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
@@ -444,14 +635,14 @@ static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
444 return -ENOMEM; 635 return -ENOMEM;
445 ap_msg.psmid = (((unsigned long long) current->pid) << 32) + 636 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
446 atomic_inc_return(&zcrypt_step); 637 atomic_inc_return(&zcrypt_step);
447 ap_msg.private = &work; 638 ap_msg.private = &resp_type;
448 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex); 639 rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
449 if (rc) 640 if (rc)
450 goto out_free; 641 goto out_free;
451 init_completion(&work); 642 init_completion(&resp_type.work);
452 ap_queue_message(zdev->ap_dev, &ap_msg); 643 ap_queue_message(zdev->ap_dev, &ap_msg);
453 rc = wait_for_completion_interruptible_timeout( 644 rc = wait_for_completion_interruptible_timeout(
454 &work, PCIXCC_CLEANUP_TIME); 645 &resp_type.work, PCIXCC_CLEANUP_TIME);
455 if (rc > 0) 646 if (rc > 0)
456 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata, 647 rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
457 mex->outputdatalength); 648 mex->outputdatalength);
@@ -478,7 +669,9 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
478 struct ica_rsa_modexpo_crt *crt) 669 struct ica_rsa_modexpo_crt *crt)
479{ 670{
480 struct ap_message ap_msg; 671 struct ap_message ap_msg;
481 struct completion work; 672 struct response_type resp_type = {
673 .type = PCIXCC_RESPONSE_TYPE_ICA,
674 };
482 int rc; 675 int rc;
483 676
484 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL); 677 ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
@@ -486,14 +679,14 @@ static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
486 return -ENOMEM; 679 return -ENOMEM;
487 ap_msg.psmid = (((unsigned long long) current->pid) << 32) + 680 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
488 atomic_inc_return(&zcrypt_step); 681 atomic_inc_return(&zcrypt_step);
489 ap_msg.private = &work; 682 ap_msg.private = &resp_type;
490 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt); 683 rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
491 if (rc) 684 if (rc)
492 goto out_free; 685 goto out_free;
493 init_completion(&work); 686 init_completion(&resp_type.work);
494 ap_queue_message(zdev->ap_dev, &ap_msg); 687 ap_queue_message(zdev->ap_dev, &ap_msg);
495 rc = wait_for_completion_interruptible_timeout( 688 rc = wait_for_completion_interruptible_timeout(
496 &work, PCIXCC_CLEANUP_TIME); 689 &resp_type.work, PCIXCC_CLEANUP_TIME);
497 if (rc > 0) 690 if (rc > 0)
498 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata, 691 rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
499 crt->outputdatalength); 692 crt->outputdatalength);
@@ -510,11 +703,55 @@ out_free:
510} 703}
511 704
512/** 705/**
706 * The request distributor calls this function if it picked the PCIXCC/CEX2C
707 * device to handle a send_cprb request.
708 * @zdev: pointer to zcrypt_device structure that identifies the
709 * PCIXCC/CEX2C device to the request distributor
710 * @xcRB: pointer to the send_cprb request buffer
711 */
712long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev, struct ica_xcRB *xcRB)
713{
714 struct ap_message ap_msg;
715 struct response_type resp_type = {
716 .type = PCIXCC_RESPONSE_TYPE_XCRB,
717 };
718 int rc;
719
720 ap_msg.message = (void *) kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
721 if (!ap_msg.message)
722 return -ENOMEM;
723 ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
724 atomic_inc_return(&zcrypt_step);
725 ap_msg.private = &resp_type;
726 rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB);
727 if (rc)
728 goto out_free;
729 init_completion(&resp_type.work);
730 ap_queue_message(zdev->ap_dev, &ap_msg);
731 rc = wait_for_completion_interruptible_timeout(
732 &resp_type.work, PCIXCC_CLEANUP_TIME);
733 if (rc > 0)
734 rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
735 else {
736 /* Signal pending or message timed out. */
737 ap_cancel_message(zdev->ap_dev, &ap_msg);
738 if (rc == 0)
739 /* Message timed out. */
740 rc = -ETIME;
741 }
742out_free:
743 memset(ap_msg.message, 0x0, ap_msg.length);
744 kfree(ap_msg.message);
745 return rc;
746}
747
748/**
513 * The crypto operations for a PCIXCC/CEX2C card. 749 * The crypto operations for a PCIXCC/CEX2C card.
514 */ 750 */
515static struct zcrypt_ops zcrypt_pcixcc_ops = { 751static struct zcrypt_ops zcrypt_pcixcc_ops = {
516 .rsa_modexpo = zcrypt_pcixcc_modexpo, 752 .rsa_modexpo = zcrypt_pcixcc_modexpo,
517 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt, 753 .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
754 .send_cprb = zcrypt_pcixcc_send_cprb,
518}; 755};
519 756
520/** 757/**