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
30 static unsigned int nvindex;
31 static BOOL nvindex_set;
32 static unsigned int nvperm;
33 static unsigned int nvsize;
34 static const char *ownerpass;
35 static BOOL ownerWellKnown;
36 static BOOL askOwnerPass;
37 static const char *datapass;
38 static BOOL dataWellKnown;
39 static BOOL askDataPass;
40 static int end;
41 static UINT32 selectedPcrsRead[24];
42 static UINT32 selectedPcrsWrite[24];
43 static UINT32 selectedPcrsReadLen = 0;
44 static UINT32 selectedPcrsWriteLen = 0;
45 static const char *filename;
46
47 TSS_HCONTEXT hContext = 0;
48
49
parse(const int aOpt,const char * aArg)50 static 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
help(const char * aCmd)135 static 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
logInvalidPcrInfoFile()163 void 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
170 int
parseNVPermsFile(FILE * f,TSS_HCONTEXT * hContext,TSS_HNVSTORE * nvObject,TSS_HPCRS * hPcrsRead,TSS_HPCRS * hPcrsWrite)171 parseNVPermsFile(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;
233 out:
234 return rc;
235 }
236
main(int argc,char ** argv)237 int 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