xref: /freebsd/sys/dev/tpm/tpm20.c (revision a259b98fa211ed87bfee58c575de4e2de94ee0fa)
1 /*-
2  * Copyright (c) 2018 Stormshield.
3  * Copyright (c) 2018 Semihalf.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <sys/random.h>
29 #include <dev/random/randomdev.h>
30 
31 #include <machine/atomic.h>
32 
33 #include "tpm20.h"
34 
35 #define TPM_HARVEST_SIZE     16
36 
37 #define	TPM2_ST_NO_SESSIONS	0x8001
38 #define	TPM2_RC_SUCCESS		0x0000
39 #define	TPM2_RC_INITIALIZE	0x0100
40 #define	TPM2_RC_TESTING		0x090a
41 #define	TPM2_RC_RETRY		0x0922
42 
43 #define	TPM2_SU_CLEAR		0x0000
44 #define	TPM2_SU_STATE		0x0001
45 
46 #define	TPM2_RETRY_INITIAL_MS	20
47 #define	TPM2_RETRY_MAX_MS	(TPM_TIMEOUT_B / 1000)
48 /*
49  * Perform a harvest every 10 seconds.
50  * Since discrete TPMs are painfully slow
51  * we don't want to execute this too often
52  * as the chip is likely to be used by others too.
53  */
54 #define TPM_HARVEST_INTERVAL 10
55 
56 MALLOC_DEFINE(M_TPM20, "tpm_buffer", "buffer for tpm 2.0 driver");
57 
58 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
59 static void tpm20_harvest(void *arg, int unused);
60 #endif
61 static int  tpm20_command(device_t, uint32_t, uint16_t, uint32_t,
62     const char *);
63 static int  tpm20_restart(device_t dev, bool clear);
64 static int  tpm20_save_state(device_t dev, bool suspend);
65 
66 static d_open_t		tpm20_open;
67 static d_close_t	tpm20_close;
68 static d_read_t		tpm20_read;
69 static d_write_t	tpm20_write;
70 static d_ioctl_t	tpm20_ioctl;
71 
72 static struct cdevsw tpm20_cdevsw = {
73 	.d_version = D_VERSION,
74 	.d_open = tpm20_open,
75 	.d_close = tpm20_close,
76 	.d_read = tpm20_read,
77 	.d_write = tpm20_write,
78 	.d_ioctl = tpm20_ioctl,
79 	.d_name = "tpm20",
80 };
81 
82 int
83 tpm20_read(struct cdev *dev, struct uio *uio, int flags)
84 {
85 	struct tpm_sc *sc;
86 	struct tpm_priv *priv;
87 	size_t bytes_to_transfer;
88 	size_t offset;
89 	ssize_t resid;
90 	int result;
91 
92 	sc = (struct tpm_sc *)dev->si_drv1;
93 	result = devfs_get_cdevpriv((void **)&priv);
94 	if (result != 0)
95 		return (result);
96 
97 	sx_xlock(&priv->io_lock);
98 	sx_xlock(&sc->dev_lock);
99 	if (atomic_load_bool(&sc->dying)) {
100 		result = ENXIO;
101 		goto out_locked;
102 	}
103 	if (sc->suspended) {
104 		result = EBUSY;
105 		goto out_locked;
106 	}
107 	offset = priv->offset;
108 	bytes_to_transfer = MIN(priv->len, uio->uio_resid);
109 	sx_xunlock(&sc->dev_lock);
110 
111 	if (bytes_to_transfer > 0) {
112 		resid = uio->uio_resid;
113 		result = uiomove((caddr_t)priv->buf + offset,
114 		    (int)bytes_to_transfer, uio);
115 		bytes_to_transfer = resid - uio->uio_resid;
116 		priv->offset += bytes_to_transfer;
117 		priv->len -= bytes_to_transfer;
118 	} else {
119 		result = 0;
120 	}
121 	sx_xunlock(&priv->io_lock);
122 	return (result);
123 
124 out_locked:
125 	sx_xunlock(&sc->dev_lock);
126 	sx_xunlock(&priv->io_lock);
127 	return (result);
128 }
129 
130 int
131 tpm20_write(struct cdev *dev, struct uio *uio, int flags)
132 {
133 	struct tpm_sc *sc;
134 	struct tpm_priv *priv;
135 	uint8_t *command;
136 	size_t byte_count;
137 	int result;
138 
139 	sc = (struct tpm_sc *)dev->si_drv1;
140 	result = devfs_get_cdevpriv((void **)&priv);
141 	if (result != 0)
142 		return (result);
143 
144 	byte_count = uio->uio_resid;
145 	if (byte_count < TPM_HEADER_SIZE) {
146 		device_printf(sc->dev,
147 		    "Requested transfer is too small\n");
148 		return (EINVAL);
149 	}
150 
151 	if (byte_count > TPM_BUFSIZE) {
152 		device_printf(sc->dev,
153 		    "Requested transfer is too large\n");
154 		return (E2BIG);
155 	}
156 
157 	command = malloc(byte_count, M_TPM20, M_WAITOK);
158 	sx_xlock(&priv->io_lock);
159 	result = uiomove(command, byte_count, uio);
160 	if (result != 0)
161 		goto out_priv;
162 
163 	sx_xlock(&sc->dev_lock);
164 	if (atomic_load_bool(&sc->dying)) {
165 		result = ENXIO;
166 		goto out;
167 	}
168 	if (sc->suspended) {
169 		result = EBUSY;
170 		goto out;
171 	}
172 
173 	memcpy(priv->buf, command, byte_count);
174 	result = TPM_TRANSMIT(sc->dev, priv, byte_count);
175 
176 out:
177 	sx_xunlock(&sc->dev_lock);
178 	if (result != 0)
179 		uio->uio_resid = byte_count;
180 out_priv:
181 	sx_xunlock(&priv->io_lock);
182 	free(command, M_TPM20);
183 	return (result);
184 }
185 
186 static struct tpm_priv *
187 tpm20_priv_alloc(void)
188 {
189 	struct tpm_priv *priv;
190 
191 	priv = malloc(sizeof (*priv), M_TPM20, M_WAITOK | M_ZERO);
192 	sx_init(&priv->io_lock, "TPM per-open I/O lock");
193 	return (priv);
194 }
195 
196 static void
197 tpm20_priv_dtor(void *data)
198 {
199 	struct tpm_priv *priv = data;
200 
201 	sx_destroy(&priv->io_lock);
202 	free(priv, M_TPM20);
203 }
204 
205 int
206 tpm20_open(struct cdev *dev, int flag, int mode, struct thread *td)
207 {
208 	struct tpm_sc *sc;
209 	struct tpm_priv *priv;
210 	int error;
211 
212 	sc = (struct tpm_sc *)dev->si_drv1;
213 	sx_xlock(&sc->dev_lock);
214 	if (atomic_load_bool(&sc->dying)) {
215 		error = ENXIO;
216 		goto out;
217 	}
218 	if (sc->suspended) {
219 		error = EBUSY;
220 		goto out;
221 	}
222 	priv = tpm20_priv_alloc();
223 	error = devfs_set_cdevpriv(priv, tpm20_priv_dtor);
224 	if (error != 0)
225 		tpm20_priv_dtor(priv);
226 
227 out:
228 	sx_xunlock(&sc->dev_lock);
229 	return (error);
230 }
231 
232 int
233 tpm20_close(struct cdev *dev, int flag, int mode, struct thread *td)
234 {
235 
236 	return (0);
237 }
238 
239 int
240 tpm20_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
241     int flags, struct thread *td)
242 {
243 
244 	return (ENOTTY);
245 }
246 
247 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
248 static const struct random_source random_tpm = {
249 	.rs_ident = "TPM",
250 	.rs_source = RANDOM_PURE_TPM,
251 };
252 #endif
253 
254 int
255 tpm20_init(struct tpm_sc *sc)
256 {
257 	struct make_dev_args args;
258 	int result;
259 
260 	atomic_store_bool(&sc->dying, false);
261 	sc->suspended = false;
262 	sc->internal_priv = tpm20_priv_alloc();
263 
264 	make_dev_args_init(&args);
265 	args.mda_devsw = &tpm20_cdevsw;
266 	args.mda_uid = UID_ROOT;
267 	args.mda_gid = GID_WHEEL;
268 	args.mda_mode = TPM_CDEV_PERM_FLAG;
269 	args.mda_si_drv1 = sc;
270 	result = make_dev_s(&args, &sc->sc_cdev, TPM_CDEV_NAME);
271 	if (result != 0)
272 		return (result);
273 
274 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
275 	random_source_register(&random_tpm);
276 	TIMEOUT_TASK_INIT(taskqueue_thread, &sc->harvest_task, 0,
277 	    tpm20_harvest, sc);
278 	taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task, 0);
279 #endif
280 	sc->common_initialized = true;
281 
282 	return (result);
283 
284 }
285 
286 void
287 tpm20_release(struct tpm_sc *sc)
288 {
289 
290 	/* Publish teardown so a retrying command stops using the device. */
291 	atomic_store_bool(&sc->dying, true);
292 	sx_xlock(&sc->dev_lock);
293 	sx_xunlock(&sc->dev_lock);
294 
295 	/* Stop and drain character-device methods before freeing their state. */
296 	if (sc->sc_cdev != NULL) {
297 		destroy_dev(sc->sc_cdev);
298 		sc->sc_cdev = NULL;
299 	}
300 	if (!sc->common_initialized)
301 		goto out;
302 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
303 	taskqueue_drain_timeout(taskqueue_thread, &sc->harvest_task);
304 	random_source_deregister(&random_tpm);
305 #endif
306 	sc->common_initialized = false;
307 out:
308 	if (sc->internal_priv != NULL) {
309 		tpm20_priv_dtor(sc->internal_priv);
310 		sc->internal_priv = NULL;
311 	}
312 	sx_destroy(&sc->dev_lock);
313 }
314 
315 int
316 tpm20_resume(device_t dev)
317 {
318 	struct tpm_sc *sc;
319 	int error;
320 
321 	sc = device_get_softc(dev);
322 	sx_xlock(&sc->dev_lock);
323 	if (atomic_load_bool(&sc->dying)) {
324 		error = ENXIO;
325 		goto out;
326 	}
327 	error = tpm20_restart(dev, false);
328 	if (error == 0)
329 		sc->suspended = false;
330 out:
331 	sx_xunlock(&sc->dev_lock);
332 	if (error != 0)
333 		return (error);
334 
335 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
336 	taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task,
337 	    hz * TPM_HARVEST_INTERVAL);
338 #endif
339 	return (0);
340 }
341 
342 int
343 tpm20_suspend(device_t dev)
344 {
345 	struct tpm_sc *sc;
346 	int error;
347 
348 	sc = device_get_softc(dev);
349 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
350 	taskqueue_drain_timeout(taskqueue_thread, &sc->harvest_task);
351 #endif
352 	sx_xlock(&sc->dev_lock);
353 	if (atomic_load_bool(&sc->dying)) {
354 		error = ENXIO;
355 		goto out;
356 	}
357 	if (sc->suspended) {
358 		error = 0;
359 		goto out;
360 	}
361 	error = tpm20_save_state(dev, true);
362 	if (error == 0)
363 		sc->suspended = true;
364 out:
365 	sx_xunlock(&sc->dev_lock);
366 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
367 	if (error != 0)
368 		taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task,
369 		    hz * TPM_HARVEST_INTERVAL);
370 #endif
371 	return (error);
372 }
373 
374 int
375 tpm20_shutdown(device_t dev)
376 {
377 	struct tpm_sc *sc;
378 	int error;
379 
380 	sc = device_get_softc(dev);
381 	sx_xlock(&sc->dev_lock);
382 	if (atomic_load_bool(&sc->dying))
383 		error = ENXIO;
384 	else
385 		error = tpm20_save_state(dev, false);
386 	sx_xunlock(&sc->dev_lock);
387 	return (error);
388 }
389 
390 #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM
391 /*
392  * Get TPM_HARVEST_SIZE random bytes and add them
393  * into system entropy pool.
394  */
395 static void
396 tpm20_harvest(void *arg, int unused)
397 {
398 	struct tpm_sc *sc;
399 	struct tpm_priv *priv;
400 	unsigned char entropy[TPM_HARVEST_SIZE];
401 	uint16_t entropy_size;
402 	int result;
403 	uint8_t cmd[] = {
404 		0x80, 0x01,		/* TPM_ST_NO_SESSIONS tag*/
405 		0x00, 0x00, 0x00, 0x0c,	/* cmd length */
406 		0x00, 0x00, 0x01, 0x7b,	/* cmd TPM_CC_GetRandom */
407 		0x00, TPM_HARVEST_SIZE 	/* number of bytes requested */
408 	};
409 
410 	sc = arg;
411 	sx_xlock(&sc->dev_lock);
412 	if (atomic_load_bool(&sc->dying) || sc->suspended) {
413 		sx_xunlock(&sc->dev_lock);
414 		return;
415 	}
416 
417 	priv = sc->internal_priv;
418 	memcpy(priv->buf, cmd, sizeof(cmd));
419 
420 	entropy_size = 0;
421 	result = TPM_TRANSMIT(sc->dev, priv, sizeof(cmd));
422 	if (result == 0) {
423 		/* The byte count is placed immediately after the header. */
424 		entropy_size = (uint16_t)priv->buf[TPM_HEADER_SIZE + 1];
425 		if (entropy_size > 0) {
426 			entropy_size = MIN(entropy_size, TPM_HARVEST_SIZE);
427 			memcpy(entropy,
428 			    priv->buf + TPM_HEADER_SIZE + sizeof(uint16_t),
429 			    entropy_size);
430 		}
431 	}
432 	taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task,
433 	    hz * TPM_HARVEST_INTERVAL);
434 
435 	sx_xunlock(&sc->dev_lock);
436 	if (entropy_size > 0)
437 		random_harvest_queue(entropy, entropy_size, RANDOM_PURE_TPM);
438 }
439 #endif	/* TPM_HARVEST */
440 
441 /*
442  * Send a TPM 2.0 command whose successful response contains only a header.
443  */
444 static int
445 tpm20_command(device_t dev, uint32_t command, uint16_t parameter,
446     uint32_t alternate_rc, const char *name)
447 {
448 	struct tpm_priv *priv;
449 	struct tpm_sc *sc;
450 	uint32_t response_rc, response_size;
451 	uint8_t cmd[12];
452 	int delay_ms, error;
453 
454 	sc = device_get_softc(dev);
455 	if (sc == NULL)
456 		return (ENXIO);
457 
458 	sx_assert(&sc->dev_lock, SA_XLOCKED);
459 	if (atomic_load_bool(&sc->dying))
460 		return (ENXIO);
461 	priv = sc->internal_priv;
462 
463 	be16enc(cmd, TPM2_ST_NO_SESSIONS);
464 	be32enc(cmd + 2, sizeof(cmd));
465 	be32enc(cmd + 6, command);
466 	be16enc(cmd + 10, parameter);
467 
468 	delay_ms = TPM2_RETRY_INITIAL_MS;
469 	for (;;) {
470 		if (atomic_load_bool(&sc->dying))
471 			return (ENXIO);
472 		memcpy(priv->buf, cmd, sizeof(cmd));
473 		error = TPM_TRANSMIT(sc->dev, priv, sizeof(cmd));
474 		if (error != 0)
475 			break;
476 		if (priv->len < TPM_HEADER_SIZE) {
477 			error = EPROTO;
478 			break;
479 		}
480 
481 		response_size = be32dec(priv->buf + 2);
482 		response_rc = be32dec(priv->buf + 6);
483 		if (be16dec(priv->buf) != TPM2_ST_NO_SESSIONS ||
484 		    response_size != TPM_HEADER_SIZE ||
485 		    priv->len != response_size) {
486 			error = EPROTO;
487 			break;
488 		}
489 		if (response_rc != TPM2_RC_RETRY &&
490 		    response_rc != TPM2_RC_TESTING)
491 			break;
492 		if (atomic_load_bool(&sc->dying))
493 			return (ENXIO);
494 		if (delay_ms > TPM2_RETRY_MAX_MS)
495 			break;
496 		pause("tpm2retry", MAX(hz * delay_ms / 1000, 1));
497 		delay_ms *= 2;
498 	}
499 	if (error != 0) {
500 		device_printf(dev, "%s command failed: %d\n", name, error);
501 		return (error);
502 	}
503 	if (response_rc != TPM2_RC_SUCCESS && response_rc != alternate_rc) {
504 		device_printf(dev, "%s failed: TPM error 0x%x\n", name,
505 		    response_rc);
506 		return (EIO);
507 	}
508 	return (0);
509 }
510 
511 static int
512 tpm20_restart(device_t dev, bool clear)
513 {
514 	uint16_t startup_type;
515 
516 	startup_type = clear ? TPM2_SU_CLEAR : TPM2_SU_STATE;
517 	return (tpm20_command(dev, TPM_CC_Startup, startup_type,
518 	    TPM2_RC_INITIALIZE, "Startup"));
519 }
520 
521 static int
522 tpm20_save_state(device_t dev, bool suspend)
523 {
524 	uint16_t shutdown_type;
525 
526 	shutdown_type = suspend ? TPM2_SU_STATE : TPM2_SU_CLEAR;
527 	return (tpm20_command(dev, TPM_CC_Shutdown, shutdown_type,
528 	    TPM2_RC_SUCCESS, "Shutdown"));
529 }
530 
531 int32_t
532 tpm20_get_timeout(uint32_t command)
533 {
534 	int32_t timeout;
535 
536 	switch (command) {
537 		case TPM_CC_CreatePrimary:
538 		case TPM_CC_Create:
539 		case TPM_CC_CreateLoaded:
540 			timeout = TPM_TIMEOUT_LONG;
541 			break;
542 		case TPM_CC_SequenceComplete:
543 		case TPM_CC_Startup:
544 		case TPM_CC_SequenceUpdate:
545 		case TPM_CC_GetCapability:
546 		case TPM_CC_PCR_Extend:
547 		case TPM_CC_EventSequenceComplete:
548 		case TPM_CC_HashSequenceStart:
549 			timeout = TPM_TIMEOUT_C;
550 			break;
551 		default:
552 			timeout = TPM_TIMEOUT_B;
553 			break;
554 	}
555 	return timeout;
556 }
557