Kees Cook | f0605cb | 2012-02-29 16:09:14 -0800 | [diff] [blame] | 1 | /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 2 | * Use of this source code is governed by a BSD-style license that can be |
| 3 | * found in the LICENSE file. |
| 4 | */ |
| 5 | |
| 6 | /* This program generates partially filled TPM datagrams and other compile-time |
| 7 | * constants (e.g. structure sizes and offsets). Compile this file---and ONLY |
| 8 | * this file---with -fpack-struct. We take advantage of the fact that the |
| 9 | * (packed) TPM structures layout (mostly) match the TPM request and response |
| 10 | * datagram layout. When they don't completely match, some fixing is necessary |
| 11 | * (see PCR_SELECTION_FIX below). |
| 12 | */ |
| 13 | |
Gaurav Shah | 553d00e | 2010-07-19 19:22:10 -0700 | [diff] [blame] | 14 | #include <assert.h> |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 15 | #include <stddef.h> |
| 16 | #include <stdio.h> |
| 17 | #include <stdlib.h> |
| 18 | #include <tss/tcs.h> |
| 19 | |
Luigi Semenzato | 5896b96 | 2010-08-25 07:16:03 -0700 | [diff] [blame] | 20 | #include "sysincludes.h" |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 21 | #include "tlcl_internal.h" |
| 22 | #include "tpmextras.h" |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 23 | |
| 24 | /* See struct Command below. This structure represent a field in a TPM |
| 25 | * command. [name] is the field name. [visible] is 1 if the field is |
| 26 | * modified by the run-time. Non-visible fields are initialized at build time |
| 27 | * and remain constant. [size] is the field size in bytes. [value] is the |
| 28 | * fixed value of non-visible fields. |
| 29 | */ |
| 30 | typedef struct Field { |
| 31 | const char* name; |
| 32 | int visible; |
| 33 | int offset; |
| 34 | int size; |
| 35 | uint32_t value; /* large enough for all initializers */ |
| 36 | struct Field* next; |
| 37 | } Field; |
| 38 | |
| 39 | /* This structure is used to build (at build time) and manipulate (at firmware |
| 40 | * or emulation run time) buffers containing TPM datagrams. [name] is the name |
| 41 | * of a TPM command. [size] is the size of the command buffer in bytes, when |
| 42 | * known. [max_size] is the maximum size allowed for variable-length commands |
| 43 | * (such as Read and Write). [fields] is a link-list of command fields. |
| 44 | */ |
| 45 | typedef struct Command { |
| 46 | const char* name; |
| 47 | int size; |
| 48 | int max_size; |
| 49 | Field* fields; |
| 50 | struct Command* next; |
| 51 | } Command; |
| 52 | |
| 53 | /* Adds a field to a command, and makes its offset visible. The fields must be |
| 54 | * added at increasing offsets. |
| 55 | */ |
| 56 | static void AddVisibleField(Command* cmd, const char* name, int offset) { |
Luigi Semenzato | d6acfd4 | 2013-01-08 16:23:11 -0800 | [diff] [blame] | 57 | Field* fld = (Field*) calloc(1, sizeof(Field)); |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 58 | if (cmd->fields != NULL) { |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 59 | assert(offset > fn->offset); |
| 60 | } |
| 61 | fld->next = cmd->fields; |
| 62 | cmd->fields = fld; |
| 63 | fld->name = name; |
| 64 | fld->visible = 1; |
| 65 | fld->offset = offset; |
| 66 | } |
| 67 | |
| 68 | /* Adds a constant field with its value. The fields must be added at |
| 69 | * increasing offsets. |
| 70 | */ |
| 71 | static void AddInitializedField(Command* cmd, int offset, |
| 72 | int size, uint32_t value) { |
Luigi Semenzato | d6acfd4 | 2013-01-08 16:23:11 -0800 | [diff] [blame] | 73 | Field* fld = (Field*) calloc(1, sizeof(Field)); |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 74 | fld->next = cmd->fields; |
| 75 | cmd->fields = fld; |
| 76 | fld->name = NULL; |
| 77 | fld->visible = 0; |
| 78 | fld->size = size; |
| 79 | fld->offset = offset; |
| 80 | fld->value = value; |
| 81 | } |
| 82 | |
| 83 | /* Create a structure representing a TPM command datagram. |
| 84 | */ |
| 85 | Command* newCommand(TPM_COMMAND_CODE code, int size) { |
Luigi Semenzato | d6acfd4 | 2013-01-08 16:23:11 -0800 | [diff] [blame] | 86 | Command* cmd = (Command*) calloc(1, sizeof(Command)); |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 87 | cmd->size = size; |
| 88 | AddInitializedField(cmd, 0, sizeof(TPM_TAG), TPM_TAG_RQU_COMMAND); |
| 89 | AddInitializedField(cmd, sizeof(TPM_TAG), sizeof(uint32_t), size); |
| 90 | AddInitializedField(cmd, sizeof(TPM_TAG) + sizeof(uint32_t), |
| 91 | sizeof(TPM_COMMAND_CODE), code); |
| 92 | return cmd; |
| 93 | } |
| 94 | |
| 95 | /* The TPM_PCR_SELECTION structure in /usr/include/tss/tpm.h contains a pointer |
| 96 | * instead of an array[3] of bytes, so we need to adjust sizes and offsets |
| 97 | * accordingly. |
| 98 | */ |
| 99 | #define PCR_SELECTION_FIX (3 - sizeof(char *)) |
| 100 | |
| 101 | /* BuildXXX builds TPM command XXX. |
| 102 | */ |
| 103 | Command* BuildDefineSpaceCommand(void) { |
| 104 | int nv_data_public = kTpmRequestHeaderLength; |
| 105 | int nv_index = nv_data_public + offsetof(TPM_NV_DATA_PUBLIC, nvIndex); |
| 106 | int nv_pcr_info_read = nv_data_public + |
| 107 | offsetof(TPM_NV_DATA_PUBLIC, pcrInfoRead); |
| 108 | /* |
| 109 | * Here we need to carefully add PCR_SELECTION_FIX (or twice that much) in |
| 110 | * all the places where the offset calculation would be wrong without it. |
| 111 | * The mismatch occurs in the TPM_PCR_SELECTION structure, and it must be |
| 112 | * accounted for in all the structures that include it, directly or |
| 113 | * indirectly. |
| 114 | */ |
| 115 | int read_locality = nv_pcr_info_read + |
| 116 | offsetof(TPM_PCR_INFO_SHORT, localityAtRelease) + PCR_SELECTION_FIX; |
| 117 | int nv_pcr_info_write = nv_data_public + |
| 118 | offsetof(TPM_NV_DATA_PUBLIC, pcrInfoWrite) + PCR_SELECTION_FIX; |
| 119 | int write_locality = nv_pcr_info_write + |
| 120 | offsetof(TPM_PCR_INFO_SHORT, localityAtRelease) + PCR_SELECTION_FIX; |
| 121 | int nv_permission = nv_data_public + |
| 122 | offsetof(TPM_NV_DATA_PUBLIC, permission) + 2 * PCR_SELECTION_FIX; |
| 123 | int nv_permission_tag = |
| 124 | nv_permission + offsetof(TPM_NV_ATTRIBUTES, tag); |
| 125 | int nv_permission_attributes = |
| 126 | nv_permission + offsetof(TPM_NV_ATTRIBUTES, attributes); |
| 127 | int nv_datasize = nv_data_public + |
| 128 | offsetof(TPM_NV_DATA_PUBLIC, dataSize) + 2 * PCR_SELECTION_FIX; |
| 129 | |
| 130 | int size = kTpmRequestHeaderLength + sizeof(TPM_NV_DATA_PUBLIC) + |
| 131 | 2 * PCR_SELECTION_FIX + kEncAuthLength; |
| 132 | Command* cmd = newCommand(TPM_ORD_NV_DefineSpace, size); |
| 133 | cmd->name = "tpm_nv_definespace_cmd"; |
| 134 | |
| 135 | AddVisibleField(cmd, "index", nv_index); |
| 136 | AddVisibleField(cmd, "perm", nv_permission_attributes); |
| 137 | AddVisibleField(cmd, "size", nv_datasize); |
| 138 | |
| 139 | AddInitializedField(cmd, nv_data_public, sizeof(uint16_t), |
| 140 | TPM_TAG_NV_DATA_PUBLIC); |
| 141 | AddInitializedField(cmd, nv_pcr_info_read, sizeof(uint16_t), 3); |
| 142 | AddInitializedField(cmd, read_locality, sizeof(TPM_LOCALITY_SELECTION), |
| 143 | TPM_ALL_LOCALITIES); |
| 144 | AddInitializedField(cmd, nv_pcr_info_write, sizeof(uint16_t), 3); |
| 145 | AddInitializedField(cmd, write_locality, sizeof(TPM_LOCALITY_SELECTION), |
| 146 | TPM_ALL_LOCALITIES); |
| 147 | AddInitializedField(cmd, nv_permission_tag, sizeof(TPM_STRUCTURE_TAG), |
| 148 | TPM_TAG_NV_ATTRIBUTES); |
| 149 | return cmd; |
| 150 | } |
| 151 | |
| 152 | /* BuildXXX builds TPM command XXX. |
| 153 | */ |
| 154 | Command* BuildWriteCommand(void) { |
| 155 | Command* cmd = newCommand(TPM_ORD_NV_WriteValue, 0); |
| 156 | cmd->name = "tpm_nv_write_cmd"; |
| 157 | cmd->max_size = TPM_LARGE_ENOUGH_COMMAND_SIZE; |
| 158 | AddVisibleField(cmd, "index", kTpmRequestHeaderLength); |
| 159 | AddVisibleField(cmd, "length", kTpmRequestHeaderLength + 8); |
| 160 | AddVisibleField(cmd, "data", kTpmRequestHeaderLength + 12); |
| 161 | return cmd; |
| 162 | } |
| 163 | |
| 164 | Command* BuildReadCommand(void) { |
| 165 | int size = kTpmRequestHeaderLength + kTpmReadInfoLength; |
| 166 | Command* cmd = newCommand(TPM_ORD_NV_ReadValue, size); |
| 167 | cmd->name = "tpm_nv_read_cmd"; |
| 168 | AddVisibleField(cmd, "index", kTpmRequestHeaderLength); |
| 169 | AddVisibleField(cmd, "length", kTpmRequestHeaderLength + 8); |
| 170 | return cmd; |
| 171 | } |
| 172 | |
Kees Cook | 946370d | 2012-01-09 14:17:40 -0800 | [diff] [blame] | 173 | Command* BuildPCRReadCommand(void) { |
| 174 | int size = kTpmRequestHeaderLength + sizeof(uint32_t); |
| 175 | Command* cmd = newCommand(TPM_ORD_PcrRead, size); |
| 176 | cmd->name = "tpm_pcr_read_cmd"; |
| 177 | AddVisibleField(cmd, "pcrNum", kTpmRequestHeaderLength); |
| 178 | return cmd; |
| 179 | } |
| 180 | |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 181 | Command* BuildPPAssertCommand(void) { |
| 182 | int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE); |
| 183 | Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size); |
| 184 | cmd->name = "tpm_ppassert_cmd"; |
| 185 | AddInitializedField(cmd, kTpmRequestHeaderLength, |
| 186 | sizeof(TPM_PHYSICAL_PRESENCE), |
| 187 | TPM_PHYSICAL_PRESENCE_PRESENT); |
| 188 | return cmd; |
| 189 | } |
| 190 | |
Luigi Semenzato | 1d83dd1 | 2010-08-30 10:23:43 -0700 | [diff] [blame] | 191 | Command* BuildPPEnableCommand(void) { |
| 192 | int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE); |
| 193 | Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size); |
| 194 | cmd->name = "tpm_ppenable_cmd"; |
| 195 | AddInitializedField(cmd, kTpmRequestHeaderLength, |
| 196 | sizeof(TPM_PHYSICAL_PRESENCE), |
| 197 | TPM_PHYSICAL_PRESENCE_CMD_ENABLE); |
| 198 | return cmd; |
| 199 | } |
| 200 | |
Luigi Semenzato | 377557f | 2010-08-31 13:20:53 -0700 | [diff] [blame] | 201 | Command* BuildFinalizePPCommand(void) { |
| 202 | int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE); |
| 203 | Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size); |
| 204 | cmd->name = "tpm_finalizepp_cmd"; |
| 205 | AddInitializedField(cmd, kTpmRequestHeaderLength, |
| 206 | sizeof(TPM_PHYSICAL_PRESENCE), |
| 207 | TPM_PHYSICAL_PRESENCE_CMD_ENABLE | |
| 208 | TPM_PHYSICAL_PRESENCE_HW_DISABLE | |
| 209 | TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK); |
| 210 | return cmd; |
| 211 | } |
| 212 | |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 213 | Command* BuildPPLockCommand(void) { |
| 214 | int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE); |
| 215 | Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size); |
| 216 | cmd->name = "tpm_pplock_cmd"; |
| 217 | AddInitializedField(cmd, kTpmRequestHeaderLength, |
| 218 | sizeof(TPM_PHYSICAL_PRESENCE), |
| 219 | TPM_PHYSICAL_PRESENCE_LOCK); |
| 220 | return cmd; |
| 221 | } |
| 222 | |
| 223 | Command* BuildStartupCommand(void) { |
Luigi Semenzato | 3da063e | 2010-08-31 14:31:30 -0700 | [diff] [blame] | 224 | int size = kTpmRequestHeaderLength + sizeof(TPM_STARTUP_TYPE); |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 225 | Command* cmd = newCommand(TPM_ORD_Startup, size); |
| 226 | cmd->name = "tpm_startup_cmd"; |
| 227 | AddInitializedField(cmd, kTpmRequestHeaderLength, |
| 228 | sizeof(TPM_STARTUP_TYPE), |
| 229 | TPM_ST_CLEAR); |
| 230 | return cmd; |
| 231 | } |
| 232 | |
Luigi Semenzato | 54992f9 | 2011-03-16 10:56:48 -0700 | [diff] [blame] | 233 | Command* BuildSaveStateCommand(void) { |
| 234 | int size = kTpmRequestHeaderLength; |
| 235 | Command* cmd = newCommand(TPM_ORD_SaveState, size); |
| 236 | cmd->name = "tpm_savestate_cmd"; |
| 237 | return cmd; |
| 238 | } |
| 239 | |
Luigi Semenzato | 3da063e | 2010-08-31 14:31:30 -0700 | [diff] [blame] | 240 | Command* BuildResumeCommand(void) { |
| 241 | int size = kTpmRequestHeaderLength + sizeof(TPM_STARTUP_TYPE); |
| 242 | Command* cmd = newCommand(TPM_ORD_Startup, size); |
| 243 | cmd->name = "tpm_resume_cmd"; |
| 244 | AddInitializedField(cmd, kTpmRequestHeaderLength, |
| 245 | sizeof(TPM_STARTUP_TYPE), |
| 246 | TPM_ST_STATE); |
| 247 | return cmd; |
| 248 | } |
| 249 | |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 250 | Command* BuildSelftestfullCommand(void) { |
| 251 | int size = kTpmRequestHeaderLength; |
| 252 | Command* cmd = newCommand(TPM_ORD_SelfTestFull, size); |
| 253 | cmd->name = "tpm_selftestfull_cmd"; |
| 254 | return cmd; |
| 255 | } |
| 256 | |
| 257 | Command* BuildContinueSelfTestCommand(void) { |
| 258 | int size = kTpmRequestHeaderLength; |
| 259 | Command* cmd = newCommand(TPM_ORD_ContinueSelfTest, size); |
| 260 | cmd->name = "tpm_continueselftest_cmd"; |
| 261 | return cmd; |
| 262 | } |
| 263 | |
| 264 | Command* BuildReadPubekCommand(void) { |
| 265 | int size = kTpmRequestHeaderLength + sizeof(TPM_NONCE); |
| 266 | Command* cmd = newCommand(TPM_ORD_ReadPubek, size); |
| 267 | cmd->name = "tpm_readpubek_cmd"; |
| 268 | return cmd; |
| 269 | } |
| 270 | |
| 271 | Command* BuildForceClearCommand(void) { |
| 272 | int size = kTpmRequestHeaderLength; |
| 273 | Command* cmd = newCommand(TPM_ORD_ForceClear, size); |
| 274 | cmd->name = "tpm_forceclear_cmd"; |
| 275 | return cmd; |
| 276 | } |
| 277 | |
| 278 | Command* BuildPhysicalEnableCommand(void) { |
| 279 | int size = kTpmRequestHeaderLength; |
| 280 | Command* cmd = newCommand(TPM_ORD_PhysicalEnable, size); |
| 281 | cmd->name = "tpm_physicalenable_cmd"; |
| 282 | return cmd; |
| 283 | } |
| 284 | |
| 285 | Command* BuildPhysicalDisableCommand(void) { |
| 286 | int size = kTpmRequestHeaderLength; |
| 287 | Command* cmd = newCommand(TPM_ORD_PhysicalDisable, size); |
| 288 | cmd->name = "tpm_physicaldisable_cmd"; |
| 289 | return cmd; |
| 290 | } |
| 291 | |
| 292 | Command* BuildPhysicalSetDeactivatedCommand(void) { |
| 293 | int size = kTpmRequestHeaderLength + sizeof(uint8_t); |
| 294 | Command* cmd = newCommand(TPM_ORD_PhysicalSetDeactivated, size); |
| 295 | cmd->name = "tpm_physicalsetdeactivated_cmd"; |
| 296 | AddVisibleField(cmd, "deactivated", kTpmRequestHeaderLength); |
| 297 | return cmd; |
| 298 | } |
| 299 | |
| 300 | Command* BuildExtendCommand(void) { |
| 301 | int size = kTpmRequestHeaderLength + sizeof(uint32_t) + kPcrDigestLength; |
| 302 | Command* cmd = newCommand(TPM_ORD_Extend, size); |
| 303 | cmd->name = "tpm_extend_cmd"; |
| 304 | AddVisibleField(cmd, "pcrNum", kTpmRequestHeaderLength); |
| 305 | AddVisibleField(cmd, "inDigest", kTpmRequestHeaderLength + sizeof(uint32_t)); |
| 306 | return cmd; |
| 307 | } |
| 308 | |
| 309 | Command* BuildGetFlagsCommand(void) { |
| 310 | int size = (kTpmRequestHeaderLength + |
| 311 | sizeof(TPM_CAPABILITY_AREA) + /* capArea */ |
| 312 | sizeof(uint32_t) + /* subCapSize */ |
| 313 | sizeof(uint32_t)); /* subCap */ |
| 314 | |
| 315 | Command* cmd = newCommand(TPM_ORD_GetCapability, size); |
| 316 | cmd->name = "tpm_getflags_cmd"; |
| 317 | AddInitializedField(cmd, kTpmRequestHeaderLength, |
| 318 | sizeof(TPM_CAPABILITY_AREA), TPM_CAP_FLAG); |
| 319 | AddInitializedField(cmd, kTpmRequestHeaderLength + |
| 320 | sizeof(TPM_CAPABILITY_AREA), |
| 321 | sizeof(uint32_t), sizeof(uint32_t)); |
| 322 | AddInitializedField(cmd, kTpmRequestHeaderLength + |
| 323 | sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t), |
| 324 | sizeof(uint32_t), TPM_CAP_FLAG_PERMANENT); |
| 325 | return cmd; |
| 326 | } |
| 327 | |
Luigi Semenzato | 5896b96 | 2010-08-25 07:16:03 -0700 | [diff] [blame] | 328 | Command* BuildGetSTClearFlagsCommand(void) { |
| 329 | int size = (kTpmRequestHeaderLength + |
| 330 | sizeof(TPM_CAPABILITY_AREA) + /* capArea */ |
| 331 | sizeof(uint32_t) + /* subCapSize */ |
| 332 | sizeof(uint32_t)); /* subCap */ |
| 333 | |
| 334 | Command* cmd = newCommand(TPM_ORD_GetCapability, size); |
| 335 | cmd->name = "tpm_getstclearflags_cmd"; |
| 336 | AddInitializedField(cmd, kTpmRequestHeaderLength, |
| 337 | sizeof(TPM_CAPABILITY_AREA), TPM_CAP_FLAG); |
| 338 | AddInitializedField(cmd, kTpmRequestHeaderLength + |
| 339 | sizeof(TPM_CAPABILITY_AREA), |
| 340 | sizeof(uint32_t), sizeof(uint32_t)); |
| 341 | AddInitializedField(cmd, kTpmRequestHeaderLength + |
| 342 | sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t), |
| 343 | sizeof(uint32_t), TPM_CAP_FLAG_VOLATILE); |
| 344 | return cmd; |
| 345 | } |
| 346 | |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 347 | Command* BuildGetPermissionsCommand(void) { |
| 348 | int size = (kTpmRequestHeaderLength + |
| 349 | sizeof(TPM_CAPABILITY_AREA) + /* capArea */ |
| 350 | sizeof(uint32_t) + /* subCapSize */ |
| 351 | sizeof(uint32_t)); /* subCap */ |
| 352 | |
| 353 | Command* cmd = newCommand(TPM_ORD_GetCapability, size); |
| 354 | cmd->name = "tpm_getpermissions_cmd"; |
| 355 | AddInitializedField(cmd, kTpmRequestHeaderLength, |
| 356 | sizeof(TPM_CAPABILITY_AREA), TPM_CAP_NV_INDEX); |
| 357 | AddInitializedField(cmd, kTpmRequestHeaderLength + |
| 358 | sizeof(TPM_CAPABILITY_AREA), |
| 359 | sizeof(uint32_t), sizeof(uint32_t)); |
| 360 | AddVisibleField(cmd, "index", kTpmRequestHeaderLength + |
| 361 | sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t)); |
| 362 | return cmd; |
| 363 | } |
| 364 | |
Kees Cook | 8b6da26 | 2012-06-07 13:48:26 -0700 | [diff] [blame] | 365 | Command* BuildGetOwnershipCommand(void) { |
| 366 | int size = (kTpmRequestHeaderLength + |
| 367 | sizeof(TPM_CAPABILITY_AREA) + /* capArea */ |
| 368 | sizeof(uint32_t) + /* subCapSize */ |
| 369 | sizeof(uint32_t)); /* subCap */ |
| 370 | |
| 371 | Command* cmd = newCommand(TPM_ORD_GetCapability, size); |
| 372 | cmd->name = "tpm_getownership_cmd"; |
| 373 | AddInitializedField(cmd, kTpmRequestHeaderLength, |
| 374 | sizeof(TPM_CAPABILITY_AREA), TPM_CAP_PROPERTY); |
| 375 | AddInitializedField(cmd, kTpmRequestHeaderLength + |
| 376 | sizeof(TPM_CAPABILITY_AREA), |
| 377 | sizeof(uint32_t), sizeof(uint32_t)); |
| 378 | AddInitializedField(cmd, kTpmRequestHeaderLength + |
| 379 | sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t), |
| 380 | sizeof(uint32_t), TPM_CAP_PROP_OWNER); |
| 381 | return cmd; |
| 382 | } |
| 383 | |
Kees Cook | f0605cb | 2012-02-29 16:09:14 -0800 | [diff] [blame] | 384 | Command* BuildGetRandomCommand(void) { |
| 385 | int size = kTpmRequestHeaderLength + sizeof(uint32_t); |
| 386 | Command* cmd = newCommand(TPM_ORD_GetRandom, size); |
| 387 | cmd->name = "tpm_get_random_cmd"; |
| 388 | AddVisibleField(cmd, "bytesRequested", kTpmRequestHeaderLength); |
| 389 | return cmd; |
| 390 | } |
| 391 | |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 392 | /* Output the fields of a structure. |
| 393 | */ |
| 394 | void OutputFields(Field* fld) { |
| 395 | /* |
| 396 | * Field order is reversed. |
| 397 | */ |
| 398 | if (fld != NULL) { |
| 399 | OutputFields(fld->next); |
| 400 | if (fld->visible) { |
Gaurav Shah | 553d00e | 2010-07-19 19:22:10 -0700 | [diff] [blame] | 401 | printf(" uint16_t %s;\n", fld->name); |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 402 | } |
| 403 | } |
| 404 | } |
| 405 | |
| 406 | /* Outputs a structure initializer. |
| 407 | */ |
| 408 | int OutputBytes_(Command* cmd, Field* fld) { |
| 409 | int cursor = 0; |
| 410 | int i; |
| 411 | /* |
| 412 | * Field order is reversed. |
| 413 | */ |
| 414 | if (fld != NULL) { |
| 415 | cursor = OutputBytes_(cmd, fld->next); |
| 416 | } else { |
| 417 | return 0; |
| 418 | } |
| 419 | if (!fld->visible) { |
| 420 | /* |
| 421 | * Catch up missing fields. |
| 422 | */ |
| 423 | assert(fld->offset >= cursor); |
| 424 | for (i = 0; i < fld->offset - cursor; i++) { |
| 425 | printf("0, "); |
| 426 | } |
| 427 | cursor = fld->offset; |
| 428 | switch (fld->size) { |
| 429 | case 1: |
| 430 | printf("0x%x, ", fld->value); |
| 431 | cursor += 1; |
| 432 | break; |
| 433 | case 2: |
| 434 | printf("0x%x, 0x%x, ", fld->value >> 8, fld->value & 0xff); |
| 435 | cursor += 2; |
| 436 | break; |
| 437 | case 4: |
| 438 | printf("0x%x, 0x%x, 0x%x, 0x%x, ", fld->value >> 24, |
| 439 | (fld->value >> 16) & 0xff, |
| 440 | (fld->value >> 8) & 0xff, |
| 441 | fld->value & 0xff); |
| 442 | cursor += 4; |
| 443 | break; |
| 444 | default: |
Gaurav Shah | 553d00e | 2010-07-19 19:22:10 -0700 | [diff] [blame] | 445 | fprintf(stderr, "invalid field size %d\n", fld->size); |
| 446 | exit(1); |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 447 | break; |
| 448 | } |
| 449 | } |
| 450 | return cursor; |
| 451 | } |
| 452 | |
| 453 | /* Helper to output a structure initializer. |
| 454 | */ |
| 455 | void OutputBytes(Command* cmd) { |
| 456 | (void) OutputBytes_(cmd, cmd->fields); |
| 457 | } |
| 458 | |
| 459 | void OutputFieldPointers(Command* cmd, Field* fld) { |
| 460 | if (fld == NULL) { |
| 461 | return; |
| 462 | } else { |
| 463 | OutputFieldPointers(cmd, fld->next); |
| 464 | if (fld->visible) { |
Gaurav Shah | 553d00e | 2010-07-19 19:22:10 -0700 | [diff] [blame] | 465 | printf("%d, ", fld->offset); |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 466 | } |
| 467 | } |
| 468 | } |
| 469 | |
| 470 | /* Outputs the structure initializers for all commands. |
| 471 | */ |
| 472 | void OutputCommands(Command* cmd) { |
| 473 | if (cmd == NULL) { |
| 474 | return; |
| 475 | } else { |
Luigi Semenzato | 89a02c1 | 2010-08-31 15:49:56 -0700 | [diff] [blame] | 476 | printf("const struct s_%s{\n uint8_t buffer[%d];\n", |
Gaurav Shah | 553d00e | 2010-07-19 19:22:10 -0700 | [diff] [blame] | 477 | cmd->name, cmd->size == 0 ? cmd->max_size : cmd->size); |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 478 | OutputFields(cmd->fields); |
| 479 | printf("} %s = {{", cmd->name); |
| 480 | OutputBytes(cmd); |
| 481 | printf("},\n"); |
| 482 | OutputFieldPointers(cmd, cmd->fields); |
| 483 | printf("};\n\n"); |
| 484 | } |
| 485 | OutputCommands(cmd->next); |
| 486 | } |
| 487 | |
| 488 | Command* (*builders[])(void) = { |
| 489 | BuildDefineSpaceCommand, |
| 490 | BuildWriteCommand, |
| 491 | BuildReadCommand, |
Kees Cook | 946370d | 2012-01-09 14:17:40 -0800 | [diff] [blame] | 492 | BuildPCRReadCommand, |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 493 | BuildPPAssertCommand, |
Luigi Semenzato | 1d83dd1 | 2010-08-30 10:23:43 -0700 | [diff] [blame] | 494 | BuildPPEnableCommand, |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 495 | BuildPPLockCommand, |
Luigi Semenzato | 377557f | 2010-08-31 13:20:53 -0700 | [diff] [blame] | 496 | BuildFinalizePPCommand, |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 497 | BuildStartupCommand, |
Luigi Semenzato | 54992f9 | 2011-03-16 10:56:48 -0700 | [diff] [blame] | 498 | BuildSaveStateCommand, |
Luigi Semenzato | 3da063e | 2010-08-31 14:31:30 -0700 | [diff] [blame] | 499 | BuildResumeCommand, |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 500 | BuildSelftestfullCommand, |
| 501 | BuildContinueSelfTestCommand, |
| 502 | BuildReadPubekCommand, |
| 503 | BuildForceClearCommand, |
| 504 | BuildPhysicalDisableCommand, |
| 505 | BuildPhysicalEnableCommand, |
| 506 | BuildPhysicalSetDeactivatedCommand, |
| 507 | BuildGetFlagsCommand, |
Luigi Semenzato | 5896b96 | 2010-08-25 07:16:03 -0700 | [diff] [blame] | 508 | BuildGetSTClearFlagsCommand, |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 509 | BuildGetPermissionsCommand, |
Kees Cook | 8b6da26 | 2012-06-07 13:48:26 -0700 | [diff] [blame] | 510 | BuildGetOwnershipCommand, |
Kees Cook | f0605cb | 2012-02-29 16:09:14 -0800 | [diff] [blame] | 511 | BuildGetRandomCommand, |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 512 | BuildExtendCommand, |
| 513 | }; |
| 514 | |
| 515 | static void FreeFields(Field* fld) { |
| 516 | if (fld != NULL) { |
| 517 | Field* next_field = fld->next; |
Gaurav Shah | 553d00e | 2010-07-19 19:22:10 -0700 | [diff] [blame] | 518 | free(fld); |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 519 | FreeFields(next_field); |
| 520 | } |
| 521 | } |
| 522 | |
| 523 | static void FreeCommands(Command* cmd) { |
| 524 | if (cmd != NULL) { |
| 525 | Command* next_command = cmd->next; |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 526 | FreeFields(cmd->fields); |
Luigi Semenzato | d6acfd4 | 2013-01-08 16:23:11 -0800 | [diff] [blame] | 527 | free(cmd); |
Randall Spangler | 39f6611 | 2010-07-14 09:10:23 -0700 | [diff] [blame] | 528 | FreeCommands(next_command); |
| 529 | } |
| 530 | } |
| 531 | |
| 532 | int main(void) { |
| 533 | Command* commands = NULL; |
| 534 | int i; |
| 535 | for (i = 0; i < sizeof(builders) / sizeof(builders[0]); i++) { |
| 536 | Command* cmd = builders[i](); |
| 537 | cmd->next = commands; |
| 538 | commands = cmd; |
| 539 | } |
| 540 | |
| 541 | printf("/* This file is automatically generated */\n\n"); |
| 542 | OutputCommands(commands); |
| 543 | printf("const int kWriteInfoLength = %d;\n", (int) sizeof(TPM_WRITE_INFO)); |
| 544 | printf("const int kNvDataPublicPermissionsOffset = %d;\n", |
| 545 | (int) (offsetof(TPM_NV_DATA_PUBLIC, permission) + |
| 546 | 2 * PCR_SELECTION_FIX + |
| 547 | offsetof(TPM_NV_ATTRIBUTES, attributes))); |
| 548 | |
| 549 | FreeCommands(commands); |
| 550 | return 0; |
| 551 | } |