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
45int cmd_status(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
46int cmd_init(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
47int cmd_clear(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
48int cmd_auth(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
49int cmd_keyinfo(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
50int cmd_deletekey(TSS_HCONTEXT hContext, TSS_HTPM hTPM, int argc, char *argv[]);
51
52cmdtable_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
62BYTE well_known[] = TSS_WELL_KNOWN_SECRET;
63TSS_UUID srk_uuid = TSS_UUID_SRK;
64
65
66/*
67 * TPM status
68 */
69
70static int
71print_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
98static int
99tpm_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
110static int
111print_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
153static int
154print_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*/
190int
191cmd_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
212typedef struct {
213	UINT32 code;
214	char *str;
215} decode_map_t;
216
217decode_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
228decode_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
242decode_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
249decode_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
258static char *
259decode(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
273static void
274print_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
347typedef 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
354hash_node_t *hash_table[HASHSIZE];
355
356static hash_node_t *
357hash_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
385static void
386add_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
399static void
400print_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*/
418int
419cmd_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*/
484int
485cmd_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
518static int
519clearowner(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
535static int
536resetlock(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*/
553int
554cmd_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
575static int
576get_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
604static int
605createek(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*/
643int
644cmd_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, 0);
665	if (ret == TPM_E_NO_ENDORSEMENT) {
666		if (createek(hContext, hTPM))
667			return (ERR_FAIL);
668		ret = Tspi_TPM_TakeOwnership(hTPM, hKeySRK, 0);
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*/
683int
684cmd_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, 0, 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}
712