blob: df8f0c4dacb7c49bc3e15670ad8bac976b989670 [file] [log] [blame]
Martin Schwidefsky6684af12006-09-20 15:58:32 +02001/*
Ralph Wuerthner54321142006-09-20 15:58:36 +02002 * zcrypt 2.1.0
Martin Schwidefsky6684af12006-09-20 15:58:32 +02003 *
Holger Dengler5e55a482012-08-28 16:45:36 +02004 * Copyright IBM Corp. 2001, 2012
Martin Schwidefsky6684af12006-09-20 15:58:32 +02005 * 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>
Holger Dengler5e55a482012-08-28 16:45:36 +020011 * MSGTYPE restruct: Holger Dengler <hd@linux.vnet.ibm.com>
Martin Schwidefsky6684af12006-09-20 15:58:32 +020012 *
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>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090032#include <linux/slab.h>
Arun Sharma600634972011-07-26 16:09:06 -070033#include <linux/atomic.h>
Martin Schwidefsky6684af12006-09-20 15:58:32 +020034#include <asm/uaccess.h>
35
36#include "ap_bus.h"
37#include "zcrypt_api.h"
38#include "zcrypt_error.h"
Holger Dengler5e55a482012-08-28 16:45:36 +020039#include "zcrypt_msgtype6.h"
Martin Schwidefsky6684af12006-09-20 15:58:32 +020040#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 */
Felix Beck8e89b6b2009-12-07 12:51:57 +010046#define CEX3C_MIN_MOD_SIZE PCIXCC_MIN_MOD_SIZE
Felix Beck2ade1fa2011-01-05 12:47:46 +010047#define CEX3C_MAX_MOD_SIZE 512 /* 4096 bits */
Martin Schwidefsky6684af12006-09-20 15:58:32 +020048
Felix Beck18278df2009-12-07 12:51:58 +010049#define PCIXCC_MCL2_SPEED_RATING 7870
Martin Schwidefsky6684af12006-09-20 15:58:32 +020050#define PCIXCC_MCL3_SPEED_RATING 7870
Felix Beck18278df2009-12-07 12:51:58 +010051#define CEX2C_SPEED_RATING 7000
Felix Beck2ade1fa2011-01-05 12:47:46 +010052#define CEX3C_SPEED_RATING 6500
Martin Schwidefsky6684af12006-09-20 15:58:32 +020053
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)
Martin Schwidefsky6684af12006-09-20 15:58:32 +020058
59#define PCIXCC_CLEANUP_TIME (15*HZ)
60
Ralph Wuerthner54321142006-09-20 15:58:36 +020061#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
Martin Schwidefsky6684af12006-09-20 15:58:32 +020070static struct ap_device_id zcrypt_pcixcc_ids[] = {
71 { AP_DEVICE(AP_DEVICE_TYPE_PCIXCC) },
72 { AP_DEVICE(AP_DEVICE_TYPE_CEX2C) },
Felix Beckffda4f72009-12-07 12:51:56 +010073 { AP_DEVICE(AP_DEVICE_TYPE_CEX3C) },
Martin Schwidefsky6684af12006-09-20 15:58:32 +020074 { /* end of list */ },
75};
76
Martin Schwidefsky6684af12006-09-20 15:58:32 +020077MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids);
78MODULE_AUTHOR("IBM Corporation");
Holger Dengler5e55a482012-08-28 16:45:36 +020079MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, " \
80 "Copyright IBM Corp. 2001, 2012");
Martin Schwidefsky6684af12006-09-20 15:58:32 +020081MODULE_LICENSE("GPL");
Martin Schwidefsky6684af12006-09-20 15:58:32 +020082
83static int zcrypt_pcixcc_probe(struct ap_device *ap_dev);
84static void zcrypt_pcixcc_remove(struct ap_device *ap_dev);
Martin Schwidefsky6684af12006-09-20 15:58:32 +020085
86static struct ap_driver zcrypt_pcixcc_driver = {
87 .probe = zcrypt_pcixcc_probe,
88 .remove = zcrypt_pcixcc_remove,
Martin Schwidefsky6684af12006-09-20 15:58:32 +020089 .ids = zcrypt_pcixcc_ids,
Ralph Wuerthneraf512ed02007-07-10 11:24:19 +020090 .request_timeout = PCIXCC_CLEANUP_TIME,
Martin Schwidefsky6684af12006-09-20 15:58:32 +020091};
92
93/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +020094 * 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++) {
Heiko Carstense4e18992015-08-17 07:59:47 +0200185 msleep(300);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200186 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/**
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200208 * 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
Felix Beck468ffdd2009-12-07 12:51:54 +0100225 ap_init_message(&ap_msg);
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200226 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/**
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200261 * 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;
Felix Beck8e89b6b2009-12-07 12:51:57 +0100270 int rc = 0;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200271
Holger Dengler7fe6f092011-12-27 11:27:19 +0100272 zdev = zcrypt_device_alloc(PCIXCC_MAX_XCRB_MESSAGE_SIZE);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200273 if (!zdev)
274 return -ENOMEM;
275 zdev->ap_dev = ap_dev;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200276 zdev->online = 1;
Felix Beck8e89b6b2009-12-07 12:51:57 +0100277 switch (ap_dev->device_type) {
278 case AP_DEVICE_TYPE_PCIXCC:
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200279 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;
Felix Beckc2567f82011-01-05 12:47:47 +0100290 zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200291 } 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;
Felix Beckc2567f82011-01-05 12:47:47 +0100296 zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200297 }
Felix Beck8e89b6b2009-12-07 12:51:57 +0100298 break;
299 case AP_DEVICE_TYPE_CEX2C:
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200300 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;
Felix Beckc2567f82011-01-05 12:47:47 +0100305 zdev->max_exp_bit_length = PCIXCC_MAX_MOD_SIZE;
Felix Beck8e89b6b2009-12-07 12:51:57 +0100306 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;
Felix Beckc2567f82011-01-05 12:47:47 +0100313 zdev->max_exp_bit_length = CEX3C_MAX_MOD_SIZE;
Felix Beck8e89b6b2009-12-07 12:51:57 +0100314 break;
315 default:
316 goto out_free;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200317 }
Felix Beck8e89b6b2009-12-07 12:51:57 +0100318
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200319 rc = zcrypt_pcixcc_rng_supported(ap_dev);
320 if (rc < 0) {
321 zcrypt_device_free(zdev);
322 return rc;
323 }
324 if (rc)
Holger Dengler5e55a482012-08-28 16:45:36 +0200325 zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME,
326 MSGTYPE06_VARIANT_DEFAULT);
Ralph Wuerthner2f7c8bd2008-04-17 07:46:15 +0200327 else
Holger Dengler5e55a482012-08-28 16:45:36 +0200328 zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME,
329 MSGTYPE06_VARIANT_NORNG);
Ingo Tuchschererd6d86c52016-07-25 14:52:28 +0200330 ap_device_init_reply(ap_dev, &zdev->reply);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200331 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;
Holger Dengler5e55a482012-08-28 16:45:36 +0200339 zcrypt_msgtype_release(zdev->ops);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200340 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;
Holger Dengler5e55a482012-08-28 16:45:36 +0200351 struct zcrypt_ops *zops = zdev->ops;
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200352
353 zcrypt_device_unregister(zdev);
Holger Dengler5e55a482012-08-28 16:45:36 +0200354 zcrypt_msgtype_release(zops);
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200355}
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
Martin Schwidefsky6684af12006-09-20 15:58:32 +0200367module_init(zcrypt_pcixcc_init);
368module_exit(zcrypt_pcixcc_exit);