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 25 #include "tpm_nvcommon.h" 26 #include "tpm_tspi.h" 27 #include "tpm_utils.h" 28 29 const struct strings_with_values permvalues[] = { 30 { 31 .name = "AUTHREAD", 32 .value = TPM_NV_PER_AUTHREAD, 33 .desc = _("reading requires NVRAM area authorization"), 34 }, 35 { 36 .name = "AUTHWRITE", 37 .value = TPM_NV_PER_AUTHWRITE, 38 .desc = _("writing requires NVRAM area authorization"), 39 }, 40 { 41 .name = "OWNERREAD", 42 .value = TPM_NV_PER_OWNERREAD, 43 .desc = _("writing requires owner authorization"), 44 }, 45 { 46 .name = "OWNERWRITE", 47 .value = TPM_NV_PER_OWNERWRITE, 48 .desc = _("reading requires owner authorization"), 49 }, 50 { 51 .name = "PPREAD", 52 .value = TPM_NV_PER_PPREAD, 53 .desc = _("writing requires physical presence"), 54 }, 55 { 56 .name = "PPWRITE", 57 .value = TPM_NV_PER_PPWRITE, 58 .desc = _("reading requires physical presence"), 59 }, 60 { 61 .name = "GLOBALLOCK", 62 .value = TPM_NV_PER_GLOBALLOCK, 63 .desc = _("write to index 0 locks the NVRAM area until " 64 "TPM_STARTUP(ST_CLEAR)"), 65 }, 66 { 67 .name = "READ_STCLEAR", 68 .value = TPM_NV_PER_READ_STCLEAR, 69 .desc = _("a read with size 0 to the same index prevents further " 70 "reading until ST_STARTUP(ST_CLEAR)"), 71 }, 72 { 73 .name = "WRITE_STCLEAR", 74 .value = TPM_NV_PER_WRITE_STCLEAR, 75 .desc = _("a write with size 0 to the same index prevents further " 76 "writing until ST_STARTUP(ST_CLEAR)"), 77 }, 78 { 79 .name = "WRITEDEFINE", 80 .value = TPM_NV_PER_WRITEDEFINE, 81 .desc = _("a write with size 0 to the same index locks the " 82 "NVRAM area permanently"), 83 }, 84 { 85 .name = "WRITEALL", 86 .value = TPM_NV_PER_WRITEALL, 87 .desc = _("the value must be written in a single operation"), 88 }, 89 { 90 .name = NULL, 91 }, 92 }; 93 94 95 void displayStringsAndValues(const struct strings_with_values *svals, 96 const char *indent) 97 { 98 unsigned int i; 99 100 logMsg("%sThe following strings are available:\n", indent); 101 for (i = 0; svals[i].name; i++) 102 logMsg("%s%15s : %s\n", indent, svals[i].name, svals[i].desc); 103 } 104 105 106 int parseStringWithValues(const char *aArg, 107 const struct strings_with_values *svals, 108 unsigned int *x, unsigned int maximum, 109 const char *name) 110 { 111 unsigned int offset = 0; 112 int i, num, numbytes; 113 size_t totlen = strlen(aArg); 114 *x = 0; 115 116 while (offset < totlen) { 117 int found = 0; 118 119 while (isspace((unsigned char)*(aArg + offset))) 120 offset++; 121 122 for (i = 0; svals[i].name; i++) { 123 size_t len = strlen(svals[i].name); 124 if (strncmp(aArg + offset, svals[i].name, len) == 0 && 125 (aArg[offset+len] == '|' || 126 aArg[offset+len] == 0)) { 127 *x |= svals[i].value; 128 offset += len + 1; 129 found = 1; 130 break; 131 } 132 } 133 134 if (!found) { 135 if (strncmp(aArg + offset, "0x", 2) == 0) { 136 if (sscanf(aArg + offset, "%x%n", &num, &numbytes) 137 != 1) { 138 logError(_("Could not parse hexadecimal " 139 "number in %s.\n"), 140 aArg); 141 return -1; 142 } 143 if (aArg[offset+numbytes] == '|' || 144 aArg[offset+numbytes] == 0) { 145 logError(_("Illegal character following " 146 "hexadecimal number in %s\n"), 147 aArg + offset); 148 return -1; 149 } 150 *x |= num; 151 152 offset += numbytes + 1; 153 found = 1; 154 } 155 } 156 157 while (!found) { 158 if (!isdigit((unsigned char)*(aArg+offset))) 159 break; 160 161 if (sscanf(aArg + offset, "%u%n", &num, &numbytes) != 1) { 162 logError(_("Could not parse data in %s.\n"), 163 aArg + offset); 164 return -1; 165 } 166 167 if (!aArg[offset+numbytes] == '|' && 168 !aArg[offset+numbytes] == 0) { 169 logError(_("Illegal character following decimal " 170 "number in %s\n"), 171 aArg + offset); 172 return -1; 173 } 174 *x |= num; 175 176 offset += numbytes + 1; 177 found = 1; 178 break; 179 } 180 181 if (!found) { 182 logError(_("Unknown element in %s: %s.\n"), 183 name, aArg + offset); 184 return -1; 185 } 186 } 187 188 return 0; 189 } 190 191 192 char *printValueAsStrings(unsigned int value, 193 const struct strings_with_values *svals) 194 { 195 unsigned int mask = (1 << 31), i,c; 196 unsigned int buffer_size = 1024; 197 char *buffer = calloc(1, buffer_size); 198 char printbuf[30]; 199 size_t len; 200 201 c = 0; 202 203 while (mask && value) { 204 if (value & mask) { 205 for (i = 0; svals[i].name; i++) { 206 if (svals[i].value == mask) { 207 len = strlen(svals[i].name); 208 if (len + strlen(buffer) + 1 > 209 buffer_size) { 210 buffer_size += 1024; 211 buffer = realloc(buffer, 212 buffer_size); 213 if (!buffer) 214 return NULL; 215 } 216 if (c) 217 strcat(buffer, "|"); 218 strcat(buffer, svals[i].name); 219 c ++; 220 value ^= mask; 221 break; 222 } 223 } 224 } 225 mask >>= 1; 226 } 227 if (value) { 228 snprintf(printbuf, sizeof(printbuf), "%s0x%x", 229 c ? "|" : "", 230 value); 231 len = strlen(printbuf); 232 if (len + strlen(buffer) + 1 > buffer_size) { 233 buffer_size += 1024; 234 buffer = realloc(buffer, 235 buffer_size); 236 if (!buffer) 237 return NULL; 238 } 239 if (c) 240 strcat(buffer, printbuf); 241 } 242 return buffer; 243 } 244 245 246 int parseHexOrDecimal(const char *aArg, unsigned int *x, 247 unsigned int minimum, unsigned int maximum, 248 const char *name) 249 { 250 while (isspace((unsigned char)*aArg)) 251 aArg++; 252 253 if (strncmp(aArg, "0x", 2) == 0) { 254 if (sscanf(aArg, "%x", x) != 1) { 255 return -1; 256 } 257 } else { 258 if (!isdigit((unsigned char)*aArg)) { 259 fprintf(stderr, 260 "%s must be a positive integer.\n", name); 261 return -1; 262 } 263 264 if (sscanf(aArg, "%u", x) != 1) { 265 return -1; 266 } 267 } 268 269 if ((*x > maximum) || (*x < minimum)) { 270 fprintf(stderr, "%s is out of valid range [%u, %u]\n", 271 name, minimum, maximum); 272 return -1; 273 } 274 275 return 0; 276 } 277 278 279 TSS_RESULT getNVDataPublic(TSS_HTPM hTpm, TPM_NV_INDEX nvindex, 280 TPM_NV_DATA_PUBLIC **pub) 281 { 282 TSS_RESULT res; 283 UINT32 ulResultLen; 284 BYTE *pResult; 285 UINT64 off = 0; 286 287 res = getCapability(hTpm, TSS_TPMCAP_NV_INDEX, sizeof(UINT32), 288 (BYTE *)&nvindex, &ulResultLen, &pResult); 289 290 if (res != TSS_SUCCESS) 291 return res; 292 293 *pub = calloc(1, sizeof(TPM_NV_DATA_PUBLIC)); 294 if (*pub == NULL) { 295 res = TSS_E_OUTOFMEMORY; 296 goto err_exit; 297 } 298 299 res = unloadNVDataPublic(&off, pResult, ulResultLen, *pub); 300 301 if (res != TSS_SUCCESS) { 302 freeNVDataPublic(*pub); 303 *pub = NULL; 304 } 305 err_exit: 306 return res; 307 } 308 309 void freeNVDataPublic(TPM_NV_DATA_PUBLIC *pub) 310 { 311 if (!pub) 312 return; 313 314 free(pub->pcrInfoRead.pcrSelection.pcrSelect); 315 free(pub->pcrInfoWrite.pcrSelection.pcrSelect); 316 free(pub); 317 } 318