linux/drivers/s390/crypto/zcrypt_pcixcc.c
<<
>>
Prefs
   1/*
   2 *  zcrypt 2.1.0
   3 *
   4 *  Copyright IBM Corp. 2001, 2012
   5 *  Author(s): Robert Burroughs
   6 *             Eric Rossman (edrossma@us.ibm.com)
   7 *
   8 *  Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
   9 *  Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
  10 *                                Ralph Wuerthner <rwuerthn@de.ibm.com>
  11 *  MSGTYPE restruct:             Holger Dengler <hd@linux.vnet.ibm.com>
  12 *
  13 * This program is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License as published by
  15 * the Free Software Foundation; either version 2, or (at your option)
  16 * any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21 * GNU General Public License for more details.
  22 *
  23 * You should have received a copy of the GNU General Public License
  24 * along with this program; if not, write to the Free Software
  25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26 */
  27
  28#include <linux/module.h>
  29#include <linux/init.h>
  30#include <linux/err.h>
  31#include <linux/delay.h>
  32#include <linux/slab.h>
  33#include <linux/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_msgtype6.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#define CEX3C_MIN_MOD_SIZE      PCIXCC_MIN_MOD_SIZE
  47#define CEX3C_MAX_MOD_SIZE      512     /* 4096 bits    */
  48
  49#define PCIXCC_MCL2_SPEED_RATING        7870
  50#define PCIXCC_MCL3_SPEED_RATING        7870
  51#define CEX2C_SPEED_RATING              7000
  52#define CEX3C_SPEED_RATING              6500
  53
  54#define PCIXCC_MAX_ICA_MESSAGE_SIZE 0x77c  /* max size type6 v2 crt message */
  55#define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply      */
  56
  57#define PCIXCC_MAX_XCRB_MESSAGE_SIZE (12*1024)
  58
  59#define PCIXCC_CLEANUP_TIME     (15*HZ)
  60
  61#define CEIL4(x) ((((x)+3)/4)*4)
  62
  63struct response_type {
  64        struct completion work;
  65        int type;
  66};
  67#define PCIXCC_RESPONSE_TYPE_ICA  0
  68#define PCIXCC_RESPONSE_TYPE_XCRB 1
  69
  70static struct ap_device_id zcrypt_pcixcc_ids[] = {
  71        { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) },
  72        { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) },
  73        { AP_DEVICE(AP_DEVICE_TYPE_CEX3C) },
  74        { /* end of list */ },
  75};
  76
  77MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids);
  78MODULE_AUTHOR("IBM Corporation");
  79MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, " \
  80                   "Copyright IBM Corp. 2001, 2012");
  81MODULE_LICENSE("GPL");
  82
  83static int zcrypt_pcixcc_probe(struct ap_device *ap_dev);
  84static void zcrypt_pcixcc_remove(struct ap_device *ap_dev);
  85
  86static struct ap_driver zcrypt_pcixcc_driver = {
  87        .probe = zcrypt_pcixcc_probe,
  88        .remove = zcrypt_pcixcc_remove,
  89        .ids = zcrypt_pcixcc_ids,
  90        .request_timeout = PCIXCC_CLEANUP_TIME,
  91};
  92
  93/**
  94 * Micro-code detection function. Its sends a message to a pcixcc card
  95 * to find out the microcode level.
  96 * @ap_dev: pointer to the AP device.
  97 */
  98static int zcrypt_pcixcc_mcl(struct ap_device *ap_dev)
  99{
 100        static unsigned char msg[] = {
 101                0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
 102                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 103                0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,
 104                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 105                0x43,0x41,0x00,0x00,0x00,0x00,0x00,0x00,
 106                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 107                0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x00,
 108                0x00,0x00,0x01,0xC4,0x00,0x00,0x00,0x00,
 109                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 110                0x00,0x00,0x07,0x24,0x00,0x00,0x00,0x00,
 111                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 112                0x00,0xDC,0x02,0x00,0x00,0x00,0x54,0x32,
 113                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE8,
 114                0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x24,
 115                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 116                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 117                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 118                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 119                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 120                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 121                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 122                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 123                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 124                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 125                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 126                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 127                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 128                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 129                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 130                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 131                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 132                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 133                0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,
 134                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 135                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 136                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 137                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 138                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
 139                0x00,0x00,0x00,0x00,0x50,0x4B,0x00,0x0A,
 140                0x4D,0x52,0x50,0x20,0x20,0x20,0x20,0x20,
 141                0x00,0x42,0x00,0x01,0x02,0x03,0x04,0x05,
 142                0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
 143                0x0E,0x0F,0x00,0x11,0x22,0x33,0x44,0x55,
 144                0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,
 145                0xEE,0xFF,0xFF,0xEE,0xDD,0xCC,0xBB,0xAA,
 146                0x99,0x88,0x77,0x66,0x55,0x44,0x33,0x22,
 147                0x11,0x00,0x01,0x23,0x45,0x67,0x89,0xAB,
 148                0xCD,0xEF,0xFE,0xDC,0xBA,0x98,0x76,0x54,
 149                0x32,0x10,0x00,0x9A,0x00,0x98,0x00,0x00,
 150                0x1E,0x00,0x00,0x94,0x00,0x00,0x00,0x00,
 151                0x04,0x00,0x00,0x8C,0x00,0x00,0x00,0x40,
 152                0x02,0x00,0x00,0x40,0xBA,0xE8,0x23,0x3C,
 153                0x75,0xF3,0x91,0x61,0xD6,0x73,0x39,0xCF,
 154                0x7B,0x6D,0x8E,0x61,0x97,0x63,0x9E,0xD9,
 155                0x60,0x55,0xD6,0xC7,0xEF,0xF8,0x1E,0x63,
 156                0x95,0x17,0xCC,0x28,0x45,0x60,0x11,0xC5,
 157                0xC4,0x4E,0x66,0xC6,0xE6,0xC3,0xDE,0x8A,
 158                0x19,0x30,0xCF,0x0E,0xD7,0xAA,0xDB,0x01,
 159                0xD8,0x00,0xBB,0x8F,0x39,0x9F,0x64,0x28,
 160                0xF5,0x7A,0x77,0x49,0xCC,0x6B,0xA3,0x91,
 161                0x97,0x70,0xE7,0x60,0x1E,0x39,0xE1,0xE5,
 162                0x33,0xE1,0x15,0x63,0x69,0x08,0x80,0x4C,
 163                0x67,0xC4,0x41,0x8F,0x48,0xDF,0x26,0x98,
 164                0xF1,0xD5,0x8D,0x88,0xD9,0x6A,0xA4,0x96,
 165                0xC5,0x84,0xD9,0x30,0x49,0x67,0x7D,0x19,
 166                0xB1,0xB3,0x45,0x4D,0xB2,0x53,0x9A,0x47,
 167                0x3C,0x7C,0x55,0xBF,0xCC,0x85,0x00,0x36,
 168                0xF1,0x3D,0x93,0x53
 169        };
 170        unsigned long long psmid;
 171        struct CPRBX *cprbx;
 172        char *reply;
 173        int rc, i;
 174
 175        reply = (void *) get_zeroed_page(GFP_KERNEL);
 176        if (!reply)
 177                return -ENOMEM;
 178
 179        rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, msg, sizeof(msg));
 180        if (rc)
 181                goto out_free;
 182
 183        /* Wait for the test message to complete. */
 184        for (i = 0; i < 6; i++) {
 185                mdelay(300);
 186                rc = ap_recv(ap_dev->qid, &psmid, reply, 4096);
 187                if (rc == 0 && psmid == 0x0102030405060708ULL)
 188                        break;
 189        }
 190
 191        if (i >= 6) {
 192                /* Got no answer. */
 193                rc = -ENODEV;
 194                goto out_free;
 195        }
 196
 197        cprbx = (struct CPRBX *) (reply + 48);
 198        if (cprbx->ccp_rtcode == 8 && cprbx->ccp_rscode == 33)
 199                rc = ZCRYPT_PCIXCC_MCL2;
 200        else
 201                rc = ZCRYPT_PCIXCC_MCL3;
 202out_free:
 203        free_page((unsigned long) reply);
 204        return rc;
 205}
 206
 207/**
 208 * Large random number detection function. Its sends a message to a pcixcc
 209 * card to find out if large random numbers are supported.
 210 * @ap_dev: pointer to the AP device.
 211 *
 212 * Returns 1 if large random numbers are supported, 0 if not and < 0 on error.
 213 */
 214static int zcrypt_pcixcc_rng_supported(struct ap_device *ap_dev)
 215{
 216        struct ap_message ap_msg;
 217        unsigned long long psmid;
 218        struct {
 219                struct type86_hdr hdr;
 220                struct type86_fmt2_ext fmt2;
 221                struct CPRBX cprbx;
 222        } __attribute__((packed)) *reply;
 223        int rc, i;
 224
 225        ap_init_message(&ap_msg);
 226        ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
 227        if (!ap_msg.message)
 228                return -ENOMEM;
 229
 230        rng_type6CPRB_msgX(ap_dev, &ap_msg, 4);
 231        rc = ap_send(ap_dev->qid, 0x0102030405060708ULL, ap_msg.message,
 232                     ap_msg.length);
 233        if (rc)
 234                goto out_free;
 235
 236        /* Wait for the test message to complete. */
 237        for (i = 0; i < 2 * HZ; i++) {
 238                msleep(1000 / HZ);
 239                rc = ap_recv(ap_dev->qid, &psmid, ap_msg.message, 4096);
 240                if (rc == 0 && psmid == 0x0102030405060708ULL)
 241                        break;
 242        }
 243
 244        if (i >= 2 * HZ) {
 245                /* Got no answer. */
 246                rc = -ENODEV;
 247                goto out_free;
 248        }
 249
 250        reply = ap_msg.message;
 251        if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0)
 252                rc = 1;
 253        else
 254                rc = 0;
 255out_free:
 256        free_page((unsigned long) ap_msg.message);
 257        return rc;
 258}
 259
 260/**
 261 * Probe function for PCIXCC/CEX2C cards. It always accepts the AP device
 262 * since the bus_match already checked the hardware type. The PCIXCC
 263 * cards come in two flavours: micro code level 2 and micro code level 3.
 264 * This is checked by sending a test message to the device.
 265 * @ap_dev: pointer to the AP device.
 266 */
 267static int zcrypt_pcixcc_probe(struct ap_device *ap_dev)
 268{
 269        struct zcrypt_device *zdev;
 270        int rc = 0;
 271
 272        zdev = zcrypt_device_alloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE);
 273        if (!zdev)
 274                return -ENOMEM;
 275        zdev->ap_dev = ap_dev;
 276        zdev->online = 1;
 277        switch (ap_dev->device_type) {
 278        case AP_DEVICE_TYPE_PCIXCC:
 279                rc = zcrypt_pcixcc_mcl(ap_dev);
 280                if (rc < 0) {
 281                        zcrypt_device_free(zdev);
 282                        return rc;
 283                }
 284                zdev->user_space_type = rc;
 285                if (rc == ZCRYPT_PCIXCC_MCL2) {
 286                        zdev->type_string = "PCIXCC_MCL2";
 287                        zdev->speed_rating = PCIXCC_MCL2_SPEED_RATING;
 288                        zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD;
 289                        zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
 290                        zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
 291                } else {
 292                        zdev->type_string = "PCIXCC_MCL3";
 293                        zdev->speed_rating = PCIXCC_MCL3_SPEED_RATING;
 294                        zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
 295                        zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
 296                        zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
 297                }
 298                break;
 299        case AP_DEVICE_TYPE_CEX2C:
 300                zdev->user_space_type = ZCRYPT_CEX2C;
 301                zdev->type_string = "CEX2C";
 302                zdev->speed_rating = CEX2C_SPEED_RATING;
 303                zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE;
 304                zdev->max_mod_size = PCIXCC_MAX_MOD_SIZE;
 305                zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
 306                break;
 307        case AP_DEVICE_TYPE_CEX3C:
 308                zdev->user_space_type = ZCRYPT_CEX3C;
 309                zdev->type_string = "CEX3C";
 310                zdev->speed_rating = CEX3C_SPEED_RATING;
 311                zdev->min_mod_size = CEX3C_MIN_MOD_SIZE;
 312                zdev->max_mod_size = CEX3C_MAX_MOD_SIZE;
 313                zdev->max_exp_bit_length = CEX3C_MAX_MOD_SIZE;
 314                break;
 315        default:
 316                goto out_free;
 317        }
 318
 319        rc = zcrypt_pcixcc_rng_supported(ap_dev);
 320        if (rc < 0) {
 321                zcrypt_device_free(zdev);
 322                return rc;
 323        }
 324        if (rc)
 325                zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME,
 326                                                   MSGTYPE06_VARIANT_DEFAULT);
 327        else
 328                zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME,
 329                                                   MSGTYPE06_VARIANT_NORNG);
 330        ap_dev->reply = &zdev->reply;
 331        ap_dev->private = zdev;
 332        rc = zcrypt_device_register(zdev);
 333        if (rc)
 334                goto out_free;
 335        return 0;
 336
 337 out_free:
 338        ap_dev->private = NULL;
 339        zcrypt_msgtype_release(zdev->ops);
 340        zcrypt_device_free(zdev);
 341        return rc;
 342}
 343
 344/**
 345 * This is called to remove the extended PCIXCC/CEX2C driver information
 346 * if an AP device is removed.
 347 */
 348static void zcrypt_pcixcc_remove(struct ap_device *ap_dev)
 349{
 350        struct zcrypt_device *zdev = ap_dev->private;
 351        struct zcrypt_ops *zops = zdev->ops;
 352
 353        zcrypt_device_unregister(zdev);
 354        zcrypt_msgtype_release(zops);
 355}
 356
 357int __init zcrypt_pcixcc_init(void)
 358{
 359        return ap_driver_register(&zcrypt_pcixcc_driver, THIS_MODULE, "pcixcc");
 360}
 361
 362void zcrypt_pcixcc_exit(void)
 363{
 364        ap_driver_unregister(&zcrypt_pcixcc_driver);
 365}
 366
 367module_init(zcrypt_pcixcc_init);
 368module_exit(zcrypt_pcixcc_exit);
 369
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.