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(). 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. 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 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 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