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 #include <unistd.h>
  28 #include <stdlib.h>
  29 #include <stdio.h>
  30 #include <strings.h>
  31 #include <fcntl.h>
  32 #include <sys/types.h>
  33 #include <netinet/in.h>
  34 #include <inttypes.h>
  35 #include <sha1.h>
  36 #include <uuid/uuid.h>
  37 #include <sys/stat.h>
  38 #include <libintl.h>
  39 
  40 #include <tss/tss_defines.h>
  41 #include <tss/tspi.h>
  42 
  43 #include "tpmadm.h"
  44 
  45 int cmd_status(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
  46 int cmd_init(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
  47 int cmd_clear(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
  48 int cmd_auth(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
  49 int cmd_keyinfo(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
  50 int cmd_deletekey(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
  51 
  52 cmdtable_t commands[] = {
  53         {"status", "", cmd_status},
  54         {"init", "", cmd_init},
  55         {"clear", "[owner | lock]", cmd_clear},
  56         {"auth", "", cmd_auth},
  57         {"keyinfo", "[uuid]", cmd_keyinfo},
  58         {"deletekey", "uuid", cmd_deletekey},
  59         {NULL, NULL, NULL},
  60 };
  61 
  62 BYTE well_known[] = TSS_WELL_KNOWN_SECRET;
  63 TSS_UUID srk_uuid = TSS_UUID_SRK;
  64 
  65 
  66 /*
  67  * TPM status
  68  */
  69 
  70 static int
  71 print_tpm_version(TSS_HCONTEXT hContext, TSS_HOBJECT hTPM)
  72 {
  73         struct {
  74                 TPM_CAP_VERSION_INFO vers_info;
  75                 char extra[20]; /* vendor extensions */
  76         } info;
  77 
  78         if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_VERSION_VAL,
  79             0, &info, sizeof (info)))
  80                 return (ERR_FAIL);
  81 
  82         (void) printf(gettext("TPM Version: %d.%d (%c%c%c%c Rev: %d.%d, "
  83             "SpecLevel: %d, ErrataRev: %d)\n"),
  84             info.vers_info.version.major,
  85             info.vers_info.version.minor,
  86             info.vers_info.tpmVendorID[0],
  87             info.vers_info.tpmVendorID[1],
  88             info.vers_info.tpmVendorID[2],
  89             info.vers_info.tpmVendorID[3],
  90             info.vers_info.version.revMajor,
  91             info.vers_info.version.revMinor,
  92             (int)ntohs(info.vers_info.specLevel),
  93             info.vers_info.errataRev);
  94 
  95         return (0);
  96 }
  97 
  98 static int
  99 tpm_is_owned(TSS_HCONTEXT hContext, TSS_HOBJECT hTPM)
 100 {
 101         BYTE owned;
 102 
 103         if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
 104             TSS_TPMCAP_PROP_OWNER, &owned, sizeof (owned)))
 105                 return (0);
 106 
 107         return (owned);
 108 }
 109 
 110 static int
 111 print_tpm_resources(TSS_HCONTEXT hContext, TSS_HOBJECT hTPM)
 112 {
 113         UINT32 avail, max;
 114 
 115         (void) printf(gettext("TPM resources\n"));
 116 
 117         if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
 118             TSS_TPMCAP_PROP_MAXCONTEXTS, &max, sizeof (max)))
 119                 return (ERR_FAIL);
 120         if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
 121             TSS_TPMCAP_PROP_CONTEXTS, &avail, sizeof (avail)))
 122                 return (ERR_FAIL);
 123         (void) printf(gettext("\tContexts: %d/%d available\n"), avail, max);
 124 
 125         if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
 126             TSS_TPMCAP_PROP_MAXSESSIONS, &max, sizeof (max)))
 127                 return (ERR_FAIL);
 128         if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
 129             TSS_TPMCAP_PROP_SESSIONS, &avail, sizeof (avail)))
 130                 return (ERR_FAIL);
 131         (void) printf(gettext("\tSessions: %d/%d available\n"), avail, max);
 132 
 133         if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
 134             TSS_TPMCAP_PROP_MAXAUTHSESSIONS, &max, sizeof (max)))
 135                 return (ERR_FAIL);
 136         if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
 137             TSS_TPMCAP_PROP_AUTHSESSIONS, &avail, sizeof (avail)))
 138                 return (ERR_FAIL);
 139         (void) printf(gettext("\tAuth Sessions: %d/%d available\n"),
 140             avail, max);
 141 
 142         if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
 143             TSS_TPMCAP_PROP_MAXKEYS, &max, sizeof (max)))
 144                 return (ERR_FAIL);
 145         if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
 146             TSS_TPMCAP_PROP_KEYS, &avail, sizeof (avail)))
 147                 return (ERR_FAIL);
 148         (void) printf(gettext("\tLoaded Keys: %d/%d available\n"), avail, max);
 149 
 150         return (0);
 151 }
 152 
 153 static int
 154 print_tpm_pcrs(TSS_HCONTEXT hContext, TSS_HOBJECT hTPM)
 155 {
 156         UINT32 num_pcrs;
 157         int i;
 158 
 159         if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
 160             TSS_TPMCAP_PROP_PCR, &num_pcrs, sizeof (num_pcrs)))
 161                 return (ERR_FAIL);
 162         (void) printf(gettext("Platform Configuration Registers (%u)\n"),
 163             num_pcrs);
 164 
 165         /* Print each PCR */
 166         for (i = 0; i < num_pcrs; i++) {
 167                 TSS_RESULT ret;
 168                 UINT32 datalen;
 169                 BYTE *data;
 170 
 171                 ret = Tspi_TPM_PcrRead(hTPM, i, &datalen, &data);
 172                 if (ret) {
 173                         print_error(ret, gettext("Read PCR"));
 174                         return (ret);
 175                 }
 176 
 177                 (void) printf("\tPCR %u:\t", i);
 178                 print_bytes(data, datalen, FALSE);
 179 
 180                 ret = Tspi_Context_FreeMemory(hContext, data);
 181                 if (ret) {
 182                         print_error(ret, gettext("Free PCR memory"));
 183                         return (ret);
 184                 }
 185         }
 186         return (0);
 187 }
 188 
 189 /*ARGSUSED*/
 190 int
 191 cmd_status(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[])
 192 {
 193         if (set_object_policy(hTPM, TSS_SECRET_MODE_POPUP, NULL, 0, NULL))
 194                 return (ERR_FAIL);
 195 
 196         (void) print_tpm_version(hContext, hTPM);
 197         if (tpm_is_owned(hContext, hTPM)) {
 198                 (void) print_tpm_resources(hContext, hTPM);
 199                 (void) print_tpm_pcrs(hContext, hTPM);
 200         } else {
 201                 (void) printf(gettext("No TPM owner installed.\n"));
 202         }
 203 
 204         return (0);
 205 }
 206 
 207 
 208 /*
 209  * Key Information
 210  */
 211 
 212 typedef struct {
 213         UINT32 code;
 214         char *str;
 215 } decode_map_t;
 216 
 217 decode_map_t key_usage[] = {
 218         { TSS_KEYUSAGE_SIGN, "Signing" },
 219         { TSS_KEYUSAGE_STORAGE, "Storage" },
 220         { TSS_KEYUSAGE_IDENTITY, "Identity" },
 221         { TSS_KEYUSAGE_AUTHCHANGE, "Authchange" },
 222         { TSS_KEYUSAGE_BIND, "Bind" },
 223         { TSS_KEYUSAGE_LEGACY, "Legacy" },
 224         { TSS_KEYUSAGE_MIGRATE, "Migrate" },
 225         { 0, NULL },
 226 };
 227 
 228 decode_map_t key_algorithm[] = {
 229         { TSS_ALG_RSA, "RSA" },
 230         { TSS_ALG_DES, "DES" },
 231         { TSS_ALG_3DES, "3-DES" },
 232         { TSS_ALG_SHA, "SHA" },
 233         { TSS_ALG_HMAC, "HMAC" },
 234         { TSS_ALG_AES, "AES" },
 235         { TSS_ALG_MGF1, "MGF1" },
 236         { TSS_ALG_AES192, "AES192" },
 237         { TSS_ALG_AES256, "AES256" },
 238         { TSS_ALG_XOR, "XOR" },
 239         { 0, NULL },
 240 };
 241 
 242 decode_map_t key_sigscheme[] = {
 243         { TSS_SS_NONE, "None" },
 244         { TSS_SS_RSASSAPKCS1V15_SHA1, "RSASSAPKCS1v15_SHA1" },
 245         { TSS_SS_RSASSAPKCS1V15_DER, "RSASSAPKCS1v15_DER" },
 246         { 0, NULL },
 247 };
 248 
 249 decode_map_t key_encscheme[] = {
 250         { TSS_ES_NONE, "None" },
 251         { TSS_ES_RSAESPKCSV15, "RSAESPKCSv15" },
 252         { TSS_ES_RSAESOAEP_SHA1_MGF1, "RSAESOAEP_SHA1_MGF1" },
 253         { TSS_ES_SYM_CNT, "SYM_CNT" },
 254         { TSS_ES_SYM_OFB, "SYM_OFB" },
 255         { 0, NULL },
 256 };
 257 
 258 static char *
 259 decode(decode_map_t *table, UINT32 code)
 260 {
 261         static char buf[20];
 262         int i;
 263 
 264         for (i = 0; table[i].str != NULL; i++) {
 265                 if (table[i].code == code)
 266                         return (table[i].str);
 267         }
 268 
 269         (void) snprintf(buf, sizeof (buf), gettext("Unknown (%u)"), code);
 270         return (buf);
 271 }
 272 
 273 static void
 274 print_key_info(TSS_HCONTEXT hContext, TSS_HOBJECT hKey)
 275 {
 276         TSS_RESULT ret;
 277         UINT32 attrib;
 278         UINT32 keyInfoSize;
 279         BYTE *keyInfo;
 280 
 281         /* Key size */
 282         ret = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
 283             TSS_TSPATTRIB_KEYINFO_SIZE, &attrib);
 284         if (ret) {
 285                 print_error(ret, gettext("Get key size"));
 286         }
 287         (void) printf(gettext("Key Size: %d bits\n"), attrib);
 288 
 289         /* Key usage */
 290         ret = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
 291             TSS_TSPATTRIB_KEYINFO_USAGE, &attrib);
 292         if (ret) {
 293                 print_error(ret, gettext("Get key usage"));
 294         }
 295         (void) printf(gettext("Key Usage: %s\n"), decode(key_usage, attrib));
 296 
 297         /* Algorithm */
 298         ret = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
 299             TSS_TSPATTRIB_KEYINFO_ALGORITHM, &attrib);
 300         if (ret) {
 301                 print_error(ret, gettext("Get key algorithm"));
 302         }
 303         (void) printf(gettext("Algorithm: %s\n"),
 304             decode(key_algorithm, attrib));
 305 
 306         /* Authorization required */
 307         ret = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
 308             TSS_TSPATTRIB_KEYINFO_AUTHUSAGE, &attrib);
 309         if (ret) {
 310                 print_error(ret, gettext("Get key authusage"));
 311         }
 312         (void) printf(gettext("Authorization required: %s\n"),
 313             attrib ? gettext("Yes") : gettext("No"));
 314 
 315         /* Signature scheme */
 316         ret = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
 317             TSS_TSPATTRIB_KEYINFO_SIGSCHEME, &attrib);
 318         if (ret) {
 319                 print_error(ret, gettext("Get key signature scheme"));
 320         }
 321         (void) printf(gettext("Signature scheme: %s\n"),
 322             decode(key_sigscheme, attrib));
 323 
 324         /* Encoding scheme */
 325         ret = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
 326             TSS_TSPATTRIB_KEYINFO_ENCSCHEME, &attrib);
 327         if (ret) {
 328                 print_error(ret, gettext("Get key encoding scheme"));
 329         }
 330         (void) printf(gettext("Encoding scheme: %s\n"),
 331             decode(key_encscheme, attrib));
 332 
 333         /* Key blob */
 334         ret = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB,
 335             TSS_TSPATTRIB_KEYBLOB_BLOB, &keyInfoSize, &keyInfo);
 336         if (ret) {
 337                 print_error(ret, gettext("Get key blob"));
 338         }
 339         (void) printf(gettext("TPM Key Blob:\n"));
 340         print_bytes(keyInfo, keyInfoSize, TRUE);
 341         ret = Tspi_Context_FreeMemory(hContext, keyInfo);
 342         if (ret) {
 343                 print_error(ret, gettext("Free key info buffer"));
 344         }
 345 }
 346 
 347 typedef struct hash_node {
 348         struct hash_node *next, *sibling, *child;
 349         TSS_UUID uuid;
 350         TSS_KM_KEYINFO2 *key_data;
 351 } hash_node_t;
 352 
 353 #define HASHSIZE 17
 354 hash_node_t *hash_table[HASHSIZE];
 355 
 356 static hash_node_t *
 357 hash_insert(TSS_UUID uuid, TSS_KM_KEYINFO2 *key_data)
 358 {
 359         UINT32 i, index = 0;
 360         hash_node_t *node;
 361         char *cp;
 362 
 363         cp = (char *)&uuid;
 364         for (i = 0; i < sizeof (TSS_UUID); i++)
 365                 index += cp[i];
 366         index = index % HASHSIZE;
 367 
 368         for (node = hash_table[index]; node != NULL; node = node->next) {
 369                 if (memcmp(&(node->uuid), &uuid, sizeof (TSS_UUID)) == 0)
 370                         break;
 371         }
 372 
 373         if (node == NULL) {
 374                 node = calloc(1, sizeof (hash_node_t));
 375                 node->uuid = uuid;
 376                 node->next = hash_table[index];
 377                 hash_table[index] = node;
 378         }
 379         if (node->key_data == NULL)
 380                 node->key_data = key_data;
 381 
 382         return (node);
 383 }
 384 
 385 static void
 386 add_child(hash_node_t *parent, hash_node_t *child)
 387 {
 388         hash_node_t *node;
 389 
 390         for (node = parent->child; node != NULL; node = node->next) {
 391                 if (node == child)
 392                         return;
 393         }
 394 
 395         child->sibling = parent->child;
 396         parent->child = child;
 397 }
 398 
 399 static void
 400 print_all(hash_node_t *parent, int indent)
 401 {
 402         char uuidstr[UUID_PRINTABLE_STRING_LENGTH];
 403         hash_node_t *node;
 404         char *type, *loaded;
 405 
 406         uuid_unparse(*(uuid_t *)&parent->uuid, uuidstr);
 407         type = (parent->key_data->persistentStorageType == TSS_PS_TYPE_USER) ?
 408             "USER" : "SYSTEM";
 409         loaded = parent->key_data->fIsLoaded ? "(loaded)" : "";
 410         (void) printf("%*s[%s] %s %s\n", indent, "",
 411             type, uuidstr, loaded);
 412 
 413         for (node = parent->child; node != NULL; node = node->sibling)
 414                 print_all(node, indent + 4);
 415 }
 416 
 417 /*ARGSUSED*/
 418 int
 419 cmd_keyinfo(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[])
 420 {
 421         TSS_RESULT ret;
 422         UINT32 i, num_keys;
 423         TSS_KM_KEYINFO2 *keys;
 424         hash_node_t *parent, *child, *srk = NULL;
 425         TSS_HKEY hKey;
 426         union {
 427                 uuid_t arr_uuid;
 428                 TSS_UUID tss_uuid;
 429         } uuid;
 430 
 431         switch (argc) {
 432         case 1:
 433                 /* Print key hierarchy */
 434                 ret = Tspi_Context_GetRegisteredKeysByUUID2(hContext,
 435                     TSS_PS_TYPE_USER, NULL, &num_keys, &keys);
 436                 if (ret) {
 437                         print_error(ret, gettext("Get key hierarchy"));
 438                         return (ERR_FAIL);
 439                 }
 440 
 441                 for (i = 0; i < num_keys; i++) {
 442                         parent = hash_insert(keys[i].parentKeyUUID, NULL);
 443                         child = hash_insert(keys[i].keyUUID, &keys[i]);
 444                         add_child(parent, child);
 445                         if (memcmp(&(keys[i].keyUUID), &srk_uuid,
 446                             sizeof (TSS_UUID)) == 0)
 447                                 srk = child;
 448                 }
 449 
 450                 if (srk != NULL)
 451                         print_all(srk, 0);
 452                 ret = Tspi_Context_FreeMemory(hContext, (BYTE *) keys);
 453                 if (ret) {
 454                         print_error(ret, gettext("Free key list"));
 455                         return (ERR_FAIL);
 456                 }
 457                 return (0);
 458 
 459         case 2:
 460                 /* Print detailed info about a single key */
 461                 if (uuid_parse(argv[1], uuid.arr_uuid))
 462                         return (ERR_FAIL);
 463                 ret = Tspi_Context_GetKeyByUUID(hContext, TSS_PS_TYPE_USER,
 464                     uuid.tss_uuid, &hKey);
 465                 if (ret == TSP_ERROR(TSS_E_PS_KEY_NOTFOUND)) {
 466                         ret = Tspi_Context_GetKeyByUUID(hContext,
 467                             TSS_PS_TYPE_SYSTEM, uuid.tss_uuid, &hKey);
 468                 }
 469                 if (ret) {
 470                         print_error(ret, gettext("Get key by UUID"));
 471                         return (ERR_FAIL);
 472                 }
 473                 print_key_info(hContext, hKey);
 474                 return (0);
 475 
 476         default:
 477                 (void) fprintf(stderr, gettext("Usage:\n"));
 478                 (void) fprintf(stderr, "\tkeyinfo [uuid]\n");
 479                 return (ERR_USAGE);
 480         }
 481 }
 482 
 483 /*ARGSUSED*/
 484 int
 485 cmd_deletekey(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[])
 486 {
 487         TSS_RESULT ret;
 488         TSS_HOBJECT hKey;
 489         union {
 490                 uuid_t arr_uuid;
 491                 TSS_UUID tss_uuid;
 492         } uuid;
 493 
 494         if (argc < 2) {
 495                 (void) fprintf(stderr, gettext("Usage:\n"));
 496                 (void) fprintf(stderr, "\tdeletekey [uuid]\n");
 497                 return (ERR_USAGE);
 498         }
 499         if (uuid_parse(argv[1], uuid.arr_uuid))
 500                 return (ERR_FAIL);
 501         ret = Tspi_Context_UnregisterKey(hContext, TSS_PS_TYPE_USER,
 502             uuid.tss_uuid, &hKey);
 503         if (ret == TSP_ERROR(TSS_E_PS_KEY_NOTFOUND)) {
 504                 ret = Tspi_Context_UnregisterKey(hContext, TSS_PS_TYPE_SYSTEM,
 505                     uuid.tss_uuid, &hKey);
 506         }
 507         if (ret) {
 508                 print_error(ret, gettext("Unregister key"));
 509                 return (ERR_FAIL);
 510         }
 511         return (0);
 512 }
 513 
 514 /*
 515  * Clear
 516  */
 517 
 518 static int
 519 clearowner(TSS_HTPM hTPM)
 520 {
 521         TSS_RESULT ret;
 522 
 523         if (set_object_policy(hTPM, TSS_SECRET_MODE_POPUP,
 524             gettext("= TPM owner passphrase ="), 0, NULL))
 525                 return (ERR_FAIL);
 526 
 527         ret = Tspi_TPM_ClearOwner(hTPM, FALSE);
 528         if (ret) {
 529                 print_error(ret, gettext("Clear TPM owner"));
 530                 return (ERR_FAIL);
 531         }
 532         return (0);
 533 }
 534 
 535 static int
 536 resetlock(TSS_HTPM hTPM)
 537 {
 538         TSS_RESULT ret;
 539 
 540         if (set_object_policy(hTPM, TSS_SECRET_MODE_POPUP,
 541             gettext("= TPM owner passphrase ="), 0, NULL))
 542                 return (ERR_FAIL);
 543 
 544         ret = Tspi_TPM_SetStatus(hTPM, TSS_TPMSTATUS_RESETLOCK, TRUE);
 545         if (ret) {
 546                 print_error(ret, gettext("Reset Lock"));
 547                 return (ERR_FAIL);
 548         }
 549         return (0);
 550 }
 551 
 552 /*ARGSUSED*/
 553 int
 554 cmd_clear(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[])
 555 {
 556         char *subcmd = argv[1];
 557 
 558         if (subcmd && strcmp(subcmd, "lock") == 0) {
 559                 return (resetlock(hTPM));
 560         } else if (subcmd && strcmp(subcmd, "owner") == 0) {
 561                 return (clearowner(hTPM));
 562         } else {
 563                 (void) fprintf(stderr, gettext("Usage:\n"));
 564                 (void) fprintf(stderr, "\tclear owner\n");
 565                 (void) fprintf(stderr, "\tclear lock\n");
 566                 return (ERR_USAGE);
 567         }
 568 }
 569 
 570 
 571 /*
 572  * TPM initialization
 573  */
 574 
 575 static int
 576 get_random(UINT32 size, BYTE *randomBytes)
 577 {
 578         int fd, len;
 579         BYTE *buf;
 580 
 581         fd = open("/dev/random", O_RDONLY);
 582         if (fd == -1) {
 583                 (void) fprintf(stderr, gettext("Unable to open /dev/random"));
 584                 return (-1);
 585         }
 586 
 587         buf = randomBytes;
 588         while (size > 0) {
 589                 len = read(fd, buf, size);
 590                 if (len <= 0) {
 591                         (void) close(fd);
 592                         (void) fprintf(stderr,
 593                             gettext("Error reading /dev/random"));
 594                         return (-1);
 595                 }
 596                 size -= len;
 597                 buf += len;
 598         }
 599 
 600         (void) close(fd);
 601         return (0);
 602 }
 603 
 604 static int
 605 createek(TSS_HCONTEXT hContext, TSS_HTPM hTPM)
 606 {
 607         TSS_RESULT ret;
 608         TSS_HOBJECT hKeyEK;
 609         TSS_VALIDATION ValidationData;
 610         TPM_NONCE nonce;
 611         TPM_DIGEST digest;
 612 
 613         /* Create the empty key struct for EK */
 614         ret = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY,
 615             (TSS_KEY_NO_AUTHORIZATION | TSS_KEY_NON_VOLATILE |
 616             TSS_KEY_NOT_MIGRATABLE | TSS_KEY_TYPE_STORAGE |
 617             TSS_KEY_SIZE_2048 | TSS_KEY_NOT_CERTIFIED_MIGRATABLE |
 618             TSS_KEY_STRUCT_KEY12 | TSS_KEY_EMPTY_KEY),
 619             &hKeyEK);
 620         if (ret) {
 621                 print_error(ret, gettext("Create endorsement key object"));
 622                 return (ERR_FAIL);
 623         }
 624 
 625         ValidationData.ulExternalDataLength = sizeof (nonce);
 626         ValidationData.rgbExternalData = (BYTE *) &nonce;
 627         ret = get_random(sizeof (nonce), (BYTE *) &nonce);
 628         if (ret)
 629                 return (ERR_FAIL);
 630         ValidationData.ulValidationDataLength = sizeof (digest);
 631         ValidationData.rgbValidationData = (BYTE *) &digest;
 632 
 633         ret = Tspi_TPM_CreateEndorsementKey(hTPM, hKeyEK, &ValidationData);
 634         if (ret) {
 635                 print_error(ret, gettext("Create endorsement key"));
 636                 return (ERR_FAIL);
 637         }
 638 
 639         return (0);
 640 }
 641 
 642 /*ARGSUSED*/
 643 int
 644 cmd_init(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[])
 645 {
 646         TSS_RESULT ret;
 647         TSS_HOBJECT hKeySRK;
 648 
 649         if (set_object_policy(hTPM, TSS_SECRET_MODE_POPUP,
 650             gettext("= TPM owner passphrase ="), 0, NULL))
 651                 return (ERR_FAIL);
 652 
 653         ret = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY,
 654             TSS_KEY_TSP_SRK | TSS_KEY_AUTHORIZATION, &hKeySRK);
 655         if (ret) {
 656                 print_error(ret, gettext("Create storage root key"));
 657                 return (ERR_FAIL);
 658         }
 659 
 660         if (set_object_policy(hKeySRK, TSS_SECRET_MODE_SHA1, NULL,
 661             sizeof (well_known), well_known))
 662                 return (ERR_FAIL);
 663 
 664         ret = Tspi_TPM_TakeOwnership(hTPM, hKeySRK, (TSS_HKEY)NULL);
 665         if (ret == TPM_E_NO_ENDORSEMENT) {
 666                 if (createek(hContext, hTPM))
 667                         return (ERR_FAIL);
 668                 ret = Tspi_TPM_TakeOwnership(hTPM, hKeySRK, (TSS_HKEY)NULL);
 669         }
 670         if (ret) {
 671                 print_error(ret, gettext("Take ownership"));
 672                 return (ERR_FAIL);
 673         }
 674 
 675         return (0);
 676 }
 677 
 678 /*
 679  * Auth
 680  */
 681 
 682 /*ARGSUSED*/
 683 int
 684 cmd_auth(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[])
 685 {
 686         TSS_RESULT ret;
 687         TSS_HPOLICY hNewPolicy;
 688 
 689         if (set_object_policy(hTPM, TSS_SECRET_MODE_POPUP,
 690             gettext("= TPM owner passphrase ="), 0, NULL))
 691                 return (ERR_FAIL);
 692 
 693         /* policy object for new passphrase */
 694         ret = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_POLICY,
 695             TSS_POLICY_USAGE, &hNewPolicy);
 696         if (ret) {
 697                 print_error(ret, gettext("Create policy object"));
 698                 return (ERR_FAIL);
 699         }
 700         if (set_policy_options(hNewPolicy, TSS_SECRET_MODE_POPUP,
 701             gettext("= New TPM owner passphrase ="), 0, NULL))
 702                 return (ERR_FAIL);
 703 
 704         ret = Tspi_ChangeAuth(hTPM, (TSS_HOBJECT)NULL, hNewPolicy);
 705         if (ret && ret != TSP_ERROR(TSS_E_POLICY_NO_SECRET)) {
 706                 print_error(ret, gettext("Change authorization"));
 707                 return (ERR_FAIL);
 708         }
 709 
 710         return (0);
 711 }