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 */ 29struct 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 */ 41enum { 42 cmdEnable = 0, 43 hwdEnable, 44 lifeLock, 45 present, 46 lock, 47 num_flags 48}; 49 50static 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}; 58static BOOL bCheck = FALSE; 59static BOOL bChangeRequested = FALSE; 60static BOOL bYes = FALSE; 61static TSS_BOOL bValue; 62static BOOL isWellKnown = FALSE; 63static BYTE well_known[] = TSS_WELL_KNOWN_SECRET; 64TSS_HCONTEXT hContext = 0; 65 66 67static 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 93static 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 163static 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 (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 */ 259int 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