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