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 <limits.h> 23 #include <ctype.h> 24 #include <fcntl.h> 25 #include <unistd.h> 26 27 #include "tpm_nvcommon.h" 28 #include "tpm_tspi.h" 29 #include "tpm_utils.h" 30 31 static unsigned int nvindex; 32 static unsigned int offset; 33 static unsigned int length; 34 static BOOL length_set; 35 static const char *filename; 36 static BOOL passWellKnown; 37 static const char *password; 38 static BOOL askPassword; 39 40 TSS_HCONTEXT hContext = 0; 41 42 43 static int parse(const int aOpt, const char *aArg) 44 { 45 46 switch (aOpt) { 47 case 'i': 48 if (parseHexOrDecimal(aArg, &nvindex, 0, UINT_MAX, 49 "NVRAM index") != 0) 50 return -1; 51 break; 52 53 case 'n': 54 if (parseHexOrDecimal(aArg, &offset, 0, UINT_MAX, 55 "read offset") != 0) 56 return -1; 57 break; 58 59 case 's': 60 if (parseHexOrDecimal(aArg, &length, 0, UINT_MAX, 61 "length of data") != 0) 62 return -1; 63 length_set = TRUE; 64 break; 65 66 case 'f': 67 filename = aArg; 68 break; 69 70 case 'p': 71 password = aArg; 72 if (!password) 73 askPassword = TRUE; 74 else 75 askPassword = FALSE; 76 passWellKnown = FALSE; 77 break; 78 79 case 'z': 80 password = NULL; 81 passWellKnown = TRUE; 82 askPassword = FALSE; 83 break; 84 85 case 'u': 86 useUnicode = TRUE; 87 break; 88 89 default: 90 return -1; 91 } 92 return 0; 93 } 94 95 static void displayData(FILE *stream, UINT32 offset, BYTE *data, UINT32 length) 96 { 97 unsigned int len = (length + 0xf) & ~0xf; 98 unsigned int c; 99 unsigned char buf[17] = { 0, }; 100 101 for (c = 0; c < len; c++) { 102 if ((c & 0xf) == 0) 103 printf("%08x ", c + offset); 104 105 if (c < length) { 106 printf("%02x ", data[c]); 107 if (isgraph(data[c])) 108 buf[c & 0xf] = data[c]; 109 else 110 buf[c & 0xf] = ' '; 111 } else { 112 printf(" "); 113 buf[c & 0xf] = 0; 114 } 115 116 if ((c & 0xf) == 0xf) { 117 printf(" %s\n", buf); 118 } 119 } 120 } 121 122 static void help(const char* aCmd) 123 { 124 logCmdHelp(aCmd); 125 logUnicodeCmdOption(); 126 logCmdOption("-z, --well-known", 127 _("Use 20 bytes of zeros (TSS_WELL_KNOWN_SECRET) as the TPM secret authorization data")); 128 logCmdOption("-p, --password", 129 _("Owner or NVRAM area password depending on permissions")); 130 logNVIndexCmdOption(); 131 logCmdOption("-s, --size", 132 _("Number of bytes to read from the NVRAM area")); 133 logCmdOption("-n, --offset", 134 _("Offset at which to start reading from the NVRAM area")); 135 logCmdOption("-f, --filename", 136 _("File to write data to.")); 137 } 138 139 int main(int argc, char **argv) 140 { 141 142 TSS_HTPM hTpm; 143 TSS_HNVSTORE nvObject; 144 TSS_FLAG fNvAttrs; 145 TSS_HPOLICY hTpmPolicy, hDataPolicy; 146 int iRc = -1; 147 int pswd_len = -1; 148 BYTE well_known_secret[] = TSS_WELL_KNOWN_SECRET; 149 UINT32 ulDataLength; 150 BYTE *rgbDataRead = NULL; 151 TPM_NV_DATA_PUBLIC *nvpub = NULL; 152 struct option hOpts[] = { 153 {"index" , required_argument, NULL, 'i'}, 154 {"size" , required_argument, NULL, 's'}, 155 {"offset" , required_argument, NULL, 'n'}, 156 {"filename" , required_argument, NULL, 'f'}, 157 {"password" , optional_argument, NULL, 'p'}, 158 {"use-unicode", no_argument, NULL, 'u'}, 159 {"well-known" , no_argument, NULL, 'z'}, 160 {NULL , no_argument, NULL, 0}, 161 }; 162 int fd = -1; 163 ssize_t written; 164 165 initIntlSys(); 166 167 if (genericOptHandler 168 (argc, argv, "i:s:n:f:p::zu", hOpts, 169 sizeof(hOpts) / sizeof(struct option), parse, help) != 0) 170 goto out; 171 172 if (nvindex == 0) { 173 logError(_("You must provide an index (!= 0) for the " 174 "NVRAM area.\n")); 175 goto out; 176 } 177 178 ulDataLength = length; 179 180 if (contextCreate(&hContext) != TSS_SUCCESS) 181 goto out; 182 183 if (contextConnect(hContext) != TSS_SUCCESS) 184 goto out_close; 185 186 if (contextGetTpm(hContext, &hTpm) != TSS_SUCCESS) 187 goto out_close; 188 189 fNvAttrs = 0; 190 191 if (contextCreateObject(hContext, 192 TSS_OBJECT_TYPE_NV, 193 fNvAttrs, 194 &nvObject) != TSS_SUCCESS) 195 goto out_close; 196 197 if (askPassword) { 198 password = _GETPASSWD(_("Enter NVRAM access password: "), &pswd_len, 199 FALSE, useUnicode ); 200 if (!password) { 201 logError(_("Failed to get NVRAM access password\n")); 202 goto out_close; 203 } 204 } 205 206 if (password || passWellKnown) { 207 if (policyGet(hTpm, &hTpmPolicy) != TSS_SUCCESS) 208 goto out_close; 209 210 if (password) { 211 if (pswd_len < 0) 212 pswd_len = strlen(password); 213 if (policySetSecret(hTpmPolicy, pswd_len, 214 (BYTE *)password) != TSS_SUCCESS) 215 goto out_close; 216 } else { 217 if (policySetSecret(hTpmPolicy, TCPA_SHA1_160_HASH_LEN, 218 (BYTE *)well_known_secret) != TSS_SUCCESS) 219 goto out_close; 220 } 221 222 if (contextCreateObject 223 (hContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, 224 &hDataPolicy) != TSS_SUCCESS) 225 goto out_close; 226 227 if (password) { 228 if (policySetSecret(hDataPolicy, pswd_len, 229 (BYTE *)password) != TSS_SUCCESS) 230 goto out_close; 231 } else { 232 if (policySetSecret(hDataPolicy, TCPA_SHA1_160_HASH_LEN, 233 (BYTE *)well_known_secret) != TSS_SUCCESS) 234 goto out_close; 235 } 236 237 if (Tspi_Policy_AssignToObject(hDataPolicy, nvObject) != 238 TSS_SUCCESS) 239 goto out_close; 240 } 241 242 if (getNVDataPublic(hTpm, nvindex, &nvpub) != TSS_SUCCESS) { 243 logError(_("Could not get the NVRAM area's public information.\n")); 244 goto out_close_obj; 245 } 246 247 if (!length_set) 248 ulDataLength = nvpub->dataSize; 249 250 if ((UINT32)offset > nvpub->dataSize) { 251 logError(_("The offset is outside the NVRAM area's size of " 252 "%u bytes.\n"), 253 nvpub->dataSize); 254 goto out_close_obj; 255 } 256 257 if ((UINT32)offset + ulDataLength > nvpub->dataSize) { 258 ulDataLength = nvpub->dataSize - (UINT32)offset; 259 } 260 261 if (Tspi_SetAttribUint32(nvObject, 262 TSS_TSPATTRIB_NV_INDEX, 263 0, 264 nvindex) != TSS_SUCCESS) 265 goto out_close_obj; 266 267 268 if (NVReadValue(nvObject, offset, &ulDataLength, &rgbDataRead) != 269 TSS_SUCCESS) 270 goto out_close_obj; 271 272 if (filename) { 273 fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR); 274 if (fd < 0) { 275 logError(_("Could not open file %s for writing."), 276 filename); 277 goto out_close_obj; 278 } 279 280 written = write(fd, rgbDataRead, ulDataLength); 281 282 if (written < 0 || ulDataLength != (UINT32)written) { 283 logError(_("Error while writing to file.\n")); 284 close(fd); 285 fd = -1; 286 goto out_close_obj; 287 } 288 close(fd); 289 fd = -1; 290 logMsg(_("Successfully wrote data from NVRAM area 0x%x (%u) " 291 "to file.\n"), nvindex, nvindex); 292 } else { 293 displayData(stdout, offset, rgbDataRead, ulDataLength); 294 } 295 296 iRc = 0; 297 298 goto out_close; 299 300 out_close_obj: 301 contextCloseObject(hContext, nvObject); 302 303 out_close: 304 contextClose(hContext); 305 306 out: 307 free(rgbDataRead); 308 freeNVDataPublic(nvpub); 309 310 return iRc; 311 } 312