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