linux/drivers/s390/crypto/zcrypt_pcixcc.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/s390/crypto/zcrypt_pcixcc.c
   3 *
   4 *  zcrypt 2.1.0
   5 *
   6 *  Copyright (C)  2001, 2006 IBM Corporation
   7 *  Author(s): Robert Burroughs
   8 *             Eric Rossman (edrossma@us.ibm.com)
   9 *
  10 *  Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
  11 *  Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
  12 *                                Ralph Wuerthner <rwuerthn@de.ibm.com>
  13 *
  14 * 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 * the Free Software Foundation; either version 2, or (at your option)
  17 * any later version.
  18 *
  19 * This program is distributed in the hope that it will be useful,
  20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22 * GNU General Public License for more details.
  23 *
  24 * You should have received a copy of the GNU General Public License
  25 * along with this program; if not, write to the Free Software
  26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  27 */
  28
  29#include <linux/module.h>
  30#include <linux/init.h>
  31#include <linux/err.h>
  32#include <linux/delay.h>
  33#include <asm/atomic.h>
  34#include <asm/uaccess.h>
  35
  36#include "ap_bus.h"
  37#include "zcrypt_api.h"
  38#include "zcrypt_error.h"
  39#include "zcrypt_pcicc.h"
  40#include "zcrypt_pcixcc.h"
  41#include "zcrypt_cca_key.h"
  42
  43#define PCIXCC_MIN_MOD_SIZE      16     /*  128 bits    */
  44#define PCIXCC_MIN_MOD_SIZE_OLD  64     /*  512 bits    */
  45#define PCIXCC_MAX_MOD_SIZE     256     /* 2048 bits    */
  46
  47#define PCIXCC_MCL2_SPEED_RATING        7870    /* FIXME: needs finetuning */
  48#define PCIXCC_MCL3_SPEED_RATING        7870
  49#define CEX2C_SPEED_RATING              8540
  50
  51#define PCIXCC_MAX_ICA_MESSAGE_SIZE 0x77c  /* max size type6 v2 crt message */
  52#define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply      */
  53
  54#define PCIXCC_MAX_XCRB_MESSAGE_SIZE (12*1024)
  55#define PCIXCC_MAX_XCRB_RESPONSE_SIZE PCIXCC_MAX_XCRB_MESSAGE_SIZE
  56#define PCIXCC_MAX_XCRB_DATA_SIZE (11*1024)
  57#define PCIXCC_MAX_XCRB_REPLY_SIZE (5*1024)
  58
  59#define PCIXCC_MAX_RESPONSE_SIZE PCIXCC_MAX_XCRB_RESPONSE_SIZE
  60
  61#define PCIXCC_CLEANUP_TIME     (15*HZ)
  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
  72static struct ap_device_id zcrypt_pcixcc_ids[] = {
  73        { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) },
  74        { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) },
  75        { /* end of list */ },
  76};
  77
  78#ifndef CONFIG_ZCRYPT_MONOLITHIC
  79MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids);
  80MODULE_AUTHOR("IBM Corporation");
  81MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, "
  82                   "Copyright 2001, 2006 IBM Corporation");
  83MODULE_LICENSE("GPL");
  84#endif
  85
  86static int zcrypt_pcixcc_probe(struct ap_device *ap_dev);
  87static void zcrypt_pcixcc_remove(struct ap_device *ap_dev);
  88static void zcrypt_pcixcc_receive(struct ap_device *, struct ap_message *,
  89                                 struct ap_message *);
  90
  91static struct ap_driver zcrypt_pcixcc_driver = {
  92        .probe = zcrypt_pcixcc_probe,
  93        .remove = zcrypt_pcixcc_remove,
  94        .receive = zcrypt_pcixcc_receive,
  95        .ids = zcrypt_pcixcc_ids,
  96        .request_timeout = PCIXCC_CLEANUP_TIME,
  97};
  98
  99/**
 100 * The following is used to initialize the CPRBX passed to the PCIXCC/CEX2C
 101 * card in a type6 message. The 3 fields that must be filled in at execution
 102 * time are  req_parml, rpl_parml and usage_domain.
 103 * Everything about this interface is ascii/big-endian, since the
 104 * device does *not* have 'Intel inside'.
 105 *
 106 * The CPRBX is followed immediately by the parm block.
 107 * The parm block contains:
 108 * - function code ('PD' 0x5044 or 'PK' 0x504B)
 109 * - rule block (one of:)
 110 *   + 0x000A 'PKCS-1.2' (MCL2 'PD')
 111 *   + 0x000A 'ZERO-PAD' (MCL2 'PK')
 112 *   + 0x000A 'ZERO-PAD' (MCL3 'PD' or CEX2C 'PD')
 113 *   + 0x000A 'MRP     ' (MCL3 'PK' or CEX2C 'PK')
 114 * - VUD block
 115 */
 116static struct CPRBX static_cprbx = {
 117        .cprb_len       =  0x00DC,
 118        .cprb_ver_id    =  0x02,
 119        .func_id        = {0x54,0x32},
 120};
 121
 122/**
 123 * Convert a ICAMEX message to a type6 MEX message.
 124 *
 125 * @zdev: crypto device pointer
 126 * @ap_msg: pointer to AP message
 127 * @mex: pointer to user input data
 128 *
 129 * Returns 0 on success or -EFAULT.
 130 */
 131static int ICAMEX_msg_to_type6MEX_msgX(struct zcrypt_device *zdev,
 132                                       struct ap_message *ap_msg,
 133                                       struct ica_rsa_modexpo *mex)
 134{
 135        static struct type6_hdr static_type6_hdrX = {
 136                .type           =  0x06,
 137                .offset1        =  0x00000058,
 138                .agent_id       = {'C','A',},
 139                .function_code  = {'P','K'},
 140        };
 141        static struct function_and_rules_block static_pke_fnr = {
 142                .function_code  = {'P','K'},
 143                .ulen           = 10,
 144                .only_rule      = {'M','R','P',' ',' ',' ',' ',' '}
 145        };
 146        static struct function_and_rules_block static_pke_fnr_MCL2 = {
 147                .function_code  = {'P','K'},
 148                .ulen           = 10,
 149                .only_rule      = {'Z','E','R','O','-','P','A','D'}
 150        };
 151        struct {
 152                struct type6_hdr hdr;
 153                struct CPRBX cprbx;
 154                struct function_and_rules_block fr;
 155                unsigned short length;
 156                char text[0];
 157        } __attribute__((packed)) *msg = ap_msg->message;
 158        int size;
 159
 160        /* VUD.ciphertext */
 161        msg->length = mex->inputdatalength + 2;
 162        if (copy_from_user(msg->text, mex->inputdata, mex->inputdatalength))
 163                return -EFAULT;
 164
 165        /* Set up key which is located after the variable length text. */
 166        size = zcrypt_type6_mex_key_en(mex, msg->text+mex->inputdatalength, 1);
 167        if (size < 0)
 168                return size;
 169        size += sizeof(*msg) + mex->inputdatalength;
 170
 171        /* message header, cprbx and f&r */
 172        msg->hdr = static_type6_hdrX;
 173        msg->hdr.ToCardLen1 = size - sizeof(msg->hdr);
 174        msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
 175
 176        msg->cprbx = static_cprbx;
 177        msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
 178        msg->cprbx.rpl_msgbl = msg->hdr.FromCardLen1;
 179
 180        msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
 181                static_pke_fnr_MCL2 : static_pke_fnr;
 182
 183        msg->cprbx.req_parml = size - sizeof(msg->hdr) - sizeof(msg->cprbx);
 184
 185        ap_msg->length = size;
 186        return 0;
 187}
 188
 189/**
 190 * Convert a ICACRT message to a type6 CRT message.
 191 *
 192 * @zdev: crypto device pointer
 193 * @ap_msg: pointer to AP message
 194 * @crt: pointer to user input data
 195 *
 196 * Returns 0 on success or -EFAULT.
 197 */
 198static int ICACRT_msg_to_type6CRT_msgX(struct zcrypt_device *zdev,
 199                                       struct ap_message *ap_msg,
 200                                       struct ica_rsa_modexpo_crt *crt)
 201{
 202        static struct type6_hdr static_type6_hdrX = {
 203                .type           =  0x06,
 204                .offset1        =  0x00000058,
 205                .agent_id       = {'C','A',},
 206                .function_code  = {'P','D'},
 207        };
 208        static struct function_and_rules_block static_pkd_fnr = {
 209                .function_code  = {'P','D'},
 210                .ulen           = 10,
 211                .only_rule      = {'Z','E','R','O','-','P','A','D'}
 212        };
 213
 214        static struct function_and_rules_block static_pkd_fnr_MCL2 = {
 215                .function_code  = {'P','D'},
 216                .ulen           = 10,
 217                .only_rule      = {'P','K','C','S','-','1','.','2'}
 218        };
 219        struct {
 220                struct type6_hdr hdr;
 221                struct CPRBX cprbx;
 222                struct function_and_rules_block fr;
 223                unsigned short length;
 224                char text[0];
 225        } __attribute__((packed)) *msg = ap_msg->message;
 226        int size;
 227
 228        /* VUD.ciphertext */
 229        msg->length = crt->inputdatalength + 2;
 230        if (copy_from_user(msg->text, crt->inputdata, crt->inputdatalength))
 231                return -EFAULT;
 232
 233        /* Set up key which is located after the variable length text. */
 234        size = zcrypt_type6_crt_key(crt, msg->text + crt->inputdatalength, 1);
 235        if (size < 0)
 236                return size;
 237        size += sizeof(*msg) + crt->inputdatalength;    /* total size of msg */
 238
 239        /* message header, cprbx and f&r */
 240        msg->hdr = static_type6_hdrX;
 241        msg->hdr.ToCardLen1 = size -  sizeof(msg->hdr);
 242        msg->hdr.FromCardLen1 = PCIXCC_MAX_ICA_RESPONSE_SIZE - sizeof(msg->hdr);
 243
 244        msg->cprbx = static_cprbx;
 245        msg->cprbx.domain = AP_QID_QUEUE(zdev->ap_dev->qid);
 246        msg->cprbx.req_parml = msg->cprbx.rpl_msgbl =
 247                size - sizeof(msg->hdr) - sizeof(msg->cprbx);
 248
 249        msg->fr = (zdev->user_space_type == ZCRYPT_PCIXCC_MCL2) ?
 250                static_pkd_fnr_MCL2 : static_pkd_fnr;
 251
 252        ap_msg->length = size;
 253        return 0;
 254}
 255
 256/**
 257 * Convert a XCRB message to a type6 CPRB message.
 258 *
 259 * @zdev: crypto device pointer
 260 * @ap_msg: pointer to AP message
 261 * @xcRB: pointer to user input data
 262 *
 263 * Returns 0 on success or -EFAULT.
 264 */
 265struct type86_fmt2_msg {
 266        struct type86_hdr hdr;
 267        struct type86_fmt2_ext fmt2;
 268} __attribute__((packed));
 269
 270static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev,
 271                                       struct ap_message *ap_msg,
 272                                       struct ica_xcRB *xcRB)
 273{
 274        static struct type6_hdr static_type6_hdrX = {
 275                .type           =  0x06,
 276                .offset1        =  0x00000058,
 277        };
 278        struct {
 279                struct type6_hdr hdr;
 280                struct CPRBX cprbx;
 281        } __attribute__((packed)) *msg = ap_msg->message;
 282
 283        int rcblen = CEIL4(xcRB->request_control_blk_length);
 284        int replylen;
 285        char *req_data = ap_msg->message + sizeof(struct type6_hdr) + rcblen;
 286        char *function_code;
 287
 288        /* length checks */
 289        ap_msg->length = sizeof(struct type6_hdr) +
 290                CEIL4(xcRB->request_control_blk_length) +
 291                xcRB->request_data_length;
 292        if (ap_msg->length > PCIXCC_MAX_XCRB_MESSAGE_SIZE) {
 293                PRINTK("Combined message is too large (%ld/%d/%d).\n",
 294                    sizeof(struct type6_hdr),
 295                    xcRB->request_control_blk_length,
 296                    xcRB->request_data_length);
 297                return -EFAULT;
 298        }
 299        if (CEIL4(xcRB->reply_control_blk_length) >
 300            PCIXCC_MAX_XCRB_REPLY_SIZE) {
 301                PDEBUG("Reply CPRB length is too large (%d).\n",
 302                    xcRB->request_control_blk_length);
 303                return -EFAULT;
 304        }
 305        if (CEIL4(xcRB->reply_data_length) > PCIXCC_MAX_XCRB_DATA_SIZE) {
 306                PDEBUG("Reply data block length is too large (%d).\n",
 307                    xcRB->reply_data_length);
 308                return -EFAULT;
 309        }
 310        replylen = CEIL4(xcRB->reply_control_blk_length) +
 311                CEIL4(xcRB->reply_data_length) +
 312                sizeof(struct type86_fmt2_msg);
 313        if (replylen > PCIXCC_MAX_XCRB_RESPONSE_SIZE) {
 314                PDEBUG("Reply CPRB + data block > PCIXCC_MAX_XCRB_RESPONSE_SIZE"
 315                       " (%d/%d/%d).\n",
 316                       sizeof(struct type86_fmt2_msg),
 317                       xcRB->reply_control_blk_length,
 318                       xcRB->reply_data_length);
 319                xcRB->reply_control_blk_length = PCIXCC_MAX_XCRB_RESPONSE_SIZE -
 320                        (sizeof(struct type86_fmt2_msg) +
 321                            CEIL4(xcRB->reply_data_length));
 322                PDEBUG("Capping Reply CPRB length at %d\n",
 323                       xcRB->reply_control_blk_length);
 324        }
 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                PDEBUG("cprb_len too large (%d/%d)\n", msg->cprbx.cprb_len,
 344                    xcRB->request_control_blk_length);
 345                return -EFAULT;
 346        }
 347        function_code = ((unsigned char *)&msg->cprbx) + msg->cprbx.cprb_len;
 348        memcpy(msg->hdr.function_code, function_code, sizeof(msg->hdr.function_code));
 349
 350        /* copy data block */
 351        if (xcRB->request_data_length &&
 352            copy_from_user(req_data, xcRB->request_data_address,
 353                xcRB->request_data_length))
 354                return -EFAULT;
 355        return 0;
 356}
 357
 358/**
 359 * Copy results from a type 86 ICA reply message back to user space.
 360 *
 361 * @zdev: crypto device pointer
 362 * @reply: reply AP message.
 363 * @data: pointer to user output data
 364 * @length: size of user output data
 365 *
 366 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
 367 */
 368struct type86x_reply {
 369        struct type86_hdr hdr;
 370        struct type86_fmt2_ext fmt2;
 371        struct CPRBX cprbx;
 372        unsigned char pad[4];   /* 4 byte function code/rules block ? */
 373        unsigned short length;
 374        char text[0];
 375} __attribute__((packed));
 376
 377static int convert_type86_ica(struct zcrypt_device *zdev,
 378                          struct ap_message *reply,
 379                          char __user *outputdata,
 380                          unsigned int outputdatalength)
 381{
 382        static unsigned char static_pad[] = {
 383                0x00,0x02,
 384                0x1B,0x7B,0x5D,0xB5,0x75,0x01,0x3D,0xFD,
 385                0x8D,0xD1,0xC7,0x03,0x2D,0x09,0x23,0x57,
 386                0x89,0x49,0xB9,0x3F,0xBB,0x99,0x41,0x5B,
 387                0x75,0x21,0x7B,0x9D,0x3B,0x6B,0x51,0x39,
 388                0xBB,0x0D,0x35,0xB9,0x89,0x0F,0x93,0xA5,
 389                0x0B,0x47,0xF1,0xD3,0xBB,0xCB,0xF1,0x9D,
 390                0x23,0x73,0x71,0xFF,0xF3,0xF5,0x45,0xFB,
 391                0x61,0x29,0x23,0xFD,0xF1,0x29,0x3F,0x7F,
 392                0x17,0xB7,0x1B,0xA9,0x19,0xBD,0x57,0xA9,
 393                0xD7,0x95,0xA3,0xCB,0xED,0x1D,0xDB,0x45,
 394                0x7D,0x11,0xD1,0x51,0x1B,0xED,0x71,0xE9,
 395                0xB1,0xD1,0xAB,0xAB,0x21,0x2B,0x1B,0x9F,
 396                0x3B,0x9F,0xF7,0xF7,0xBD,0x63,0xEB,0xAD,
 397                0xDF,0xB3,0x6F,0x5B,0xDB,0x8D,0xA9,0x5D,
 398                0xE3,0x7D,0x77,0x49,0x47,0xF5,0xA7,0xFD,
 399                0xAB,0x2F,0x27,0x35,0x77,0xD3,0x49,0xC9,
 400                0x09,0xEB,0xB1,0xF9,0xBF,0x4B,0xCB,0x2B,
 401                0xEB,0xEB,0x05,0xFF,0x7D,0xC7,0x91,0x8B,
 402                0x09,0x83,0xB9,0xB9,0x69,0x33,0x39,0x6B,
 403                0x79,0x75,0x19,0xBF,0xBB,0x07,0x1D,0xBD,
 404                0x29,0xBF,0x39,0x95,0x93,0x1D,0x35,0xC7,
 405                0xC9,0x4D,0xE5,0x97,0x0B,0x43,0x9B,0xF1,
 406                0x16,0x93,0x03,0x1F,0xA5,0xFB,0xDB,0xF3,
 407                0x27,0x4F,0x27,0x61,0x05,0x1F,0xB9,0x23,
 408                0x2F,0xC3,0x81,0xA9,0x23,0x71,0x55,0x55,
 409                0xEB,0xED,0x41,0xE5,0xF3,0x11,0xF1,0x43,
 410                0x69,0x03,0xBD,0x0B,0x37,0x0F,0x51,0x8F,
 411                0x0B,0xB5,0x89,0x5B,0x67,0xA9,0xD9,0x4F,
 412                0x01,0xF9,0x21,0x77,0x37,0x73,0x79,0xC5,
 413                0x7F,0x51,0xC1,0xCF,0x97,0xA1,0x75,0xAD,
 414                0x35,0x9D,0xD3,0xD3,0xA7,0x9D,0x5D,0x41,
 415                0x6F,0x65,0x1B,0xCF,0xA9,0x87,0x91,0x09
 416        };
 417        struct type86x_reply *msg = reply->message;
 418        unsigned short service_rc, service_rs;
 419        unsigned int reply_len, pad_len;
 420        char *data;
 421
 422        service_rc = msg->cprbx.ccp_rtcode;
 423        if (unlikely(service_rc != 0)) {
 424                service_rs = msg->cprbx.ccp_rscode;
 425                if (service_rc == 8 && service_rs == 66) {
 426                        PDEBUG("Bad block format on PCIXCC/CEX2C\n");
 427                        return -EINVAL;
 428                }
 429                if (service_rc == 8 && service_rs == 65) {
 430                        PDEBUG("Probably an even modulus on PCIXCC/CEX2C\n");
 431                        return -EINVAL;
 432                }
 433                if (service_rc == 8 && service_rs == 770) {
 434                        PDEBUG("Invalid key length on PCIXCC/CEX2C\n");
 435                        return -EINVAL;
 436                }
 437                if (service_rc == 8 && service_rs == 783) {
 438                        PDEBUG("Extended bitlengths not enabled on PCIXCC/CEX2C\n");
 439                        zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
 440                        return -EAGAIN;
 441                }
 442                if (service_rc == 12 && service_rs == 769) {
 443                        PDEBUG("Invalid key on PCIXCC/CEX2C\n");
 444                        return -EINVAL;
 445                }
 446                PRINTK("Unknown service rc/rs (PCIXCC/CEX2C): %d/%d\n",
 447                       service_rc, service_rs);
 448                zdev->online = 0;
 449                return -EAGAIN; /* repeat the request on a different device. */
 450        }
 451        data = msg->text;
 452        reply_len = msg->length - 2;
 453        if (reply_len > outputdatalength)
 454                return -EINVAL;
 455        /**
 456         * For all encipher requests, the length of the ciphertext (reply_len)
 457         * will always equal the modulus length. For MEX decipher requests
 458         * the output needs to get padded. Minimum pad size is 10.
 459         *
 460         * Currently, the cases where padding will be added is for:
 461         * - PCIXCC_MCL2 using a CRT form token (since PKD didn't support
 462         *   ZERO-PAD and CRT is only supported for PKD requests)
 463         * - PCICC, always
 464         */
 465        pad_len = outputdatalength - reply_len;
 466        if (pad_len > 0) {
 467                if (pad_len < 10)
 468                        return -EINVAL;
 469                /* 'restore' padding left in the PCICC/PCIXCC card. */
 470                if (copy_to_user(outputdata, static_pad, pad_len - 1))
 471                        return -EFAULT;
 472                if (put_user(0, outputdata + pad_len - 1))
 473                        return -EFAULT;
 474        }
 475        /* Copy the crypto response to user space. */
 476        if (copy_to_user(outputdata + pad_len, data, reply_len))
 477                return -EFAULT;
 478        return 0;
 479}
 480
 481/**
 482 * Copy results from a type 86 XCRB reply message back to user space.
 483 *
 484 * @zdev: crypto device pointer
 485 * @reply: reply AP message.
 486 * @xcRB: pointer to XCRB
 487 *
 488 * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error.
 489 */
 490static int convert_type86_xcrb(struct zcrypt_device *zdev,
 491                               struct ap_message *reply,
 492                               struct ica_xcRB *xcRB)
 493{
 494        struct type86_fmt2_msg *msg = reply->message;
 495        char *data = reply->message;
 496
 497        /* Copy CPRB to user */
 498        if (copy_to_user(xcRB->reply_control_blk_addr,
 499                data + msg->fmt2.offset1, msg->fmt2.count1))
 500                return -EFAULT;
 501        xcRB->reply_control_blk_length = msg->fmt2.count1;
 502
 503        /* Copy data buffer to user */
 504        if (msg->fmt2.count2)
 505                if (copy_to_user(xcRB->reply_data_addr,
 506                        data + msg->fmt2.offset2, msg->fmt2.count2))
 507                        return -EFAULT;
 508        xcRB->reply_data_length = msg->fmt2.count2;
 509        return 0;
 510}
 511
 512static int convert_response_ica(struct zcrypt_device *zdev,
 513                            struct ap_message *reply,
 514                            char __user *outputdata,
 515                            unsigned int outputdatalength)
 516{
 517        struct type86x_reply *msg = reply->message;
 518
 519        /* Response type byte is the second byte in the response. */
 520        switch (((unsigned char *) reply->message)[1]) {
 521        case TYPE82_RSP_CODE:
 522        case TYPE88_RSP_CODE:
 523                return convert_error(zdev, reply);
 524        case TYPE86_RSP_CODE:
 525                if (msg->hdr.reply_code)
 526                        return convert_error(zdev, reply);
 527                if (msg->cprbx.cprb_ver_id == 0x02)
 528                        return convert_type86_ica(zdev, reply,
 529                                                  outputdata, outputdatalength);
 530                /* no break, incorrect cprb version is an unknown response */
 531        default: /* Unknown response type, this should NEVER EVER happen */
 532                PRINTK("Unrecognized Message Header: %08x%08x\n",
 533                       *(unsigned int *) reply->message,
 534                       *(unsigned int *) (reply->message+4));
 535                zdev->online = 0;
 536                return -EAGAIN; /* repeat the request on a different device. */
 537        }
 538}
 539
 540static int convert_response_xcrb(struct zcrypt_device *zdev,
 541                            struct ap_message *reply,
 542                            struct ica_xcRB *xcRB)
 543{
 544        struct type86x_reply *msg = reply->message;
 545
 546        /* Response type byte is the second byte in the response. */
 547        switch (((unsigned char *) reply->message)[1]) {
 548        case TYPE82_RSP_CODE:
 549        case TYPE88_RSP_CODE:
 550                xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
 551                return convert_error(zdev, reply);
 552        case TYPE86_RSP_CODE:
 553                if (msg->hdr.reply_code) {
 554                        memcpy(&(xcRB->status), msg->fmt2.apfs, sizeof(u32));
 555                        return convert_error(zdev, reply);
 556                }
 557                if (msg->cprbx.cprb_ver_id == 0x02)
 558                        return convert_type86_xcrb(zdev, reply, xcRB);
 559                /* no break, incorrect cprb version is an unknown response */
 560        default: /* Unknown response type, this should NEVER EVER happen */
 561                PRINTK("Unrecognized Message Header: %08x%08x\n",
 562                       *(unsigned int *) reply->message,
 563                       *(unsigned int *) (reply->message+4));
 564                xcRB->status = 0x0008044DL; /* HDD_InvalidParm */
 565                zdev->online = 0;
 566                return -EAGAIN; /* repeat the request on a different device. */
 567        }
 568}
 569
 570/**
 571 * This function is called from the AP bus code after a crypto request
 572 * "msg" has finished with the reply message "reply".
 573 * It is called from tasklet context.
 574 * @ap_dev: pointer to the AP device
 575 * @msg: pointer to the AP message
 576 * @reply: pointer to the AP reply message
 577 */
 578static void zcrypt_pcixcc_receive(struct ap_device *ap_dev,
 579                                  struct ap_message *msg,
 580                                  struct ap_message *reply)
 581{
 582        static struct error_hdr error_reply = {
 583                .type = TYPE82_RSP_CODE,
 584                .reply_code = REP82_ERROR_MACHINE_FAILURE,
 585        };
 586        struct response_type *resp_type =
 587                (struct response_type *) msg->private;
 588        struct type86x_reply *t86r = reply->message;
 589        int length;
 590
 591        /* Copy the reply message to the request message buffer. */
 592        if (IS_ERR(reply))
 593                memcpy(msg->message, &error_reply, sizeof(error_reply));
 594        else if (t86r->hdr.type == TYPE86_RSP_CODE &&
 595                 t86r->cprbx.cprb_ver_id == 0x02) {
 596                switch (resp_type->type) {
 597                case PCIXCC_RESPONSE_TYPE_ICA:
 598                        length = sizeof(struct type86x_reply)
 599                                + t86r->length - 2;
 600                        length = min(PCIXCC_MAX_ICA_RESPONSE_SIZE, length);
 601                        memcpy(msg->message, reply->message, length);
 602                        break;
 603                case PCIXCC_RESPONSE_TYPE_XCRB:
 604                        length = t86r->fmt2.offset2 + t86r->fmt2.count2;
 605                        length = min(PCIXCC_MAX_XCRB_RESPONSE_SIZE, length);
 606                        memcpy(msg->message, reply->message, length);
 607                        break;
 608                default:
 609                        PRINTK("Invalid internal response type: %i\n",
 610                            resp_type->type);
 611                        memcpy(msg->message, &error_reply,
 612                            sizeof error_reply);
 613                }
 614        } else
 615                memcpy(msg->message, reply->message, sizeof error_reply);
 616        complete(&(resp_type->work));
 617}
 618
 619static atomic_t zcrypt_step = ATOMIC_INIT(0);
 620
 621/**
 622 * The request distributor calls this function if it picked the PCIXCC/CEX2C
 623 * device to handle a modexpo request.
 624 * @zdev: pointer to zcrypt_device structure that identifies the
 625 *        PCIXCC/CEX2C device to the request distributor
 626 * @mex: pointer to the modexpo request buffer
 627 */
 628static long zcrypt_pcixcc_modexpo(struct zcrypt_device *zdev,
 629                                  struct ica_rsa_modexpo *mex)
 630{
 631        struct ap_message ap_msg;
 632        struct response_type resp_type = {
 633                .type = PCIXCC_RESPONSE_TYPE_ICA,
 634        };
 635        int rc;
 636
 637        ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
 638        if (!ap_msg.message)
 639                return -ENOMEM;
 640        ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 641                                atomic_inc_return(&zcrypt_step);
 642        ap_msg.private = &resp_type;
 643        rc = ICAMEX_msg_to_type6MEX_msgX(zdev, &ap_msg, mex);
 644        if (rc)
 645                goto out_free;
 646        init_completion(&resp_type.work);
 647        ap_queue_message(zdev->ap_dev, &ap_msg);
 648        rc = wait_for_completion_interruptible(&resp_type.work);
 649        if (rc == 0)
 650                rc = convert_response_ica(zdev, &ap_msg, mex->outputdata,
 651                                          mex->outputdatalength);
 652        else
 653                /* Signal pending. */
 654                ap_cancel_message(zdev->ap_dev, &ap_msg);
 655out_free:
 656        free_page((unsigned long) ap_msg.message);
 657        return rc;
 658}
 659
 660/**
 661 * The request distributor calls this function if it picked the PCIXCC/CEX2C
 662 * device to handle a modexpo_crt request.
 663 * @zdev: pointer to zcrypt_device structure that identifies the
 664 *        PCIXCC/CEX2C device to the request distributor
 665 * @crt: pointer to the modexpoc_crt request buffer
 666 */
 667static long zcrypt_pcixcc_modexpo_crt(struct zcrypt_device *zdev,
 668                                      struct ica_rsa_modexpo_crt *crt)
 669{
 670        struct ap_message ap_msg;
 671        struct response_type resp_type = {
 672                .type = PCIXCC_RESPONSE_TYPE_ICA,
 673        };
 674        int rc;
 675
 676        ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
 677        if (!ap_msg.message)
 678                return -ENOMEM;
 679        ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 680                                atomic_inc_return(&zcrypt_step);
 681        ap_msg.private = &resp_type;
 682        rc = ICACRT_msg_to_type6CRT_msgX(zdev, &ap_msg, crt);
 683        if (rc)
 684                goto out_free;
 685        init_completion(&resp_type.work);
 686        ap_queue_message(zdev->ap_dev, &ap_msg);
 687        rc = wait_for_completion_interruptible(&resp_type.work);
 688        if (rc == 0)
 689                rc = convert_response_ica(zdev, &ap_msg, crt->outputdata,
 690                                          crt->outputdatalength);
 691        else
 692                /* Signal pending. */
 693                ap_cancel_message(zdev->ap_dev, &ap_msg);
 694out_free:
 695        free_page((unsigned long) ap_msg.message);
 696        return rc;
 697}
 698
 699/**
 700 * The request distributor calls this function if it picked the PCIXCC/CEX2C
 701 * device to handle a send_cprb request.
 702 * @zdev: pointer to zcrypt_device structure that identifies the
 703 *        PCIXCC/CEX2C device to the request distributor
 704 * @xcRB: pointer to the send_cprb request buffer
 705 */
 706static long zcrypt_pcixcc_send_cprb(struct zcrypt_device *zdev,
 707                                    struct ica_xcRB *xcRB)
 708{
 709        struct ap_message ap_msg;
 710        struct response_type resp_type = {
 711                .type = PCIXCC_RESPONSE_TYPE_XCRB,
 712        };
 713        int rc;
 714
 715        ap_msg.message = kmalloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE, GFP_KERNEL);
 716        if (!ap_msg.message)
 717                return -ENOMEM;
 718        ap_msg.psmid = (((unsigned long long) current->pid) << 32) +
 719                                atomic_inc_return(&zcrypt_step);
 720        ap_msg.private = &resp_type;
 721        rc = XCRB_msg_to_type6CPRB_msgX(zdev, &ap_msg, xcRB);
 722        if (rc)
 723                goto out_free;
 724        init_completion(&resp_type.work);
 725        ap_queue_message(zdev->ap_dev, &ap_msg);
 726        rc = wait_for_completion_interruptible(&resp_type.work);
 727        if (rc == 0)
 728                rc = convert_response_xcrb(zdev, &ap_msg, xcRB);
 729        else
 730                /* Signal pending. */
 731                ap_cancel_message(zdev->ap_dev, &ap_msg);
 732out_free:
 733        memset(ap_msg.message, 0x0, ap_msg.length);
 734        kfree(ap_msg.message);
 735        return rc;
 736}
 737
 738/**
 739 * The crypto operations for a PCIXCC/CEX2C card.
 740 */
 741static struct zcrypt_ops zcrypt_pcixcc_ops = {
 742        .rsa_modexpo = zcrypt_pcixcc_modexpo,
 743        .rsa_modexpo_crt = zcrypt_pcixcc_modexpo_crt,
 744        .send_cprb = zcrypt_pcixcc_send_cprb,
 745};
 746
 747/**
 748 * Micro-code detection function. Its sends a message to a pcixcc card
 749 * to find out the microcode level.
 750 * @ap_dev: pointer to the AP device.
 751 */
 752static int zcrypt_pcixcc_mcl(struct ap_device *ap_dev)
 753{
 754        static unsigned char msg[] = {
 755                0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
 756                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 757                0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
 758                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 759                0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
 760                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 761                0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00,
 762                0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00,
 763                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 764                0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00,
 765                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 766                0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32,
 767                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,
 768                0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,
 769                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 770                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 771                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 772                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 773                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 774                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 775                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 776                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 777                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 778                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 779                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 780                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 781                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 782                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 783                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 784                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 785                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 786                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 787                0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
 788                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 789                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 790                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 791                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 792                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 793                0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x0A,
 794                0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20,
 795                0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05,
 796                0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
 797                0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55,
 798                0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,
 799                0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,
 800                0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,
 801                0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB,
 802                0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54,
 803                0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00,
 804                0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00,
 805                0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40,
 806                0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C,
 807                0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF,
 808                0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9,
 809                0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63,
 810                0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5,
 811                0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A,
 812                0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01,
 813                0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28,
 814                0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91,
 815                0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5,
 816                0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C,
 817                0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98,
 818                0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96,
 819                0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19,
 820                0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47,
 821                0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36,
 822                0xF1,0x3D,0x93,0x53
 823        };
 824        unsigned long long psmid;
 825        struct CPRBX *cprbx;
 826        char *reply;
 827        int rc, i;
 828
 829        reply = (void *) get_zeroed_page(GFP_KERNEL);
 830        if (!reply)
 831                return -ENOMEM;
 832
 833        rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, msg, sizeof(msg));
 834        if (rc)
 835                goto out_free;
 836
 837        /* Wait for the test message to complete. */
 838        for (i = 0; i < 6; i++) {
 839                mdelay(300);
 840                rc = ap_recv(ap_dev->qid, &psmid, reply, 4096);
 841                if (rc == 0 && psmid == 0x0102030405060708ULL)
 842                        break;
 843        }
 844
 845        if (i >= 6) {
 846                /* Got no answer. */
 847                rc = -ENODEV;
 848                goto out_free;
 849        }
 850
 851        cprbx = (struct CPRBX *) (reply + 48);
 852        if (cprbx->ccp_rtcode == 8 && cprbx->ccp_rscode == 33)
 853                rc = ZCRYPT_PCIXCC_MCL2;
 854        else
 855                rc = ZCRYPT_PCIXCC_MCL3;
 856out_free:
 857        free_page((unsigned long) reply);
 858        return rc;
 859}
 860
 861/**
 862 * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device
 863 * since the bus_match already checked the hardware type. The PCIXCC
 864 * cards come in two flavours: micro code level 2 and micro code level 3.
 865 * This is checked by sending a test message to the device.
 866 * @ap_dev: pointer to the AP device.
 867 */
 868static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
 869{
 870        struct zcrypt_device *zdev;
 871        int rc;
 872
 873        zdev = zcrypt_device_alloc(PCIXCC_MAX_RESPONSE_SIZE);
 874        if (!zdev)
 875                return -ENOMEM;
 876        zdev->ap_dev = ap_dev;
 877        zdev->ops = &zcrypt_pcixcc_ops;
 878        zdev->online = 1;
 879        if (ap_dev->device_type == AP_DEVICE_TYPE_PCIXCC) {
 880                rc = zcrypt_pcixcc_mcl(ap_dev);
 881                if (rc < 0) {
 882                        zcrypt_device_free(zdev);
 883                        return rc;
 884                }
 885                zdev->user_space_type = rc;
 886                if (rc == ZCRYPT_PCIXCC_MCL2) {
 887                        zdev->type_string = "PCIXCC_MCL2";
 888                        zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING;
 889                        zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
 890                        zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
 891                } else {
 892                        zdev->type_string = "PCIXCC_MCL3";
 893                        zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING;
 894                        zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
 895                        zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
 896                }
 897        } else {
 898                zdev->user_space_type = ZCRYPT_CEX2C;
 899                zdev->type_string = "CEX2C";
 900                zdev->speed_rating = CEX2C_SPEED_RATING;
 901                zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
 902                zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
 903        }
 904        ap_dev->reply = &zdev->reply;
 905        ap_dev->private = zdev;
 906        rc = zcrypt_device_register(zdev);
 907        if (rc)
 908                goto out_free;
 909        return 0;
 910
 911 out_free:
 912        ap_dev->private = NULL;
 913        zcrypt_device_free(zdev);
 914        return rc;
 915}
 916
 917/**
 918 * This is called to remove the extended PCIXCC/CEX2C driver information
 919 * if an AP device is removed.
 920 */
 921static void zcrypt_pcixcc_remove(struct ap_device *ap_dev)
 922{
 923        struct zcrypt_device *zdev = ap_dev->private;
 924
 925        zcrypt_device_unregister(zdev);
 926}
 927
 928int __init zcrypt_pcixcc_init(void)
 929{
 930        return ap_driver_register(&zcrypt_pcixcc_driver, THIS_MODULE, "pcixcc");
 931}
 932
 933void zcrypt_pcixcc_exit(void)
 934{
 935        ap_driver_unregister(&zcrypt_pcixcc_driver);
 936}
 937
 938#ifndef CONFIG_ZCRYPT_MONOLITHIC
 939module_init(zcrypt_pcixcc_init);
 940module_exit(zcrypt_pcixcc_exit);
 941#endif
 942