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 <limits.h>
23 #include <ctype.h>
24
25 #include "tpm_nvcommon.h"
26 #include "tpm_tspi.h"
27 #include "tpm_utils.h"
28
29 const struct strings_with_values permvalues[] = {
30 {
31 .name = "AUTHREAD",
32 .value = TPM_NV_PER_AUTHREAD,
33 .desc = _("reading requires NVRAM area authorization"),
34 },
35 {
36 .name = "AUTHWRITE",
37 .value = TPM_NV_PER_AUTHWRITE,
38 .desc = _("writing requires NVRAM area authorization"),
39 },
40 {
41 .name = "OWNERREAD",
42 .value = TPM_NV_PER_OWNERREAD,
43 .desc = _("writing requires owner authorization"),
44 },
45 {
46 .name = "OWNERWRITE",
47 .value = TPM_NV_PER_OWNERWRITE,
48 .desc = _("reading requires owner authorization"),
49 },
50 {
51 .name = "PPREAD",
52 .value = TPM_NV_PER_PPREAD,
53 .desc = _("writing requires physical presence"),
54 },
55 {
56 .name = "PPWRITE",
57 .value = TPM_NV_PER_PPWRITE,
58 .desc = _("reading requires physical presence"),
59 },
60 {
61 .name = "GLOBALLOCK",
62 .value = TPM_NV_PER_GLOBALLOCK,
63 .desc = _("write to index 0 locks the NVRAM area until "
64 "TPM_STARTUP(ST_CLEAR)"),
65 },
66 {
67 .name = "READ_STCLEAR",
68 .value = TPM_NV_PER_READ_STCLEAR,
69 .desc = _("a read with size 0 to the same index prevents further "
70 "reading until ST_STARTUP(ST_CLEAR)"),
71 },
72 {
73 .name = "WRITE_STCLEAR",
74 .value = TPM_NV_PER_WRITE_STCLEAR,
75 .desc = _("a write with size 0 to the same index prevents further "
76 "writing until ST_STARTUP(ST_CLEAR)"),
77 },
78 {
79 .name = "WRITEDEFINE",
80 .value = TPM_NV_PER_WRITEDEFINE,
81 .desc = _("a write with size 0 to the same index locks the "
82 "NVRAM area permanently"),
83 },
84 {
85 .name = "WRITEALL",
86 .value = TPM_NV_PER_WRITEALL,
87 .desc = _("the value must be written in a single operation"),
88 },
89 {
90 .name = NULL,
91 },
92 };
93
94
displayStringsAndValues(const struct strings_with_values * svals,const char * indent)95 void displayStringsAndValues(const struct strings_with_values *svals,
96 const char *indent)
97 {
98 unsigned int i;
99
100 logMsg("%sThe following strings are available:\n", indent);
101 for (i = 0; svals[i].name; i++)
102 logMsg("%s%15s : %s\n", indent, svals[i].name, svals[i].desc);
103 }
104
105
parseStringWithValues(const char * aArg,const struct strings_with_values * svals,unsigned int * x,unsigned int maximum,const char * name)106 int parseStringWithValues(const char *aArg,
107 const struct strings_with_values *svals,
108 unsigned int *x, unsigned int maximum,
109 const char *name)
110 {
111 unsigned int offset = 0;
112 int i, num, numbytes;
113 size_t totlen = strlen(aArg);
114 *x = 0;
115
116 while (offset < totlen) {
117 int found = 0;
118
119 while (isspace(*(aArg + offset)))
120 offset++;
121
122 for (i = 0; svals[i].name; i++) {
123 size_t len = strlen(svals[i].name);
124 if (strncmp(aArg + offset, svals[i].name, len) == 0 &&
125 (aArg[offset+len] == '|' ||
126 aArg[offset+len] == 0)) {
127 *x |= svals[i].value;
128 offset += len + 1;
129 found = 1;
130 break;
131 }
132 }
133
134 if (!found) {
135 if (strncmp(aArg + offset, "0x", 2) == 0) {
136 if (sscanf(aArg + offset, "%x%n", &num, &numbytes)
137 != 1) {
138 logError(_("Could not parse hexadecimal "
139 "number in %s.\n"),
140 aArg);
141 return -1;
142 }
143 if (aArg[offset+numbytes] != '|' ||
144 aArg[offset+numbytes] != 0) {
145 logError(_("Illegal character following "
146 "hexadecimal number in %s\n"),
147 aArg + offset);
148 return -1;
149 }
150 *x |= num;
151
152 offset += numbytes + 1;
153 found = 1;
154 }
155 }
156
157 while (!found) {
158 if (!isdigit(*(aArg+offset)))
159 break;
160
161 if (sscanf(aArg + offset, "%u%n", &num, &numbytes) != 1) {
162 logError(_("Could not parse data in %s.\n"),
163 aArg + offset);
164 return -1;
165 }
166
167 if (aArg[offset+numbytes] != '|' &&
168 aArg[offset+numbytes] != 0) {
169 logError(_("Illegal character following decimal "
170 "number in %s\n"),
171 aArg + offset);
172 return -1;
173 }
174 *x |= num;
175
176 offset += numbytes + 1;
177 found = 1;
178 break;
179 }
180
181 if (!found) {
182 logError(_("Unknown element in %s: %s.\n"),
183 name, aArg + offset);
184 return -1;
185 }
186 }
187
188 return 0;
189 }
190
191
printValueAsStrings(unsigned int value,const struct strings_with_values * svals)192 char *printValueAsStrings(unsigned int value,
193 const struct strings_with_values *svals)
194 {
195 unsigned int mask = (1 << 31), i,c;
196 unsigned int buffer_size = 1024;
197 char *buffer = calloc(1, buffer_size);
198 char printbuf[30];
199 size_t len;
200
201 c = 0;
202
203 while (mask && value) {
204 if (value & mask) {
205 for (i = 0; svals[i].name; i++) {
206 if (svals[i].value == mask) {
207 len = strlen(svals[i].name);
208 if (len + strlen(buffer) + 1 >
209 buffer_size) {
210 buffer_size += 1024;
211 buffer = realloc(buffer,
212 buffer_size);
213 if (!buffer)
214 return NULL;
215 }
216 if (c)
217 strcat(buffer, "|");
218 strcat(buffer, svals[i].name);
219 c ++;
220 value ^= mask;
221 break;
222 }
223 }
224 }
225 mask >>= 1;
226 }
227 if (value) {
228 snprintf(printbuf, sizeof(printbuf), "%s0x%x",
229 c ? "|" : "",
230 value);
231 len = strlen(printbuf);
232 if (len + strlen(buffer) + 1 > buffer_size) {
233 buffer_size += 1024;
234 buffer = realloc(buffer,
235 buffer_size);
236 if (!buffer)
237 return NULL;
238 }
239 if (c)
240 strcat(buffer, printbuf);
241 }
242 return buffer;
243 }
244
245
parseHexOrDecimal(const char * aArg,unsigned int * x,unsigned int minimum,unsigned int maximum,const char * name)246 int parseHexOrDecimal(const char *aArg, unsigned int *x,
247 unsigned int minimum, unsigned int maximum,
248 const char *name)
249 {
250 while (isspace(*aArg))
251 aArg++;
252
253 if (strncmp(aArg, "0x", 2) == 0) {
254 if (sscanf(aArg, "%x", x) != 1) {
255 return -1;
256 }
257 } else {
258 if (!isdigit(*aArg)) {
259 fprintf(stderr,
260 "%s must be a positive integer.\n", name);
261 return -1;
262 }
263
264 if (sscanf(aArg, "%u", x) != 1) {
265 return -1;
266 }
267 }
268
269 if ((*x > maximum) || (*x < minimum)) {
270 fprintf(stderr, "%s is out of valid range [%u, %u]\n",
271 name, minimum, maximum);
272 return -1;
273 }
274
275 return 0;
276 }
277
278
getNVDataPublic(TSS_HTPM hTpm,TPM_NV_INDEX nvindex,TPM_NV_DATA_PUBLIC ** pub)279 TSS_RESULT getNVDataPublic(TSS_HTPM hTpm, TPM_NV_INDEX nvindex,
280 TPM_NV_DATA_PUBLIC **pub)
281 {
282 TSS_RESULT res;
283 UINT32 ulResultLen;
284 BYTE *pResult;
285 UINT64 off = 0;
286
287 res = getCapability(hTpm, TSS_TPMCAP_NV_INDEX, sizeof(UINT32),
288 (BYTE *)&nvindex, &ulResultLen, &pResult);
289
290 if (res != TSS_SUCCESS)
291 return res;
292
293 *pub = calloc(1, sizeof(TPM_NV_DATA_PUBLIC));
294 if (*pub == NULL) {
295 res = TSS_E_OUTOFMEMORY;
296 goto err_exit;
297 }
298
299 res = unloadNVDataPublic(&off, pResult, ulResultLen, *pub);
300
301 if (res != TSS_SUCCESS) {
302 freeNVDataPublic(*pub);
303 *pub = NULL;
304 }
305 err_exit:
306 return res;
307 }
308
freeNVDataPublic(TPM_NV_DATA_PUBLIC * pub)309 void freeNVDataPublic(TPM_NV_DATA_PUBLIC *pub)
310 {
311 if (!pub)
312 return;
313
314 free(pub->pcrInfoRead.pcrSelection.pcrSelect);
315 free(pub->pcrInfoWrite.pcrSelection.pcrSelect);
316 free(pub);
317 }
318