xref: /netbsd-src/crypto/external/cpl/tpm-tools/dist/src/tpm_mgmt/tpm_nvread.c (revision 71d1bfd50f50f14f555c954beda6ecce1f33bc9a)
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