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 <stdio.h> 23#include <errno.h> 24#include <limits.h> 25 26#include "tpm_tspi.h" 27#include "tpm_utils.h" 28#include "tpm_nvcommon.h" 29 30static unsigned int nvindex; 31static BOOL nvindex_set; 32static unsigned int nvperm; 33static unsigned int nvsize; 34static const char *ownerpass; 35static BOOL ownerWellKnown; 36static BOOL askOwnerPass; 37static const char *datapass; 38static BOOL dataWellKnown; 39static BOOL askDataPass; 40static int end; 41static UINT32 selectedPcrsRead[24]; 42static UINT32 selectedPcrsWrite[24]; 43static UINT32 selectedPcrsReadLen = 0; 44static UINT32 selectedPcrsWriteLen = 0; 45static const char *filename; 46 47TSS_HCONTEXT hContext = 0; 48 49 50static int parse(const int aOpt, const char *aArg) 51{ 52 switch (aOpt) { 53 case 'i': 54 if (parseHexOrDecimal(aArg, &nvindex, 0, UINT_MAX, 55 "NVRAM index") != 0) 56 return -1; 57 nvindex_set = TRUE; 58 break; 59 60 case 'p': 61 if (!strcmp(aArg, "?")) { 62 displayStringsAndValues(permvalues, ""); 63 end = 1; 64 return 0; 65 } 66 if (parseStringWithValues(aArg, permvalues, &nvperm, UINT_MAX, 67 "NVRAM permission") != 0) 68 return -1; 69 break; 70 71 case 's': 72 if (parseHexOrDecimal(aArg, &nvsize, 0, UINT_MAX, 73 "NVRAM index size") != 0) 74 return -1; 75 break; 76 77 case 'o': 78 ownerpass = aArg; 79 if (!ownerpass) 80 askOwnerPass = TRUE; 81 else 82 askOwnerPass = FALSE; 83 ownerWellKnown = FALSE; 84 break; 85 86 case 'y': 87 ownerWellKnown = TRUE; 88 ownerpass = NULL; 89 askOwnerPass = FALSE; 90 break; 91 92 case 'a': 93 datapass = aArg; 94 if (!datapass) 95 askDataPass = TRUE; 96 else 97 askDataPass = FALSE; 98 dataWellKnown = FALSE; 99 break; 100 101 case 'z': 102 dataWellKnown = TRUE; 103 datapass = NULL; 104 askDataPass = FALSE; 105 break; 106 107 case 'u': 108 useUnicode = TRUE; 109 break; 110 111 case 'r': 112 if (aArg && atoi(aArg) >= 0 && atoi(aArg) < 24) { 113 selectedPcrsRead[selectedPcrsReadLen++] = atoi(aArg); 114 } else 115 return -1; 116 break; 117 118 case 'w': 119 if (aArg && atoi(aArg) >= 0 && atoi(aArg) < 24) { 120 selectedPcrsWrite[selectedPcrsWriteLen++] = atoi(aArg); 121 } else 122 return -1; 123 break; 124 125 case 'f': 126 filename = aArg; 127 break; 128 129 default: 130 return -1; 131 } 132 return 0; 133} 134 135static void help(const char* aCmd) 136{ 137 logCmdHelp(aCmd); 138 logUnicodeCmdOption(); 139 logCmdOption("-y, --owner-well-known", 140 _("Use 20 bytes of zeros (TSS_WELL_KNOWN_SECRET) as the " 141 "TPM owner secret")); 142 logCmdOption("-z, --data-well-known", 143 _("Use 20 bytes of zeros (TSS_WELL_KNOWN_SECRET) as the " 144 "NVRAM area's secret")); 145 logOwnerPassCmdOption(); 146 logCmdOption("-a, --pwda", 147 _("NVRAM area password")); 148 logNVIndexCmdOption(); 149 logCmdOption("-s, --size", 150 _("Size of the NVRAM area")); 151 logCmdOption("-r, --rpcrs", 152 _("PCRs to seal the NVRAM area to for reading (use multiple times)")); 153 logCmdOption("-w, --wpcrs", 154 _("PCRs to seal the NVRAM area to for writing (use multiple times)")); 155 logCmdOption("-f, --filename", 156 _("File containing PCR info for the NVRAM area")); 157 158 logCmdOption("-p, --permissions", 159 _("Permissions of the NVRAM area")); 160 displayStringsAndValues(permvalues, " "); 161} 162 163void logInvalidPcrInfoFile() 164{ 165 logError(_("Invalid PCR info file. Format is:\n" 166 "[r/w] [PCR IDX] [SHA-1 ascii]\n\nExample:\n" 167 "r 9 00112233445566778899AABBCCDDEEFF00112233")); 168} 169 170int 171parseNVPermsFile(FILE *f, TSS_HCONTEXT *hContext, TSS_HNVSTORE *nvObject, 172 TSS_HPCRS *hPcrsRead, TSS_HPCRS *hPcrsWrite) 173{ 174 UINT32 pcrSize; 175 char rw; 176 unsigned int pcr, n; 177 char hash_ascii[65], hash_bin[32], save; 178 int rc = -1; 179 180 while (!feof(f)) { 181 errno = 0; 182 n = fscanf(f, "%c %u %s\n", &rw, &pcr, hash_ascii); 183 if (n != 3) { 184 logInvalidPcrInfoFile(); 185 goto out; 186 } else if (errno != 0) { 187 perror("fscanf"); 188 goto out; 189 } 190 191 if (rw != 'r' && rw != 'w') { 192 logInvalidPcrInfoFile(); 193 goto out; 194 } 195 196 if (pcr > 15) { 197 logError(_("Cannot seal NVRAM area to PCR > 15\n")); 198 goto out; 199 } 200 201 for (n = 0; n < strlen(hash_ascii); n += 2) { 202 save = hash_ascii[n + 2]; 203 hash_ascii[n + 2] = '\0'; 204 hash_bin[n/2] = strtoul(&hash_ascii[n], NULL, 16); 205 hash_ascii[n + 2] = save; 206 } 207 pcrSize = n/2; 208 209 if (rw == 'r') { 210 if (*hPcrsRead == NULL_HPCRS) 211 if (contextCreateObject(*hContext, TSS_OBJECT_TYPE_PCRS, 212 TSS_PCRS_STRUCT_INFO_SHORT, 213 hPcrsRead) != TSS_SUCCESS) 214 goto out; 215 216 if (pcrcompositeSetPcrValue(*hPcrsRead, pcr, pcrSize, (BYTE *)hash_bin) 217 != TSS_SUCCESS) 218 goto out; 219 } else { 220 if (*hPcrsWrite == NULL_HPCRS) 221 if (contextCreateObject(*hContext, TSS_OBJECT_TYPE_PCRS, 222 TSS_PCRS_STRUCT_INFO_SHORT, 223 hPcrsWrite) != TSS_SUCCESS) 224 goto out; 225 226 if (pcrcompositeSetPcrValue(*hPcrsWrite, pcr, pcrSize, (BYTE *)hash_bin) 227 != TSS_SUCCESS) 228 goto out; 229 } 230 } 231 232 rc = 0; 233out: 234 return rc; 235} 236 237int main(int argc, char **argv) 238{ 239 TSS_HTPM hTpm; 240 TSS_HNVSTORE nvObject; 241 TSS_FLAG fNvAttrs; 242 TSS_HPOLICY hTpmPolicy, hDataPolicy; 243 int iRc = -1; 244 BYTE well_known_secret[] = TSS_WELL_KNOWN_SECRET; 245 int opswd_len = -1; 246 int dpswd_len = -1; 247 TSS_HPCRS hPcrsRead = 0, hPcrsWrite = 0; 248 struct option hOpts[] = { 249 {"index" , required_argument, NULL, 'i'}, 250 {"size" , required_argument, NULL, 's'}, 251 {"permissions" , required_argument, NULL, 'p'}, 252 {"rpcrs" , required_argument, NULL, 'r'}, 253 {"wpcrs" , required_argument, NULL, 'w'}, 254 {"filename" , required_argument, NULL, 'f'}, 255 {"pwdo" , optional_argument, NULL, 'o'}, 256 {"pwda" , optional_argument, NULL, 'a'}, 257 {"use-unicode" , no_argument, NULL, 'u'}, 258 {"data-well-known" , no_argument, NULL, 'z'}, 259 {"owner-well-known", no_argument, NULL, 'y'}, 260 {NULL , no_argument, NULL, 0}, 261 }; 262 TSS_FLAG initFlag = TSS_PCRS_STRUCT_INFO_SHORT; 263 UINT32 localityValue = TPM_LOC_ZERO | TPM_LOC_ONE | TPM_LOC_TWO | 264 TPM_LOC_THREE | TPM_LOC_FOUR; 265 266 initIntlSys(); 267 268 if (genericOptHandler 269 (argc, argv, "i:s:p:o:a:r:w:f:yzu", hOpts, 270 sizeof(hOpts) / sizeof(struct option), parse, help) != 0) 271 goto out; 272 273 if (end) { 274 iRc = 0; 275 goto out; 276 } 277 278 if (!nvindex_set) { 279 logError(_("You must provide an index for the NVRAM area.\n")); 280 goto out; 281 } 282 283 if (nvperm == 0 && 284 (UINT32)nvindex != TPM_NV_INDEX_LOCK && 285 (UINT32)nvindex != TPM_NV_INDEX0) { 286 logError(_("You must provide permission bits for the NVRAM area.\n")); 287 goto out; 288 } 289 290 logDebug("permissions = 0x%08x\n", nvperm); 291 292 if (contextCreate(&hContext) != TSS_SUCCESS) 293 goto out; 294 295 if (contextConnect(hContext) != TSS_SUCCESS) 296 goto out_close; 297 298 if (contextGetTpm(hContext, &hTpm) != TSS_SUCCESS) 299 goto out_close; 300 301 fNvAttrs = 0; 302 303 if (contextCreateObject(hContext, 304 TSS_OBJECT_TYPE_NV, 305 fNvAttrs, 306 &nvObject) != TSS_SUCCESS) 307 goto out_close; 308 309 if (askOwnerPass) { 310 ownerpass = _GETPASSWD(_("Enter owner password: "), &opswd_len, 311 FALSE, useUnicode ); 312 if (!ownerpass) { 313 logError(_("Failed to get owner password\n")); 314 goto out_close; 315 } 316 } 317 318 if (ownerpass || ownerWellKnown) { 319 if (policyGet(hTpm, &hTpmPolicy) != TSS_SUCCESS) 320 goto out_close; 321 if (ownerpass) { 322 if (opswd_len < 0) 323 opswd_len = strlen(ownerpass); 324 if (policySetSecret(hTpmPolicy, opswd_len, 325 (BYTE *)ownerpass) != TSS_SUCCESS) 326 goto out_close; 327 } else { 328 if (policySetSecret(hTpmPolicy, TCPA_SHA1_160_HASH_LEN, 329 (BYTE *)well_known_secret) != TSS_SUCCESS) 330 goto out_close; 331 } 332 } 333 334 if (askDataPass) { 335 datapass = _GETPASSWD(_("Enter NVRAM data password: "), &dpswd_len, 336 TRUE, useUnicode ); 337 if (!datapass) { 338 logError(_("Failed to get NVRAM data password\n")); 339 goto out_close; 340 } 341 } 342 343 if (datapass || dataWellKnown) { 344 if (contextCreateObject 345 (hContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, 346 &hDataPolicy) != TSS_SUCCESS) 347 goto out_close; 348 349 if (datapass) { 350 if (dpswd_len < 0) 351 dpswd_len = strlen(datapass); 352 if (policySetSecret(hDataPolicy, dpswd_len, 353 (BYTE *)datapass) != TSS_SUCCESS) 354 goto out_close; 355 } else { 356 if (policySetSecret(hDataPolicy, TCPA_SHA1_160_HASH_LEN, 357 (BYTE *)well_known_secret) != TSS_SUCCESS) 358 goto out_close; 359 } 360 361 if (Tspi_Policy_AssignToObject(hDataPolicy, nvObject) != 362 TSS_SUCCESS) 363 goto out_close; 364 } 365 366 if (Tspi_SetAttribUint32(nvObject, 367 TSS_TSPATTRIB_NV_INDEX, 368 0, 369 nvindex) != TSS_SUCCESS) 370 goto out_close_obj; 371 372 if (Tspi_SetAttribUint32(nvObject, 373 TSS_TSPATTRIB_NV_PERMISSIONS, 374 0, 375 nvperm) != TSS_SUCCESS) 376 goto out_close_obj; 377 378 if (Tspi_SetAttribUint32(nvObject, 379 TSS_TSPATTRIB_NV_DATASIZE, 380 0, 381 nvsize) != TSS_SUCCESS) 382 goto out_close_obj; 383 384 if (selectedPcrsReadLen) { 385 UINT32 pcrSize; 386 BYTE *pcrValue; 387 UINT32 i; 388 389 for (i = 0; i < selectedPcrsReadLen; i++) { 390 if (selectedPcrsRead[i] > 15) { 391 logError(_("Cannot seal NVRAM area to PCR > 15\n")); 392 goto out_close; 393 } 394 } 395 396 if (contextCreateObject(hContext, TSS_OBJECT_TYPE_PCRS, initFlag, 397 &hPcrsRead) != TSS_SUCCESS) 398 goto out_close; 399 400 for (i = 0; i < selectedPcrsReadLen; i++) { 401 if (tpmPcrRead(hTpm, selectedPcrsRead[i], &pcrSize, &pcrValue) != 402 TSS_SUCCESS) 403 goto out_close; 404 405 if (pcrcompositeSetPcrValue(hPcrsRead, selectedPcrsRead[i], 406 pcrSize, pcrValue) 407 != TSS_SUCCESS) 408 goto out_close; 409 } 410 } 411 412 if (selectedPcrsWriteLen) { 413 UINT32 pcrSize; 414 BYTE *pcrValue; 415 UINT32 i; 416 417 for (i = 0; i < selectedPcrsWriteLen; i++) { 418 if (selectedPcrsWrite[i] > 15) { 419 logError(_("Cannot seal NVRAM area to PCR > 15\n")); 420 goto out_close; 421 } 422 } 423 424 if (contextCreateObject(hContext, TSS_OBJECT_TYPE_PCRS, initFlag, 425 &hPcrsWrite) != TSS_SUCCESS) 426 goto out_close; 427 428 for (i = 0; i < selectedPcrsWriteLen; i++) { 429 if (tpmPcrRead(hTpm, selectedPcrsWrite[i], &pcrSize, &pcrValue) != 430 TSS_SUCCESS) 431 goto out_close; 432 433 if (pcrcompositeSetPcrValue(hPcrsWrite, selectedPcrsWrite[i], 434 pcrSize, pcrValue) 435 != TSS_SUCCESS) 436 goto out_close; 437 } 438 } 439 440 if (filename) { 441 FILE *f; 442 443 f = fopen(filename, "r"); 444 if (!f) { 445 logError(_("Could not access file '%s'\n"), filename); 446 goto out_close_obj; 447 } 448 449 if (parseNVPermsFile(f, &hContext, &nvObject, &hPcrsRead, &hPcrsWrite) 450 != TSS_SUCCESS) 451 goto out_close_obj; 452 } 453 454 if (hPcrsRead) 455 if (pcrcompositeSetPcrLocality(hPcrsRead, localityValue) != TSS_SUCCESS) 456 goto out_close; 457 458 if (hPcrsWrite) 459 if (pcrcompositeSetPcrLocality(hPcrsWrite, localityValue) != TSS_SUCCESS) 460 goto out_close; 461 462 if (NVDefineSpace(nvObject, hPcrsRead, hPcrsWrite) != TSS_SUCCESS) 463 goto out_close; 464 465 logMsg(_("Successfully created NVRAM area at index 0x%x (%u).\n"), 466 nvindex, nvindex); 467 468 iRc = 0; 469 470 goto out_close; 471 472 out_close_obj: 473 contextCloseObject(hContext, nvObject); 474 475 out_close: 476 contextClose(hContext); 477 478 out: 479 return iRc; 480} 481