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