xref: /onnv-gate/usr/src/cmd/cmd-crypto/tpmadm/admin_cmds.c (revision 11070:3ac202191cfa)
19126SWyllys.Ingersoll@Sun.COM /*
29126SWyllys.Ingersoll@Sun.COM  * CDDL HEADER START
39126SWyllys.Ingersoll@Sun.COM  *
49126SWyllys.Ingersoll@Sun.COM  * The contents of this file are subject to the terms of the
59126SWyllys.Ingersoll@Sun.COM  * Common Development and Distribution License (the "License").
69126SWyllys.Ingersoll@Sun.COM  * You may not use this file except in compliance with the License.
79126SWyllys.Ingersoll@Sun.COM  *
89126SWyllys.Ingersoll@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99126SWyllys.Ingersoll@Sun.COM  * or http://www.opensolaris.org/os/licensing.
109126SWyllys.Ingersoll@Sun.COM  * See the License for the specific language governing permissions
119126SWyllys.Ingersoll@Sun.COM  * and limitations under the License.
129126SWyllys.Ingersoll@Sun.COM  *
139126SWyllys.Ingersoll@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
149126SWyllys.Ingersoll@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159126SWyllys.Ingersoll@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
169126SWyllys.Ingersoll@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
179126SWyllys.Ingersoll@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
189126SWyllys.Ingersoll@Sun.COM  *
199126SWyllys.Ingersoll@Sun.COM  * CDDL HEADER END
209126SWyllys.Ingersoll@Sun.COM  */
219126SWyllys.Ingersoll@Sun.COM 
229126SWyllys.Ingersoll@Sun.COM /*
239126SWyllys.Ingersoll@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
249126SWyllys.Ingersoll@Sun.COM  * Use is subject to license terms.
259126SWyllys.Ingersoll@Sun.COM  */
269126SWyllys.Ingersoll@Sun.COM 
279126SWyllys.Ingersoll@Sun.COM #include <unistd.h>
289126SWyllys.Ingersoll@Sun.COM #include <stdlib.h>
299126SWyllys.Ingersoll@Sun.COM #include <stdio.h>
309126SWyllys.Ingersoll@Sun.COM #include <strings.h>
319126SWyllys.Ingersoll@Sun.COM #include <fcntl.h>
329126SWyllys.Ingersoll@Sun.COM #include <sys/types.h>
339126SWyllys.Ingersoll@Sun.COM #include <netinet/in.h>
349126SWyllys.Ingersoll@Sun.COM #include <inttypes.h>
359126SWyllys.Ingersoll@Sun.COM #include <sha1.h>
369126SWyllys.Ingersoll@Sun.COM #include <uuid/uuid.h>
379126SWyllys.Ingersoll@Sun.COM #include <sys/stat.h>
389126SWyllys.Ingersoll@Sun.COM #include <libintl.h>
399126SWyllys.Ingersoll@Sun.COM 
409126SWyllys.Ingersoll@Sun.COM #include <tss/tss_defines.h>
419126SWyllys.Ingersoll@Sun.COM #include <tss/tspi.h>
429126SWyllys.Ingersoll@Sun.COM 
439126SWyllys.Ingersoll@Sun.COM #include "tpmadm.h"
449126SWyllys.Ingersoll@Sun.COM 
459126SWyllys.Ingersoll@Sun.COM int cmd_status(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
469126SWyllys.Ingersoll@Sun.COM int cmd_init(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
479126SWyllys.Ingersoll@Sun.COM int cmd_clear(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
489126SWyllys.Ingersoll@Sun.COM int cmd_auth(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
499126SWyllys.Ingersoll@Sun.COM int cmd_keyinfo(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
509126SWyllys.Ingersoll@Sun.COM int cmd_deletekey(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
519126SWyllys.Ingersoll@Sun.COM 
529126SWyllys.Ingersoll@Sun.COM cmdtable_t commands[] = {
539126SWyllys.Ingersoll@Sun.COM 	{"status", "", cmd_status},
549126SWyllys.Ingersoll@Sun.COM 	{"init", "", cmd_init},
559126SWyllys.Ingersoll@Sun.COM 	{"clear", "[owner | lock]", cmd_clear},
569126SWyllys.Ingersoll@Sun.COM 	{"auth", "", cmd_auth},
579126SWyllys.Ingersoll@Sun.COM 	{"keyinfo", "[uuid]", cmd_keyinfo},
589126SWyllys.Ingersoll@Sun.COM 	{"deletekey", "uuid", cmd_deletekey},
599126SWyllys.Ingersoll@Sun.COM 	{NULL, NULL, NULL},
609126SWyllys.Ingersoll@Sun.COM };
619126SWyllys.Ingersoll@Sun.COM 
629126SWyllys.Ingersoll@Sun.COM BYTE well_known[] = TSS_WELL_KNOWN_SECRET;
639126SWyllys.Ingersoll@Sun.COM TSS_UUID srk_uuid = TSS_UUID_SRK;
649126SWyllys.Ingersoll@Sun.COM 
659126SWyllys.Ingersoll@Sun.COM 
669126SWyllys.Ingersoll@Sun.COM /*
679126SWyllys.Ingersoll@Sun.COM  * TPM status
689126SWyllys.Ingersoll@Sun.COM  */
699126SWyllys.Ingersoll@Sun.COM 
709126SWyllys.Ingersoll@Sun.COM static int
print_tpm_version(TSS_HCONTEXT hContext,TSS_HOBJECT hTPM)719126SWyllys.Ingersoll@Sun.COM print_tpm_version(TSS_HCONTEXT hContext, TSS_HOBJECT hTPM)
729126SWyllys.Ingersoll@Sun.COM {
739126SWyllys.Ingersoll@Sun.COM 	struct {
749126SWyllys.Ingersoll@Sun.COM 		TPM_CAP_VERSION_INFO vers_info;
759126SWyllys.Ingersoll@Sun.COM 		char extra[20]; /* vendor extensions */
769126SWyllys.Ingersoll@Sun.COM 	} info;
779126SWyllys.Ingersoll@Sun.COM 
789126SWyllys.Ingersoll@Sun.COM 	if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_VERSION_VAL,
799126SWyllys.Ingersoll@Sun.COM 	    0, &info, sizeof (info)))
809126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
819126SWyllys.Ingersoll@Sun.COM 
829126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("TPM Version: %d.%d (%c%c%c%c Rev: %d.%d, "
839126SWyllys.Ingersoll@Sun.COM 	    "SpecLevel: %d, ErrataRev: %d)\n"),
849126SWyllys.Ingersoll@Sun.COM 	    info.vers_info.version.major,
859126SWyllys.Ingersoll@Sun.COM 	    info.vers_info.version.minor,
869126SWyllys.Ingersoll@Sun.COM 	    info.vers_info.tpmVendorID[0],
879126SWyllys.Ingersoll@Sun.COM 	    info.vers_info.tpmVendorID[1],
889126SWyllys.Ingersoll@Sun.COM 	    info.vers_info.tpmVendorID[2],
899126SWyllys.Ingersoll@Sun.COM 	    info.vers_info.tpmVendorID[3],
909126SWyllys.Ingersoll@Sun.COM 	    info.vers_info.version.revMajor,
919126SWyllys.Ingersoll@Sun.COM 	    info.vers_info.version.revMinor,
929126SWyllys.Ingersoll@Sun.COM 	    (int)ntohs(info.vers_info.specLevel),
939126SWyllys.Ingersoll@Sun.COM 	    info.vers_info.errataRev);
949126SWyllys.Ingersoll@Sun.COM 
959126SWyllys.Ingersoll@Sun.COM 	return (0);
969126SWyllys.Ingersoll@Sun.COM }
979126SWyllys.Ingersoll@Sun.COM 
989126SWyllys.Ingersoll@Sun.COM static int
tpm_is_owned(TSS_HCONTEXT hContext,TSS_HOBJECT hTPM)999126SWyllys.Ingersoll@Sun.COM tpm_is_owned(TSS_HCONTEXT hContext, TSS_HOBJECT hTPM)
1009126SWyllys.Ingersoll@Sun.COM {
1019126SWyllys.Ingersoll@Sun.COM 	BYTE owned;
1029126SWyllys.Ingersoll@Sun.COM 
1039126SWyllys.Ingersoll@Sun.COM 	if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
1049126SWyllys.Ingersoll@Sun.COM 	    TSS_TPMCAP_PROP_OWNER, &owned, sizeof (owned)))
1059126SWyllys.Ingersoll@Sun.COM 		return (0);
1069126SWyllys.Ingersoll@Sun.COM 
1079126SWyllys.Ingersoll@Sun.COM 	return (owned);
1089126SWyllys.Ingersoll@Sun.COM }
1099126SWyllys.Ingersoll@Sun.COM 
1109126SWyllys.Ingersoll@Sun.COM static int
print_tpm_resources(TSS_HCONTEXT hContext,TSS_HOBJECT hTPM)1119126SWyllys.Ingersoll@Sun.COM print_tpm_resources(TSS_HCONTEXT hContext, TSS_HOBJECT hTPM)
1129126SWyllys.Ingersoll@Sun.COM {
1139126SWyllys.Ingersoll@Sun.COM 	UINT32 avail, max;
1149126SWyllys.Ingersoll@Sun.COM 
1159126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("TPM resources\n"));
1169126SWyllys.Ingersoll@Sun.COM 
1179126SWyllys.Ingersoll@Sun.COM 	if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
1189126SWyllys.Ingersoll@Sun.COM 	    TSS_TPMCAP_PROP_MAXCONTEXTS, &max, sizeof (max)))
1199126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
1209126SWyllys.Ingersoll@Sun.COM 	if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
1219126SWyllys.Ingersoll@Sun.COM 	    TSS_TPMCAP_PROP_CONTEXTS, &avail, sizeof (avail)))
1229126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
1239126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("\tContexts: %d/%d available\n"), avail, max);
1249126SWyllys.Ingersoll@Sun.COM 
1259126SWyllys.Ingersoll@Sun.COM 	if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
1269126SWyllys.Ingersoll@Sun.COM 	    TSS_TPMCAP_PROP_MAXSESSIONS, &max, sizeof (max)))
1279126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
1289126SWyllys.Ingersoll@Sun.COM 	if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
1299126SWyllys.Ingersoll@Sun.COM 	    TSS_TPMCAP_PROP_SESSIONS, &avail, sizeof (avail)))
1309126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
1319126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("\tSessions: %d/%d available\n"), avail, max);
1329126SWyllys.Ingersoll@Sun.COM 
1339126SWyllys.Ingersoll@Sun.COM 	if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
1349126SWyllys.Ingersoll@Sun.COM 	    TSS_TPMCAP_PROP_MAXAUTHSESSIONS, &max, sizeof (max)))
1359126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
1369126SWyllys.Ingersoll@Sun.COM 	if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
1379126SWyllys.Ingersoll@Sun.COM 	    TSS_TPMCAP_PROP_AUTHSESSIONS, &avail, sizeof (avail)))
1389126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
1399126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("\tAuth Sessions: %d/%d available\n"),
1409126SWyllys.Ingersoll@Sun.COM 	    avail, max);
1419126SWyllys.Ingersoll@Sun.COM 
1429126SWyllys.Ingersoll@Sun.COM 	if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
1439126SWyllys.Ingersoll@Sun.COM 	    TSS_TPMCAP_PROP_MAXKEYS, &max, sizeof (max)))
1449126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
1459126SWyllys.Ingersoll@Sun.COM 	if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
1469126SWyllys.Ingersoll@Sun.COM 	    TSS_TPMCAP_PROP_KEYS, &avail, sizeof (avail)))
1479126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
1489126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("\tLoaded Keys: %d/%d available\n"), avail, max);
1499126SWyllys.Ingersoll@Sun.COM 
1509126SWyllys.Ingersoll@Sun.COM 	return (0);
1519126SWyllys.Ingersoll@Sun.COM }
1529126SWyllys.Ingersoll@Sun.COM 
1539126SWyllys.Ingersoll@Sun.COM static int
print_tpm_pcrs(TSS_HCONTEXT hContext,TSS_HOBJECT hTPM)1549126SWyllys.Ingersoll@Sun.COM print_tpm_pcrs(TSS_HCONTEXT hContext, TSS_HOBJECT hTPM)
1559126SWyllys.Ingersoll@Sun.COM {
1569126SWyllys.Ingersoll@Sun.COM 	UINT32 num_pcrs;
1579126SWyllys.Ingersoll@Sun.COM 	int i;
1589126SWyllys.Ingersoll@Sun.COM 
1599126SWyllys.Ingersoll@Sun.COM 	if (get_tpm_capability(hContext, hTPM, TSS_TPMCAP_PROPERTY,
1609126SWyllys.Ingersoll@Sun.COM 	    TSS_TPMCAP_PROP_PCR, &num_pcrs, sizeof (num_pcrs)))
1619126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
1629126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("Platform Configuration Registers (%u)\n"),
1639126SWyllys.Ingersoll@Sun.COM 	    num_pcrs);
1649126SWyllys.Ingersoll@Sun.COM 
1659126SWyllys.Ingersoll@Sun.COM 	/* Print each PCR */
1669126SWyllys.Ingersoll@Sun.COM 	for (i = 0; i < num_pcrs; i++) {
1679126SWyllys.Ingersoll@Sun.COM 		TSS_RESULT ret;
1689126SWyllys.Ingersoll@Sun.COM 		UINT32 datalen;
1699126SWyllys.Ingersoll@Sun.COM 		BYTE *data;
1709126SWyllys.Ingersoll@Sun.COM 
1719126SWyllys.Ingersoll@Sun.COM 		ret = Tspi_TPM_PcrRead(hTPM, i, &datalen, &data);
1729126SWyllys.Ingersoll@Sun.COM 		if (ret) {
1739126SWyllys.Ingersoll@Sun.COM 			print_error(ret, gettext("Read PCR"));
1749126SWyllys.Ingersoll@Sun.COM 			return (ret);
1759126SWyllys.Ingersoll@Sun.COM 		}
1769126SWyllys.Ingersoll@Sun.COM 
1779126SWyllys.Ingersoll@Sun.COM 		(void) printf("\tPCR %u:\t", i);
1789126SWyllys.Ingersoll@Sun.COM 		print_bytes(data, datalen, FALSE);
1799126SWyllys.Ingersoll@Sun.COM 
1809126SWyllys.Ingersoll@Sun.COM 		ret = Tspi_Context_FreeMemory(hContext, data);
1819126SWyllys.Ingersoll@Sun.COM 		if (ret) {
1829126SWyllys.Ingersoll@Sun.COM 			print_error(ret, gettext("Free PCR memory"));
1839126SWyllys.Ingersoll@Sun.COM 			return (ret);
1849126SWyllys.Ingersoll@Sun.COM 		}
1859126SWyllys.Ingersoll@Sun.COM 	}
1869126SWyllys.Ingersoll@Sun.COM 	return (0);
1879126SWyllys.Ingersoll@Sun.COM }
1889126SWyllys.Ingersoll@Sun.COM 
1899126SWyllys.Ingersoll@Sun.COM /*ARGSUSED*/
1909126SWyllys.Ingersoll@Sun.COM int
cmd_status(TSS_HCONTEXT hContext,TSS_HTPM hTPM,int argc,char * argv[])1919126SWyllys.Ingersoll@Sun.COM cmd_status(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[])
1929126SWyllys.Ingersoll@Sun.COM {
193*11070SScott.Rotondo@Sun.COM 	if (set_object_policy(hTPM, TSS_SECRET_MODE_POPUP, NULL, 0, NULL))
1949126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
1959126SWyllys.Ingersoll@Sun.COM 
1969126SWyllys.Ingersoll@Sun.COM 	(void) print_tpm_version(hContext, hTPM);
1979126SWyllys.Ingersoll@Sun.COM 	if (tpm_is_owned(hContext, hTPM)) {
1989126SWyllys.Ingersoll@Sun.COM 		(void) print_tpm_resources(hContext, hTPM);
1999126SWyllys.Ingersoll@Sun.COM 		(void) print_tpm_pcrs(hContext, hTPM);
2009126SWyllys.Ingersoll@Sun.COM 	} else {
2019126SWyllys.Ingersoll@Sun.COM 		(void) printf(gettext("No TPM owner installed.\n"));
2029126SWyllys.Ingersoll@Sun.COM 	}
2039126SWyllys.Ingersoll@Sun.COM 
2049126SWyllys.Ingersoll@Sun.COM 	return (0);
2059126SWyllys.Ingersoll@Sun.COM }
2069126SWyllys.Ingersoll@Sun.COM 
2079126SWyllys.Ingersoll@Sun.COM 
2089126SWyllys.Ingersoll@Sun.COM /*
2099126SWyllys.Ingersoll@Sun.COM  * Key Information
2109126SWyllys.Ingersoll@Sun.COM  */
2119126SWyllys.Ingersoll@Sun.COM 
2129126SWyllys.Ingersoll@Sun.COM typedef struct {
2139126SWyllys.Ingersoll@Sun.COM 	UINT32 code;
2149126SWyllys.Ingersoll@Sun.COM 	char *str;
2159126SWyllys.Ingersoll@Sun.COM } decode_map_t;
2169126SWyllys.Ingersoll@Sun.COM 
2179126SWyllys.Ingersoll@Sun.COM decode_map_t key_usage[] = {
2189126SWyllys.Ingersoll@Sun.COM 	{ TSS_KEYUSAGE_SIGN, "Signing" },
2199126SWyllys.Ingersoll@Sun.COM 	{ TSS_KEYUSAGE_STORAGE, "Storage" },
2209126SWyllys.Ingersoll@Sun.COM 	{ TSS_KEYUSAGE_IDENTITY, "Identity" },
2219126SWyllys.Ingersoll@Sun.COM 	{ TSS_KEYUSAGE_AUTHCHANGE, "Authchange" },
2229126SWyllys.Ingersoll@Sun.COM 	{ TSS_KEYUSAGE_BIND, "Bind" },
2239126SWyllys.Ingersoll@Sun.COM 	{ TSS_KEYUSAGE_LEGACY, "Legacy" },
2249126SWyllys.Ingersoll@Sun.COM 	{ TSS_KEYUSAGE_MIGRATE, "Migrate" },
2259126SWyllys.Ingersoll@Sun.COM 	{ 0, NULL },
2269126SWyllys.Ingersoll@Sun.COM };
2279126SWyllys.Ingersoll@Sun.COM 
2289126SWyllys.Ingersoll@Sun.COM decode_map_t key_algorithm[] = {
2299126SWyllys.Ingersoll@Sun.COM 	{ TSS_ALG_RSA, "RSA" },
2309126SWyllys.Ingersoll@Sun.COM 	{ TSS_ALG_DES, "DES" },
2319126SWyllys.Ingersoll@Sun.COM 	{ TSS_ALG_3DES, "3-DES" },
2329126SWyllys.Ingersoll@Sun.COM 	{ TSS_ALG_SHA, "SHA" },
2339126SWyllys.Ingersoll@Sun.COM 	{ TSS_ALG_HMAC, "HMAC" },
2349126SWyllys.Ingersoll@Sun.COM 	{ TSS_ALG_AES, "AES" },
2359126SWyllys.Ingersoll@Sun.COM 	{ TSS_ALG_MGF1, "MGF1" },
2369126SWyllys.Ingersoll@Sun.COM 	{ TSS_ALG_AES192, "AES192" },
2379126SWyllys.Ingersoll@Sun.COM 	{ TSS_ALG_AES256, "AES256" },
2389126SWyllys.Ingersoll@Sun.COM 	{ TSS_ALG_XOR, "XOR" },
2399126SWyllys.Ingersoll@Sun.COM 	{ 0, NULL },
2409126SWyllys.Ingersoll@Sun.COM };
2419126SWyllys.Ingersoll@Sun.COM 
2429126SWyllys.Ingersoll@Sun.COM decode_map_t key_sigscheme[] = {
2439126SWyllys.Ingersoll@Sun.COM 	{ TSS_SS_NONE, "None" },
2449126SWyllys.Ingersoll@Sun.COM 	{ TSS_SS_RSASSAPKCS1V15_SHA1, "RSASSAPKCS1v15_SHA1" },
2459126SWyllys.Ingersoll@Sun.COM 	{ TSS_SS_RSASSAPKCS1V15_DER, "RSASSAPKCS1v15_DER" },
2469126SWyllys.Ingersoll@Sun.COM 	{ 0, NULL },
2479126SWyllys.Ingersoll@Sun.COM };
2489126SWyllys.Ingersoll@Sun.COM 
2499126SWyllys.Ingersoll@Sun.COM decode_map_t key_encscheme[] = {
2509126SWyllys.Ingersoll@Sun.COM 	{ TSS_ES_NONE, "None" },
2519126SWyllys.Ingersoll@Sun.COM 	{ TSS_ES_RSAESPKCSV15, "RSAESPKCSv15" },
2529126SWyllys.Ingersoll@Sun.COM 	{ TSS_ES_RSAESOAEP_SHA1_MGF1, "RSAESOAEP_SHA1_MGF1" },
2539126SWyllys.Ingersoll@Sun.COM 	{ TSS_ES_SYM_CNT, "SYM_CNT" },
2549126SWyllys.Ingersoll@Sun.COM 	{ TSS_ES_SYM_OFB, "SYM_OFB" },
2559126SWyllys.Ingersoll@Sun.COM 	{ 0, NULL },
2569126SWyllys.Ingersoll@Sun.COM };
2579126SWyllys.Ingersoll@Sun.COM 
2589126SWyllys.Ingersoll@Sun.COM static char *
decode(decode_map_t * table,UINT32 code)2599126SWyllys.Ingersoll@Sun.COM decode(decode_map_t *table, UINT32 code)
2609126SWyllys.Ingersoll@Sun.COM {
2619126SWyllys.Ingersoll@Sun.COM 	static char buf[20];
2629126SWyllys.Ingersoll@Sun.COM 	int i;
2639126SWyllys.Ingersoll@Sun.COM 
2649126SWyllys.Ingersoll@Sun.COM 	for (i = 0; table[i].str != NULL; i++) {
2659126SWyllys.Ingersoll@Sun.COM 		if (table[i].code == code)
2669126SWyllys.Ingersoll@Sun.COM 			return (table[i].str);
2679126SWyllys.Ingersoll@Sun.COM 	}
2689126SWyllys.Ingersoll@Sun.COM 
2699126SWyllys.Ingersoll@Sun.COM 	(void) snprintf(buf, sizeof (buf), gettext("Unknown (%u)"), code);
2709126SWyllys.Ingersoll@Sun.COM 	return (buf);
2719126SWyllys.Ingersoll@Sun.COM }
2729126SWyllys.Ingersoll@Sun.COM 
2739126SWyllys.Ingersoll@Sun.COM static void
print_key_info(TSS_HCONTEXT hContext,TSS_HOBJECT hKey)2749126SWyllys.Ingersoll@Sun.COM print_key_info(TSS_HCONTEXT hContext, TSS_HOBJECT hKey)
2759126SWyllys.Ingersoll@Sun.COM {
2769126SWyllys.Ingersoll@Sun.COM 	TSS_RESULT ret;
2779126SWyllys.Ingersoll@Sun.COM 	UINT32 attrib;
2789126SWyllys.Ingersoll@Sun.COM 	UINT32 keyInfoSize;
2799126SWyllys.Ingersoll@Sun.COM 	BYTE *keyInfo;
2809126SWyllys.Ingersoll@Sun.COM 
2819126SWyllys.Ingersoll@Sun.COM 	/* Key size */
2829126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
2839126SWyllys.Ingersoll@Sun.COM 	    TSS_TSPATTRIB_KEYINFO_SIZE, &attrib);
2849126SWyllys.Ingersoll@Sun.COM 	if (ret) {
2859126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Get key size"));
2869126SWyllys.Ingersoll@Sun.COM 	}
2879126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("Key Size: %d bits\n"), attrib);
2889126SWyllys.Ingersoll@Sun.COM 
2899126SWyllys.Ingersoll@Sun.COM 	/* Key usage */
2909126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
2919126SWyllys.Ingersoll@Sun.COM 	    TSS_TSPATTRIB_KEYINFO_USAGE, &attrib);
2929126SWyllys.Ingersoll@Sun.COM 	if (ret) {
2939126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Get key usage"));
2949126SWyllys.Ingersoll@Sun.COM 	}
2959126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("Key Usage: %s\n"), decode(key_usage, attrib));
2969126SWyllys.Ingersoll@Sun.COM 
2979126SWyllys.Ingersoll@Sun.COM 	/* Algorithm */
2989126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
2999126SWyllys.Ingersoll@Sun.COM 	    TSS_TSPATTRIB_KEYINFO_ALGORITHM, &attrib);
3009126SWyllys.Ingersoll@Sun.COM 	if (ret) {
3019126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Get key algorithm"));
3029126SWyllys.Ingersoll@Sun.COM 	}
3039126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("Algorithm: %s\n"),
3049126SWyllys.Ingersoll@Sun.COM 	    decode(key_algorithm, attrib));
3059126SWyllys.Ingersoll@Sun.COM 
3069126SWyllys.Ingersoll@Sun.COM 	/* Authorization required */
3079126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
3089126SWyllys.Ingersoll@Sun.COM 	    TSS_TSPATTRIB_KEYINFO_AUTHUSAGE, &attrib);
3099126SWyllys.Ingersoll@Sun.COM 	if (ret) {
3109126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Get key authusage"));
3119126SWyllys.Ingersoll@Sun.COM 	}
3129126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("Authorization required: %s\n"),
3139126SWyllys.Ingersoll@Sun.COM 	    attrib ? gettext("Yes") : gettext("No"));
3149126SWyllys.Ingersoll@Sun.COM 
3159126SWyllys.Ingersoll@Sun.COM 	/* Signature scheme */
3169126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
3179126SWyllys.Ingersoll@Sun.COM 	    TSS_TSPATTRIB_KEYINFO_SIGSCHEME, &attrib);
3189126SWyllys.Ingersoll@Sun.COM 	if (ret) {
3199126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Get key signature scheme"));
3209126SWyllys.Ingersoll@Sun.COM 	}
3219126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("Signature scheme: %s\n"),
3229126SWyllys.Ingersoll@Sun.COM 	    decode(key_sigscheme, attrib));
3239126SWyllys.Ingersoll@Sun.COM 
3249126SWyllys.Ingersoll@Sun.COM 	/* Encoding scheme */
3259126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_GetAttribUint32(hKey, TSS_TSPATTRIB_KEY_INFO,
3269126SWyllys.Ingersoll@Sun.COM 	    TSS_TSPATTRIB_KEYINFO_ENCSCHEME, &attrib);
3279126SWyllys.Ingersoll@Sun.COM 	if (ret) {
3289126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Get key encoding scheme"));
3299126SWyllys.Ingersoll@Sun.COM 	}
3309126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("Encoding scheme: %s\n"),
3319126SWyllys.Ingersoll@Sun.COM 	    decode(key_encscheme, attrib));
3329126SWyllys.Ingersoll@Sun.COM 
3339126SWyllys.Ingersoll@Sun.COM 	/* Key blob */
3349126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_GetAttribData(hKey, TSS_TSPATTRIB_KEY_BLOB,
3359126SWyllys.Ingersoll@Sun.COM 	    TSS_TSPATTRIB_KEYBLOB_BLOB, &keyInfoSize, &keyInfo);
3369126SWyllys.Ingersoll@Sun.COM 	if (ret) {
3379126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Get key blob"));
3389126SWyllys.Ingersoll@Sun.COM 	}
3399126SWyllys.Ingersoll@Sun.COM 	(void) printf(gettext("TPM Key Blob:\n"));
3409126SWyllys.Ingersoll@Sun.COM 	print_bytes(keyInfo, keyInfoSize, TRUE);
3419126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_Context_FreeMemory(hContext, keyInfo);
3429126SWyllys.Ingersoll@Sun.COM 	if (ret) {
3439126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Free key info buffer"));
3449126SWyllys.Ingersoll@Sun.COM 	}
3459126SWyllys.Ingersoll@Sun.COM }
3469126SWyllys.Ingersoll@Sun.COM 
3479126SWyllys.Ingersoll@Sun.COM typedef struct hash_node {
3489126SWyllys.Ingersoll@Sun.COM 	struct hash_node *next, *sibling, *child;
3499126SWyllys.Ingersoll@Sun.COM 	TSS_UUID uuid;
3509126SWyllys.Ingersoll@Sun.COM 	TSS_KM_KEYINFO2 *key_data;
3519126SWyllys.Ingersoll@Sun.COM } hash_node_t;
3529126SWyllys.Ingersoll@Sun.COM 
3539126SWyllys.Ingersoll@Sun.COM #define	HASHSIZE 17
3549126SWyllys.Ingersoll@Sun.COM hash_node_t *hash_table[HASHSIZE];
3559126SWyllys.Ingersoll@Sun.COM 
3569126SWyllys.Ingersoll@Sun.COM static hash_node_t *
hash_insert(TSS_UUID uuid,TSS_KM_KEYINFO2 * key_data)3579126SWyllys.Ingersoll@Sun.COM hash_insert(TSS_UUID uuid, TSS_KM_KEYINFO2 *key_data)
3589126SWyllys.Ingersoll@Sun.COM {
3599126SWyllys.Ingersoll@Sun.COM 	UINT32 i, index = 0;
3609126SWyllys.Ingersoll@Sun.COM 	hash_node_t *node;
3619126SWyllys.Ingersoll@Sun.COM 	char *cp;
3629126SWyllys.Ingersoll@Sun.COM 
3639126SWyllys.Ingersoll@Sun.COM 	cp = (char *)&uuid;
3649126SWyllys.Ingersoll@Sun.COM 	for (i = 0; i < sizeof (TSS_UUID); i++)
3659126SWyllys.Ingersoll@Sun.COM 		index += cp[i];
3669126SWyllys.Ingersoll@Sun.COM 	index = index % HASHSIZE;
3679126SWyllys.Ingersoll@Sun.COM 
3689126SWyllys.Ingersoll@Sun.COM 	for (node = hash_table[index]; node != NULL; node = node->next) {
3699126SWyllys.Ingersoll@Sun.COM 		if (memcmp(&(node->uuid), &uuid, sizeof (TSS_UUID)) == 0)
3709126SWyllys.Ingersoll@Sun.COM 			break;
3719126SWyllys.Ingersoll@Sun.COM 	}
3729126SWyllys.Ingersoll@Sun.COM 
3739126SWyllys.Ingersoll@Sun.COM 	if (node == NULL) {
3749126SWyllys.Ingersoll@Sun.COM 		node = calloc(1, sizeof (hash_node_t));
3759126SWyllys.Ingersoll@Sun.COM 		node->uuid = uuid;
3769126SWyllys.Ingersoll@Sun.COM 		node->next = hash_table[index];
3779126SWyllys.Ingersoll@Sun.COM 		hash_table[index] = node;
3789126SWyllys.Ingersoll@Sun.COM 	}
3799126SWyllys.Ingersoll@Sun.COM 	if (node->key_data == NULL)
3809126SWyllys.Ingersoll@Sun.COM 		node->key_data = key_data;
3819126SWyllys.Ingersoll@Sun.COM 
3829126SWyllys.Ingersoll@Sun.COM 	return (node);
3839126SWyllys.Ingersoll@Sun.COM }
3849126SWyllys.Ingersoll@Sun.COM 
3859126SWyllys.Ingersoll@Sun.COM static void
add_child(hash_node_t * parent,hash_node_t * child)3869126SWyllys.Ingersoll@Sun.COM add_child(hash_node_t *parent, hash_node_t *child)
3879126SWyllys.Ingersoll@Sun.COM {
3889126SWyllys.Ingersoll@Sun.COM 	hash_node_t *node;
3899126SWyllys.Ingersoll@Sun.COM 
3909126SWyllys.Ingersoll@Sun.COM 	for (node = parent->child; node != NULL; node = node->next) {
3919126SWyllys.Ingersoll@Sun.COM 		if (node == child)
3929126SWyllys.Ingersoll@Sun.COM 			return;
3939126SWyllys.Ingersoll@Sun.COM 	}
3949126SWyllys.Ingersoll@Sun.COM 
3959126SWyllys.Ingersoll@Sun.COM 	child->sibling = parent->child;
3969126SWyllys.Ingersoll@Sun.COM 	parent->child = child;
3979126SWyllys.Ingersoll@Sun.COM }
3989126SWyllys.Ingersoll@Sun.COM 
3999126SWyllys.Ingersoll@Sun.COM static void
print_all(hash_node_t * parent,int indent)4009126SWyllys.Ingersoll@Sun.COM print_all(hash_node_t *parent, int indent)
4019126SWyllys.Ingersoll@Sun.COM {
4029126SWyllys.Ingersoll@Sun.COM 	char uuidstr[UUID_PRINTABLE_STRING_LENGTH];
4039126SWyllys.Ingersoll@Sun.COM 	hash_node_t *node;
4049126SWyllys.Ingersoll@Sun.COM 	char *type, *loaded;
4059126SWyllys.Ingersoll@Sun.COM 
4069126SWyllys.Ingersoll@Sun.COM 	uuid_unparse(*(uuid_t *)&parent->uuid, uuidstr);
4079126SWyllys.Ingersoll@Sun.COM 	type = (parent->key_data->persistentStorageType == TSS_PS_TYPE_USER) ?
4089126SWyllys.Ingersoll@Sun.COM 	    "USER" : "SYSTEM";
4099126SWyllys.Ingersoll@Sun.COM 	loaded = parent->key_data->fIsLoaded ? "(loaded)" : "";
4109126SWyllys.Ingersoll@Sun.COM 	(void) printf("%*s[%s] %s %s\n", indent, "",
4119126SWyllys.Ingersoll@Sun.COM 	    type, uuidstr, loaded);
4129126SWyllys.Ingersoll@Sun.COM 
4139126SWyllys.Ingersoll@Sun.COM 	for (node = parent->child; node != NULL; node = node->sibling)
4149126SWyllys.Ingersoll@Sun.COM 		print_all(node, indent + 4);
4159126SWyllys.Ingersoll@Sun.COM }
4169126SWyllys.Ingersoll@Sun.COM 
4179126SWyllys.Ingersoll@Sun.COM /*ARGSUSED*/
4189126SWyllys.Ingersoll@Sun.COM int
cmd_keyinfo(TSS_HCONTEXT hContext,TSS_HTPM hTPM,int argc,char * argv[])4199126SWyllys.Ingersoll@Sun.COM cmd_keyinfo(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[])
4209126SWyllys.Ingersoll@Sun.COM {
4219126SWyllys.Ingersoll@Sun.COM 	TSS_RESULT ret;
4229126SWyllys.Ingersoll@Sun.COM 	UINT32 i, num_keys;
4239126SWyllys.Ingersoll@Sun.COM 	TSS_KM_KEYINFO2 *keys;
4249126SWyllys.Ingersoll@Sun.COM 	hash_node_t *parent, *child, *srk = NULL;
4259126SWyllys.Ingersoll@Sun.COM 	TSS_HKEY hKey;
4269126SWyllys.Ingersoll@Sun.COM 	union {
4279126SWyllys.Ingersoll@Sun.COM 		uuid_t arr_uuid;
4289126SWyllys.Ingersoll@Sun.COM 		TSS_UUID tss_uuid;
4299126SWyllys.Ingersoll@Sun.COM 	} uuid;
4309126SWyllys.Ingersoll@Sun.COM 
4319126SWyllys.Ingersoll@Sun.COM 	switch (argc) {
432*11070SScott.Rotondo@Sun.COM 	case 1:
4339126SWyllys.Ingersoll@Sun.COM 		/* Print key hierarchy */
4349126SWyllys.Ingersoll@Sun.COM 		ret = Tspi_Context_GetRegisteredKeysByUUID2(hContext,
4359126SWyllys.Ingersoll@Sun.COM 		    TSS_PS_TYPE_USER, NULL, &num_keys, &keys);
4369126SWyllys.Ingersoll@Sun.COM 		if (ret) {
4379126SWyllys.Ingersoll@Sun.COM 			print_error(ret, gettext("Get key hierarchy"));
4389126SWyllys.Ingersoll@Sun.COM 			return (ERR_FAIL);
4399126SWyllys.Ingersoll@Sun.COM 		}
4409126SWyllys.Ingersoll@Sun.COM 
4419126SWyllys.Ingersoll@Sun.COM 		for (i = 0; i < num_keys; i++) {
4429126SWyllys.Ingersoll@Sun.COM 			parent = hash_insert(keys[i].parentKeyUUID, NULL);
4439126SWyllys.Ingersoll@Sun.COM 			child = hash_insert(keys[i].keyUUID, &keys[i]);
4449126SWyllys.Ingersoll@Sun.COM 			add_child(parent, child);
4459126SWyllys.Ingersoll@Sun.COM 			if (memcmp(&(keys[i].keyUUID), &srk_uuid,
4469126SWyllys.Ingersoll@Sun.COM 			    sizeof (TSS_UUID)) == 0)
4479126SWyllys.Ingersoll@Sun.COM 				srk = child;
4489126SWyllys.Ingersoll@Sun.COM 		}
4499126SWyllys.Ingersoll@Sun.COM 
4509126SWyllys.Ingersoll@Sun.COM 		if (srk != NULL)
4519126SWyllys.Ingersoll@Sun.COM 			print_all(srk, 0);
4529126SWyllys.Ingersoll@Sun.COM 		ret = Tspi_Context_FreeMemory(hContext, (BYTE *) keys);
4539126SWyllys.Ingersoll@Sun.COM 		if (ret) {
4549126SWyllys.Ingersoll@Sun.COM 			print_error(ret, gettext("Free key list"));
4559126SWyllys.Ingersoll@Sun.COM 			return (ERR_FAIL);
4569126SWyllys.Ingersoll@Sun.COM 		}
4579126SWyllys.Ingersoll@Sun.COM 		return (0);
4589126SWyllys.Ingersoll@Sun.COM 
459*11070SScott.Rotondo@Sun.COM 	case 2:
4609126SWyllys.Ingersoll@Sun.COM 		/* Print detailed info about a single key */
4619126SWyllys.Ingersoll@Sun.COM 		if (uuid_parse(argv[1], uuid.arr_uuid))
4629126SWyllys.Ingersoll@Sun.COM 			return (ERR_FAIL);
4639126SWyllys.Ingersoll@Sun.COM 		ret = Tspi_Context_GetKeyByUUID(hContext, TSS_PS_TYPE_USER,
4649126SWyllys.Ingersoll@Sun.COM 		    uuid.tss_uuid, &hKey);
4659126SWyllys.Ingersoll@Sun.COM 		if (ret == TSP_ERROR(TSS_E_PS_KEY_NOTFOUND)) {
4669126SWyllys.Ingersoll@Sun.COM 			ret = Tspi_Context_GetKeyByUUID(hContext,
4679126SWyllys.Ingersoll@Sun.COM 			    TSS_PS_TYPE_SYSTEM, uuid.tss_uuid, &hKey);
4689126SWyllys.Ingersoll@Sun.COM 		}
4699126SWyllys.Ingersoll@Sun.COM 		if (ret) {
4709126SWyllys.Ingersoll@Sun.COM 			print_error(ret, gettext("Get key by UUID"));
4719126SWyllys.Ingersoll@Sun.COM 			return (ERR_FAIL);
4729126SWyllys.Ingersoll@Sun.COM 		}
4739126SWyllys.Ingersoll@Sun.COM 		print_key_info(hContext, hKey);
4749126SWyllys.Ingersoll@Sun.COM 		return (0);
4759126SWyllys.Ingersoll@Sun.COM 
476*11070SScott.Rotondo@Sun.COM 	default:
4779126SWyllys.Ingersoll@Sun.COM 		(void) fprintf(stderr, gettext("Usage:\n"));
4789126SWyllys.Ingersoll@Sun.COM 		(void) fprintf(stderr, "\tkeyinfo [uuid]\n");
4799126SWyllys.Ingersoll@Sun.COM 		return (ERR_USAGE);
4809126SWyllys.Ingersoll@Sun.COM 	}
4819126SWyllys.Ingersoll@Sun.COM }
4829126SWyllys.Ingersoll@Sun.COM 
4839126SWyllys.Ingersoll@Sun.COM /*ARGSUSED*/
4849126SWyllys.Ingersoll@Sun.COM int
cmd_deletekey(TSS_HCONTEXT hContext,TSS_HTPM hTPM,int argc,char * argv[])4859126SWyllys.Ingersoll@Sun.COM cmd_deletekey(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[])
4869126SWyllys.Ingersoll@Sun.COM {
4879126SWyllys.Ingersoll@Sun.COM 	TSS_RESULT ret;
4889126SWyllys.Ingersoll@Sun.COM 	TSS_HOBJECT hKey;
4899126SWyllys.Ingersoll@Sun.COM 	union {
4909126SWyllys.Ingersoll@Sun.COM 		uuid_t arr_uuid;
4919126SWyllys.Ingersoll@Sun.COM 		TSS_UUID tss_uuid;
4929126SWyllys.Ingersoll@Sun.COM 	} uuid;
4939126SWyllys.Ingersoll@Sun.COM 
4949126SWyllys.Ingersoll@Sun.COM 	if (argc < 2) {
4959126SWyllys.Ingersoll@Sun.COM 		(void) fprintf(stderr, gettext("Usage:\n"));
4969126SWyllys.Ingersoll@Sun.COM 		(void) fprintf(stderr, "\tdeletekey [uuid]\n");
4979126SWyllys.Ingersoll@Sun.COM 		return (ERR_USAGE);
4989126SWyllys.Ingersoll@Sun.COM 	}
4999126SWyllys.Ingersoll@Sun.COM 	if (uuid_parse(argv[1], uuid.arr_uuid))
5009126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
5019126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_Context_UnregisterKey(hContext, TSS_PS_TYPE_USER,
5029126SWyllys.Ingersoll@Sun.COM 	    uuid.tss_uuid, &hKey);
5039126SWyllys.Ingersoll@Sun.COM 	if (ret == TSP_ERROR(TSS_E_PS_KEY_NOTFOUND)) {
5049126SWyllys.Ingersoll@Sun.COM 		ret = Tspi_Context_UnregisterKey(hContext, TSS_PS_TYPE_SYSTEM,
5059126SWyllys.Ingersoll@Sun.COM 		    uuid.tss_uuid, &hKey);
5069126SWyllys.Ingersoll@Sun.COM 	}
5079126SWyllys.Ingersoll@Sun.COM 	if (ret) {
5089126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Unregister key"));
5099126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
5109126SWyllys.Ingersoll@Sun.COM 	}
5119126SWyllys.Ingersoll@Sun.COM 	return (0);
5129126SWyllys.Ingersoll@Sun.COM }
5139126SWyllys.Ingersoll@Sun.COM 
5149126SWyllys.Ingersoll@Sun.COM /*
5159126SWyllys.Ingersoll@Sun.COM  * Clear
5169126SWyllys.Ingersoll@Sun.COM  */
5179126SWyllys.Ingersoll@Sun.COM 
5189126SWyllys.Ingersoll@Sun.COM static int
clearowner(TSS_HTPM hTPM)5199126SWyllys.Ingersoll@Sun.COM clearowner(TSS_HTPM hTPM)
5209126SWyllys.Ingersoll@Sun.COM {
5219126SWyllys.Ingersoll@Sun.COM 	TSS_RESULT ret;
5229126SWyllys.Ingersoll@Sun.COM 
523*11070SScott.Rotondo@Sun.COM 	if (set_object_policy(hTPM, TSS_SECRET_MODE_POPUP,
524*11070SScott.Rotondo@Sun.COM 	    gettext("= TPM owner passphrase ="), 0, NULL))
5259126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
5269126SWyllys.Ingersoll@Sun.COM 
5279126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_TPM_ClearOwner(hTPM, FALSE);
5289126SWyllys.Ingersoll@Sun.COM 	if (ret) {
5299126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Clear TPM owner"));
5309126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
5319126SWyllys.Ingersoll@Sun.COM 	}
5329126SWyllys.Ingersoll@Sun.COM 	return (0);
5339126SWyllys.Ingersoll@Sun.COM }
5349126SWyllys.Ingersoll@Sun.COM 
5359126SWyllys.Ingersoll@Sun.COM static int
resetlock(TSS_HTPM hTPM)5369126SWyllys.Ingersoll@Sun.COM resetlock(TSS_HTPM hTPM)
5379126SWyllys.Ingersoll@Sun.COM {
5389126SWyllys.Ingersoll@Sun.COM 	TSS_RESULT ret;
5399126SWyllys.Ingersoll@Sun.COM 
540*11070SScott.Rotondo@Sun.COM 	if (set_object_policy(hTPM, TSS_SECRET_MODE_POPUP,
541*11070SScott.Rotondo@Sun.COM 	    gettext("= TPM owner passphrase ="), 0, NULL))
5429126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
5439126SWyllys.Ingersoll@Sun.COM 
5449126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_TPM_SetStatus(hTPM, TSS_TPMSTATUS_RESETLOCK, TRUE);
5459126SWyllys.Ingersoll@Sun.COM 	if (ret) {
5469126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Reset Lock"));
5479126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
5489126SWyllys.Ingersoll@Sun.COM 	}
5499126SWyllys.Ingersoll@Sun.COM 	return (0);
5509126SWyllys.Ingersoll@Sun.COM }
5519126SWyllys.Ingersoll@Sun.COM 
5529126SWyllys.Ingersoll@Sun.COM /*ARGSUSED*/
5539126SWyllys.Ingersoll@Sun.COM int
cmd_clear(TSS_HCONTEXT hContext,TSS_HTPM hTPM,int argc,char * argv[])5549126SWyllys.Ingersoll@Sun.COM cmd_clear(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[])
5559126SWyllys.Ingersoll@Sun.COM {
5569126SWyllys.Ingersoll@Sun.COM 	char *subcmd = argv[1];
5579126SWyllys.Ingersoll@Sun.COM 
5589126SWyllys.Ingersoll@Sun.COM 	if (subcmd && strcmp(subcmd, "lock") == 0) {
5599126SWyllys.Ingersoll@Sun.COM 		return (resetlock(hTPM));
5609126SWyllys.Ingersoll@Sun.COM 	} else if (subcmd && strcmp(subcmd, "owner") == 0) {
5619126SWyllys.Ingersoll@Sun.COM 		return (clearowner(hTPM));
5629126SWyllys.Ingersoll@Sun.COM 	} else {
5639126SWyllys.Ingersoll@Sun.COM 		(void) fprintf(stderr, gettext("Usage:\n"));
5649126SWyllys.Ingersoll@Sun.COM 		(void) fprintf(stderr, "\tclear owner\n");
5659126SWyllys.Ingersoll@Sun.COM 		(void) fprintf(stderr, "\tclear lock\n");
5669126SWyllys.Ingersoll@Sun.COM 		return (ERR_USAGE);
5679126SWyllys.Ingersoll@Sun.COM 	}
5689126SWyllys.Ingersoll@Sun.COM }
5699126SWyllys.Ingersoll@Sun.COM 
5709126SWyllys.Ingersoll@Sun.COM 
5719126SWyllys.Ingersoll@Sun.COM /*
5729126SWyllys.Ingersoll@Sun.COM  * TPM initialization
5739126SWyllys.Ingersoll@Sun.COM  */
5749126SWyllys.Ingersoll@Sun.COM 
5759126SWyllys.Ingersoll@Sun.COM static int
get_random(UINT32 size,BYTE * randomBytes)5769126SWyllys.Ingersoll@Sun.COM get_random(UINT32 size,	BYTE *randomBytes)
5779126SWyllys.Ingersoll@Sun.COM {
5789126SWyllys.Ingersoll@Sun.COM 	int fd, len;
5799126SWyllys.Ingersoll@Sun.COM 	BYTE *buf;
5809126SWyllys.Ingersoll@Sun.COM 
5819126SWyllys.Ingersoll@Sun.COM 	fd = open("/dev/random", O_RDONLY);
5829126SWyllys.Ingersoll@Sun.COM 	if (fd == -1) {
5839126SWyllys.Ingersoll@Sun.COM 		(void) fprintf(stderr, gettext("Unable to open /dev/random"));
5849126SWyllys.Ingersoll@Sun.COM 		return (-1);
5859126SWyllys.Ingersoll@Sun.COM 	}
5869126SWyllys.Ingersoll@Sun.COM 
5879126SWyllys.Ingersoll@Sun.COM 	buf = randomBytes;
5889126SWyllys.Ingersoll@Sun.COM 	while (size > 0) {
5899126SWyllys.Ingersoll@Sun.COM 		len = read(fd, buf, size);
5909126SWyllys.Ingersoll@Sun.COM 		if (len <= 0) {
5919126SWyllys.Ingersoll@Sun.COM 			(void) close(fd);
5929126SWyllys.Ingersoll@Sun.COM 			(void) fprintf(stderr,
5939126SWyllys.Ingersoll@Sun.COM 			    gettext("Error reading /dev/random"));
5949126SWyllys.Ingersoll@Sun.COM 			return (-1);
5959126SWyllys.Ingersoll@Sun.COM 		}
5969126SWyllys.Ingersoll@Sun.COM 		size -= len;
5979126SWyllys.Ingersoll@Sun.COM 		buf += len;
5989126SWyllys.Ingersoll@Sun.COM 	}
5999126SWyllys.Ingersoll@Sun.COM 
6009126SWyllys.Ingersoll@Sun.COM 	(void) close(fd);
6019126SWyllys.Ingersoll@Sun.COM 	return (0);
6029126SWyllys.Ingersoll@Sun.COM }
6039126SWyllys.Ingersoll@Sun.COM 
6049126SWyllys.Ingersoll@Sun.COM static int
createek(TSS_HCONTEXT hContext,TSS_HTPM hTPM)6059126SWyllys.Ingersoll@Sun.COM createek(TSS_HCONTEXT hContext, TSS_HTPM hTPM)
6069126SWyllys.Ingersoll@Sun.COM {
6079126SWyllys.Ingersoll@Sun.COM 	TSS_RESULT ret;
6089126SWyllys.Ingersoll@Sun.COM 	TSS_HOBJECT hKeyEK;
6099126SWyllys.Ingersoll@Sun.COM 	TSS_VALIDATION ValidationData;
6109126SWyllys.Ingersoll@Sun.COM 	TPM_NONCE nonce;
6119126SWyllys.Ingersoll@Sun.COM 	TPM_DIGEST digest;
6129126SWyllys.Ingersoll@Sun.COM 
6139126SWyllys.Ingersoll@Sun.COM 	/* Create the empty key struct for EK */
6149126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY,
6159126SWyllys.Ingersoll@Sun.COM 	    (TSS_KEY_NO_AUTHORIZATION | TSS_KEY_NON_VOLATILE |
6169126SWyllys.Ingersoll@Sun.COM 	    TSS_KEY_NOT_MIGRATABLE | TSS_KEY_TYPE_STORAGE |
6179126SWyllys.Ingersoll@Sun.COM 	    TSS_KEY_SIZE_2048 | TSS_KEY_NOT_CERTIFIED_MIGRATABLE |
6189126SWyllys.Ingersoll@Sun.COM 	    TSS_KEY_STRUCT_KEY12 | TSS_KEY_EMPTY_KEY),
6199126SWyllys.Ingersoll@Sun.COM 	    &hKeyEK);
6209126SWyllys.Ingersoll@Sun.COM 	if (ret) {
6219126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Create endorsement key object"));
6229126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
6239126SWyllys.Ingersoll@Sun.COM 	}
6249126SWyllys.Ingersoll@Sun.COM 
6259126SWyllys.Ingersoll@Sun.COM 	ValidationData.ulExternalDataLength = sizeof (nonce);
6269126SWyllys.Ingersoll@Sun.COM 	ValidationData.rgbExternalData = (BYTE *) &nonce;
6279126SWyllys.Ingersoll@Sun.COM 	ret = get_random(sizeof (nonce), (BYTE *) &nonce);
6289126SWyllys.Ingersoll@Sun.COM 	if (ret)
6299126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
6309126SWyllys.Ingersoll@Sun.COM 	ValidationData.ulValidationDataLength = sizeof (digest);
6319126SWyllys.Ingersoll@Sun.COM 	ValidationData.rgbValidationData = (BYTE *) &digest;
6329126SWyllys.Ingersoll@Sun.COM 
6339126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_TPM_CreateEndorsementKey(hTPM, hKeyEK, &ValidationData);
6349126SWyllys.Ingersoll@Sun.COM 	if (ret) {
6359126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Create endorsement key"));
6369126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
6379126SWyllys.Ingersoll@Sun.COM 	}
6389126SWyllys.Ingersoll@Sun.COM 
6399126SWyllys.Ingersoll@Sun.COM 	return (0);
6409126SWyllys.Ingersoll@Sun.COM }
6419126SWyllys.Ingersoll@Sun.COM 
6429126SWyllys.Ingersoll@Sun.COM /*ARGSUSED*/
6439126SWyllys.Ingersoll@Sun.COM int
cmd_init(TSS_HCONTEXT hContext,TSS_HTPM hTPM,int argc,char * argv[])6449126SWyllys.Ingersoll@Sun.COM cmd_init(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[])
6459126SWyllys.Ingersoll@Sun.COM {
6469126SWyllys.Ingersoll@Sun.COM 	TSS_RESULT ret;
6479126SWyllys.Ingersoll@Sun.COM 	TSS_HOBJECT hKeySRK;
6489126SWyllys.Ingersoll@Sun.COM 
649*11070SScott.Rotondo@Sun.COM 	if (set_object_policy(hTPM, TSS_SECRET_MODE_POPUP,
650*11070SScott.Rotondo@Sun.COM 	    gettext("= TPM owner passphrase ="), 0, NULL))
6519126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
6529126SWyllys.Ingersoll@Sun.COM 
6539126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY,
6549126SWyllys.Ingersoll@Sun.COM 	    TSS_KEY_TSP_SRK | TSS_KEY_AUTHORIZATION, &hKeySRK);
6559126SWyllys.Ingersoll@Sun.COM 	if (ret) {
6569126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Create storage root key"));
6579126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
6589126SWyllys.Ingersoll@Sun.COM 	}
6599126SWyllys.Ingersoll@Sun.COM 
660*11070SScott.Rotondo@Sun.COM 	if (set_object_policy(hKeySRK, TSS_SECRET_MODE_SHA1, NULL,
6619126SWyllys.Ingersoll@Sun.COM 	    sizeof (well_known), well_known))
6629126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
6639126SWyllys.Ingersoll@Sun.COM 
6649126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_TPM_TakeOwnership(hTPM, hKeySRK, NULL);
6659126SWyllys.Ingersoll@Sun.COM 	if (ret == TPM_E_NO_ENDORSEMENT) {
6669126SWyllys.Ingersoll@Sun.COM 		if (createek(hContext, hTPM))
6679126SWyllys.Ingersoll@Sun.COM 			return (ERR_FAIL);
6689126SWyllys.Ingersoll@Sun.COM 		ret = Tspi_TPM_TakeOwnership(hTPM, hKeySRK, NULL);
6699126SWyllys.Ingersoll@Sun.COM 	}
6709126SWyllys.Ingersoll@Sun.COM 	if (ret) {
6719126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Take ownership"));
6729126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
6739126SWyllys.Ingersoll@Sun.COM 	}
6749126SWyllys.Ingersoll@Sun.COM 
6759126SWyllys.Ingersoll@Sun.COM 	return (0);
6769126SWyllys.Ingersoll@Sun.COM }
6779126SWyllys.Ingersoll@Sun.COM 
6789126SWyllys.Ingersoll@Sun.COM /*
6799126SWyllys.Ingersoll@Sun.COM  * Auth
6809126SWyllys.Ingersoll@Sun.COM  */
6819126SWyllys.Ingersoll@Sun.COM 
6829126SWyllys.Ingersoll@Sun.COM /*ARGSUSED*/
6839126SWyllys.Ingersoll@Sun.COM int
cmd_auth(TSS_HCONTEXT hContext,TSS_HTPM hTPM,int argc,char * argv[])6849126SWyllys.Ingersoll@Sun.COM cmd_auth(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[])
6859126SWyllys.Ingersoll@Sun.COM {
6869126SWyllys.Ingersoll@Sun.COM 	TSS_RESULT ret;
6879126SWyllys.Ingersoll@Sun.COM 	TSS_HPOLICY hNewPolicy;
6889126SWyllys.Ingersoll@Sun.COM 
689*11070SScott.Rotondo@Sun.COM 	if (set_object_policy(hTPM, TSS_SECRET_MODE_POPUP,
690*11070SScott.Rotondo@Sun.COM 	    gettext("= TPM owner passphrase ="), 0, NULL))
6919126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
6929126SWyllys.Ingersoll@Sun.COM 
693*11070SScott.Rotondo@Sun.COM 	/* policy object for new passphrase */
6949126SWyllys.Ingersoll@Sun.COM 	ret = Tspi_Context_CreateObject(hContext, TSS_OBJECT_TYPE_POLICY,
6959126SWyllys.Ingersoll@Sun.COM 	    TSS_POLICY_USAGE, &hNewPolicy);
6969126SWyllys.Ingersoll@Sun.COM 	if (ret) {
6979126SWyllys.Ingersoll@Sun.COM 		print_error(ret, gettext("Create policy object"));
6989126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
6999126SWyllys.Ingersoll@Sun.COM 	}
700*11070SScott.Rotondo@Sun.COM 	if (set_policy_options(hNewPolicy, TSS_SECRET_MODE_POPUP,
701*11070SScott.Rotondo@Sun.COM 	    gettext("= New TPM owner passphrase ="), 0, NULL))
702*11070SScott.Rotondo@Sun.COM 		return (ERR_FAIL);
703*11070SScott.Rotondo@Sun.COM 
704*11070SScott.Rotondo@Sun.COM 	ret = Tspi_ChangeAuth(hTPM, NULL, hNewPolicy);
705*11070SScott.Rotondo@Sun.COM 	if (ret && ret != TSP_ERROR(TSS_E_POLICY_NO_SECRET)) {
706*11070SScott.Rotondo@Sun.COM 		print_error(ret, gettext("Change authorization"));
7079126SWyllys.Ingersoll@Sun.COM 		return (ERR_FAIL);
7089126SWyllys.Ingersoll@Sun.COM 	}
7099126SWyllys.Ingersoll@Sun.COM 
7109126SWyllys.Ingersoll@Sun.COM 	return (0);
7119126SWyllys.Ingersoll@Sun.COM }
712