Skip to content

Commit 3b8c048

Browse files
author
Kent Yoder
committed
tpm_nvdefinespace: add support for PCR sealing
This patch adds the ability to seal an NVRAM area to PCR states for both reading and writing. PCR indices are passed in two ways. 1. Repeatedly using the -r (read PCR state) and -w (write PCR state) options. This will cause tpm_nvdefine to read the current PCR value from the TPM and use that to lock the NV area for reading or writing. 2. Using the -f option to pass a file containing PCR values. The format of the file is this: [r/w] [PCR index] [Hash value in ascii hex] example: r 12 00112233445566778899AABBCCDDEEFF001122233 w 15 00112233445566778899AABBCCDDEEFF001122233 This would lock the NVRAM area such that PCR 12 must have the listed hash value in order to be read, and PCR 15 such that it must have the same hash value to be written. Signed-off-by: Kent Yoder <key@linux.vnet.ibm.com>
1 parent 3bca4e6 commit 3b8c048

File tree

1 file changed

+193
-4
lines changed

1 file changed

+193
-4
lines changed

‎src/tpm_mgmt/tpm_nvdefine.c

Lines changed: 193 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
* http://www.opensource.org/licenses/cpl1.0.php.
2020
*/
2121

22+
#include <stdio.h>
23+
#include <errno.h>
2224
#include <limits.h>
2325

2426
#include "tpm_tspi.h"
@@ -36,6 +38,11 @@ static const char *datapass;
3638
static BOOL dataWellKnown;
3739
static BOOL askDataPass;
3840
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;
3946

4047
TSS_HCONTEXT hContext = 0;
4148

@@ -101,6 +108,24 @@ static int parse(const int aOpt, const char *aArg)
101108
useUnicode = TRUE;
102109
break;
103110

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+
104129
default:
105130
return -1;
106131
}
@@ -123,12 +148,92 @@ static void help(const char* aCmd)
123148
logNVIndexCmdOption();
124149
logCmdOption("-s, --size",
125150
_("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+
126158
logCmdOption("-p, --permissions",
127159
_("Permissions of the NVRAM area"));
128-
129160
displayStringsAndValues(permvalues, " ");
130161
}
131162

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
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+
132237
int main(int argc, char **argv)
133238
{
134239
TSS_HTPM hTpm;
@@ -139,22 +244,29 @@ int main(int argc, char **argv)
139244
BYTE well_known_secret[] = TSS_WELL_KNOWN_SECRET;
140245
int opswd_len = -1;
141246
int dpswd_len = -1;
247+
TSS_HPCRS hPcrsRead = 0, hPcrsWrite = 0;
142248
struct option hOpts[] = {
143249
{"index" , required_argument, NULL, 'i'},
144250
{"size" , required_argument, NULL, 's'},
145251
{"permissions" , required_argument, NULL, 'p'},
252+
{"rpcrs" , required_argument, NULL, 'r'},
253+
{"wpcrs" , required_argument, NULL, 'w'},
254+
{"filename" , required_argument, NULL, 'f'},
146255
{"pwdo" , optional_argument, NULL, 'o'},
147256
{"pwda" , optional_argument, NULL, 'a'},
148257
{"use-unicode" , no_argument, NULL, 'u'},
149258
{"data-well-known" , no_argument, NULL, 'z'},
150259
{"owner-well-known", no_argument, NULL, 'y'},
151260
{NULL , no_argument, NULL, 0},
152261
};
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;
153265

154266
initIntlSys();
155267

156268
if (genericOptHandler
157-
(argc, argv, "i:s:p:o:a:yzu", hOpts,
269+
(argc, argv, "i:s:p:o:a:r:w:f:yzu", hOpts,
158270
sizeof(hOpts) / sizeof(struct option), parse, help) != 0)
159271
goto out;
160272

@@ -269,8 +381,85 @@ int main(int argc, char **argv)
269381
nvsize) != TSS_SUCCESS)
270382
goto out_close_obj;
271383

272-
if (NVDefineSpace(nvObject, (TSS_HPCRS)0, (TSS_HPCRS)0) !=
273-
TSS_SUCCESS)
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)
274463
goto out_close;
275464

276465
logMsg(_("Successfully created NVRAM area at index 0x%x (%u).\n"),

0 commit comments

Comments
 (0)