tpm_nvwrite.c revision 1.1
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/types.h> 23#include <sys/stat.h> 24#include <unistd.h> 25#include <fcntl.h> 26#include <limits.h> 27 28#include "tpm_nvcommon.h" 29#include "tpm_tspi.h" 30#include "tpm_utils.h" 31 32static BOOL nvindex_set; 33static unsigned int nvindex; 34static unsigned int offset; 35static unsigned int length; 36static int fillvalue = -1; 37static const char *filename; 38static BOOL passWellKnown; 39static BOOL askPassword; 40static const char *password; 41static char *data; 42 43TSS_HCONTEXT hContext = 0; 44 45 46static int parse(const int aOpt, const char *aArg) 47{ 48 49 switch (aOpt) { 50 case 'i': 51 if (parseHexOrDecimal(aArg, &nvindex, 0, UINT_MAX, 52 "NVRAM index") != 0) 53 return -1; 54 55 nvindex_set = 1; 56 57 break; 58 59 case 's': 60 if (parseHexOrDecimal(aArg, &length, 0, UINT_MAX, 61 "length of data") != 0) 62 return -1; 63 break; 64 65 case 'n': 66 if (parseHexOrDecimal(aArg, &offset, 0, UINT_MAX, 67 "write offset") != 0) 68 return -1; 69 break; 70 71 case 'd': 72 data = strdup(aArg); 73 if (data == NULL) { 74 logError(_("Out of memory\n")); 75 return -1; 76 } 77 break; 78 79 case 'f': 80 filename = aArg; 81 break; 82 83 case 'm': 84 if (parseHexOrDecimal(aArg, (unsigned int *)&fillvalue, 85 0, UCHAR_MAX, 86 "fill value") != 0) 87 return -1; 88 break; 89 90 case 'p': 91 password = aArg; 92 if (!password) 93 askPassword = TRUE; 94 else 95 askPassword = FALSE; 96 passWellKnown = FALSE; 97 break; 98 99 case 'z': 100 password = NULL; 101 passWellKnown = TRUE; 102 askPassword = FALSE; 103 break; 104 105 case 'u': 106 useUnicode = TRUE; 107 break; 108 109 default: 110 return -1; 111 } 112 return 0; 113} 114 115static void help(const char* aCmd) 116{ 117 logCmdHelp(aCmd); 118 logUnicodeCmdOption(); 119 logCmdOption("-z, --well-known", 120 _("Use 20 bytes of zeros (TSS_WELL_KNOWN_SECRET) as the TPM secret authorization data")); 121 logCmdOption("-p, --password", 122 _("Owner or NVRAM area password depending on permissions")); 123 logNVIndexCmdOption(); 124 logCmdOption("-s, --size", 125 _("Number of bytes to write to the NVRAM area")); 126 logCmdOption("-n, --offset", 127 _("Offset at which to start writing into the NVRAM area")); 128 logCmdOption("-f, --filename", 129 _("File whose contents to write into the NVRAM area")); 130 logCmdOption("-d, --data", 131 _("Data to write into the NVRAM area")); 132 logCmdOption("-m, --fill-value", 133 _("The byte to fill the NVRAM area with")); 134} 135 136int main(int argc, char **argv) 137{ 138 139 TSS_HTPM hTpm; 140 TSS_HNVSTORE nvObject; 141 TSS_FLAG fNvAttrs; 142 UINT32 ulDataLength, bytesToWrite, off; 143 BYTE *rgbDataToWrite = NULL; 144 TSS_HPOLICY hTpmPolicy, hDataPolicy; 145 TPM_NV_DATA_PUBLIC *nvpub = NULL; 146 int iRc = -1; 147 BYTE well_known_secret[] = TSS_WELL_KNOWN_SECRET; 148 int pswd_len = -1; 149 struct option hOpts[] = { 150 {"index" , required_argument, NULL, 'i'}, 151 {"size" , required_argument, NULL, 's'}, 152 {"offset" , required_argument, NULL, 'n'}, 153 {"data" , required_argument, NULL, 'd'}, 154 {"filename" , required_argument, NULL, 'f'}, 155 {"fillvalue" , required_argument, NULL, 'm'}, 156 {"password" , optional_argument, NULL, 'p'}, 157 {"use-unicode", no_argument, NULL, 'u'}, 158 {"well-known" , no_argument, NULL, 'z'}, 159 {NULL , no_argument, NULL, 0}, 160 }; 161 struct stat statbuf; 162 int fd = -1; 163 ssize_t read_bytes; 164 165 initIntlSys(); 166 167 if (genericOptHandler 168 (argc, argv, "i:s:n:d:f:m:p::zu", hOpts, 169 sizeof(hOpts) / sizeof(struct option), parse, help) != 0) 170 goto out; 171 172 if (nvindex_set == 0) { 173 logError(_("You must provide an index for the NVRAM area.\n")); 174 goto out; 175 } 176 177 if (length > 0 && data == NULL && 178 filename == NULL && 179 fillvalue == -1) { 180 logError(_("Either data, name of file or fill value must be " 181 "provided.\n")); 182 goto out; 183 } 184 185 if (data) { 186 ulDataLength = strlen(data); 187 188 if (length > 0 && (UINT32)length < ulDataLength) 189 ulDataLength = length; 190 191 rgbDataToWrite = (BYTE *)data; 192 data = NULL; 193 } else if (filename) { 194 if (stat(filename, &statbuf) != 0) { 195 logError(_("Could not access file '%s'\n"), 196 filename); 197 goto out; 198 } 199 ulDataLength = statbuf.st_size; 200 201 if (length > 0 && (UINT32)length < ulDataLength) 202 ulDataLength = length; 203 204 rgbDataToWrite = malloc(ulDataLength); 205 if (rgbDataToWrite == NULL) { 206 logError(_("Out of memory.\n")); 207 return -1; 208 } 209 fd = open(filename, O_RDONLY); 210 if (fd < 0) { 211 logError(_("Could not open file %s for reading.\n")); 212 return -1; 213 } 214 read_bytes = read(fd, rgbDataToWrite, ulDataLength); 215 216 if (read_bytes < 0 || ulDataLength != (UINT32)read_bytes) { 217 logError(_("Error while reading data.\n")); 218 return -1; 219 } 220 close(fd); 221 fd = -1; 222 } else if (fillvalue >= 0) { 223 if (length < 0) { 224 logError(_("Requiring size parameter.\n")); 225 return -1; 226 } 227 ulDataLength = length; 228 rgbDataToWrite = malloc(ulDataLength); 229 if (rgbDataToWrite == NULL) { 230 logError(_("Out of memory.\n")); 231 return -1; 232 } 233 memset(rgbDataToWrite, fillvalue, ulDataLength); 234 } else { 235 ulDataLength = 0; 236 } 237 238 if (contextCreate(&hContext) != TSS_SUCCESS) 239 goto out; 240 241 if (contextConnect(hContext) != TSS_SUCCESS) 242 goto out_close; 243 244 if (contextGetTpm(hContext, &hTpm) != TSS_SUCCESS) 245 goto out_close; 246 247 fNvAttrs = 0; 248 249 if (contextCreateObject(hContext, 250 TSS_OBJECT_TYPE_NV, 251 fNvAttrs, 252 &nvObject) != TSS_SUCCESS) 253 goto out_close; 254 255 256 if (askPassword) { 257 password = _GETPASSWD(_("Enter NVRAM access password: "), &pswd_len, 258 FALSE, useUnicode ); 259 if (!password) { 260 logError(_("Failed to get NVRAM access password\n")); 261 goto out_close; 262 } 263 } 264 if (password || passWellKnown) { 265 if (policyGet(hTpm, &hTpmPolicy) != TSS_SUCCESS) 266 goto out_close; 267 268 if (password) { 269 if (pswd_len < 0) 270 pswd_len = strlen(password); 271 if (policySetSecret(hTpmPolicy, strlen(password), 272 (BYTE *)password) != TSS_SUCCESS) 273 goto out_close; 274 } else { 275 if (policySetSecret(hTpmPolicy, TCPA_SHA1_160_HASH_LEN, 276 (BYTE *)well_known_secret) != TSS_SUCCESS) 277 goto out_close; 278 } 279 280 if (contextCreateObject 281 (hContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, 282 &hDataPolicy) != TSS_SUCCESS) 283 goto out_close; 284 285 if (password) { 286 if (policySetSecret(hDataPolicy, strlen(password), 287 (BYTE *)password) != TSS_SUCCESS) 288 goto out_close; 289 } else { 290 if (policySetSecret(hDataPolicy, TCPA_SHA1_160_HASH_LEN, 291 (BYTE *)well_known_secret) != TSS_SUCCESS) 292 goto out_close; 293 } 294 295 if (Tspi_Policy_AssignToObject(hDataPolicy, nvObject) != 296 TSS_SUCCESS) 297 goto out_close; 298 } 299 300 if (nvindex != TPM_NV_INDEX0) { 301 if (getNVDataPublic(hTpm, nvindex, &nvpub) != TSS_SUCCESS) { 302 logError(_("Could not get NVRAM area public information.\n")); 303 goto out_close_obj; 304 } 305 306 if ((UINT32)offset > nvpub->dataSize) { 307 logError(_("The offset is outside the NVRAM area's size of " 308 "%u bytes.\n"), 309 nvpub->dataSize); 310 goto out_close_obj; 311 } 312 313 if ((UINT32)offset + ulDataLength > nvpub->dataSize) { 314 logError(_("Writing of data would go beyond the NVRAM area's size " 315 "of %u bytes.\n"), 316 nvpub->dataSize); 317 goto out_close_obj; 318 } 319 } 320 321 if (Tspi_SetAttribUint32(nvObject, 322 TSS_TSPATTRIB_NV_INDEX, 323 0, 324 nvindex) != TSS_SUCCESS) 325 goto out_close_obj; 326 327 328 bytesToWrite = ulDataLength; 329 off = offset; 330 331 if (bytesToWrite == 0 && 332 NVWriteValue(nvObject, 0, 0, NULL) != TSS_SUCCESS) 333 goto out_close_obj; 334 335#define WRITE_CHUNK_SIZE 1024 336 while (bytesToWrite > 0) { 337 UINT32 chunk = (bytesToWrite > WRITE_CHUNK_SIZE) 338 ? WRITE_CHUNK_SIZE 339 : bytesToWrite; 340 if (NVWriteValue(nvObject, off, chunk, &rgbDataToWrite[off-offset]) 341 != TSS_SUCCESS) 342 goto out_close_obj; 343 344 bytesToWrite -= chunk; 345 off += chunk; 346 } 347 348 logMsg(_("Successfully wrote %d bytes at offset %d to NVRAM index " 349 "0x%x (%u).\n"), 350 ulDataLength, offset, nvindex, nvindex); 351 352 iRc = 0; 353 354 goto out_close; 355 356 out_close_obj: 357 contextCloseObject(hContext, nvObject); 358 359 out_close: 360 contextClose(hContext); 361 362 out: 363 free(rgbDataToWrite); 364 freeNVDataPublic(nvpub); 365 366 return iRc; 367} 368