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