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 <sys/stat.h>
23 #include <limits.h>
24 #include <ctype.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <sys/stat.h>
28
29 #include "tpm_nvcommon.h"
30 #include "tpm_tspi.h"
31 #include "tpm_utils.h"
32
33 static unsigned int nvindex;
34 static unsigned int offset;
35 static unsigned int length;
36 static BOOL length_set;
37 static const char *filename;
38 static BOOL passWellKnown;
39 static const char *password;
40 static BOOL askPassword;
41
42 TSS_HCONTEXT hContext = 0;
43
44
parse(const int aOpt,const char * aArg)45 static int parse(const int aOpt, const char *aArg)
46 {
47
48 switch (aOpt) {
49 case 'i':
50 if (parseHexOrDecimal(aArg, &nvindex, 0, UINT_MAX,
51 "NVRAM index") != 0)
52 return -1;
53 break;
54
55 case 'n':
56 if (parseHexOrDecimal(aArg, &offset, 0, UINT_MAX,
57 "read offset") != 0)
58 return -1;
59 break;
60
61 case 's':
62 if (parseHexOrDecimal(aArg, &length, 0, UINT_MAX,
63 "length of data") != 0)
64 return -1;
65 length_set = TRUE;
66 break;
67
68 case 'f':
69 filename = aArg;
70 break;
71
72 case 'p':
73 password = aArg;
74 if (!password)
75 askPassword = TRUE;
76 else
77 askPassword = FALSE;
78 passWellKnown = FALSE;
79 break;
80
81 case 'z':
82 password = NULL;
83 passWellKnown = TRUE;
84 askPassword = FALSE;
85 break;
86
87 case 'u':
88 useUnicode = TRUE;
89 break;
90
91 default:
92 return -1;
93 }
94 return 0;
95 }
96
displayData(FILE * stream,UINT32 offset,BYTE * data,UINT32 length)97 static void displayData(FILE *stream, UINT32 offset, BYTE *data, UINT32 length)
98 {
99 unsigned int len = (length + 0xf) & ~0xf;
100 unsigned int c;
101 unsigned char buf[17] = { 0, };
102
103 for (c = 0; c < len; c++) {
104 if ((c & 0xf) == 0)
105 printf("%08x ", c + offset);
106
107 if (c < length) {
108 printf("%02x ", data[c]);
109 if (isgraph(data[c]))
110 buf[c & 0xf] = data[c];
111 else
112 buf[c & 0xf] = ' ';
113 } else {
114 printf(" ");
115 buf[c & 0xf] = 0;
116 }
117
118 if ((c & 0xf) == 0xf) {
119 printf(" %s\n", buf);
120 }
121 }
122 }
123
help(const char * aCmd)124 static void help(const char* aCmd)
125 {
126 logCmdHelp(aCmd);
127 logUnicodeCmdOption();
128 logCmdOption("-z, --well-known",
129 _("Use 20 bytes of zeros (TSS_WELL_KNOWN_SECRET) as the TPM secret authorization data"));
130 logCmdOption("-p, --password",
131 _("Owner or NVRAM area password depending on permissions"));
132 logNVIndexCmdOption();
133 logCmdOption("-s, --size",
134 _("Number of bytes to read from the NVRAM area"));
135 logCmdOption("-n, --offset",
136 _("Offset at which to start reading from the NVRAM area"));
137 logCmdOption("-f, --filename",
138 _("File to write data to."));
139 }
140
main(int argc,char ** argv)141 int main(int argc, char **argv)
142 {
143
144 TSS_HTPM hTpm;
145 TSS_HNVSTORE nvObject;
146 TSS_FLAG fNvAttrs;
147 TSS_HPOLICY hTpmPolicy, hDataPolicy;
148 int iRc = -1;
149 int pswd_len = -1;
150 BYTE well_known_secret[] = TSS_WELL_KNOWN_SECRET;
151 UINT32 ulDataLength;
152 BYTE *rgbDataRead = NULL;
153 TPM_NV_DATA_PUBLIC *nvpub = NULL;
154 struct option hOpts[] = {
155 {"index" , required_argument, NULL, 'i'},
156 {"size" , required_argument, NULL, 's'},
157 {"offset" , required_argument, NULL, 'n'},
158 {"filename" , required_argument, NULL, 'f'},
159 {"password" , optional_argument, NULL, 'p'},
160 {"use-unicode", no_argument, NULL, 'u'},
161 {"well-known" , no_argument, NULL, 'z'},
162 {NULL , no_argument, NULL, 0},
163 };
164 int fd = -1;
165 ssize_t written;
166
167 initIntlSys();
168
169 if (genericOptHandler
170 (argc, argv, "i:s:n:f:p::zu", hOpts,
171 sizeof(hOpts) / sizeof(struct option), parse, help) != 0)
172 goto out;
173
174 if (nvindex == 0) {
175 logError(_("You must provide an index (!= 0) for the "
176 "NVRAM area.\n"));
177 goto out;
178 }
179
180 ulDataLength = length;
181
182 if (contextCreate(&hContext) != TSS_SUCCESS)
183 goto out;
184
185 if (contextConnect(hContext) != TSS_SUCCESS)
186 goto out_close;
187
188 if (contextGetTpm(hContext, &hTpm) != TSS_SUCCESS)
189 goto out_close;
190
191 fNvAttrs = 0;
192
193 if (contextCreateObject(hContext,
194 TSS_OBJECT_TYPE_NV,
195 fNvAttrs,
196 &nvObject) != TSS_SUCCESS)
197 goto out_close;
198
199 if (askPassword) {
200 password = _GETPASSWD(_("Enter NVRAM access password: "), &pswd_len,
201 FALSE, useUnicode );
202 if (!password) {
203 logError(_("Failed to get NVRAM access password\n"));
204 goto out_close;
205 }
206 }
207
208 if (password || passWellKnown) {
209 if (policyGet(hTpm, &hTpmPolicy) != TSS_SUCCESS)
210 goto out_close;
211
212 if (password) {
213 if (pswd_len < 0)
214 pswd_len = strlen(password);
215 if (policySetSecret(hTpmPolicy, pswd_len,
216 (BYTE *)password) != TSS_SUCCESS)
217 goto out_close;
218 } else {
219 if (policySetSecret(hTpmPolicy, TCPA_SHA1_160_HASH_LEN,
220 (BYTE *)well_known_secret) != TSS_SUCCESS)
221 goto out_close;
222 }
223
224 if (contextCreateObject
225 (hContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE,
226 &hDataPolicy) != TSS_SUCCESS)
227 goto out_close;
228
229 if (password) {
230 if (policySetSecret(hDataPolicy, pswd_len,
231 (BYTE *)password) != TSS_SUCCESS)
232 goto out_close;
233 } else {
234 if (policySetSecret(hDataPolicy, TCPA_SHA1_160_HASH_LEN,
235 (BYTE *)well_known_secret) != TSS_SUCCESS)
236 goto out_close;
237 }
238
239 if (Tspi_Policy_AssignToObject(hDataPolicy, nvObject) !=
240 TSS_SUCCESS)
241 goto out_close;
242 }
243
244 if (getNVDataPublic(hTpm, nvindex, &nvpub) != TSS_SUCCESS) {
245 logError(_("Could not get the NVRAM area's public information.\n"));
246 goto out_close_obj;
247 }
248
249 if (!length_set)
250 ulDataLength = nvpub->dataSize;
251
252 if ((UINT32)offset > nvpub->dataSize) {
253 logError(_("The offset is outside the NVRAM area's size of "
254 "%u bytes.\n"),
255 nvpub->dataSize);
256 goto out_close_obj;
257 }
258
259 if ((UINT32)offset + ulDataLength > nvpub->dataSize) {
260 ulDataLength = nvpub->dataSize - (UINT32)offset;
261 }
262
263 if (Tspi_SetAttribUint32(nvObject,
264 TSS_TSPATTRIB_NV_INDEX,
265 0,
266 nvindex) != TSS_SUCCESS)
267 goto out_close_obj;
268
269
270 if (NVReadValue(nvObject, offset, &ulDataLength, &rgbDataRead) !=
271 TSS_SUCCESS)
272 goto out_close_obj;
273
274 if (filename) {
275 fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR);
276 if (fd < 0) {
277 logError(_("Could not open file %s for writing."),
278 filename);
279 goto out_close_obj;
280 }
281
282 written = write(fd, rgbDataRead, ulDataLength);
283
284 if (written < 0 || ulDataLength != (UINT32)written) {
285 logError(_("Error while writing to file.\n"));
286 close(fd);
287 fd = -1;
288 goto out_close_obj;
289 }
290 close(fd);
291 fd = -1;
292 logMsg(_("Successfully wrote data from NVRAM area 0x%x (%u) "
293 "to file.\n"), nvindex, nvindex);
294 } else {
295 displayData(stdout, offset, rgbDataRead, ulDataLength);
296 }
297
298 iRc = 0;
299
300 goto out_close;
301
302 out_close_obj:
303 contextCloseObject(hContext, nvObject);
304
305 out_close:
306 contextClose(hContext);
307
308 out:
309 free(rgbDataRead);
310 freeNVDataPublic(nvpub);
311
312 return iRc;
313 }
314