1/*
2 * The Initial Developer of the Original Code is International
3 * Business Machines Corporation. Portions created by IBM
4 * Corporation are Copyright (C) 2005 International Business
5 * Machines Corporation. All Rights Reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the Common Public License as published by
9 * IBM Corporation; either version 1 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * Common Public License for more details.
16 *
17 * You should have received a copy of the Common Public License
18 * along with this program; if not, a copy can be viewed at
19 * http://www.opensource.org/licenses/cpl1.0.php.
20 */
21
22#include "tpm_tspi.h"
23#include "tpm_utils.h"
24
25static void help(const char *aCmd)
26{
27	logCmdHelp(aCmd);
28	logUnicodeCmdOption();
29	logCmdOption("-s, --status",
30		     _("Report current status."));
31	logCmdOption("-o, --owner",
32		     _("Remove ability of the owner to clear TPM."));
33	logCmdOption("-f, --force",
34		     _("Remove ability to clear TPM with physical presence.\n\t\tThis action is not persistent"));
35	logCmdOption("-z, --well-known",
36		      _("Use 20 bytes of zeros (TSS_WELL_KNOWN_SECRET) as the TPM secret authorization data"));
37}
38
39enum {
40	owner = 0,
41	force
42};
43
44struct physFlag {
45	const char *name;
46	const TSS_FLAG property;
47	BOOL disable;
48};
49
50//Controlled by input options
51static struct physFlag flags[] = { {N_("Owner Clear"),
52				    TSS_TPMSTATUS_DISABLEOWNERCLEAR},
53{N_("Force Clear"),
54 TSS_TPMSTATUS_DISABLEFORCECLEAR},
55{0, 0, 0}
56};
57static BOOL bCheck = FALSE;
58static BOOL bChangeRequested = FALSE;
59static BOOL isWellKnown = FALSE;
60TSS_HCONTEXT hContext = 0;
61
62static int parse(const int aOpt, const char *aArg)
63{
64
65	switch (aOpt) {
66	case 's':
67		bCheck = TRUE;
68		break;
69	case 'o':
70		flags[owner].disable = TRUE;
71		bChangeRequested = TRUE;
72		break;
73	case 'f':
74		flags[force].disable = TRUE;
75		bChangeRequested = TRUE;
76		break;
77	case 'z':
78		logDebug(_("Using TSS_WELL_KNOWN_SECRET to authorize the TPM command\n"));
79		isWellKnown = TRUE;
80		break;
81	default:
82		return -1;
83	}
84
85	return 0;
86}
87
88/*
89 * Affect: Toggle OwnerClear and ForceClear from being available
90 * Default: Display current states
91 * Requires: Owner auth to set OwnerClear and display current states
92 */
93
94int main(int argc, char **argv)
95{
96
97	char *szTpmPasswd = NULL;
98	int pswd_len;
99	TSS_HTPM hTpm;
100	TSS_HPOLICY hTpmPolicy;
101	int iRc = -1;
102	int i = 0;
103	struct option opts[] = { {"status", no_argument, NULL, 's'},
104	{"owner", no_argument, NULL, 'o'},
105	{"force", no_argument, NULL, 'f'},
106	{"well-known", no_argument, NULL, 'z'},
107	};
108	BYTE well_known[] = TSS_WELL_KNOWN_SECRET;
109
110        initIntlSys();
111
112	if (genericOptHandler
113	    (argc, argv, "ofsz", opts, sizeof(opts) / sizeof(struct option),
114	     parse, help) != 0)
115		goto out;
116
117	//Connect to TSS and TPM
118	if (contextCreate(&hContext) != TSS_SUCCESS)
119		goto out;
120
121	if (contextConnect(hContext) != TSS_SUCCESS)
122		goto out_close;
123
124	if (contextGetTpm(hContext, &hTpm) != TSS_SUCCESS)
125		goto out_close;
126
127	if (bCheck || !bChangeRequested) {
128		logInfo(_("Checking current status: \n"));
129		if (isWellKnown){
130			szTpmPasswd = (char *)well_known;
131			pswd_len = sizeof(well_known);
132		} else {
133			szTpmPasswd = GETPASSWD(_("Enter owner password: "), &pswd_len, FALSE);
134			if (!szTpmPasswd) {
135				logMsg(_("Failed to get password\n"));
136				goto out_close;
137			}
138		}
139		if (policyGet(hTpm, &hTpmPolicy) != TSS_SUCCESS)
140			goto out_close;
141
142		if (policySetSecret
143		    (hTpmPolicy,
144		     pswd_len, (BYTE *)szTpmPasswd) != TSS_SUCCESS)
145			goto out_close;
146		do {
147			TSS_BOOL bValue;
148			if (tpmGetStatus(hTpm, flags[i].property, &bValue)
149			    != TSS_SUCCESS)
150				goto out_close;
151
152			logMsg("%s Disabled: %s\n", _(flags[i].name),
153			       logBool(mapTssBool(bValue)));
154
155		} while (flags[++i].name);
156		goto out_success;
157	}
158
159	do {
160		if (flags[i].disable) {
161			logDebug(_("Requested to disable: %s ability.\n"),
162				 _(flags[i].name));
163			if (i == owner) {
164				if (isWellKnown){
165					szTpmPasswd = (char *)well_known;
166					pswd_len = sizeof(well_known);
167				} else {
168					szTpmPasswd = GETPASSWD(_("Enter owner password: "),
169								&pswd_len, FALSE);
170					if (!szTpmPasswd) {
171						logMsg(_("Failed to get password\n"));
172						goto out_close;
173					}
174				}
175				if (policyGet(hTpm, &hTpmPolicy) != TSS_SUCCESS)
176					goto out_close;
177
178				if (policySetSecret
179				    (hTpmPolicy,
180				     pswd_len,
181				     (BYTE *)szTpmPasswd) != TSS_SUCCESS)
182					goto out_close;
183			}
184
185			if (tpmSetStatus(hTpm, flags[i].property, 0)
186			    != TSS_SUCCESS)
187				goto out_close;
188			logInfo(_("Disabling %s successful.\n"),
189				_(flags[i].name));
190		}
191	}
192	while (flags[++i].name);
193      out_success:
194	logSuccess(argv[0]);
195	iRc = 0;
196
197      out_close:
198	contextClose(hContext);
199      out:
200	if (szTpmPasswd && !isWellKnown)
201		shredPasswd(szTpmPasswd);
202	return iRc;
203}
204