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 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 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 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 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