xref: /netbsd-src/crypto/external/cpl/tpm-tools/dist/src/tpm_mgmt/tpm_present.c (revision 8cc77b481a5f7140fcf2d44453fb92dcd15fbbc6)
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, 2006 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_utils.h"
23 #include "tpm_tspi.h"
24 
25 /*
26  * Never set change to false.
27  * Value doesn't matter for the locks.
28  */
29 struct physFlag {
30 	char *name;
31 	TSS_FLAG property;
32 	BOOL change;
33 	BOOL value;
34 };
35 
36 /*
37  * Order is important.
38  * First must set cmd and hw enable correctly followed by the lock.
39  * Then setting presence can be attempted followed by the lock
40  */
41 enum {
42 	cmdEnable = 0,
43 	hwdEnable,
44 	lifeLock,
45 	present,
46 	lock,
47 	num_flags
48 };
49 
50 static struct physFlag flags[] = {
51 	{N_("Command Enable"), TSS_TPMSTATUS_PHYSPRES_CMDENABLE},
52 	{N_("Hardware Enable"), TSS_TPMSTATUS_PHYSPRES_HWENABLE},
53 	{N_("Lifetime Lock"), TSS_TPMSTATUS_PHYSPRES_LIFETIMELOCK},
54 	{N_("Physical Presence"), TSS_TPMSTATUS_PHYSPRESENCE},
55 	{N_("Lock"), TSS_TPMSTATUS_PHYSPRES_LOCK},
56 	{0, 0, 0, 0}
57 };
58 static BOOL bCheck = FALSE;
59 static BOOL bChangeRequested = FALSE;
60 static BOOL bYes = FALSE;
61 static TSS_BOOL bValue;
62 static BOOL isWellKnown = FALSE;
63 static BYTE well_known[] = TSS_WELL_KNOWN_SECRET;
64 TSS_HCONTEXT hContext = 0;
65 
66 
help(const char * aCmd)67 static void help(const char *aCmd)
68 {
69 	logCmdHelp(aCmd);
70 	logUnicodeCmdOption();
71 	logCmdOption("-s, --status",
72 		     _("Report current physical presence states."));
73 	logCmdOption("-a, --assert", _("Assert that admin is present."));
74 	logCmdOption("-c, --clear", _("Clear assertion of admin presence."));
75 	logCmdOption("--lock",
76 		     _("Lock TPM presence assertion into specified state."));
77 	logCmdOption("--enable-cmd",
78 		     _("Allow TPM to accept Physical Presence Command."));
79 	logCmdOption("--disable-cmd",
80 		     _("Disallow TPM to accept Physical Presence Command."));
81 	logCmdOption("--enable-hw",
82 		     _("Allow TPM to accept Hardware Physical Presence."));
83 	logCmdOption("--disable-hw",
84 		     _("Disallow TPM to accept Hardware Physical Presence."));
85 	logCmdOption("--set-lifetime-lock",
86 		     _("Prevent further modification of TPM Physical Presence\n\t\tCommand and Hardware Enablement states.\n\t\tTHIS ACTION IS PERMANENT AND CAN NEVER BE UNDONE."));
87 	logCmdOption("-y, --yes",
88 		     _("Automatically respond yes to all prompts.  Only use\n\t\tthis if you are sure of the current state and don't want\n\t\tany textra checking done before setting the lifetime lock"));
89 	logCmdOption("-z, --well-known",
90 		     _("Use 20 bytes of zeros (TSS_WELL_KNOWN_SECRET) as the TPM secret authorization data."));
91 }
92 
parse(const int aOpt,const char * aArg)93 static int parse(const int aOpt, const char *aArg)
94 {
95 	switch (aOpt) {
96 	case 's':
97 		logDebug(_("Changing mode to check status.\n"));
98 		bCheck = TRUE;
99 		break;
100 	case 'a':
101 		logDebug(_("Changing mode to assert presence.\n"));
102 		flags[present].change = TRUE;
103 		flags[present].value = TRUE;
104 		bChangeRequested = TRUE;
105 		break;
106 	case 'c':
107 		logDebug(_("Changing mode to clear presence.\n"));
108 		flags[present].change = TRUE;
109 		flags[present].value = FALSE;
110 		bChangeRequested = TRUE;
111 		break;
112 	case 'k':
113 		logDebug(_("Changing mode to lock presence.\n"));
114 		flags[lock].change = TRUE;
115 		flags[lock].value = TRUE;
116 		bChangeRequested = TRUE;
117 		break;
118 	case 'm':
119 		logDebug(_("Changing mode to enable command presence.\n"));
120 		flags[cmdEnable].change = TRUE;
121 		flags[cmdEnable].value = TRUE;
122 		bChangeRequested = TRUE;
123 		break;
124 	case 'd':
125 		logDebug(_("Changing mode to disable command presence.\n"));
126 		flags[cmdEnable].change = TRUE;
127 		flags[cmdEnable].value = FALSE;
128 		bChangeRequested = TRUE;
129 		break;
130 	case 'e':
131 		logDebug(_("Changing mode to enable hardware presence.\n"));
132 		flags[hwdEnable].change = TRUE;
133 		flags[hwdEnable].value = TRUE;
134 		bChangeRequested = TRUE;
135 		break;
136 	case 'h':
137 		logDebug(_("Changing mode to disable hardware presence.\n"));
138 		flags[hwdEnable].change = TRUE;
139 		flags[hwdEnable].value = FALSE;
140 		bChangeRequested = TRUE;
141 		break;
142 	case 't':
143 		logDebug(_("Changing mode to set lifetime presence lock.\n"));
144 		flags[lifeLock].change = TRUE;
145 		flags[lifeLock].value = TRUE;
146 		bChangeRequested = TRUE;
147 		break;
148 	case 'y':
149 		logDebug(_("Changing mode to automatically answer yes.\n"));
150 		bYes = TRUE;
151 		break;
152 	case 'z':
153 		logDebug(_("Using TSS_WELL_KNOWN_SECRET to authorize the TPM command\n"));
154 		isWellKnown = TRUE;
155 		break;
156 	default:
157 		return -1;
158 	}
159 	return 0;
160 
161 }
162 
confirmLifeLock(TSS_HCONTEXT hContext,TSS_HTPM hTpm)163 static BOOL confirmLifeLock(TSS_HCONTEXT hContext, TSS_HTPM hTpm)
164 {
165 
166 	TSS_BOOL bCmd, bHwd;
167 	BOOL bRc;
168 	TSS_HPOLICY hTpmPolicy;
169 	char *pwd = NULL;
170 	int pswd_len;
171 	char rsp[5];
172 	int scanCount;
173 
174 	//get status w/o owner auth (FAILS 1.1, should PASS 1.2)
175 	if (tpmGetStatus(hTpm, flags[cmdEnable].property, &bCmd) !=
176 	    TSS_SUCCESS
177 	    || tpmGetStatus(hTpm, flags[hwdEnable].property,
178 			    &bHwd) != TSS_SUCCESS) {
179 		logDebug
180 		    (_("Unable to determine current state without authorization\n"));
181 		if (isTpmOwned(hContext)) {
182 			logDebug(_("TPM is owned\n"));
183 			if (isWellKnown) {
184 				pwd = (char *)well_known;
185 				pswd_len = sizeof(well_known);
186 			} else {
187 				// Prompt for owner password
188 				pwd = GETPASSWD(_("Enter owner password: "), &pswd_len, FALSE);
189 				if (!pwd) {
190 					logMsg(_("Failed to get password\n"));
191 					goto warn;
192 				}
193 			}
194 
195 			if (policyGet(hTpm, &hTpmPolicy) != TSS_SUCCESS)
196 				goto warn;
197 
198 			if (policySetSecret(hTpmPolicy, pswd_len, (BYTE *)pwd)
199 			    != TSS_SUCCESS)
200 				goto warn;
201 			//get status w/ owner auth
202 			if (tpmGetStatus
203 			    (hTpm, flags[cmdEnable].property,
204 			     &bCmd) != TSS_SUCCESS
205 			    || tpmGetStatus(hTpm,
206 					    flags[hwdEnable].property,
207 					    &bHwd) != TSS_SUCCESS) {
208 				logDebug
209 				    (_("Unable to determine current state with the entered password.\n"));
210 				goto warn;
211 			}
212 			goto give_vals;
213 		} else {	//can't determine values
214 		      warn:
215 			logMsg
216 			    (_("Unable to programatically determine the current setting of TPM Physcial Presence Command Enable and Hardware Enable states.  Make sure you are aware of and comfortable with the current states.\n"));
217 		}
218 	} else {
219 	      give_vals:
220 		logMsg(_("Current State:\n"));
221 		logMsg("\t%s: %s\n", _(flags[cmdEnable].name), logBool(mapTssBool(bCmd)));
222 		logMsg("\t%s: %s\n", _(flags[hwdEnable].name), logBool(mapTssBool(bHwd)));
223 		logMsg
224 		    (_("These will be the permanent values if you choose to proceed.\n"));
225 	}
226 	logMsg
227 	    (_("This command cannot be undone.  Are you sure you want to continue?[y/N]\n"));
228 	scanCount = scanf("%5s", rsp);
229 
230 	 /* TRANSLATORS: this should be the affirmative letter that was  prompted for in the message corresponding to: "Are you sure you want to continue?[y/N]" */
231 	if (scanCount >= 1 && strcmp(rsp, _("y")) == 0) {
232 		logMsg
233 		    (_("Setting the lifetime lock was confirmed.\nContinuing.\n"));
234 		bRc = TRUE;
235 
236 	} else {
237 		logMsg
238 		    (_("Continuing to set the lifetime lock was declined.\nAction canceled.\n"));
239 		bRc = FALSE;
240 	}
241 
242 	if (hTpmPolicy)
243 		policyFlushSecret(hTpmPolicy);
244 
245 	if (pwd && !isWellKnown)
246 		shredPasswd(pwd);
247 
248 	return bRc;
249 }
250 
251 
252 
253 /*
254  * Affect: Toggle TPM presence states
255  * Default: Display current states
256  * Requires: Display requires owner auth.
257  * 	Lifetime lock will attempt owner auth to warn about current states before confirming
258  */
main(int argc,char ** argv)259 int main(int argc, char **argv)
260 {
261 
262 	char *szTpmPasswd = NULL;
263 	int pswd_len;
264 	TSS_HTPM hTpm;
265 	TSS_HPOLICY hTpmPolicy;
266 	int iRc = -1;
267 	int i = 0;
268 	struct option opts[] = { {"status", no_argument, NULL, 's'},
269 	{"assert", no_argument, NULL, 'a'},
270 	{"clear", no_argument, NULL, 'c'},
271 	{"lock", no_argument, NULL, 'k'},
272 	{"enable-cmd", no_argument, NULL, 'm'},
273 	{"disable-cmd", no_argument, NULL, 'd'},
274 	{"enable-hw", no_argument, NULL, 'e'},
275 	{"disable-hw", no_argument, NULL, 'w'},
276 	{"set-lifetime-lock", no_argument, NULL, 't'},
277 	{"yes", no_argument, NULL, 'y'},
278 	{"well-known", no_argument, NULL, 'z'},
279 	};
280 
281 	initIntlSys();
282 
283 	if (genericOptHandler
284 	    (argc, argv, "acsyz", opts,
285 	     sizeof(opts) / sizeof(struct option), parse, help) != 0)
286 		goto out;
287 
288 	//Connect to TSS and TPM
289 	if (contextCreate(&hContext) != TSS_SUCCESS)
290 		goto out;
291 
292 	if (contextConnect(hContext) != TSS_SUCCESS)
293 		goto out_close;
294 
295 	if (contextGetTpm(hContext, &hTpm) != TSS_SUCCESS)
296 		goto out_close;
297 
298 	if (bCheck || !bChangeRequested) {
299 		logInfo(_("Checking current status: \n"));
300 		if (isWellKnown) {
301 			szTpmPasswd = (char *)well_known;
302 			pswd_len = sizeof(well_known);
303 		} else {
304 			// Prompt for owner password
305 			szTpmPasswd = GETPASSWD(_("Enter owner password: "), &pswd_len, FALSE);
306 			if (!szTpmPasswd) {
307 				logMsg(_("Failed to get password\n"));
308 				goto out_close;
309 			}
310 		}
311 
312 		if (policyGet(hTpm, &hTpmPolicy) != TSS_SUCCESS)
313 			goto out_close;
314 
315 		if (policySetSecret(hTpmPolicy, pswd_len,
316 				    (BYTE *)szTpmPasswd) != TSS_SUCCESS)
317 			goto out_close;
318 
319 		logMsg(_("Physical Presence Status:\n"));
320 
321 		do {
322 			if (tpmGetStatus(hTpm, flags[i].property,
323 					 &bValue) != TSS_SUCCESS)
324 				goto out_close;
325 			logMsg("\t%s: %s\n", _(flags[i].name),
326 			       logBool(mapTssBool(bValue)));
327 		} while (flags[++i].name);
328 
329 		goto out_success;
330 	}
331 
332 	do {
333 		if (flags[i].change) {
334 			logInfo(_("Requested to Change %s to %s\n"),
335 				_(flags[i].name), logBool(flags[i].value));
336 
337 			if (i == lifeLock && !
338 			    (bYes || confirmLifeLock(hContext, hTpm)))
339 				continue;
340 
341 			if (tpmSetStatus(hTpm, flags[i].property,
342 					 flags[i].value) != TSS_SUCCESS) {
343 				logError(_("Change to %s Failed\n"),
344 					 _(flags[i].name));
345 				goto out;
346 			}
347 			logInfo(_("Change to %s Successful\n"),
348 				_(flags[i].name));
349 		}
350 	} while (flags[++i].name);
351 
352 out_success:
353 	logSuccess(argv[0]);
354 	iRc = 0;
355 out_close:
356 	contextClose(hContext);
357 out:
358     if (szTpmPasswd && !isWellKnown)
359 	shredPasswd( szTpmPasswd );
360 	return iRc;
361 }
362