xref: /netbsd-src/crypto/external/cpl/tpm-tools/dist/src/tpm_mgmt/tpm_version.c (revision 8cc77b481a5f7140fcf2d44453fb92dcd15fbbc6)
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 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <netinet/in.h>
24 #include <stdlib.h>		//for def. exit
25 #include <unistd.h>
26 #include "tpm_tspi.h"
27 
28 
29 TSS_HCONTEXT hContext = 0;
30 
31 // Redirect all stderr output to a temporary file.
32 // Returns a cloned version of the original stderr, for use with end_capture_stderr().
capture_stderr()33 int capture_stderr()
34 {
35   // Save a copy of stderr.
36   int olderr = dup(STDERR_FILENO);
37   if (olderr < 0) {
38     perror("dup(STDERR_FILENO)");
39     return -1;
40   }
41 
42   // Open file that will become new stderr.
43   FILE* f = tmpfile();
44   if (f == NULL) {
45     close(olderr);
46     perror("tmpfile()");
47     return -1;
48   }
49 
50   // Override stderr with temp file.
51   if (0 > dup2(fileno(f), STDERR_FILENO)) {
52     fclose(f);
53     close(olderr);
54     perror("dup2(, STDERR_FILENO)");
55     return -1;
56   }
57 
58   // Old handle for temp file no longer needed.
59   fclose(f);
60   return olderr;
61 }
62 
63 // Restore stderr and return a newly allocated buffer with the captured stderr output.
64 // Caller frees the returned buffer.
end_capture_stderr(int olderr)65 char* end_capture_stderr(int olderr)
66 {
67   char* buf = NULL;
68   struct stat st;
69   int memsize;
70 
71   if (olderr == -1) {
72     // capture_stderr() must have failed. Nothing to restore.
73     return strdup("");
74   }
75 
76   // Find out how much to read.
77   if (0 > fstat(STDERR_FILENO, &st)) {
78     perror("fstat()");
79     goto errout;
80   }
81   memsize = st.st_size + 1;
82   if (memsize <= st.st_size) {
83     // Something fishy is going on. Fall back to getting 100 bytes (arbitrary).
84     perror("int overflow");
85     memsize = 100;
86     st.st_size = memsize - 1;
87   }
88   if (!(buf = malloc(memsize))) {
89     perror("malloc()");
90     goto errout;
91   }
92 
93   // Read file content.
94   if (0 > lseek(STDERR_FILENO, 0, SEEK_SET)) {
95     perror("lseek()");
96     goto errout;
97   }
98   if (st.st_size != read(STDERR_FILENO, buf, st.st_size)) {
99     perror("read()");
100   }
101 
102   // Restore stderr.
103  errout:
104   if (0 > dup2(olderr, STDERR_FILENO)) {
105     perror("dup2()");
106     return buf;
107   }
108   if (0 > close(olderr)) {
109     perror("close()");
110   }
111   return buf;
112 }
113 
cmdVersion(const char * a_szCmd)114 int cmdVersion(const char *a_szCmd)
115 {
116 	TSS_HTPM hTpm;
117 	UINT32 uiSubCap;
118 	BYTE *pSubCap;
119 	UINT32 uiResultLen;
120 	BYTE *pResult;
121 	int iRc = -1;
122 
123 	if (contextCreate(&hContext) != TSS_SUCCESS)
124 		goto out;
125 
126 	if (contextConnect(hContext) != TSS_SUCCESS)
127 		goto out_close;
128 
129 	if (contextGetTpm(hContext, &hTpm) != TSS_SUCCESS)
130 		goto out_close;
131 #ifdef TSS_LIB_IS_12
132 	{
133 		UINT64 offset;
134 		TSS_RESULT uiResult;
135 		TPM_CAP_VERSION_INFO versionInfo;
136 		char *errbuf = NULL; // Buffer containing what was sent to stderr during getCapability.
137 
138 		/* Disable logging to of "Bad Mode" during this call.
139 		 * If we're on a 1.1 TPM, it'd throw an error.
140 		 * Save data sent to stderr in case it was any other type of error.
141 		 */
142 	        int olderr;   // Saved copy of stderr.
143 
144 		// Redirect stderr to tempfile.
145 		olderr = capture_stderr();
146 
147 		// Get capabilities. Stderr output is captured.
148 		uiResult = getCapability(hTpm, TSS_TPMCAP_VERSION_VAL, 0, NULL, &uiResultLen,
149 					 &pResult);
150 
151 		// Restore output to stderr.
152 		errbuf = end_capture_stderr(olderr);
153 
154 		// Don't print errors due to "Bad Mode", that just means we're on a 1.1 TPM.
155 		if (uiResult == TPM_E_BAD_MODE) {
156 		        free(errbuf);
157 			goto print_cap_version;
158 		}
159 
160 		fprintf(stderr, "%s", errbuf);
161 		free(errbuf);
162 
163 		if (uiResult != TSS_SUCCESS) {
164 			goto out_close;
165 		}
166 
167 		offset = 0;
168 		if ((uiResult = unloadVersionInfo(&offset, pResult, &versionInfo))) {
169 			goto out_close;
170 		}
171 
172 		logMsg(_("  TPM 1.2 Version Info:\n"));
173 		logMsg(_("  Chip Version:        %hhu.%hhu.%hhu.%hhu\n"),
174 		       versionInfo.version.major, versionInfo.version.minor,
175 		       versionInfo.version.revMajor, versionInfo.version.revMinor);
176 		logMsg(_("  Spec Level:          %hu\n"), versionInfo.specLevel);
177 		logMsg(_("  Errata Revision:     %hhu\n"), versionInfo.errataRev);
178 		logMsg(_("  TPM Vendor ID:       %c%c%c%c\n"),
179 		       versionInfo.tpmVendorID[0], versionInfo.tpmVendorID[1],
180 		       versionInfo.tpmVendorID[2], versionInfo.tpmVendorID[3]);
181 
182 		if (versionInfo.vendorSpecificSize) {
183 			logMsg(_("  Vendor Specific data: "));
184 			logHex(versionInfo.vendorSpecificSize, versionInfo.vendorSpecific);
185 
186 			free(versionInfo.vendorSpecific);
187 		}
188 	}
189 
190 print_cap_version:
191 #endif
192 	if (getCapability(hTpm, TSS_TPMCAP_VERSION, 0, NULL, &uiResultLen,
193 			  &pResult) != TSS_SUCCESS)
194 		goto out_close;
195 	logMsg(_("  TPM Version:         "));
196 	logHex(uiResultLen, pResult);
197 
198 	uiSubCap = TSS_TPMCAP_PROP_MANUFACTURER;
199 	pSubCap = (BYTE *) & uiSubCap;
200 	if (getCapability(hTpm, TSS_TPMCAP_PROPERTY, sizeof(uiSubCap),
201 			  pSubCap, &uiResultLen, &pResult) != TSS_SUCCESS)
202 		goto out_close;
203 	logMsg(_("  Manufacturer Info:   "));
204 	logHex(uiResultLen, pResult);
205 
206 	iRc = 0;
207 	logSuccess(a_szCmd);
208 
209       out_close:
210 	contextClose(hContext);
211 
212       out:
213 	return iRc;
214 }
215 
216 
main(int argc,char * argv[])217 int main(int argc, char *argv[])
218 {
219 	int rc;
220 
221         initIntlSys();
222 
223 	rc = genericOptHandler(argc, argv, "", NULL, 0, NULL, NULL);
224 	if (rc)
225 		exit(0);
226 
227 	rc = cmdVersion(argv[0]);
228 
229 	return rc;
230 }
231