1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2021 Jason King
26 */
27
28 /*
29 * TPM 1.2 Driver for the TPMs that follow TIS v1.2
30 */
31
32 #include <sys/devops.h> /* used by dev_ops */
33 #include <sys/conf.h> /* used by dev_ops,cb_ops */
34 #include <sys/modctl.h> /* for _init,_info,_fini,mod_* */
35 #include <sys/ddi.h> /* used by all entry points */
36 #include <sys/sunddi.h> /* used by all entry points */
37 #include <sys/cmn_err.h> /* used for debug outputs */
38 #include <sys/types.h> /* used by prop_op, ddi_prop_op */
39
40 #include <sys/file.h> /* used by open, close */
41 #include <sys/errno.h> /* used by open,close,read,write */
42 #include <sys/open.h> /* used by open,close,read,write */
43 #include <sys/cred.h> /* used by open,close,read */
44 #include <sys/uio.h> /* used by read */
45 #include <sys/stat.h> /* defines S_IFCHR */
46
47 #include <sys/byteorder.h> /* for ntohs, ntohl, htons, htonl */
48
49 #ifdef sun4v
50 #include <sys/hypervisor_api.h>
51 #include <sys/hsvc.h>
52 #endif
53
54 #include <tss/platform.h> /* from SUNWtss */
55 #include <tss/tpm.h> /* from SUNWtss */
56
57 #include "tpm_tis.h"
58 #include "tpm_ddi.h"
59 #include "tpm_duration.h"
60
61 #define TPM_HEADER_SIZE 10
62 typedef enum {
63 TPM_TAG_OFFSET = 0,
64 TPM_PARAMSIZE_OFFSET = 2,
65 TPM_RETURN_OFFSET = 6,
66 TPM_COMMAND_CODE_OFFSET = 6,
67 } TPM_HEADER_OFFSET_T;
68
69 /*
70 * This is to address some TPMs that does not report the correct duration
71 * and timeouts. In our experience with the production TPMs, we encountered
72 * time errors such as GetCapability command from TPM reporting the timeout
73 * and durations in milliseconds rather than microseconds. Some other TPMs
74 * report the value 0's
75 *
76 * Short Duration is based on section 11.3.4 of TIS speciciation, that
77 * TPM_GetCapability (short duration) commands should not be longer than 750ms
78 * and that section 11.3.7 states that TPM_ContinueSelfTest (medium duration)
79 * should not be longer than 1 second.
80 */
81 #define DEFAULT_SHORT_DURATION 750000
82 #define DEFAULT_MEDIUM_DURATION 1000000
83 #define DEFAULT_LONG_DURATION 300000000
84 #define DEFAULT_TIMEOUT_A 750000
85 #define DEFAULT_TIMEOUT_B 2000000
86 #define DEFAULT_TIMEOUT_C 750000
87 #define DEFAULT_TIMEOUT_D 750000
88
89 /*
90 * In order to test the 'millisecond bug', we test if DURATIONS and TIMEOUTS
91 * are unreasonably low...such as 10 milliseconds (TPM isn't that fast).
92 * and 400 milliseconds for long duration
93 */
94 #define TEN_MILLISECONDS 10000 /* 10 milliseconds */
95 #define FOUR_HUNDRED_MILLISECONDS 400000 /* 4 hundred milliseconds */
96
97 #define DEFAULT_LOCALITY 0
98 /*
99 * TPM input/output buffer offsets
100 */
101
102 typedef enum {
103 TPM_CAP_RESPSIZE_OFFSET = 10,
104 TPM_CAP_RESP_OFFSET = 14,
105 } TPM_CAP_RET_OFFSET_T;
106
107 typedef enum {
108 TPM_CAP_TIMEOUT_A_OFFSET = 14,
109 TPM_CAP_TIMEOUT_B_OFFSET = 18,
110 TPM_CAP_TIMEOUT_C_OFFSET = 22,
111 TPM_CAP_TIMEOUT_D_OFFSET = 26,
112 } TPM_CAP_TIMEOUT_OFFSET_T;
113
114 typedef enum {
115 TPM_CAP_DUR_SHORT_OFFSET = 14,
116 TPM_CAP_DUR_MEDIUM_OFFSET = 18,
117 TPM_CAP_DUR_LONG_OFFSET = 22,
118 } TPM_CAP_DURATION_OFFSET_T;
119
120 #define TPM_CAP_VERSION_INFO_OFFSET 14
121 #define TPM_CAP_VERSION_INFO_SIZE 15
122
123 /*
124 * Internal TPM command functions
125 */
126 static int itpm_command(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz);
127 static int tpm_get_timeouts(tpm_state_t *tpm);
128 static int tpm_get_duration(tpm_state_t *tpm);
129 static int tpm_get_version(tpm_state_t *tpm);
130 static int tpm_continue_selftest(tpm_state_t *tpm);
131
132 /*
133 * Internal TIS related functions
134 */
135 static int tpm_wait_for_stat(tpm_state_t *, uint8_t, clock_t);
136 static clock_t tpm_get_ordinal_duration(tpm_state_t *, uint8_t);
137 static int tis_check_active_locality(tpm_state_t *, char);
138 static int tis_request_locality(tpm_state_t *, char);
139 static void tis_release_locality(tpm_state_t *, char, int);
140 static int tis_init(tpm_state_t *);
141 static uint8_t tis_get_status(tpm_state_t *);
142 static int tis_send_data(tpm_state_t *, uint8_t *, size_t);
143 static int tis_recv_data(tpm_state_t *, uint8_t *, size_t);
144
145 /* Auxilliary */
146 static int receive_data(tpm_state_t *, uint8_t *, size_t);
147 static inline int tpm_io_lock(tpm_state_t *);
148 static inline void tpm_unlock(tpm_state_t *);
149 static void tpm_cleanup(dev_info_t *, tpm_state_t *);
150
151 /*
152 * Sun DDI/DDK entry points
153 */
154
155 /* Declaration of autoconfig functions */
156 static int tpm_attach(dev_info_t *, ddi_attach_cmd_t);
157 static int tpm_detach(dev_info_t *, ddi_detach_cmd_t);
158 static int tpm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
159 static int tpm_quiesce(dev_info_t *);
160 /* End of autoconfig functions */
161
162 /* Declaration of driver entry point functions */
163 static int tpm_open(dev_t *, int, int, cred_t *);
164 static int tpm_close(dev_t, int, int, cred_t *);
165 static int tpm_read(dev_t, struct uio *, cred_t *);
166 static int tpm_write(dev_t, struct uio *, cred_t *);
167 /* End of driver entry point functions */
168
169 /* cb_ops structure */
170 static struct cb_ops tpm_cb_ops = {
171 tpm_open,
172 tpm_close,
173 nodev, /* no strategy - nodev returns ENXIO */
174 nodev, /* no print */
175 nodev, /* no dump */
176 tpm_read,
177 tpm_write,
178 nodev, /* no ioctl */
179 nodev, /* no devmap */
180 nodev, /* no mmap */
181 nodev, /* no segmap */
182 nochpoll, /* returns ENXIO for non-pollable devices */
183 ddi_prop_op,
184 NULL, /* streamtab struc */
185 D_MP, /* compatibility flags */
186 CB_REV, /* cb_ops revision number */
187 nodev, /* no aread */
188 nodev /* no awrite */
189 };
190
191 /* dev_ops structure */
192 static struct dev_ops tpm_dev_ops = {
193 DEVO_REV,
194 0, /* reference count */
195 tpm_getinfo,
196 nulldev, /* no identify - nulldev returns 0 */
197 nulldev,
198 tpm_attach,
199 tpm_detach,
200 nodev, /* no reset - nodev returns ENXIO */
201 &tpm_cb_ops,
202 (struct bus_ops *)NULL,
203 nodev, /* no power */
204 tpm_quiesce
205 };
206
207 /* modldrv structure */
208 static struct modldrv modldrv = {
209 &mod_driverops, /* Type: This is a driver */
210 "TPM 1.2 driver", /* Name of the module. */
211 &tpm_dev_ops
212 };
213
214 /* modlinkage structure */
215 static struct modlinkage tpm_ml = {
216 MODREV_1,
217 &modldrv,
218 NULL
219 };
220
221
222 #ifdef KCF_TPM_RNG_PROVIDER
223
224 #define IDENT_TPMRNG "TPM Random Number Generator"
225
226 #include <sys/crypto/common.h>
227 #include <sys/crypto/impl.h>
228 #include <sys/crypto/spi.h>
229 /*
230 * CSPI information (entry points, provider info, etc.)
231 */
232 static void tpmrng_provider_status(crypto_provider_handle_t, uint_t *);
233
234 static crypto_control_ops_t tpmrng_control_ops = {
235 tpmrng_provider_status
236 };
237
238 static int tpmrng_seed_random(crypto_provider_handle_t, crypto_session_id_t,
239 uchar_t *, size_t, uint_t, uint32_t, crypto_req_handle_t);
240
241 static int tpmrng_generate_random(crypto_provider_handle_t,
242 crypto_session_id_t, uchar_t *, size_t, crypto_req_handle_t);
243
244 static crypto_random_number_ops_t tpmrng_random_number_ops = {
245 tpmrng_seed_random,
246 tpmrng_generate_random
247 };
248
249 static int tpmrng_ext_info(crypto_provider_handle_t,
250 crypto_provider_ext_info_t *,
251 crypto_req_handle_t);
252
253 static crypto_provider_management_ops_t tpmrng_extinfo_op = {
254 tpmrng_ext_info,
255 NULL,
256 NULL,
257 NULL
258 };
259
260 static int tpmrng_register(tpm_state_t *);
261 static int tpmrng_unregister(tpm_state_t *);
262
263 static crypto_ops_t tpmrng_crypto_ops = {
264 &tpmrng_control_ops,
265 NULL,
266 NULL,
267 NULL,
268 NULL,
269 NULL,
270 NULL,
271 NULL,
272 &tpmrng_random_number_ops,
273 NULL,
274 NULL,
275 NULL,
276 &tpmrng_extinfo_op,
277 NULL,
278 NULL
279 };
280
281 static crypto_provider_info_t tpmrng_prov_info = {
282 CRYPTO_SPI_VERSION_2,
283 "TPM Random Number Provider",
284 CRYPTO_HW_PROVIDER,
285 NULL,
286 NULL,
287 &tpmrng_crypto_ops,
288 0,
289 NULL,
290 0,
291 NULL
292 };
293 #endif /* KCF_TPM_RNG_PROVIDER */
294
295 static void *statep = NULL;
296
297 /*
298 * Inline code to get exclusive lock on the TPM device and to make sure
299 * the device is not suspended. This grabs the primary TPM mutex (pm_mutex)
300 * and then checks the suspend status. If suspended, it will wait until
301 * the device is "resumed" before releasing the pm_mutex and continuing.
302 */
303 #define TPM_EXCLUSIVE_LOCK(tpm) { \
304 mutex_enter(&tpm->pm_mutex); \
305 while (tpm->suspended) \
306 cv_wait(&tpm->suspend_cv, &tpm->pm_mutex); \
307 mutex_exit(&tpm->pm_mutex); }
308
309 /*
310 * TPM accessor functions
311 */
312 #ifdef sun4v
313
314 extern uint64_t
315 hcall_tpm_get(uint64_t, uint64_t, uint64_t, uint64_t *);
316
317 extern uint64_t
318 hcall_tpm_put(uint64_t, uint64_t, uint64_t, uint64_t);
319
320 static inline uint8_t
tpm_get8(tpm_state_t * tpm,unsigned long offset)321 tpm_get8(tpm_state_t *tpm, unsigned long offset)
322 {
323 uint64_t value;
324
325 ASSERT(tpm != NULL);
326 (void) hcall_tpm_get(tpm->locality, offset, sizeof (uint8_t), &value);
327 return ((uint8_t)value);
328 }
329
330 static inline uint32_t
tpm_get32(tpm_state_t * tpm,unsigned long offset)331 tpm_get32(tpm_state_t *tpm, unsigned long offset)
332 {
333 uint64_t value;
334
335 ASSERT(tpm != NULL);
336 (void) hcall_tpm_get(tpm->locality, offset, sizeof (uint32_t), &value);
337 return ((uint32_t)value);
338 }
339
340 static inline void
tpm_put8(tpm_state_t * tpm,unsigned long offset,uint8_t value)341 tpm_put8(tpm_state_t *tpm, unsigned long offset, uint8_t value)
342 {
343 ASSERT(tpm != NULL);
344 (void) hcall_tpm_put(tpm->locality, offset, sizeof (uint8_t), value);
345 }
346
347 #else
348
349 static inline uint8_t
tpm_get8(tpm_state_t * tpm,unsigned long offset)350 tpm_get8(tpm_state_t *tpm, unsigned long offset)
351 {
352 ASSERT(tpm != NULL);
353
354 return (ddi_get8(tpm->handle,
355 (uint8_t *)(TPM_LOCALITY_OFFSET(tpm->locality) |
356 (uintptr_t)tpm->addr + offset)));
357 }
358
359 static inline uint32_t
tpm_get32(tpm_state_t * tpm,unsigned long offset)360 tpm_get32(tpm_state_t *tpm, unsigned long offset)
361 {
362 ASSERT(tpm != NULL);
363 return (ddi_get32(tpm->handle,
364 (uint32_t *)(TPM_LOCALITY_OFFSET(tpm->locality) |
365 (uintptr_t)tpm->addr + offset)));
366 }
367
368 static inline void
tpm_put8(tpm_state_t * tpm,unsigned long offset,uint8_t value)369 tpm_put8(tpm_state_t *tpm, unsigned long offset, uint8_t value)
370 {
371 ASSERT(tpm != NULL);
372 ddi_put8(tpm->handle,
373 (uint8_t *)(TPM_LOCALITY_OFFSET(tpm->locality) |
374 (uintptr_t)tpm->addr + offset), value);
375 }
376
377 #endif /* sun4v */
378
379 /*
380 * TPM commands to get the TPM's properties, e.g.,timeout
381 */
382 /*ARGSUSED*/
383 static int
tpm_quiesce(dev_info_t * dip)384 tpm_quiesce(dev_info_t *dip)
385 {
386 return (DDI_SUCCESS);
387 }
388
389 static uint32_t
load32(uchar_t * ptr,uint32_t offset)390 load32(uchar_t *ptr, uint32_t offset)
391 {
392 uint32_t val;
393 bcopy(ptr + offset, &val, sizeof (uint32_t));
394
395 return (ntohl(val));
396 }
397
398 /*
399 * Get the actual timeouts supported by the TPM by issuing TPM_GetCapability
400 * with the subcommand TPM_CAP_PROP_TIS_TIMEOUT
401 * TPM_GetCapability (TPM Main Part 3 Rev. 94, pg.38)
402 */
403 static int
tpm_get_timeouts(tpm_state_t * tpm)404 tpm_get_timeouts(tpm_state_t *tpm)
405 {
406 int ret;
407 uint32_t timeout; /* in milliseconds */
408 uint32_t len;
409
410 /* The buffer size (30) needs room for 4 timeout values (uint32_t) */
411 uint8_t buf[30] = {
412 0, 193, /* TPM_TAG_RQU_COMMAND */
413 0, 0, 0, 22, /* paramsize in bytes */
414 0, 0, 0, 101, /* TPM_ORD_GetCapability */
415 0, 0, 0, 5, /* TPM_CAP_Prop */
416 0, 0, 0, 4, /* SUB_CAP size in bytes */
417 0, 0, 1, 21 /* TPM_CAP_PROP_TIS_TIMEOUT(0x115) */
418 };
419
420 ASSERT(tpm != NULL);
421
422 ret = itpm_command(tpm, buf, sizeof (buf));
423 if (ret != DDI_SUCCESS) {
424 #ifdef DEBUG
425 cmn_err(CE_WARN, "!%s: itpm_command failed", __func__);
426 #endif
427 return (DDI_FAILURE);
428 }
429
430 /*
431 * Get the length of the returned buffer
432 * Make sure that there are 4 timeout values returned
433 * length of the capability response is stored in data[10-13]
434 * Also the TPM is in network byte order
435 */
436 len = load32(buf, TPM_CAP_RESPSIZE_OFFSET);
437 if (len != 4 * sizeof (uint32_t)) {
438 #ifdef DEBUG
439 cmn_err(CE_WARN, "!%s: capability response size should be %d"
440 "instead len = %d",
441 __func__, (int)(4 * sizeof (uint32_t)), (int)len);
442 #endif
443 return (DDI_FAILURE);
444 }
445
446 /* Get the four timeout's: a,b,c,d (they are 4 bytes long each) */
447 timeout = load32(buf, TPM_CAP_TIMEOUT_A_OFFSET);
448 if (timeout == 0) {
449 timeout = DEFAULT_TIMEOUT_A;
450 } else if (timeout < TEN_MILLISECONDS) {
451 /* timeout is in millisecond range (should be microseconds) */
452 timeout *= 1000;
453 }
454 tpm->timeout_a = drv_usectohz(timeout);
455
456 timeout = load32(buf, TPM_CAP_TIMEOUT_B_OFFSET);
457 if (timeout == 0) {
458 timeout = DEFAULT_TIMEOUT_B;
459 } else if (timeout < TEN_MILLISECONDS) {
460 /* timeout is in millisecond range (should be microseconds) */
461 timeout *= 1000;
462 }
463 tpm->timeout_b = drv_usectohz(timeout);
464
465 timeout = load32(buf, TPM_CAP_TIMEOUT_C_OFFSET);
466 if (timeout == 0) {
467 timeout = DEFAULT_TIMEOUT_C;
468 } else if (timeout < TEN_MILLISECONDS) {
469 /* timeout is in millisecond range (should be microseconds) */
470 timeout *= 1000;
471 }
472 tpm->timeout_c = drv_usectohz(timeout);
473
474 timeout = load32(buf, TPM_CAP_TIMEOUT_D_OFFSET);
475 if (timeout == 0) {
476 timeout = DEFAULT_TIMEOUT_D;
477 } else if (timeout < TEN_MILLISECONDS) {
478 /* timeout is in millisecond range (should be microseconds) */
479 timeout *= 1000;
480 }
481 tpm->timeout_d = drv_usectohz(timeout);
482
483 return (DDI_SUCCESS);
484 }
485
486 /*
487 * Get the actual timeouts supported by the TPM by issuing TPM_GetCapability
488 * with the subcommand TPM_CAP_PROP_TIS_DURATION
489 * TPM_GetCapability (TPM Main Part 3 Rev. 94, pg.38)
490 */
491 static int
tpm_get_duration(tpm_state_t * tpm)492 tpm_get_duration(tpm_state_t *tpm)
493 {
494 int ret;
495 uint32_t duration;
496 uint32_t len;
497 uint8_t buf[30] = {
498 0, 193, /* TPM_TAG_RQU_COMMAND */
499 0, 0, 0, 22, /* paramsize in bytes */
500 0, 0, 0, 101, /* TPM_ORD_GetCapability */
501 0, 0, 0, 5, /* TPM_CAP_Prop */
502 0, 0, 0, 4, /* SUB_CAP size in bytes */
503 0, 0, 1, 32 /* TPM_CAP_PROP_TIS_DURATION(0x120) */
504 };
505
506 ASSERT(tpm != NULL);
507
508 ret = itpm_command(tpm, buf, sizeof (buf));
509 if (ret != DDI_SUCCESS) {
510 #ifdef DEBUG
511 cmn_err(CE_WARN, "!%s: itpm_command failed with ret code: 0x%x",
512 __func__, ret);
513 #endif
514 return (DDI_FAILURE);
515 }
516
517 /*
518 * Get the length of the returned buffer
519 * Make sure that there are 3 duration values (S,M,L: in that order)
520 * length of the capability response is stored in data[10-13]
521 * Also the TPM is in network byte order
522 */
523 len = load32(buf, TPM_CAP_RESPSIZE_OFFSET);
524 if (len != 3 * sizeof (uint32_t)) {
525 #ifdef DEBUG
526 cmn_err(CE_WARN, "!%s: capability response should be %d, "
527 "instead, it's %d",
528 __func__, (int)(3 * sizeof (uint32_t)), (int)len);
529 #endif
530 return (DDI_FAILURE);
531 }
532
533 duration = load32(buf, TPM_CAP_DUR_SHORT_OFFSET);
534 if (duration == 0) {
535 duration = DEFAULT_SHORT_DURATION;
536 } else if (duration < TEN_MILLISECONDS) {
537 duration *= 1000;
538 }
539 tpm->duration[TPM_SHORT] = drv_usectohz(duration);
540
541 duration = load32(buf, TPM_CAP_DUR_MEDIUM_OFFSET);
542 if (duration == 0) {
543 duration = DEFAULT_MEDIUM_DURATION;
544 } else if (duration < TEN_MILLISECONDS) {
545 duration *= 1000;
546 }
547 tpm->duration[TPM_MEDIUM] = drv_usectohz(duration);
548
549 duration = load32(buf, TPM_CAP_DUR_LONG_OFFSET);
550 if (duration == 0) {
551 duration = DEFAULT_LONG_DURATION;
552 } else if (duration < FOUR_HUNDRED_MILLISECONDS) {
553 duration *= 1000;
554 }
555 tpm->duration[TPM_LONG] = drv_usectohz(duration);
556
557 /* Just make the undefined duration be the same as the LONG */
558 tpm->duration[TPM_UNDEFINED] = tpm->duration[TPM_LONG];
559
560 return (DDI_SUCCESS);
561 }
562
563 /*
564 * Get the actual timeouts supported by the TPM by issuing TPM_GetCapability
565 * with the subcommand TPM_CAP_PROP_TIS_DURATION
566 * TPM_GetCapability (TPM Main Part 3 Rev. 94, pg.38)
567 */
568 static int
tpm_get_version(tpm_state_t * tpm)569 tpm_get_version(tpm_state_t *tpm)
570 {
571 int ret;
572 uint32_t len;
573 char vendorId[5];
574 /* If this buf is too small, the "vendor specific" data won't fit */
575 uint8_t buf[64] = {
576 0, 193, /* TPM_TAG_RQU_COMMAND */
577 0, 0, 0, 18, /* paramsize in bytes */
578 0, 0, 0, 101, /* TPM_ORD_GetCapability */
579 0, 0, 0, 0x1A, /* TPM_CAP_VERSION_VAL */
580 0, 0, 0, 0, /* SUB_CAP size in bytes */
581 };
582
583 ASSERT(tpm != NULL);
584
585 ret = itpm_command(tpm, buf, sizeof (buf));
586 if (ret != DDI_SUCCESS) {
587 #ifdef DEBUG
588 cmn_err(CE_WARN, "!%s: itpm_command failed with ret code: 0x%x",
589 __func__, ret);
590 #endif
591 return (DDI_FAILURE);
592 }
593
594 /*
595 * Get the length of the returned buffer.
596 */
597 len = load32(buf, TPM_CAP_RESPSIZE_OFFSET);
598 if (len < TPM_CAP_VERSION_INFO_SIZE) {
599 #ifdef DEBUG
600 cmn_err(CE_WARN, "!%s: capability response should be greater"
601 " than %d, instead, it's %d",
602 __func__, TPM_CAP_VERSION_INFO_SIZE, len);
603 #endif
604 return (DDI_FAILURE);
605 }
606
607 bcopy(buf + TPM_CAP_VERSION_INFO_OFFSET, &tpm->vers_info,
608 TPM_CAP_VERSION_INFO_SIZE);
609
610 bcopy(tpm->vers_info.tpmVendorID, vendorId,
611 sizeof (tpm->vers_info.tpmVendorID));
612 vendorId[4] = '\0';
613
614 cmn_err(CE_NOTE, "!TPM found: Ver %d.%d, Rev %d.%d, "
615 "SpecLevel %d, errataRev %d, VendorId '%s'",
616 tpm->vers_info.version.major, /* Version */
617 tpm->vers_info.version.minor,
618 tpm->vers_info.version.revMajor, /* Revision */
619 tpm->vers_info.version.revMinor,
620 (int)ntohs(tpm->vers_info.specLevel),
621 tpm->vers_info.errataRev,
622 vendorId);
623
624 /*
625 * This driver only supports TPM Version 1.2
626 */
627 if (tpm->vers_info.version.major != 1 &&
628 tpm->vers_info.version.minor != 2) {
629 cmn_err(CE_WARN, "!%s: Unsupported TPM version (%d.%d)",
630 __func__,
631 tpm->vers_info.version.major, /* Version */
632 tpm->vers_info.version.minor);
633 return (DDI_FAILURE);
634 }
635
636 return (DDI_SUCCESS);
637 }
638
639 /*
640 * To prevent the TPM from complaining that certain functions are not tested
641 * we run this command when the driver attaches.
642 * For details see Section 4.2 of TPM Main Part 3 Command Specification
643 */
644 static int
tpm_continue_selftest(tpm_state_t * tpm)645 tpm_continue_selftest(tpm_state_t *tpm)
646 {
647 int ret;
648 uint8_t buf[10] = {
649 0, 193, /* TPM_TAG_RQU COMMAND */
650 0, 0, 0, 10, /* paramsize in bytes */
651 0, 0, 0, 83 /* TPM_ORD_ContinueSelfTest */
652 };
653
654 /* Need a longer timeout */
655 ret = itpm_command(tpm, buf, sizeof (buf));
656 if (ret != DDI_SUCCESS) {
657 #ifdef DEBUG
658 cmn_err(CE_WARN, "!%s: itpm_command failed", __func__);
659 #endif
660 return (DDI_FAILURE);
661 }
662
663 return (DDI_SUCCESS);
664 }
665 /*
666 * Auxilary Functions
667 */
668
669 /*
670 * Find out how long we should wait for the TPM command to complete a command
671 */
672 static clock_t
tpm_get_ordinal_duration(tpm_state_t * tpm,uint8_t ordinal)673 tpm_get_ordinal_duration(tpm_state_t *tpm, uint8_t ordinal)
674 {
675 uint8_t index;
676
677 ASSERT(tpm != NULL);
678
679 /* Default and failure case for IFX */
680 /* Is it a TSC_ORDINAL? */
681 if (ordinal & TSC_ORDINAL_MASK) {
682 if (ordinal >= TSC_ORDINAL_MAX) {
683 #ifdef DEBUG
684 cmn_err(CE_WARN,
685 "!%s: tsc ordinal: %d exceeds MAX: %d",
686 __func__, ordinal, TSC_ORDINAL_MAX);
687 #endif
688 return (0);
689 }
690 index = tsc_ords_duration[ordinal];
691 } else {
692 if (ordinal >= TPM_ORDINAL_MAX) {
693 #ifdef DEBUG
694 cmn_err(CE_WARN,
695 "!%s: ordinal %d exceeds MAX: %d",
696 __func__, ordinal, TPM_ORDINAL_MAX);
697 #endif
698 return (0);
699 }
700 index = tpm_ords_duration[ordinal];
701 }
702
703 if (index > TPM_DURATION_MAX_IDX) {
704 #ifdef DEBUG
705 cmn_err(CE_WARN, "!%s: duration index '%d' is out of bounds",
706 __func__, index);
707 #endif
708 return (0);
709 }
710 return (tpm->duration[index]);
711 }
712
713 /*
714 * Internal TPM Transmit Function:
715 * Calls implementation specific sendto and receive
716 * The code assumes that the buffer is in network byte order
717 */
718 static int
itpm_command(tpm_state_t * tpm,uint8_t * buf,size_t bufsiz)719 itpm_command(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz)
720 {
721 int ret;
722 uint32_t count;
723
724 ASSERT(tpm != NULL && buf != NULL);
725
726 /* The byte order is network byte order so convert it */
727 count = load32(buf, TPM_PARAMSIZE_OFFSET);
728
729 if (count == 0 || (count > bufsiz)) {
730 #ifdef DEBUG
731 cmn_err(CE_WARN, "!%s: invalid byte count value "
732 "(%d > bufsiz %d)", __func__, (int)count, (int)bufsiz);
733 #endif
734 return (DDI_FAILURE);
735 }
736
737 /* Send the command */
738 ret = tis_send_data(tpm, buf, count);
739 if (ret != DDI_SUCCESS) {
740 #ifdef DEBUG
741 cmn_err(CE_WARN, "!%s: tis_send_data failed with error %x",
742 __func__, ret);
743 #endif
744 return (DDI_FAILURE);
745 }
746
747 /*
748 * Now receive the data from the tpm
749 * Should at least receive "the common" 10 bytes (TPM_HEADER_SIZE)
750 */
751 ret = tis_recv_data(tpm, buf, bufsiz);
752 if (ret < TPM_HEADER_SIZE) {
753 #ifdef DEBUG
754 cmn_err(CE_WARN, "!%s: tis_recv_data failed", __func__);
755 #endif
756 return (DDI_FAILURE);
757 }
758
759 /* Check the return code */
760 ret = load32(buf, TPM_RETURN_OFFSET);
761 if (ret != TPM_SUCCESS) {
762 if (ret == TPM_E_DEACTIVATED)
763 cmn_err(CE_WARN, "!%s: TPM is deactivated", __func__);
764 else if (ret == TPM_E_DISABLED)
765 cmn_err(CE_WARN, "!%s: TPM is disabled", __func__);
766 else
767 cmn_err(CE_WARN, "!%s: TPM error code 0x%0x",
768 __func__, ret);
769 return (DDI_FAILURE);
770 }
771
772 return (DDI_SUCCESS);
773 }
774
775 /*
776 * Whenever the driver wants to write to the DATA_IO register, it must need
777 * to figure out the burstcount. This is the amount of bytes it can write
778 * before having to wait for long LPC bus cycle
779 *
780 * Returns: 0 if error, burst count if sucess
781 */
782 static uint16_t
tpm_get_burstcount(tpm_state_t * tpm)783 tpm_get_burstcount(tpm_state_t *tpm)
784 {
785 clock_t stop;
786 uint16_t burstcnt;
787
788 ASSERT(tpm != NULL);
789
790 /*
791 * Spec says timeout should be TIMEOUT_D
792 * burst count is TPM_STS bits 8..23
793 */
794 stop = ddi_get_lbolt() + tpm->timeout_d;
795 do {
796 /*
797 * burstcnt is stored as a little endian value
798 * 'ntohs' doesn't work since the value is not word-aligned
799 */
800 burstcnt = tpm_get8(tpm, TPM_STS + 1);
801 burstcnt += tpm_get8(tpm, TPM_STS + 2) << 8;
802
803 if (burstcnt)
804 return (burstcnt);
805
806 delay(tpm->timeout_poll);
807 } while (ddi_get_lbolt() < stop);
808
809 return (0);
810 }
811
812 /*
813 * Writing 1 to TPM_STS_CMD_READY bit in TPM_STS will do the following:
814 * 1. The TPM will clears IO buffers if any
815 * 2. The TPM will enters either Idle or Ready state within TIMEOUT_B
816 * (checked in the calling function)
817 */
818 static void
tpm_set_ready(tpm_state_t * tpm)819 tpm_set_ready(tpm_state_t *tpm)
820 {
821 tpm_put8(tpm, TPM_STS, TPM_STS_CMD_READY);
822 }
823
824 static int
receive_data(tpm_state_t * tpm,uint8_t * buf,size_t bufsiz)825 receive_data(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz)
826 {
827 int size = 0;
828 int retried = 0;
829 uint8_t stsbits;
830
831 /* A number of consecutive bytes that can be written to TPM */
832 uint16_t burstcnt;
833
834 ASSERT(tpm != NULL && buf != NULL);
835 retry:
836 while (size < bufsiz && (tpm_wait_for_stat(tpm,
837 (TPM_STS_DATA_AVAIL|TPM_STS_VALID),
838 tpm->timeout_c) == DDI_SUCCESS)) {
839 /*
840 * Burstcount should be available within TIMEOUT_D
841 * after STS is set to valid
842 * burstcount is dynamic, so have to get it each time
843 */
844 burstcnt = tpm_get_burstcount(tpm);
845 for (; burstcnt > 0 && size < bufsiz; burstcnt--) {
846 buf[size++] = tpm_get8(tpm, TPM_DATA_FIFO);
847 }
848 }
849 stsbits = tis_get_status(tpm);
850 /* check to see if we need to retry (just once) */
851 if (size < bufsiz && !(stsbits & TPM_STS_DATA_AVAIL) && retried == 0) {
852 /* issue responseRetry (TIS 1.2 pg 54) */
853 tpm_put8(tpm, TPM_STS, TPM_STS_RESPONSE_RETRY);
854 /* update the retry counter so we only retry once */
855 retried++;
856 /* reset the size to 0 and reread the entire response */
857 size = 0;
858 goto retry;
859 }
860 return (size);
861 }
862
863 /* Receive the data from the TPM */
864 static int
tis_recv_data(tpm_state_t * tpm,uint8_t * buf,size_t bufsiz)865 tis_recv_data(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz)
866 {
867 int ret;
868 int size = 0;
869 uint32_t expected, status;
870 uint32_t cmdresult;
871
872 ASSERT(tpm != NULL && buf != NULL);
873
874 if (bufsiz < TPM_HEADER_SIZE) {
875 /* There should be at least tag, paramsize, return code */
876 #ifdef DEBUG
877 cmn_err(CE_WARN, "!%s: received data should contain at least "
878 "the header which is %d bytes long",
879 __func__, TPM_HEADER_SIZE);
880 #endif
881 goto OUT;
882 }
883
884 /* Read tag(2 bytes), paramsize(4), and result(4) */
885 size = receive_data(tpm, buf, TPM_HEADER_SIZE);
886 if (size < TPM_HEADER_SIZE) {
887 #ifdef DEBUG
888 cmn_err(CE_WARN, "!%s: recv TPM_HEADER failed, size = %d",
889 __func__, size);
890 #endif
891 goto OUT;
892 }
893
894 cmdresult = load32(buf, TPM_RETURN_OFFSET);
895
896 /* Get 'paramsize'(4 bytes)--it includes tag and paramsize */
897 expected = load32(buf, TPM_PARAMSIZE_OFFSET);
898 if (expected > bufsiz) {
899 #ifdef DEBUG
900 cmn_err(CE_WARN, "!%s: paramSize is bigger "
901 "than the requested size: paramSize=%d bufsiz=%d result=%d",
902 __func__, (int)expected, (int)bufsiz, cmdresult);
903 #endif
904 goto OUT;
905 }
906
907 /* Read in the rest of the data from the TPM */
908 size += receive_data(tpm, (uint8_t *)&buf[TPM_HEADER_SIZE],
909 expected - TPM_HEADER_SIZE);
910 if (size < expected) {
911 #ifdef DEBUG
912 cmn_err(CE_WARN, "!%s: received data length (%d) "
913 "is less than expected (%d)", __func__, size, expected);
914 #endif
915 goto OUT;
916 }
917
918 /* The TPM MUST set the state to stsValid within TIMEOUT_C */
919 ret = tpm_wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c);
920
921 status = tis_get_status(tpm);
922 if (ret != DDI_SUCCESS) {
923 #ifdef DEBUG
924 cmn_err(CE_WARN, "!%s: TPM didn't set stsValid after its I/O: "
925 "status = 0x%08X", __func__, status);
926 #endif
927 goto OUT;
928 }
929
930 /* There is still more data? */
931 if (status & TPM_STS_DATA_AVAIL) {
932 #ifdef DEBUG
933 cmn_err(CE_WARN, "!%s: TPM_STS_DATA_AVAIL is set:0x%08X",
934 __func__, status);
935 #endif
936 goto OUT;
937 }
938
939 /*
940 * Release the control of the TPM after we are done with it
941 * it...so others can also get a chance to send data
942 */
943 tis_release_locality(tpm, tpm->locality, 0);
944
945 OUT:
946 tpm_set_ready(tpm);
947 tis_release_locality(tpm, tpm->locality, 0);
948 return (size);
949 }
950
951 /*
952 * Send the data (TPM commands) to the Data IO register
953 */
954 static int
tis_send_data(tpm_state_t * tpm,uint8_t * buf,size_t bufsiz)955 tis_send_data(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz)
956 {
957 int ret;
958 uint8_t status;
959 uint16_t burstcnt;
960 uint32_t ordinal;
961 size_t count = 0;
962
963 ASSERT(tpm != NULL && buf != NULL);
964
965 if (bufsiz == 0) {
966 #ifdef DEBUG
967 cmn_err(CE_WARN, "!%s: bufsiz arg is zero", __func__);
968 #endif
969 return (DDI_FAILURE);
970 }
971
972 /* Put the TPM in ready state */
973 status = tis_get_status(tpm);
974
975 if (!(status & TPM_STS_CMD_READY)) {
976 tpm_set_ready(tpm);
977 ret = tpm_wait_for_stat(tpm, TPM_STS_CMD_READY, tpm->timeout_b);
978 if (ret != DDI_SUCCESS) {
979 #ifdef DEBUG
980 cmn_err(CE_WARN, "!%s: could not put the TPM "
981 "in the command ready state:"
982 "tpm_wait_for_stat returned error",
983 __func__);
984 #endif
985 goto FAIL;
986 }
987 }
988
989 /*
990 * Now we are ready to send command
991 * TPM's burstcount dictates how many bytes we can write at a time
992 * Burstcount is dynamic if INTF_CAPABILITY for static burstcount is
993 * not set.
994 */
995 while (count < bufsiz - 1) {
996 burstcnt = tpm_get_burstcount(tpm);
997 if (burstcnt == 0) {
998 #ifdef DEBUG
999 cmn_err(CE_WARN, "!%s: tpm_get_burstcnt returned error",
1000 __func__);
1001 #endif
1002 ret = DDI_FAILURE;
1003 goto FAIL;
1004 }
1005
1006 for (; burstcnt > 0 && count < bufsiz - 1; burstcnt--) {
1007 tpm_put8(tpm, TPM_DATA_FIFO, buf[count]);
1008 count++;
1009 }
1010 /* Wait for TPM to indicate that it is ready for more data */
1011 ret = tpm_wait_for_stat(tpm,
1012 (TPM_STS_VALID | TPM_STS_DATA_EXPECT), tpm->timeout_c);
1013 if (ret != DDI_SUCCESS) {
1014 #ifdef DEBUG
1015 cmn_err(CE_WARN, "!%s: TPM didn't enter STS_VALID "
1016 "state", __func__);
1017 #endif
1018 goto FAIL;
1019 }
1020 }
1021 /* We can't exit the loop above unless we wrote bufsiz-1 bytes */
1022
1023 /* Write last byte */
1024 tpm_put8(tpm, TPM_DATA_FIFO, buf[count]);
1025 count++;
1026
1027 /* Wait for the TPM to enter Valid State */
1028 ret = tpm_wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c);
1029 if (ret == DDI_FAILURE) {
1030 #ifdef DEBUG
1031 cmn_err(CE_WARN, "!%s: tpm didn't enter STS_VALID state",
1032 __func__);
1033 #endif
1034 goto FAIL;
1035 }
1036
1037 status = tis_get_status(tpm);
1038 /* The TPM should NOT be expecing more data at this point */
1039 if ((status & TPM_STS_DATA_EXPECT) != 0) {
1040 #ifdef DEBUG
1041 cmn_err(CE_WARN, "!%s: DATA_EXPECT should not be set after "
1042 "writing the last byte: status=0x%08X", __func__, status);
1043 #endif
1044 ret = DDI_FAILURE;
1045 goto FAIL;
1046 }
1047
1048 /*
1049 * Final step: Writing TPM_STS_GO to TPM_STS
1050 * register will actually send the command.
1051 */
1052 tpm_put8(tpm, TPM_STS, TPM_STS_GO);
1053
1054 /* Ordinal/Command_code is located in buf[6..9] */
1055 ordinal = load32(buf, TPM_COMMAND_CODE_OFFSET);
1056
1057 ret = tpm_wait_for_stat(tpm, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
1058 tpm_get_ordinal_duration(tpm, ordinal));
1059 if (ret == DDI_FAILURE) {
1060 #ifdef DEBUG
1061 status = tis_get_status(tpm);
1062 if (!(status & TPM_STS_DATA_AVAIL) ||
1063 !(status & TPM_STS_VALID)) {
1064 cmn_err(CE_WARN, "!%s: TPM not ready or valid "
1065 "(ordinal = %d timeout = %ld status = 0x%0x)",
1066 __func__, ordinal,
1067 tpm_get_ordinal_duration(tpm, ordinal),
1068 status);
1069 } else {
1070 cmn_err(CE_WARN, "!%s: tpm_wait_for_stat "
1071 "(DATA_AVAIL | VALID) failed status = 0x%0X",
1072 __func__, status);
1073 }
1074 #endif
1075 goto FAIL;
1076 }
1077 return (DDI_SUCCESS);
1078
1079 FAIL:
1080 tpm_set_ready(tpm);
1081 tis_release_locality(tpm, tpm->locality, 0);
1082 return (ret);
1083 }
1084
1085 /*
1086 * Clear XrequestUse and Xactivelocality, where X is the current locality
1087 */
1088 static void
tis_release_locality(tpm_state_t * tpm,char locality,int force)1089 tis_release_locality(tpm_state_t *tpm, char locality, int force)
1090 {
1091 ASSERT(tpm != NULL && locality >= 0 && locality < 5);
1092
1093 if (force ||
1094 (tpm_get8(tpm, TPM_ACCESS) &
1095 (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
1096 (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) {
1097 /*
1098 * Writing 1 to active locality bit in TPM_ACCESS
1099 * register reliquishes the control of the locality
1100 */
1101 tpm_put8(tpm, TPM_ACCESS, TPM_ACCESS_ACTIVE_LOCALITY);
1102 }
1103 }
1104
1105 /*
1106 * Checks whether the given locality is active
1107 * Use TPM_ACCESS register and the masks TPM_ACCESS_VALID,TPM_ACTIVE_LOCALITY
1108 */
1109 static int
tis_check_active_locality(tpm_state_t * tpm,char locality)1110 tis_check_active_locality(tpm_state_t *tpm, char locality)
1111 {
1112 uint8_t access_bits;
1113 uint8_t old_locality;
1114
1115 ASSERT(tpm != NULL && locality >= 0 && locality < 5);
1116
1117 old_locality = tpm->locality;
1118 tpm->locality = locality;
1119
1120 /* Just check to see if the requested locality works */
1121 access_bits = tpm_get8(tpm, TPM_ACCESS);
1122 access_bits &= (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID);
1123
1124 /* this was just a check, not a request to switch */
1125 tpm->locality = old_locality;
1126
1127 if (access_bits == (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
1128 return (DDI_SUCCESS);
1129 } else {
1130 return (DDI_FAILURE);
1131 }
1132 }
1133
1134 /* Request the TPM to be in the given locality */
1135 static int
tis_request_locality(tpm_state_t * tpm,char locality)1136 tis_request_locality(tpm_state_t *tpm, char locality)
1137 {
1138 clock_t timeout;
1139 int ret;
1140
1141 ASSERT(tpm != NULL && locality >= 0 && locality < 5);
1142
1143 ret = tis_check_active_locality(tpm, locality);
1144
1145 if (ret == DDI_SUCCESS) {
1146 /* Locality is already active */
1147 tpm->locality = locality;
1148 return (DDI_SUCCESS);
1149 }
1150
1151 tpm_put8(tpm, TPM_ACCESS, TPM_ACCESS_REQUEST_USE);
1152 timeout = ddi_get_lbolt() + tpm->timeout_a;
1153
1154 /* Using polling */
1155 while (tis_check_active_locality(tpm, locality) != DDI_SUCCESS) {
1156 if (ddi_get_lbolt() >= timeout) {
1157 #ifdef DEBUG
1158 cmn_err(CE_WARN, "!%s: (interrupt-disabled) "
1159 "tis_request_locality timed out (timeout_a = %ld)",
1160 __func__, tpm->timeout_a);
1161 #endif
1162 return (DDI_FAILURE);
1163 }
1164 delay(tpm->timeout_poll);
1165 }
1166
1167 tpm->locality = locality;
1168 return (DDI_SUCCESS);
1169 }
1170
1171 /* Read the status register */
1172 static uint8_t
tis_get_status(tpm_state_t * tpm)1173 tis_get_status(tpm_state_t *tpm)
1174 {
1175 return (tpm_get8(tpm, TPM_STS));
1176 }
1177
1178 static int
tpm_wait_for_stat(tpm_state_t * tpm,uint8_t mask,clock_t timeout)1179 tpm_wait_for_stat(tpm_state_t *tpm, uint8_t mask, clock_t timeout)
1180 {
1181 clock_t absolute_timeout = ddi_get_lbolt() + timeout;
1182
1183 /* Using polling */
1184 while ((tis_get_status(tpm) & mask) != mask) {
1185 if (ddi_get_lbolt() >= absolute_timeout) {
1186 /* Timeout reached */
1187 #ifdef DEBUG
1188 cmn_err(CE_WARN, "!%s: using "
1189 "polling - reached timeout (%ld usecs)",
1190 __func__, drv_hztousec(timeout));
1191 #endif
1192 return (DDI_FAILURE);
1193 }
1194 delay(tpm->timeout_poll);
1195 }
1196 return (DDI_SUCCESS);
1197 }
1198
1199 /*
1200 * Initialize TPM device
1201 * 1. Find out supported interrupt capabilities
1202 * 2. Set up interrupt handler if supported (some BIOSes don't support
1203 * interrupts for TPMS, in which case we set up polling)
1204 * 3. Determine timeouts and commands duration
1205 */
1206 static int
tis_init(tpm_state_t * tpm)1207 tis_init(tpm_state_t *tpm)
1208 {
1209 uint32_t intf_caps;
1210 int ret;
1211
1212 /*
1213 * Temporarily set up timeouts before we get the real timeouts
1214 * by issuing TPM_CAP commands (but to issue TPM_CAP commands,
1215 * you need TIMEOUTs defined...chicken and egg problem here.
1216 * TPM timeouts: Convert the milliseconds to clock cycles
1217 */
1218 tpm->timeout_a = drv_usectohz(TIS_TIMEOUT_A);
1219 tpm->timeout_b = drv_usectohz(TIS_TIMEOUT_B);
1220 tpm->timeout_c = drv_usectohz(TIS_TIMEOUT_C);
1221 tpm->timeout_d = drv_usectohz(TIS_TIMEOUT_D);
1222 /*
1223 * Do the same with the duration (real duration will be filled out
1224 * when we call TPM_GetCapability to get the duration values from
1225 * the TPM itself).
1226 */
1227 tpm->duration[TPM_SHORT] = drv_usectohz(TPM_DEFAULT_DURATION);
1228 tpm->duration[TPM_MEDIUM] = drv_usectohz(TPM_DEFAULT_DURATION);
1229 tpm->duration[TPM_LONG] = drv_usectohz(TPM_DEFAULT_DURATION);
1230 tpm->duration[TPM_UNDEFINED] = drv_usectohz(TPM_DEFAULT_DURATION);
1231
1232 /* Find out supported capabilities */
1233 intf_caps = tpm_get32(tpm, TPM_INTF_CAP);
1234
1235 /* Upper 3 bytes should always return 0 */
1236 if (intf_caps & 0x7FFFFF00) {
1237 cmn_err(CE_WARN, "!%s: bad intf_caps value 0x%0X",
1238 __func__, intf_caps);
1239 return (DDI_FAILURE);
1240 }
1241
1242 /* These two interrupts are mandatory */
1243 if (!(intf_caps & TPM_INTF_INT_LOCALITY_CHANGE_INT)) {
1244 cmn_err(CE_WARN,
1245 "!%s: Mandatory capability Locality Change Int "
1246 "not supported", __func__);
1247 return (DDI_FAILURE);
1248 }
1249 if (!(intf_caps & TPM_INTF_INT_DATA_AVAIL_INT)) {
1250 cmn_err(CE_WARN, "!%s: Mandatory capability Data Available Int "
1251 "not supported.", __func__);
1252 return (DDI_FAILURE);
1253 }
1254
1255 /*
1256 * Before we start writing anything to TPM's registers,
1257 * make sure we are in locality 0
1258 */
1259 ret = tis_request_locality(tpm, DEFAULT_LOCALITY);
1260 if (ret != DDI_SUCCESS) {
1261 cmn_err(CE_WARN, "!%s: Unable to request locality %d", __func__,
1262 DEFAULT_LOCALITY);
1263 return (DDI_FAILURE);
1264 } /* Now we can refer to the locality as tpm->locality */
1265
1266 tpm->timeout_poll = drv_usectohz(TPM_POLLING_TIMEOUT);
1267 tpm->intr_enabled = 0;
1268
1269 /* Get the real timeouts from the TPM */
1270 ret = tpm_get_timeouts(tpm);
1271 if (ret != DDI_SUCCESS) {
1272 cmn_err(CE_WARN, "!%s: tpm_get_timeouts error", __func__);
1273 return (DDI_FAILURE);
1274 }
1275
1276 ret = tpm_get_duration(tpm);
1277 if (ret != DDI_SUCCESS) {
1278 cmn_err(CE_WARN, "!%s: tpm_get_duration error", __func__);
1279 return (DDI_FAILURE);
1280 }
1281
1282 /* This gets the TPM version information */
1283 ret = tpm_get_version(tpm);
1284 if (ret != DDI_SUCCESS) {
1285 cmn_err(CE_WARN, "!%s: tpm_get_version error", __func__);
1286 return (DDI_FAILURE);
1287 }
1288
1289 /*
1290 * Unless the TPM completes the test of its commands,
1291 * it can return an error when the untested commands are called
1292 */
1293 ret = tpm_continue_selftest(tpm);
1294 if (ret != DDI_SUCCESS) {
1295 cmn_err(CE_WARN, "!%s: tpm_continue_selftest error", __func__);
1296 return (DDI_FAILURE);
1297 }
1298 return (DDI_SUCCESS);
1299 }
1300
1301 /*
1302 * Module Entry points
1303 */
1304 int
_init(void)1305 _init(void)
1306 {
1307 int ret;
1308
1309 ret = ddi_soft_state_init(&statep, sizeof (tpm_state_t), 1);
1310 if (ret) {
1311 #ifdef DEBUG
1312 cmn_err(CE_WARN, "!ddi_soft_state_init failed: %d", ret);
1313 #endif
1314 return (ret);
1315 }
1316 ret = mod_install(&tpm_ml);
1317 if (ret != 0) {
1318 #ifdef DEBUG
1319 cmn_err(CE_WARN, "!_init: mod_install returned non-zero");
1320 #endif
1321 ddi_soft_state_fini(&statep);
1322 return (ret);
1323 }
1324
1325 return (ret);
1326 }
1327
1328 int
_info(struct modinfo * modinfop)1329 _info(struct modinfo *modinfop)
1330 {
1331 int ret;
1332 ret = mod_info(&tpm_ml, modinfop);
1333 #ifdef DEBUG
1334 if (ret == 0)
1335 cmn_err(CE_WARN, "!mod_info failed: %d", ret);
1336 #endif
1337
1338 return (ret);
1339 }
1340
1341 int
_fini()1342 _fini()
1343 {
1344 int ret;
1345
1346 ret = mod_remove(&tpm_ml);
1347 if (ret != 0)
1348 return (ret);
1349
1350 ddi_soft_state_fini(&statep);
1351
1352 return (ret);
1353 }
1354 /* End of driver configuration functions */
1355
1356 static int
tpm_resume(tpm_state_t * tpm)1357 tpm_resume(tpm_state_t *tpm)
1358 {
1359 mutex_enter(&tpm->pm_mutex);
1360 if (!tpm->suspended) {
1361 mutex_exit(&tpm->pm_mutex);
1362 return (DDI_FAILURE);
1363 }
1364 tpm->suspended = 0;
1365 cv_broadcast(&tpm->suspend_cv);
1366 mutex_exit(&tpm->pm_mutex);
1367
1368 return (DDI_SUCCESS);
1369 }
1370
1371 #ifdef sun4v
1372 static uint64_t hsvc_tpm_minor = 0;
1373 static hsvc_info_t hsvc_tpm = {
1374 HSVC_REV_1, NULL, HSVC_GROUP_TPM, 1, 0, NULL
1375 };
1376 #endif
1377
1378 /*
1379 * Sun DDI/DDK entry points
1380 */
1381 static int
tpm_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)1382 tpm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1383 {
1384 int ret;
1385 int instance;
1386 #ifndef sun4v
1387 int idx, nregs;
1388 #endif
1389 tpm_state_t *tpm = NULL;
1390
1391 ASSERT(dip != NULL);
1392
1393 instance = ddi_get_instance(dip);
1394 if (instance < 0)
1395 return (DDI_FAILURE);
1396
1397 /* Nothing out of ordinary here */
1398 switch (cmd) {
1399 case DDI_ATTACH:
1400 if (ddi_soft_state_zalloc(statep, instance) == DDI_SUCCESS) {
1401 tpm = ddi_get_soft_state(statep, instance);
1402 if (tpm == NULL) {
1403 #ifdef DEBUG
1404 cmn_err(CE_WARN,
1405 "!%s: cannot get state information.",
1406 __func__);
1407 #endif
1408 return (DDI_FAILURE);
1409 }
1410 tpm->dip = dip;
1411 } else {
1412 #ifdef DEBUG
1413 cmn_err(CE_WARN,
1414 "!%s: cannot allocate state information.",
1415 __func__);
1416 #endif
1417 return (DDI_FAILURE);
1418 }
1419 break;
1420 case DDI_RESUME:
1421 tpm = ddi_get_soft_state(statep, instance);
1422 if (tpm == NULL) {
1423 #ifdef DEBUG
1424 cmn_err(CE_WARN, "!%s: cannot get state information.",
1425 __func__);
1426 #endif
1427 return (DDI_FAILURE);
1428 }
1429 return (tpm_resume(tpm));
1430 default:
1431 #ifdef DEBUG
1432 cmn_err(CE_WARN, "!%s: cmd %d is not implemented", __func__,
1433 cmd);
1434 #endif
1435 ret = DDI_FAILURE;
1436 goto FAIL;
1437 }
1438
1439 /* Zeroize the flag, which is used to keep track of what is allocated */
1440 tpm->flags = 0;
1441
1442 #ifdef sun4v
1443 ret = hsvc_register(&hsvc_tpm, &hsvc_tpm_minor);
1444 if (ret != 0) {
1445 cmn_err(CE_WARN, "!%s: failed to register with "
1446 "hypervisor: 0x%0x", __func__, ret);
1447 goto FAIL;
1448 }
1449 tpm->flags |= TPM_HSVC_REGISTERED;
1450 #else
1451 tpm->accattr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
1452 tpm->accattr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
1453 tpm->accattr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1454
1455 idx = 0;
1456 ret = ddi_dev_nregs(tpm->dip, &nregs);
1457 if (ret != DDI_SUCCESS)
1458 goto FAIL;
1459
1460 /*
1461 * TPM vendors put the TPM registers in different
1462 * slots in their register lists. They are not always
1463 * the 1st set of registers, for instance.
1464 * Loop until we find the set that matches the expected
1465 * register size (0x5000).
1466 */
1467 for (idx = 0; idx < nregs; idx++) {
1468 off_t regsize;
1469
1470 if ((ret = ddi_dev_regsize(tpm->dip, idx, ®size)) !=
1471 DDI_SUCCESS)
1472 goto FAIL;
1473 /* The TIS spec says the TPM registers must be 0x5000 bytes */
1474 if (regsize == 0x5000)
1475 break;
1476 }
1477 if (idx == nregs) {
1478 ret = DDI_FAILURE;
1479 goto FAIL;
1480 }
1481
1482 ret = ddi_regs_map_setup(tpm->dip, idx, (caddr_t *)&tpm->addr,
1483 (offset_t)0, (offset_t)0x5000,
1484 &tpm->accattr, &tpm->handle);
1485
1486 if (ret != DDI_SUCCESS) {
1487 goto FAIL;
1488 }
1489 tpm->flags |= TPM_DIDREGSMAP;
1490 #endif
1491 /* Enable TPM device according to the TIS specification */
1492 ret = tis_init(tpm);
1493 if (ret != DDI_SUCCESS) {
1494 #ifdef DEBUG
1495 cmn_err(CE_WARN, "!%s: tis_init() failed with error %d",
1496 __func__, ret);
1497 #endif
1498
1499 /* We need to clean up the ddi_regs_map_setup call */
1500 if (tpm->flags & TPM_DIDREGSMAP) {
1501 ddi_regs_map_free(&tpm->handle);
1502 tpm->handle = NULL;
1503 tpm->flags &= ~TPM_DIDREGSMAP;
1504 }
1505 goto FAIL;
1506 }
1507
1508 /* Initialize the inter-process lock */
1509 mutex_init(&tpm->dev_lock, NULL, MUTEX_DRIVER, NULL);
1510 mutex_init(&tpm->pm_mutex, NULL, MUTEX_DRIVER, NULL);
1511 cv_init(&tpm->suspend_cv, NULL, CV_DRIVER, NULL);
1512
1513 /* Set the suspend/resume property */
1514 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
1515 "pm-hardware-state", "needs-suspend-resume");
1516
1517 mutex_enter(&tpm->pm_mutex);
1518 tpm->suspended = 0;
1519 mutex_exit(&tpm->pm_mutex);
1520
1521 tpm->flags |= TPM_DID_MUTEX;
1522
1523 /* Initialize the buffer and the lock associated with it */
1524 tpm->bufsize = TPM_IO_BUF_SIZE;
1525 tpm->iobuf = kmem_zalloc((sizeof (uint8_t))*(tpm->bufsize), KM_SLEEP);
1526 tpm->flags |= TPM_DID_IO_ALLOC;
1527
1528 mutex_init(&tpm->iobuf_lock, NULL, MUTEX_DRIVER, NULL);
1529 tpm->flags |= TPM_DID_IO_MUTEX;
1530
1531 cv_init(&tpm->iobuf_cv, NULL, CV_DRIVER, NULL);
1532 tpm->flags |= TPM_DID_IO_CV;
1533
1534 /* Create minor node */
1535 ret = ddi_create_minor_node(dip, "tpm", S_IFCHR, ddi_get_instance(dip),
1536 DDI_PSEUDO, 0);
1537 if (ret != DDI_SUCCESS) {
1538 #ifdef DEBUG
1539 cmn_err(CE_WARN, "!%s: ddi_create_minor_node failed", __func__);
1540 #endif
1541 goto FAIL;
1542 }
1543 tpm->flags |= TPM_DIDMINOR;
1544
1545 #ifdef KCF_TPM_RNG_PROVIDER
1546 /* register RNG with kcf */
1547 if (tpmrng_register(tpm) != DDI_SUCCESS)
1548 cmn_err(CE_WARN, "!%s: tpm RNG failed to register with kcf",
1549 __func__);
1550 #endif
1551
1552 return (DDI_SUCCESS);
1553 FAIL:
1554 if (tpm != NULL) {
1555 tpm_cleanup(dip, tpm);
1556 ddi_soft_state_free(statep, instance);
1557 tpm = NULL;
1558 }
1559
1560 return (DDI_FAILURE);
1561 }
1562
1563 /*
1564 * Called by tpm_detach and tpm_attach (only on failure)
1565 * Free up the resources that are allocated
1566 */
1567 static void
tpm_cleanup(dev_info_t * dip,tpm_state_t * tpm)1568 tpm_cleanup(dev_info_t *dip, tpm_state_t *tpm)
1569 {
1570 if (tpm == NULL)
1571 return;
1572
1573 #ifdef KCF_TPM_RNG_PROVIDER
1574 (void) tpmrng_unregister(tpm);
1575 #endif
1576
1577 #ifdef sun4v
1578 if (tpm->flags & TPM_HSVC_REGISTERED) {
1579 (void) hsvc_unregister(&hsvc_tpm);
1580 tpm->flags &= ~(TPM_HSVC_REGISTERED);
1581 }
1582 #endif
1583 if (tpm->flags & TPM_DID_MUTEX) {
1584 mutex_destroy(&tpm->dev_lock);
1585 mutex_destroy(&tpm->pm_mutex);
1586 cv_destroy(&tpm->suspend_cv);
1587 tpm->flags &= ~(TPM_DID_MUTEX);
1588 }
1589 if (tpm->flags & TPM_DID_IO_ALLOC) {
1590 ASSERT(tpm->iobuf != NULL);
1591 kmem_free(tpm->iobuf, (sizeof (uint8_t))*(tpm->bufsize));
1592 tpm->flags &= ~(TPM_DID_IO_ALLOC);
1593 }
1594 if (tpm->flags & TPM_DID_IO_MUTEX) {
1595 mutex_destroy(&tpm->iobuf_lock);
1596 tpm->flags &= ~(TPM_DID_IO_MUTEX);
1597 }
1598 if (tpm->flags & TPM_DID_IO_CV) {
1599 cv_destroy(&tpm->iobuf_cv);
1600 tpm->flags &= ~(TPM_DID_IO_CV);
1601 }
1602 if (tpm->flags & TPM_DIDREGSMAP) {
1603 /* Free the mapped addresses */
1604 if (tpm->handle != NULL)
1605 ddi_regs_map_free(&tpm->handle);
1606 tpm->flags &= ~(TPM_DIDREGSMAP);
1607 }
1608 if (tpm->flags & TPM_DIDMINOR) {
1609 /* Remove minor node */
1610 ddi_remove_minor_node(dip, NULL);
1611 tpm->flags &= ~(TPM_DIDMINOR);
1612 }
1613 }
1614
1615 static int
tpm_suspend(tpm_state_t * tpm)1616 tpm_suspend(tpm_state_t *tpm)
1617 {
1618 if (tpm == NULL)
1619 return (DDI_FAILURE);
1620 mutex_enter(&tpm->pm_mutex);
1621 if (tpm->suspended) {
1622 mutex_exit(&tpm->pm_mutex);
1623 return (DDI_SUCCESS);
1624 }
1625 tpm->suspended = 1;
1626 mutex_exit(&tpm->pm_mutex);
1627
1628 return (DDI_SUCCESS);
1629 }
1630
1631 static int
tpm_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)1632 tpm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1633 {
1634 int instance;
1635 tpm_state_t *tpm;
1636
1637 ASSERT(dip != NULL);
1638
1639 instance = ddi_get_instance(dip);
1640 if (instance < 0)
1641 return (DDI_FAILURE);
1642
1643 if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
1644 #ifdef DEBUG
1645 cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL",
1646 __func__);
1647 #endif
1648 return (ENXIO);
1649 }
1650
1651 switch (cmd) {
1652 case DDI_DETACH:
1653 /* Body is after the switch stmt */
1654 break;
1655 case DDI_SUSPEND:
1656 return (tpm_suspend(tpm));
1657 default:
1658 #ifdef DEBUG
1659 cmn_err(CE_WARN, "!%s: case %d not implemented", __func__, cmd);
1660 #endif
1661 return (DDI_FAILURE);
1662 }
1663
1664 /* Since we are freeing tpm structure, we need to gain the lock */
1665 tpm_cleanup(dip, tpm);
1666
1667 /* Free the soft state */
1668 ddi_soft_state_free(statep, instance);
1669 tpm = NULL;
1670
1671 return (DDI_SUCCESS);
1672 }
1673
1674 /*ARGSUSED*/
1675 static int
tpm_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** resultp)1676 tpm_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
1677 {
1678 int instance;
1679 tpm_state_t *tpm;
1680
1681 instance = ddi_get_instance(dip);
1682 if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
1683 #ifdef DEBUG
1684 cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL",
1685 __func__);
1686 #endif
1687 return (DDI_FAILURE);
1688 }
1689
1690 switch (cmd) {
1691 case DDI_INFO_DEVT2DEVINFO:
1692 *resultp = tpm->dip;
1693 break;
1694 case DDI_INFO_DEVT2INSTANCE:
1695 *resultp = 0;
1696 break;
1697 default:
1698 #ifdef DEBUG
1699 cmn_err(CE_WARN, "!%s: cmd %d is not implemented", __func__,
1700 cmd);
1701 #endif
1702 return (DDI_FAILURE);
1703 }
1704 return (DDI_SUCCESS);
1705 }
1706
1707 /*
1708 * Driver entry points
1709 */
1710
1711 /*ARGSUSED*/
1712 static int
tpm_open(dev_t * devp,int flag,int otyp,cred_t * cred)1713 tpm_open(dev_t *devp, int flag, int otyp, cred_t *cred)
1714 {
1715 int instance;
1716 tpm_state_t *tpm;
1717
1718 ASSERT(devp != NULL);
1719
1720 instance = getminor(*devp);
1721 if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
1722 #ifdef DEBUG
1723 cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL",
1724 __func__);
1725 #endif
1726 return (ENXIO);
1727 }
1728 if (otyp != OTYP_CHR) {
1729 #ifdef DEBUG
1730 cmn_err(CE_WARN, "!%s: otyp(%d) != OTYP_CHR(%d)",
1731 __func__, otyp, OTYP_CHR);
1732 #endif
1733 return (EINVAL);
1734 }
1735 TPM_EXCLUSIVE_LOCK(tpm);
1736
1737 mutex_enter(&tpm->dev_lock);
1738 if (tpm->dev_held) {
1739 #ifdef DEBUG
1740 cmn_err(CE_WARN, "!%s: the device is already being used",
1741 __func__);
1742 #endif
1743 mutex_exit(&tpm->dev_lock);
1744 return (EBUSY);
1745 }
1746
1747 /* The device is free so mark it busy */
1748 tpm->dev_held = 1;
1749 mutex_exit(&tpm->dev_lock);
1750
1751 return (0);
1752 }
1753
1754 /*ARGSUSED*/
1755 static int
tpm_close(dev_t dev,int flag,int otyp,cred_t * cred)1756 tpm_close(dev_t dev, int flag, int otyp, cred_t *cred)
1757 {
1758 int instance;
1759 tpm_state_t *tpm;
1760
1761 instance = getminor(dev);
1762 if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
1763 #ifdef DEBUG
1764 cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL",
1765 __func__);
1766 #endif
1767 return (ENXIO);
1768 }
1769 if (otyp != OTYP_CHR) {
1770 #ifdef DEBUG
1771 cmn_err(CE_WARN, "!%s: otyp(%d) != OTYP_CHR(%d)",
1772 __func__, otyp, OTYP_CHR);
1773 #endif
1774 return (EINVAL);
1775 }
1776 TPM_EXCLUSIVE_LOCK(tpm);
1777
1778 ASSERT(tpm->dev_held);
1779
1780 mutex_enter(&tpm->dev_lock);
1781 ASSERT(mutex_owned(&tpm->dev_lock));
1782 tpm->dev_held = 0;
1783 mutex_exit(&tpm->dev_lock);
1784
1785 return (0);
1786 }
1787
1788 /*ARGSUSED*/
1789 static int
tpm_read(dev_t dev,struct uio * uiop,cred_t * credp)1790 tpm_read(dev_t dev, struct uio *uiop, cred_t *credp)
1791 {
1792 int ret;
1793 uint32_t size;
1794 int instance;
1795 tpm_state_t *tpm;
1796
1797 instance = getminor(dev);
1798 if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
1799 #ifdef DEBUG
1800 cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL",
1801 __func__);
1802 #endif
1803 return (ENXIO);
1804 }
1805 if (uiop == NULL) {
1806 #ifdef DEBUG
1807 cmn_err(CE_WARN, "!%s: passed in uiop is NULL", __func__);
1808 #endif
1809 return (EFAULT);
1810 }
1811
1812 TPM_EXCLUSIVE_LOCK(tpm);
1813
1814 /* Receive the data after requiring the lock */
1815 ret = tpm_io_lock(tpm);
1816
1817 /* Timeout reached */
1818 if (ret)
1819 return (ret);
1820
1821 if (uiop->uio_resid > tpm->bufsize) {
1822 #ifdef DEBUG
1823 cmn_err(CE_WARN, "!%s: read_in data is bigger "
1824 "than tpm->bufsize:read in:%d, bufsiz:%d",
1825 __func__, (int)uiop->uio_resid, (int)tpm->bufsize);
1826 #endif
1827 ret = EIO;
1828 goto OUT;
1829 }
1830
1831 ret = tis_recv_data(tpm, tpm->iobuf, tpm->bufsize);
1832 if (ret < TPM_HEADER_SIZE) {
1833 #ifdef DEBUG
1834 cmn_err(CE_WARN, "!%s: tis_recv_data returned error", __func__);
1835 #endif
1836 ret = EIO;
1837 goto OUT;
1838 }
1839
1840 size = load32(tpm->iobuf, 2);
1841 if (ret != size) {
1842 #ifdef DEBUG
1843 cmn_err(CE_WARN, "!%s: tis_recv_data:"
1844 "expected size=%d, actually read=%d",
1845 __func__, size, ret);
1846 #endif
1847 ret = EIO;
1848 goto OUT;
1849 }
1850
1851 /* Send the buffer from the kernel to the userspace */
1852 ret = uiomove(tpm->iobuf, size, UIO_READ, uiop);
1853 if (ret) {
1854 #ifdef DEBUG
1855 cmn_err(CE_WARN, "!%s: uiomove returned error", __func__);
1856 #endif
1857 goto OUT;
1858 }
1859
1860 /* Zeroize the buffer... */
1861 bzero(tpm->iobuf, tpm->bufsize);
1862 ret = DDI_SUCCESS;
1863 OUT:
1864 /* We are done now: wake up the waiting threads */
1865 tpm_unlock(tpm);
1866
1867 return (ret);
1868 }
1869
1870 /*ARGSUSED*/
1871 static int
tpm_write(dev_t dev,struct uio * uiop,cred_t * credp)1872 tpm_write(dev_t dev, struct uio *uiop, cred_t *credp)
1873 {
1874 int ret;
1875 size_t len;
1876 uint32_t size;
1877 int instance;
1878 tpm_state_t *tpm;
1879
1880 instance = getminor(dev);
1881 if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
1882 #ifdef DEBUG
1883 cmn_err(CE_WARN, "!%s: stored pointer to tpm state is NULL",
1884 __func__);
1885 #endif
1886 return (ENXIO);
1887 }
1888
1889 if (uiop == NULL) {
1890 #ifdef DEBUG
1891 cmn_err(CE_WARN, "!%s: passed in uiop is NULL", __func__);
1892 #endif
1893 return (EFAULT);
1894 }
1895
1896 TPM_EXCLUSIVE_LOCK(tpm);
1897
1898 len = uiop->uio_resid;
1899 if (len == 0) {
1900 #ifdef DEBUG
1901 cmn_err(CE_WARN, "!%s: requested read of len 0", __func__);
1902 #endif
1903 return (0);
1904 }
1905
1906 /* Get the lock for using iobuf */
1907 ret = tpm_io_lock(tpm);
1908 /* Timeout Reached */
1909 if (ret)
1910 return (ret);
1911
1912 /* Copy the header and parse the structure to find out the size... */
1913 ret = uiomove(tpm->iobuf, TPM_HEADER_SIZE, UIO_WRITE, uiop);
1914 if (ret) {
1915 #ifdef DEBUG
1916 cmn_err(CE_WARN, "!%s: uiomove returned error"
1917 "while getting the the header",
1918 __func__);
1919 #endif
1920 goto OUT;
1921 }
1922
1923 /* Get the buffersize from the command buffer structure */
1924 size = load32(tpm->iobuf, TPM_PARAMSIZE_OFFSET);
1925
1926 /* Copy the command to the contiguous buffer */
1927 if (size > tpm->bufsize) {
1928 #ifdef DEBUG
1929 cmn_err(CE_WARN, "!%s: size %d is greater than "
1930 "the tpm input buffer size %d",
1931 __func__, (int)size, (int)tpm->bufsize);
1932 #endif
1933 ret = ENXIO;
1934 goto OUT;
1935 }
1936
1937 /* Copy the buffer from the userspace to kernel */
1938 ret = uiomove(tpm->iobuf+TPM_HEADER_SIZE, size-TPM_HEADER_SIZE,
1939 UIO_WRITE, uiop);
1940
1941 if (ret) {
1942 #ifdef DEBUG
1943 cmn_err(CE_WARN, "!%s: uiomove returned error"
1944 "while getting the rest of the command", __func__);
1945 #endif
1946 goto OUT;
1947 }
1948
1949 /* Send the command */
1950 ret = tis_send_data(tpm, tpm->iobuf, size);
1951 if (ret != DDI_SUCCESS) {
1952 #ifdef DEBUG
1953 cmn_err(CE_WARN, "!%s: tis_send_data returned error", __func__);
1954 #endif
1955 ret = EFAULT;
1956 goto OUT;
1957 }
1958
1959 /* Zeroize the buffer... */
1960 bzero(tpm->iobuf, tpm->bufsize);
1961 ret = DDI_SUCCESS;
1962 OUT:
1963 tpm_unlock(tpm);
1964 return (ret);
1965 }
1966
1967 /*
1968 * This is to deal with the contentions for the iobuf
1969 */
1970 static inline int
tpm_io_lock(tpm_state_t * tpm)1971 tpm_io_lock(tpm_state_t *tpm)
1972 {
1973 int ret;
1974 clock_t timeout;
1975
1976 mutex_enter(&tpm->iobuf_lock);
1977 ASSERT(mutex_owned(&tpm->iobuf_lock));
1978
1979 timeout = ddi_get_lbolt() + drv_usectohz(TPM_IO_TIMEOUT);
1980
1981 /* Wait until the iobuf becomes free with the timeout */
1982 while (tpm->iobuf_inuse) {
1983 ret = cv_timedwait(&tpm->iobuf_cv, &tpm->iobuf_lock, timeout);
1984 if (ret <= 0) {
1985 /* Timeout reached */
1986 mutex_exit(&tpm->iobuf_lock);
1987 #ifdef DEBUG
1988 cmn_err(CE_WARN, "!tpm_io_lock:iorequest timed out");
1989 #endif
1990 return (ETIME);
1991 }
1992 }
1993 tpm->iobuf_inuse = 1;
1994 mutex_exit(&tpm->iobuf_lock);
1995 return (0);
1996 }
1997
1998 /*
1999 * This is to deal with the contentions for the iobuf
2000 */
2001 static inline void
tpm_unlock(tpm_state_t * tpm)2002 tpm_unlock(tpm_state_t *tpm)
2003 {
2004 /* Wake up the waiting threads */
2005 mutex_enter(&tpm->iobuf_lock);
2006 ASSERT(tpm->iobuf_inuse == 1 && mutex_owned(&tpm->iobuf_lock));
2007 tpm->iobuf_inuse = 0;
2008 cv_broadcast(&tpm->iobuf_cv);
2009 mutex_exit(&tpm->iobuf_lock);
2010 }
2011
2012 #ifdef KCF_TPM_RNG_PROVIDER
2013 /*
2014 * Random number generator entry points
2015 */
2016 static void
strncpy_spacepad(uchar_t * s1,char * s2,int n)2017 strncpy_spacepad(uchar_t *s1, char *s2, int n)
2018 {
2019 int s2len = strlen(s2);
2020 (void) strncpy((char *)s1, s2, n);
2021 if (s2len < n)
2022 (void) memset(s1 + s2len, ' ', n - s2len);
2023 }
2024
2025 /*ARGSUSED*/
2026 static int
tpmrng_ext_info(crypto_provider_handle_t prov,crypto_provider_ext_info_t * ext_info,crypto_req_handle_t cfreq)2027 tpmrng_ext_info(crypto_provider_handle_t prov,
2028 crypto_provider_ext_info_t *ext_info,
2029 crypto_req_handle_t cfreq)
2030 {
2031 tpm_state_t *tpm = (tpm_state_t *)prov;
2032 char buf[64];
2033
2034 if (tpm == NULL)
2035 return (DDI_FAILURE);
2036
2037 strncpy_spacepad(ext_info->ei_manufacturerID,
2038 (char *)tpm->vers_info.tpmVendorID,
2039 sizeof (ext_info->ei_manufacturerID));
2040
2041 strncpy_spacepad(ext_info->ei_model, "0",
2042 sizeof (ext_info->ei_model));
2043 strncpy_spacepad(ext_info->ei_serial_number, "0",
2044 sizeof (ext_info->ei_serial_number));
2045
2046 ext_info->ei_flags = CRYPTO_EXTF_RNG | CRYPTO_EXTF_SO_PIN_LOCKED;
2047 ext_info->ei_max_session_count = CRYPTO_EFFECTIVELY_INFINITE;
2048 ext_info->ei_max_pin_len = 0;
2049 ext_info->ei_min_pin_len = 0;
2050 ext_info->ei_total_public_memory = CRYPTO_UNAVAILABLE_INFO;
2051 ext_info->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO;
2052 ext_info->ei_total_private_memory = CRYPTO_UNAVAILABLE_INFO;
2053 ext_info->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO;
2054 ext_info->ei_time[0] = 0;
2055
2056 ext_info->ei_hardware_version.cv_major = tpm->vers_info.version.major;
2057 ext_info->ei_hardware_version.cv_minor = tpm->vers_info.version.minor;
2058 ext_info->ei_firmware_version.cv_major =
2059 tpm->vers_info.version.revMajor;
2060 ext_info->ei_firmware_version.cv_minor =
2061 tpm->vers_info.version.revMinor;
2062
2063 (void) snprintf(buf, sizeof (buf), "tpmrng TPM RNG");
2064
2065 strncpy_spacepad(ext_info->ei_label, buf,
2066 sizeof (ext_info->ei_label));
2067 #undef BUFSZ
2068 return (CRYPTO_SUCCESS);
2069
2070 }
2071
2072 static int
tpmrng_register(tpm_state_t * tpm)2073 tpmrng_register(tpm_state_t *tpm)
2074 {
2075 int ret;
2076 char ID[64];
2077 crypto_mech_name_t *rngmech;
2078
2079 ASSERT(tpm != NULL);
2080
2081 (void) snprintf(ID, sizeof (ID), "tpmrng %s", IDENT_TPMRNG);
2082
2083 tpmrng_prov_info.pi_provider_description = ID;
2084 tpmrng_prov_info.pi_provider_dev.pd_hw = tpm->dip;
2085 tpmrng_prov_info.pi_provider_handle = tpm;
2086
2087 ret = crypto_register_provider(&tpmrng_prov_info, &tpm->n_prov);
2088 if (ret != CRYPTO_SUCCESS) {
2089 tpm->n_prov = NULL;
2090 return (DDI_FAILURE);
2091 }
2092
2093 crypto_provider_notification(tpm->n_prov, CRYPTO_PROVIDER_READY);
2094
2095 rngmech = kmem_zalloc(strlen("random") + 1, KM_SLEEP);
2096 (void) memcpy(rngmech, "random", 6);
2097 ret = crypto_load_dev_disabled("tpm", ddi_get_instance(tpm->dip),
2098 1, rngmech);
2099 #ifdef DEBUG
2100 if (ret != CRYPTO_SUCCESS)
2101 cmn_err(CE_WARN, "!crypto_load_dev_disabled failed (%d)", ret);
2102 #endif
2103 return (DDI_SUCCESS);
2104 }
2105
2106 static int
tpmrng_unregister(tpm_state_t * tpm)2107 tpmrng_unregister(tpm_state_t *tpm)
2108 {
2109 int ret;
2110 ASSERT(tpm != NULL);
2111 if (tpm->n_prov) {
2112 ret = crypto_unregister_provider(tpm->n_prov);
2113 tpm->n_prov = NULL;
2114 if (ret != CRYPTO_SUCCESS)
2115 return (DDI_FAILURE);
2116 }
2117 return (DDI_SUCCESS);
2118 }
2119
2120 /*ARGSUSED*/
2121 static void
tpmrng_provider_status(crypto_provider_handle_t provider,uint_t * status)2122 tpmrng_provider_status(crypto_provider_handle_t provider, uint_t *status)
2123 {
2124 *status = CRYPTO_PROVIDER_READY;
2125 }
2126
2127 /*ARGSUSED*/
2128 static int
tpmrng_seed_random(crypto_provider_handle_t provider,crypto_session_id_t sid,uchar_t * buf,size_t len,uint_t entropy_est,uint32_t flags,crypto_req_handle_t req)2129 tpmrng_seed_random(crypto_provider_handle_t provider, crypto_session_id_t sid,
2130 uchar_t *buf, size_t len, uint_t entropy_est, uint32_t flags,
2131 crypto_req_handle_t req)
2132 {
2133 int ret;
2134 tpm_state_t *tpm;
2135 uint32_t len32;
2136 /* Max length of seed is 256 bytes, add 14 for header. */
2137 uint8_t cmdbuf[270] = {
2138 0, 193, /* TPM_TAG_RQU COMMAND */
2139 0, 0, 0, 0x0A, /* paramsize in bytes */
2140 0, 0, 0, TPM_ORD_StirRandom,
2141 0, 0, 0, 0 /* number of input bytes (< 256) */
2142 };
2143 uint32_t buflen;
2144
2145 if (len == 0 || len > 255 || buf == NULL)
2146 return (CRYPTO_ARGUMENTS_BAD);
2147
2148 tpm = (tpm_state_t *)provider;
2149 if (tpm == NULL)
2150 return (CRYPTO_INVALID_CONTEXT);
2151
2152 /* Acquire lock for exclusive use of TPM */
2153 TPM_EXCLUSIVE_LOCK(tpm);
2154
2155 ret = tpm_io_lock(tpm);
2156 /* Timeout reached */
2157 if (ret)
2158 return (CRYPTO_BUSY);
2159
2160 /* TPM only handles 32 bit length, so truncate if too big. */
2161 len32 = (uint32_t)len;
2162 buflen = len32 + 14;
2163
2164 /* The length must be in network order */
2165 buflen = htonl(buflen);
2166 bcopy(&buflen, cmdbuf + 2, sizeof (uint32_t));
2167
2168 /* Convert it back */
2169 buflen = ntohl(buflen);
2170
2171 /* length must be in network order */
2172 len32 = htonl(len32);
2173 bcopy(&len32, cmdbuf + 10, sizeof (uint32_t));
2174
2175 /* convert it back */
2176 len32 = ntohl(len32);
2177
2178 bcopy(buf, cmdbuf + 14, len32);
2179
2180 ret = itpm_command(tpm, cmdbuf, buflen);
2181 tpm_unlock(tpm);
2182
2183 if (ret != DDI_SUCCESS) {
2184 #ifdef DEBUG
2185 cmn_err(CE_WARN, "!tpmrng_seed_random failed");
2186 #endif
2187 return (CRYPTO_FAILED);
2188 }
2189
2190 return (CRYPTO_SUCCESS);
2191 }
2192
2193 /* ARGSUSED */
2194 static int
tpmrng_generate_random(crypto_provider_handle_t provider,crypto_session_id_t sid,uchar_t * buf,size_t len,crypto_req_handle_t req)2195 tpmrng_generate_random(crypto_provider_handle_t provider,
2196 crypto_session_id_t sid, uchar_t *buf, size_t len, crypto_req_handle_t req)
2197 {
2198 int ret;
2199 tpm_state_t *tpm;
2200 uint8_t hdr[14] = {
2201 0, 193, /* TPM_TAG_RQU COMMAND */
2202 0, 0, 0, 14, /* paramsize in bytes */
2203 0, 0, 0, TPM_ORD_GetRandom,
2204 0, 0, 0, 0
2205 };
2206 uint8_t *cmdbuf = NULL;
2207 uint32_t len32 = (uint32_t)len;
2208 uint32_t buflen = len32 + sizeof (hdr);
2209
2210 if (len == 0 || buf == NULL)
2211 return (CRYPTO_ARGUMENTS_BAD);
2212
2213 tpm = (tpm_state_t *)provider;
2214 if (tpm == NULL)
2215 return (CRYPTO_INVALID_CONTEXT);
2216
2217 TPM_EXCLUSIVE_LOCK(tpm);
2218
2219 ret = tpm_io_lock(tpm);
2220 /* Timeout reached */
2221 if (ret)
2222 return (CRYPTO_BUSY);
2223
2224 cmdbuf = kmem_zalloc(buflen, KM_SLEEP);
2225 bcopy(hdr, cmdbuf, sizeof (hdr));
2226
2227 /* Length is written in network byte order */
2228 len32 = htonl(len32);
2229 bcopy(&len32, cmdbuf + 10, sizeof (uint32_t));
2230
2231 ret = itpm_command(tpm, cmdbuf, buflen);
2232 if (ret != DDI_SUCCESS) {
2233 #ifdef DEBUG
2234 cmn_err(CE_WARN, "!tpmrng_generate_random failed");
2235 #endif
2236 kmem_free(cmdbuf, buflen);
2237 tpm_unlock(tpm);
2238 return (CRYPTO_FAILED);
2239 }
2240
2241 /* Find out how many bytes were really returned */
2242 len32 = load32(cmdbuf, 10);
2243
2244 /* Copy the random bytes back to the callers buffer */
2245 bcopy(cmdbuf + 14, buf, len32);
2246
2247 kmem_free(cmdbuf, buflen);
2248 tpm_unlock(tpm);
2249
2250 return (CRYPTO_SUCCESS);
2251 }
2252 #endif /* KCF_TPM_RNG_PROVIDER */
2253