zcrypt_pcixcc.c 8.8 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3
 *  zcrypt 2.1.0
4
 *
5
 *  Copyright IBM Corp. 2001, 2012
6 7 8 9 10 11
 *  Author(s): Robert Burroughs
 *	       Eric Rossman (edrossma@us.ibm.com)
 *
 *  Hotplug & misc device support: Jochen Roehrig (roehrig@de.ibm.com)
 *  Major cleanup & driver split: Martin Schwidefsky <schwidefsky@de.ibm.com>
 *				  Ralph Wuerthner <rwuerthn@de.ibm.com>
12
 *  MSGTYPE restruct:		  Holger Dengler <hd@linux.vnet.ibm.com>
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/delay.h>
33
#include <linux/slab.h>
A
Arun Sharma 已提交
34
#include <linux/atomic.h>
35
#include <linux/uaccess.h>
36
#include <linux/mod_devicetable.h>
37 38 39 40

#include "ap_bus.h"
#include "zcrypt_api.h"
#include "zcrypt_error.h"
41
#include "zcrypt_msgtype6.h"
42 43 44 45 46 47
#include "zcrypt_pcixcc.h"
#include "zcrypt_cca_key.h"

#define PCIXCC_MIN_MOD_SIZE	 16	/*  128 bits	*/
#define PCIXCC_MIN_MOD_SIZE_OLD	 64	/*  512 bits	*/
#define PCIXCC_MAX_MOD_SIZE	256	/* 2048 bits	*/
48
#define CEX3C_MIN_MOD_SIZE	PCIXCC_MIN_MOD_SIZE
49
#define CEX3C_MAX_MOD_SIZE	512	/* 4096 bits	*/
50 51 52 53 54 55 56 57

#define PCIXCC_MAX_ICA_MESSAGE_SIZE 0x77c  /* max size type6 v2 crt message */
#define PCIXCC_MAX_ICA_RESPONSE_SIZE 0x77c /* max size type86 v2 reply	    */

#define PCIXCC_MAX_XCRB_MESSAGE_SIZE (12*1024)

#define PCIXCC_CLEANUP_TIME	(15*HZ)

58 59 60 61 62 63 64 65 66
#define CEIL4(x) ((((x)+3)/4)*4)

struct response_type {
	struct completion work;
	int type;
};
#define PCIXCC_RESPONSE_TYPE_ICA  0
#define PCIXCC_RESPONSE_TYPE_XCRB 1

67
MODULE_AUTHOR("IBM Corporation");
68 69
MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, " \
		   "Copyright IBM Corp. 2001, 2012");
70 71
MODULE_LICENSE("GPL");

72 73 74 75 76 77 78 79
static struct ap_device_id zcrypt_pcixcc_card_ids[] = {
	{ .dev_type = AP_DEVICE_TYPE_PCIXCC,
	  .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
	{ .dev_type = AP_DEVICE_TYPE_CEX2C,
	  .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
	{ .dev_type = AP_DEVICE_TYPE_CEX3C,
	  .match_flags = AP_DEVICE_ID_MATCH_CARD_TYPE },
	{ /* end of list */ },
80 81
};

82
MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_card_ids);
83

84 85 86 87 88 89 90 91 92
static struct ap_device_id zcrypt_pcixcc_queue_ids[] = {
	{ .dev_type = AP_DEVICE_TYPE_PCIXCC,
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
	{ .dev_type = AP_DEVICE_TYPE_CEX2C,
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
	{ .dev_type = AP_DEVICE_TYPE_CEX3C,
	  .match_flags = AP_DEVICE_ID_MATCH_QUEUE_TYPE },
	{ /* end of list */ },
};
93

94
MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_queue_ids);
95

96 97 98 99 100 101 102
/**
 * Large random number detection function. Its sends a message to a pcixcc
 * card to find out if large random numbers are supported.
 * @ap_dev: pointer to the AP device.
 *
 * Returns 1 if large random numbers are supported, 0 if not and < 0 on error.
 */
103
static int zcrypt_pcixcc_rng_supported(struct ap_queue *aq)
104 105 106
{
	struct ap_message ap_msg;
	unsigned long long psmid;
107
	unsigned int domain;
108 109 110 111 112
	struct {
		struct type86_hdr hdr;
		struct type86_fmt2_ext fmt2;
		struct CPRBX cprbx;
	} __attribute__((packed)) *reply;
113 114 115 116 117 118 119 120 121
	struct {
		struct type6_hdr hdr;
		struct CPRBX cprbx;
		char function_code[2];
		short int rule_length;
		char rule[8];
		short int verb_length;
		short int key_length;
	} __packed * msg;
122 123
	int rc, i;

124
	ap_init_message(&ap_msg);
125 126 127 128
	ap_msg.message = (void *) get_zeroed_page(GFP_KERNEL);
	if (!ap_msg.message)
		return -ENOMEM;

129
	rng_type6CPRB_msgX(&ap_msg, 4, &domain);
130 131

	msg = ap_msg.message;
132
	msg->cprbx.domain = AP_QID_QUEUE(aq->qid);
133

134
	rc = ap_send(aq->qid, 0x0102030405060708ULL, ap_msg.message,
135 136 137 138 139 140 141
		     ap_msg.length);
	if (rc)
		goto out_free;

	/* Wait for the test message to complete. */
	for (i = 0; i < 2 * HZ; i++) {
		msleep(1000 / HZ);
142
		rc = ap_recv(aq->qid, &psmid, ap_msg.message, 4096);
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
		if (rc == 0 && psmid == 0x0102030405060708ULL)
			break;
	}

	if (i >= 2 * HZ) {
		/* Got no answer. */
		rc = -ENODEV;
		goto out_free;
	}

	reply = ap_msg.message;
	if (reply->cprbx.ccp_rtcode == 0 && reply->cprbx.ccp_rscode == 0)
		rc = 1;
	else
		rc = 0;
out_free:
	free_page((unsigned long) ap_msg.message);
	return rc;
}

163
/**
164 165 166 167 168
 * Probe function for PCIXCC/CEX2C card devices. It always accepts the
 * AP device since the bus_match already checked the hardware type. The
 * PCIXCC cards come in two flavours: micro code level 2 and micro code
 * level 3. This is checked by sending a test message to the device.
 * @ap_dev: pointer to the AP card device.
169
 */
170
static int zcrypt_pcixcc_card_probe(struct ap_device *ap_dev)
171
{
172 173 174 175
	/*
	 * Normalized speed ratings per crypto adapter
	 * MEX_1k, MEX_2k, MEX_4k, CRT_1k, CRT_2k, CRT_4k, RNG, SECKEY
	 */
176 177 178 179 180 181 182
	static const int CEX2C_SPEED_IDX[] = {
		1000, 1400, 2400, 1100, 1500, 2600, 100, 12};
	static const int CEX3C_SPEED_IDX[] = {
		500,  700, 1400,  550,	800, 1500,  80, 10};

	struct ap_card *ac = to_ap_card(&ap_dev->device);
	struct zcrypt_card *zc;
183
	int rc = 0;
184

185 186
	zc = zcrypt_card_alloc();
	if (!zc)
187
		return -ENOMEM;
188 189 190
	zc->card = ac;
	ac->private = zc;
	switch (ac->ap_dev.device_type) {
191
	case AP_DEVICE_TYPE_CEX2C:
192 193 194
		zc->user_space_type = ZCRYPT_CEX2C;
		zc->type_string = "CEX2C";
		memcpy(zc->speed_rating, CEX2C_SPEED_IDX,
195
		       sizeof(CEX2C_SPEED_IDX));
196 197 198
		zc->min_mod_size = PCIXCC_MIN_MOD_SIZE;
		zc->max_mod_size = PCIXCC_MAX_MOD_SIZE;
		zc->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
199 200
		break;
	case AP_DEVICE_TYPE_CEX3C:
201 202 203
		zc->user_space_type = ZCRYPT_CEX3C;
		zc->type_string = "CEX3C";
		memcpy(zc->speed_rating, CEX3C_SPEED_IDX,
204
		       sizeof(CEX3C_SPEED_IDX));
205 206 207
		zc->min_mod_size = CEX3C_MIN_MOD_SIZE;
		zc->max_mod_size = CEX3C_MAX_MOD_SIZE;
		zc->max_exp_bit_length = CEX3C_MAX_MOD_SIZE;
208 209
		break;
	default:
210 211
		zcrypt_card_free(zc);
		return -ENODEV;
212
	}
213
	zc->online = 1;
214

215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
	rc = zcrypt_card_register(zc);
	if (rc) {
		ac->private = NULL;
		zcrypt_card_free(zc);
	}

	return rc;
}

/**
 * This is called to remove the PCIXCC/CEX2C card driver information
 * if an AP card device is removed.
 */
static void zcrypt_pcixcc_card_remove(struct ap_device *ap_dev)
{
	struct zcrypt_card *zc = to_ap_card(&ap_dev->device)->private;

	if (zc)
		zcrypt_card_unregister(zc);
}

static struct ap_driver zcrypt_pcixcc_card_driver = {
	.probe = zcrypt_pcixcc_card_probe,
	.remove = zcrypt_pcixcc_card_remove,
	.ids = zcrypt_pcixcc_card_ids,
};

/**
 * Probe function for PCIXCC/CEX2C queue devices. It always accepts the
 * AP device since the bus_match already checked the hardware type. The
 * PCIXCC cards come in two flavours: micro code level 2 and micro code
 * level 3. This is checked by sending a test message to the device.
 * @ap_dev: pointer to the AP card device.
 */
static int zcrypt_pcixcc_queue_probe(struct ap_device *ap_dev)
{
	struct ap_queue *aq = to_ap_queue(&ap_dev->device);
	struct zcrypt_queue *zq;
	int rc;

	zq = zcrypt_queue_alloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE);
	if (!zq)
		return -ENOMEM;
	zq->queue = aq;
	zq->online = 1;
	atomic_set(&zq->load, 0);
	rc = zcrypt_pcixcc_rng_supported(aq);
262
	if (rc < 0) {
263
		zcrypt_queue_free(zq);
264 265 266
		return rc;
	}
	if (rc)
267 268
		zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
					 MSGTYPE06_VARIANT_DEFAULT);
269
	else
270 271 272 273 274 275 276 277 278 279
		zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
					 MSGTYPE06_VARIANT_NORNG);
	ap_queue_init_reply(aq, &zq->reply);
	aq->request_timeout = PCIXCC_CLEANUP_TIME,
	aq->private = zq;
	rc = zcrypt_queue_register(zq);
	if (rc) {
		aq->private = NULL;
		zcrypt_queue_free(zq);
	}
280 281 282 283
	return rc;
}

/**
284 285
 * This is called to remove the PCIXCC/CEX2C queue driver information
 * if an AP queue device is removed.
286
 */
287
static void zcrypt_pcixcc_queue_remove(struct ap_device *ap_dev)
288
{
289 290
	struct ap_queue *aq = to_ap_queue(&ap_dev->device);
	struct zcrypt_queue *zq = aq->private;
291

292 293 294
	ap_queue_remove(aq);
	if (zq)
		zcrypt_queue_unregister(zq);
295 296
}

297 298 299 300 301 302 303 304
static struct ap_driver zcrypt_pcixcc_queue_driver = {
	.probe = zcrypt_pcixcc_queue_probe,
	.remove = zcrypt_pcixcc_queue_remove,
	.suspend = ap_queue_suspend,
	.resume = ap_queue_resume,
	.ids = zcrypt_pcixcc_queue_ids,
};

305 306
int __init zcrypt_pcixcc_init(void)
{
307 308 309 310 311 312 313 314 315 316 317 318 319
	int rc;

	rc = ap_driver_register(&zcrypt_pcixcc_card_driver,
				THIS_MODULE, "pcixcccard");
	if (rc)
		return rc;

	rc = ap_driver_register(&zcrypt_pcixcc_queue_driver,
				THIS_MODULE, "pcixccqueue");
	if (rc)
		ap_driver_unregister(&zcrypt_pcixcc_card_driver);

	return rc;
320 321 322 323
}

void zcrypt_pcixcc_exit(void)
{
324 325
	ap_driver_unregister(&zcrypt_pcixcc_queue_driver);
	ap_driver_unregister(&zcrypt_pcixcc_card_driver);
326 327 328 329
}

module_init(zcrypt_pcixcc_init);
module_exit(zcrypt_pcixcc_exit);