xref: /aosp_15_r20/external/vboot_reference/utility/tlcl_generator.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2012 The ChromiumOS Authors
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 
14 #include <assert.h>
15 #include <stdio.h>
16 
17 #include "2sysincludes.h"
18 #include "tlcl_internal.h"
19 #include "tpmextras.h"
20 #include "tss_constants.h"
21 
22 /* See struct Command below.  This structure represent a field in a TPM
23  * command.  [name] is the field name.  [visible] is 1 if the field is
24  * modified by the run-time.  Non-visible fields are initialized at build time
25  * and remain constant.  [size] is the field size in bytes.  [value] is the
26  * fixed value of non-visible fields.
27  */
28 typedef struct Field {
29   const char* name;
30   int visible;
31   int offset;
32   int size;
33   uint32_t value;     /* large enough for all initializers */
34   struct Field* next;
35 } Field;
36 
37 /* This structure is used to build (at build time) and manipulate (at firmware
38  * or emulation run time) buffers containing TPM datagrams.  [name] is the name
39  * of a TPM command.  [size] is the size of the command buffer in bytes, when
40  * known.  [max_size] is the maximum size allowed for variable-length commands
41  * (such as Read and Write).  [fields] is a link-list of command fields.
42  */
43 typedef struct Command {
44   const char* name;
45   int size;
46   int max_size;
47   Field* fields;
48   struct Command* next;
49 } Command;
50 
51 /* Adds a field to a command, and makes its offset visible.  The fields must be
52  * added at increasing offsets.
53  */
AddVisibleField(Command * cmd,const char * name,int offset)54 static void AddVisibleField(Command* cmd, const char* name, int offset) {
55   Field* fld = (Field*) calloc(1, sizeof(Field));
56   if (cmd->fields != NULL) {
57     assert(offset > fn->offset);
58   }
59   fld->next = cmd->fields;
60   cmd->fields = fld;
61   fld->name = name;
62   fld->visible = 1;
63   fld->offset = offset;
64 }
65 
66 /* Adds a constant field with its value.  The fields must be added at
67  * increasing offsets.
68  */
AddInitializedField(Command * cmd,int offset,int size,uint32_t value)69 static void AddInitializedField(Command* cmd, int offset,
70                                 int size, uint32_t value) {
71   Field* fld = (Field*) calloc(1, sizeof(Field));
72   fld->next = cmd->fields;
73   cmd->fields = fld;
74   fld->name = NULL;
75   fld->visible = 0;
76   fld->size = size;
77   fld->offset = offset;
78   fld->value = value;
79 }
80 
81 /* Create a structure representing a TPM command datagram.
82  */
newCommandWithTag(TPM_COMMAND_CODE code,int size,TPM_TAG tag)83 Command* newCommandWithTag(TPM_COMMAND_CODE code, int size, TPM_TAG tag) {
84   Command* cmd = (Command*) calloc(1, sizeof(Command));
85   cmd->size = size;
86   AddInitializedField(cmd, 0, sizeof(TPM_TAG), tag);
87   AddInitializedField(cmd, sizeof(TPM_TAG), sizeof(uint32_t), size);
88   AddInitializedField(cmd, sizeof(TPM_TAG) + sizeof(uint32_t),
89                       sizeof(TPM_COMMAND_CODE), code);
90   return cmd;
91 }
92 
newCommand(TPM_COMMAND_CODE code,int size)93 Command* newCommand(TPM_COMMAND_CODE code, int size) {
94   return newCommandWithTag(code, size, TPM_TAG_RQU_COMMAND);
95 }
96 
97 /* BuildXXX builds TPM command XXX.
98  */
BuildDefineSpaceCommand(void)99 Command* BuildDefineSpaceCommand(void) {
100   int nv_data_public = kTpmRequestHeaderLength;
101   int nv_index = nv_data_public + offsetof(TPM_NV_DATA_PUBLIC, nvIndex);
102   int nv_pcr_info_read = nv_data_public +
103     offsetof(TPM_NV_DATA_PUBLIC, pcrInfoRead);
104   int read_locality = nv_pcr_info_read +
105     offsetof(TPM_PCR_INFO_SHORT, localityAtRelease);
106   int nv_pcr_info_write = nv_data_public +
107     offsetof(TPM_NV_DATA_PUBLIC, pcrInfoWrite);
108   int write_locality = nv_pcr_info_write +
109     offsetof(TPM_PCR_INFO_SHORT, localityAtRelease);
110   int nv_permission = nv_data_public +
111     offsetof(TPM_NV_DATA_PUBLIC, permission);
112   int nv_permission_tag =
113     nv_permission + offsetof(TPM_NV_ATTRIBUTES, tag);
114   int nv_permission_attributes =
115     nv_permission + offsetof(TPM_NV_ATTRIBUTES, attributes);
116   int nv_datasize = nv_data_public +
117     offsetof(TPM_NV_DATA_PUBLIC, dataSize);
118 
119   int size = kTpmRequestHeaderLength + sizeof(TPM_NV_DATA_PUBLIC) +
120       kEncAuthLength;
121   Command* cmd = newCommand(TPM_ORD_NV_DefineSpace, size);
122   cmd->name = "tpm_nv_definespace_cmd";
123 
124   AddVisibleField(cmd, "index", nv_index);
125   AddVisibleField(cmd, "pcr_info_read", nv_pcr_info_read);
126   AddVisibleField(cmd, "pcr_info_write", nv_pcr_info_write);
127   AddVisibleField(cmd, "perm", nv_permission_attributes);
128   AddVisibleField(cmd, "size", nv_datasize);
129 
130   AddInitializedField(cmd, nv_data_public, sizeof(uint16_t),
131                       TPM_TAG_NV_DATA_PUBLIC);
132   AddInitializedField(cmd, nv_pcr_info_read, sizeof(uint16_t), 3);
133   AddInitializedField(cmd, read_locality, sizeof(TPM_LOCALITY_SELECTION),
134                       TPM_ALL_LOCALITIES);
135   AddInitializedField(cmd, nv_pcr_info_write, sizeof(uint16_t), 3);
136   AddInitializedField(cmd, write_locality, sizeof(TPM_LOCALITY_SELECTION),
137                       TPM_ALL_LOCALITIES);
138   AddInitializedField(cmd, nv_permission_tag, sizeof(TPM_STRUCTURE_TAG),
139                       TPM_TAG_NV_ATTRIBUTES);
140   return cmd;
141 }
142 
143 /* BuildXXX builds TPM command XXX.
144  */
BuildWriteCommand(void)145 Command* BuildWriteCommand(void) {
146   Command* cmd = newCommand(TPM_ORD_NV_WriteValue, 0);
147   cmd->name = "tpm_nv_write_cmd";
148   cmd->max_size = TPM_LARGE_ENOUGH_COMMAND_SIZE;
149   AddVisibleField(cmd, "index", kTpmRequestHeaderLength);
150   AddVisibleField(cmd, "length", kTpmRequestHeaderLength + 8);
151   AddVisibleField(cmd, "data", kTpmRequestHeaderLength + 12);
152   return cmd;
153 }
154 
BuildReadCommand(void)155 Command* BuildReadCommand(void) {
156   int size = kTpmRequestHeaderLength + kTpmReadInfoLength;
157   Command* cmd = newCommand(TPM_ORD_NV_ReadValue, size);
158   cmd->name = "tpm_nv_read_cmd";
159   AddVisibleField(cmd, "index", kTpmRequestHeaderLength);
160   AddVisibleField(cmd, "length", kTpmRequestHeaderLength + 8);
161   return cmd;
162 }
163 
BuildPCRReadCommand(void)164 Command* BuildPCRReadCommand(void) {
165   int size = kTpmRequestHeaderLength + sizeof(uint32_t);
166   Command* cmd = newCommand(TPM_ORD_PcrRead, size);
167   cmd->name = "tpm_pcr_read_cmd";
168   AddVisibleField(cmd, "pcrNum", kTpmRequestHeaderLength);
169   return cmd;
170 }
171 
BuildPPAssertCommand(void)172 Command* BuildPPAssertCommand(void) {
173   int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE);
174   Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size);
175   cmd->name = "tpm_ppassert_cmd";
176   AddInitializedField(cmd, kTpmRequestHeaderLength,
177                       sizeof(TPM_PHYSICAL_PRESENCE),
178                       TPM_PHYSICAL_PRESENCE_PRESENT);
179   return cmd;
180 }
181 
BuildPPEnableCommand(void)182 Command* BuildPPEnableCommand(void) {
183   int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE);
184   Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size);
185   cmd->name = "tpm_ppenable_cmd";
186   AddInitializedField(cmd, kTpmRequestHeaderLength,
187                       sizeof(TPM_PHYSICAL_PRESENCE),
188                       TPM_PHYSICAL_PRESENCE_CMD_ENABLE);
189   return cmd;
190 }
191 
BuildFinalizePPCommand(void)192 Command* BuildFinalizePPCommand(void) {
193   int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE);
194   Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size);
195   cmd->name = "tpm_finalizepp_cmd";
196   AddInitializedField(cmd, kTpmRequestHeaderLength,
197                       sizeof(TPM_PHYSICAL_PRESENCE),
198                       TPM_PHYSICAL_PRESENCE_CMD_ENABLE |
199                       TPM_PHYSICAL_PRESENCE_HW_DISABLE |
200                       TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK);
201   return cmd;
202 }
203 
BuildPPLockCommand(void)204 Command* BuildPPLockCommand(void) {
205   int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE);
206   Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size);
207   cmd->name = "tpm_pplock_cmd";
208   AddInitializedField(cmd, kTpmRequestHeaderLength,
209                       sizeof(TPM_PHYSICAL_PRESENCE),
210                       TPM_PHYSICAL_PRESENCE_LOCK);
211   return cmd;
212 }
213 
BuildStartupCommand(void)214 Command* BuildStartupCommand(void) {
215   int size = kTpmRequestHeaderLength + sizeof(TPM_STARTUP_TYPE);
216   Command* cmd = newCommand(TPM_ORD_Startup, size);
217   cmd->name = "tpm_startup_cmd";
218   AddInitializedField(cmd, kTpmRequestHeaderLength,
219                       sizeof(TPM_STARTUP_TYPE),
220                       TPM_ST_CLEAR);
221   return cmd;
222 }
223 
BuildSaveStateCommand(void)224 Command* BuildSaveStateCommand(void) {
225   int size = kTpmRequestHeaderLength;
226   Command* cmd = newCommand(TPM_ORD_SaveState, size);
227   cmd->name = "tpm_savestate_cmd";
228   return cmd;
229 }
230 
BuildResumeCommand(void)231 Command* BuildResumeCommand(void) {
232   int size = kTpmRequestHeaderLength + sizeof(TPM_STARTUP_TYPE);
233   Command* cmd = newCommand(TPM_ORD_Startup, size);
234   cmd->name = "tpm_resume_cmd";
235   AddInitializedField(cmd, kTpmRequestHeaderLength,
236                       sizeof(TPM_STARTUP_TYPE),
237                       TPM_ST_STATE);
238   return cmd;
239 }
240 
BuildSelftestfullCommand(void)241 Command* BuildSelftestfullCommand(void) {
242   int size = kTpmRequestHeaderLength;
243   Command* cmd = newCommand(TPM_ORD_SelfTestFull, size);
244   cmd->name = "tpm_selftestfull_cmd";
245   return cmd;
246 }
247 
BuildContinueSelfTestCommand(void)248 Command* BuildContinueSelfTestCommand(void) {
249   int size = kTpmRequestHeaderLength;
250   Command* cmd = newCommand(TPM_ORD_ContinueSelfTest, size);
251   cmd->name = "tpm_continueselftest_cmd";
252   return cmd;
253 }
254 
BuildReadPubekCommand(void)255 Command* BuildReadPubekCommand(void) {
256   int size = kTpmRequestHeaderLength + sizeof(TPM_NONCE);
257   Command* cmd = newCommand(TPM_ORD_ReadPubek, size);
258   cmd->name = "tpm_readpubek_cmd";
259   AddVisibleField(cmd, "antiReplay", kTpmRequestHeaderLength);
260   return cmd;
261 }
262 
BuildForceClearCommand(void)263 Command* BuildForceClearCommand(void) {
264   int size = kTpmRequestHeaderLength;
265   Command* cmd = newCommand(TPM_ORD_ForceClear, size);
266   cmd->name = "tpm_forceclear_cmd";
267   return cmd;
268 }
269 
BuildPhysicalEnableCommand(void)270 Command* BuildPhysicalEnableCommand(void) {
271   int size = kTpmRequestHeaderLength;
272   Command* cmd = newCommand(TPM_ORD_PhysicalEnable, size);
273   cmd->name = "tpm_physicalenable_cmd";
274   return cmd;
275 }
276 
BuildPhysicalDisableCommand(void)277 Command* BuildPhysicalDisableCommand(void) {
278   int size = kTpmRequestHeaderLength;
279   Command* cmd = newCommand(TPM_ORD_PhysicalDisable, size);
280   cmd->name = "tpm_physicaldisable_cmd";
281   return cmd;
282 }
283 
BuildPhysicalSetDeactivatedCommand(void)284 Command* BuildPhysicalSetDeactivatedCommand(void) {
285   int size = kTpmRequestHeaderLength + sizeof(uint8_t);
286   Command* cmd = newCommand(TPM_ORD_PhysicalSetDeactivated, size);
287   cmd->name = "tpm_physicalsetdeactivated_cmd";
288   AddVisibleField(cmd, "deactivated", kTpmRequestHeaderLength);
289   return cmd;
290 }
291 
BuildExtendCommand(void)292 Command* BuildExtendCommand(void) {
293   int size = kTpmRequestHeaderLength + sizeof(uint32_t) + kPcrDigestLength;
294   Command* cmd = newCommand(TPM_ORD_Extend, size);
295   cmd->name = "tpm_extend_cmd";
296   AddVisibleField(cmd, "pcrNum", kTpmRequestHeaderLength);
297   AddVisibleField(cmd, "inDigest", kTpmRequestHeaderLength + sizeof(uint32_t));
298   return cmd;
299 }
300 
BuildGetFlagsCommand(void)301 Command* BuildGetFlagsCommand(void) {
302   int size = (kTpmRequestHeaderLength +
303               sizeof(TPM_CAPABILITY_AREA) +   /* capArea */
304               sizeof(uint32_t) +              /* subCapSize */
305               sizeof(uint32_t));              /* subCap */
306 
307   Command* cmd = newCommand(TPM_ORD_GetCapability, size);
308   cmd->name = "tpm_getflags_cmd";
309   AddInitializedField(cmd, kTpmRequestHeaderLength,
310                       sizeof(TPM_CAPABILITY_AREA), TPM_CAP_FLAG);
311   AddInitializedField(cmd, kTpmRequestHeaderLength +
312                       sizeof(TPM_CAPABILITY_AREA),
313                       sizeof(uint32_t), sizeof(uint32_t));
314   AddInitializedField(cmd, kTpmRequestHeaderLength +
315                       sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t),
316                       sizeof(uint32_t), TPM_CAP_FLAG_PERMANENT);
317   return cmd;
318 }
319 
BuildGetSTClearFlagsCommand(void)320 Command* BuildGetSTClearFlagsCommand(void) {
321   int size = (kTpmRequestHeaderLength +
322               sizeof(TPM_CAPABILITY_AREA) +   /* capArea */
323               sizeof(uint32_t) +              /* subCapSize */
324               sizeof(uint32_t));              /* subCap */
325 
326   Command* cmd = newCommand(TPM_ORD_GetCapability, size);
327   cmd->name = "tpm_getstclearflags_cmd";
328   AddInitializedField(cmd, kTpmRequestHeaderLength,
329                       sizeof(TPM_CAPABILITY_AREA), TPM_CAP_FLAG);
330   AddInitializedField(cmd, kTpmRequestHeaderLength +
331                       sizeof(TPM_CAPABILITY_AREA),
332                       sizeof(uint32_t), sizeof(uint32_t));
333   AddInitializedField(cmd, kTpmRequestHeaderLength +
334                       sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t),
335                       sizeof(uint32_t), TPM_CAP_FLAG_VOLATILE);
336   return cmd;
337 }
338 
BuildGetSpaceInfoCommand(void)339 Command* BuildGetSpaceInfoCommand(void) {
340   int size = (kTpmRequestHeaderLength +
341               sizeof(TPM_CAPABILITY_AREA) +   /* capArea */
342               sizeof(uint32_t) +              /* subCapSize */
343               sizeof(uint32_t));              /* subCap */
344 
345   Command* cmd = newCommand(TPM_ORD_GetCapability, size);
346   cmd->name = "tpm_getspaceinfo_cmd";
347   AddInitializedField(cmd, kTpmRequestHeaderLength,
348                       sizeof(TPM_CAPABILITY_AREA), TPM_CAP_NV_INDEX);
349   AddInitializedField(cmd, kTpmRequestHeaderLength +
350                       sizeof(TPM_CAPABILITY_AREA),
351                       sizeof(uint32_t), sizeof(uint32_t));
352   AddVisibleField(cmd, "index", kTpmRequestHeaderLength +
353                   sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t));
354   return cmd;
355 }
356 
BuildGetOwnershipCommand(void)357 Command* BuildGetOwnershipCommand(void) {
358   int size = (kTpmRequestHeaderLength +
359               sizeof(TPM_CAPABILITY_AREA) +   /* capArea */
360               sizeof(uint32_t) +              /* subCapSize */
361               sizeof(uint32_t));              /* subCap */
362 
363   Command* cmd = newCommand(TPM_ORD_GetCapability, size);
364   cmd->name = "tpm_getownership_cmd";
365   AddInitializedField(cmd, kTpmRequestHeaderLength,
366                       sizeof(TPM_CAPABILITY_AREA), TPM_CAP_PROPERTY);
367   AddInitializedField(cmd, kTpmRequestHeaderLength +
368                       sizeof(TPM_CAPABILITY_AREA),
369                       sizeof(uint32_t), sizeof(uint32_t));
370   AddInitializedField(cmd, kTpmRequestHeaderLength +
371                       sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t),
372                       sizeof(uint32_t), TPM_CAP_PROP_OWNER);
373   return cmd;
374 }
375 
BuildGetRandomCommand(void)376 Command* BuildGetRandomCommand(void) {
377   int size = kTpmRequestHeaderLength + sizeof(uint32_t);
378   Command* cmd = newCommand(TPM_ORD_GetRandom, size);
379   cmd->name = "tpm_get_random_cmd";
380   AddVisibleField(cmd, "bytesRequested", kTpmRequestHeaderLength);
381   return cmd;
382 }
383 
BuildGetVersionValCommand(void)384 Command* BuildGetVersionValCommand(void) {
385   int size = (kTpmRequestHeaderLength +
386               sizeof(TPM_CAPABILITY_AREA) +   /* capArea */
387               sizeof(uint32_t));              /* subCapSize */
388 
389   Command* cmd = newCommand(TPM_ORD_GetCapability, size);
390   cmd->name = "tpm_getversionval_cmd";
391   AddInitializedField(cmd, kTpmRequestHeaderLength,
392                       sizeof(TPM_CAPABILITY_AREA), TPM_CAP_GET_VERSION_VAL);
393   AddInitializedField(cmd, kTpmRequestHeaderLength +
394                       sizeof(TPM_CAPABILITY_AREA),
395                       sizeof(uint32_t), 0);
396   return cmd;
397 }
398 
BuildIFXFieldUpgradeInfoRequest2Command(void)399 Command* BuildIFXFieldUpgradeInfoRequest2Command(void) {
400   int size = (kTpmRequestHeaderLength +
401               sizeof(TPM_IFX_FieldUpgradeInfoRequest2) +
402               sizeof(uint16_t));
403   Command* cmd = newCommand(TPM_ORD_FieldUpgrade, size);
404   cmd->name = "tpm_ifx_fieldupgradeinforequest2_cmd";
405   AddInitializedField(cmd, kTpmRequestHeaderLength,
406                       sizeof(TPM_IFX_FieldUpgradeInfoRequest2),
407                       TPM_IFX_FieldUpgradeInfoRequest2);
408   AddInitializedField(cmd, kTpmRequestHeaderLength +
409                       sizeof(TPM_IFX_FieldUpgradeInfoRequest2),
410                       sizeof(uint16_t), 0);
411   return cmd;
412 }
413 
BuildOIAPCommand(void)414 Command* BuildOIAPCommand(void) {
415   int size = kTpmRequestHeaderLength;
416   Command* cmd = newCommand(TPM_ORD_OIAP, size);
417   cmd->name = "tpm_oiap_cmd";
418   return cmd;
419 }
420 
BuildOSAPCommand(void)421 Command* BuildOSAPCommand(void) {
422   int size = kTpmRequestHeaderLength + sizeof(uint16_t) + sizeof(uint32_t) +
423              sizeof(TPM_NONCE);
424   Command* cmd = newCommand(TPM_ORD_OSAP, size);
425   cmd->name = "tpm_osap_cmd";
426   AddVisibleField(cmd, "entityType", kTpmRequestHeaderLength);
427   AddVisibleField(cmd, "entityValue",
428                   kTpmRequestHeaderLength + sizeof(uint16_t));
429   AddVisibleField(
430       cmd, "nonceOddOSAP",
431       kTpmRequestHeaderLength + sizeof(uint16_t) + sizeof(uint32_t));
432   return cmd;
433 }
434 
BuildTakeOwnershipCommand(void)435 Command* BuildTakeOwnershipCommand(void) {
436   Command* cmd = newCommandWithTag(TPM_ORD_TakeOwnership, 624,
437                                    TPM_TAG_RQU_AUTH1_COMMAND);
438   cmd->name = "tpm_takeownership_cmd";
439   int offset = kTpmRequestHeaderLength;
440   AddInitializedField(cmd, offset, sizeof(uint16_t), TPM_PID_OWNER);
441   offset += sizeof(uint16_t);
442   AddInitializedField(cmd, offset, sizeof(uint32_t), TPM_RSA_2048_LEN);
443   offset += sizeof(uint32_t);
444   AddVisibleField(cmd, "encOwnerAuth", offset);
445   offset += sizeof(uint8_t[TPM_RSA_2048_LEN]);
446   AddInitializedField(cmd, offset, sizeof(uint32_t), TPM_RSA_2048_LEN);
447   offset += sizeof(uint32_t);
448   AddVisibleField(cmd, "encSrkAuth", offset);
449   offset += sizeof(uint8_t[TPM_RSA_2048_LEN]);
450 
451   /* The remainder are the srkParams struct TPM_KEY12 contents. */
452   AddInitializedField(cmd, offset, sizeof(uint16_t), TPM_TAG_KEY12);
453   offset += sizeof(uint16_t);
454   AddInitializedField(cmd, offset, sizeof(uint16_t), 0);
455   offset += sizeof(uint16_t);
456   AddInitializedField(cmd, offset, sizeof(uint16_t), TPM_KEY_USAGE_STORAGE);
457   offset += sizeof(uint16_t);
458   AddInitializedField(cmd, offset, sizeof(uint32_t), 0 /* keyFlags */);
459   offset += sizeof(uint32_t);
460   AddInitializedField(cmd, offset, sizeof(uint8_t), TPM_AUTH_ALWAYS);
461   offset += sizeof(uint8_t);
462   AddInitializedField(cmd, offset, sizeof(uint32_t), TPM_ALG_RSA);
463   offset += sizeof(uint32_t);
464   AddInitializedField(cmd, offset, sizeof(uint16_t),
465                       TPM_ES_RSAESOAEP_SHA1_MGF1);
466   offset += sizeof(uint16_t);
467   AddInitializedField(cmd, offset, sizeof(uint16_t), TPM_SS_NONE);
468   offset += sizeof(uint16_t);
469   AddInitializedField(cmd, offset, sizeof(uint32_t),
470                       3 * sizeof(uint32_t) /* algorithmParams.parmSize */);
471   offset += sizeof(uint32_t);
472   AddInitializedField(cmd, offset, sizeof(uint32_t),
473                       2048 /* algorithmParms.parms.keyLength */);
474   offset += sizeof(uint32_t);
475   AddInitializedField(cmd, offset, sizeof(uint32_t),
476                       2 /* algorithmParms.parms.numPrimes */);
477   offset += sizeof(uint32_t);
478   AddInitializedField(cmd, offset, sizeof(uint32_t),
479                       0 /* algorithmParms.parms.exponentSize */);
480   offset += sizeof(uint32_t);
481   AddInitializedField(cmd, offset, sizeof(uint32_t), 0 /* PCRInfoSize */);
482   offset += sizeof(uint32_t);
483   AddInitializedField(cmd, offset, sizeof(uint32_t), 0 /* pubkey.keyLength */);
484   offset += sizeof(uint32_t);
485   AddInitializedField(cmd, offset, sizeof(uint32_t), 0 /* encDataSize */);
486   offset += sizeof(uint32_t);
487 
488   /* Allocate space for the auth block. */
489   offset += kTpmRequestAuthBlockLength;
490 
491   assert(offset == cmd->size);
492 
493   return cmd;
494 }
495 
BuildCreateDelegationFamilyCommand(void)496 Command* BuildCreateDelegationFamilyCommand(void) {
497   int size = kTpmRequestHeaderLength + 3 * sizeof(uint32_t) + sizeof(uint8_t);
498   Command* cmd = newCommand(TPM_ORD_Delegate_Manage, size);
499   cmd->name = "tpm_create_delegation_family_cmd";
500   AddInitializedField(cmd, kTpmRequestHeaderLength, sizeof(uint32_t),
501                       0 /* familyID */);
502   AddInitializedField(cmd, kTpmRequestHeaderLength + sizeof(uint32_t),
503                       sizeof(uint32_t), TPM_FAMILY_CREATE);
504   AddInitializedField(cmd, kTpmRequestHeaderLength + 2 * sizeof(uint32_t),
505                       sizeof(uint32_t), sizeof(uint8_t) /* opDataSize */);
506   AddVisibleField(cmd, "familyLabel",
507                   kTpmRequestHeaderLength + 3 * sizeof(uint32_t));
508   return cmd;
509 }
510 
BuildReadDelegationFamilyTableCommand(void)511 Command* BuildReadDelegationFamilyTableCommand(void) {
512   Command* cmd =
513       newCommand(TPM_ORD_Delegate_ReadTable, kTpmRequestHeaderLength);
514   cmd->name = "tpm_delegate_read_table_cmd";
515   return cmd;
516 }
517 
518 /* Output the fields of a structure.
519  */
OutputFields(Field * fld)520 void OutputFields(Field* fld) {
521   /*
522    * Field order is reversed.
523    */
524   if (fld != NULL) {
525     OutputFields(fld->next);
526     if (fld->visible) {
527       printf("  uint16_t %s;\n", fld->name);
528     }
529   }
530 }
531 
532 /* Outputs a structure initializer.
533  */
OutputBytes_(Command * cmd,Field * fld)534 int OutputBytes_(Command* cmd, Field* fld) {
535   int cursor = 0;
536   int i;
537   /*
538    * Field order is reversed.
539    */
540   if (fld != NULL) {
541     cursor = OutputBytes_(cmd, fld->next);
542   } else {
543     return 0;
544   }
545   if (!fld->visible) {
546     /*
547      * Catch up missing fields.
548      */
549     assert(fld->offset >= cursor);
550     for (i = 0; i < fld->offset - cursor; i++) {
551       printf("0, ");
552     }
553     cursor = fld->offset;
554     switch (fld->size) {
555     case 1:
556       printf("%#x, ", fld->value);
557       cursor += 1;
558       break;
559     case 2:
560       printf("%#x, %#x, ", fld->value >> 8, fld->value & 0xff);
561       cursor += 2;
562       break;
563     case 4:
564       printf("%#x, %#x, %#x, %#x, ", fld->value >> 24,
565              (fld->value >> 16) & 0xff,
566              (fld->value >> 8) & 0xff,
567              fld->value & 0xff);
568       cursor += 4;
569       break;
570     default:
571       fprintf(stderr, "invalid field size %d\n", fld->size);
572       exit(1);
573       break;
574     }
575   }
576   return cursor;
577 }
578 
579 /* Helper to output a structure initializer.
580  */
OutputBytes(Command * cmd)581 void OutputBytes(Command* cmd) {
582   (void) OutputBytes_(cmd, cmd->fields);
583 }
584 
OutputFieldPointers(Command * cmd,Field * fld)585 void OutputFieldPointers(Command* cmd, Field* fld) {
586   if (fld == NULL) {
587     return;
588   } else {
589     OutputFieldPointers(cmd, fld->next);
590     if (fld->visible) {
591       printf("%d, ", fld->offset);
592     }
593   }
594 }
595 
596 /* Outputs the structure initializers for all commands.
597  */
OutputCommands(Command * cmd)598 void OutputCommands(Command* cmd) {
599   if (cmd == NULL) {
600     return;
601   } else {
602     printf("const struct s_%s{\n  uint8_t buffer[%d];\n",
603            cmd->name, cmd->size == 0 ? cmd->max_size : cmd->size);
604     OutputFields(cmd->fields);
605     printf("} %s = {{", cmd->name);
606     OutputBytes(cmd);
607     printf("},\n");
608     OutputFieldPointers(cmd, cmd->fields);
609     printf("};\n\n");
610   }
611   OutputCommands(cmd->next);
612 }
613 
614 Command* (*builders[])(void) = {
615   BuildDefineSpaceCommand,
616   BuildWriteCommand,
617   BuildReadCommand,
618   BuildPCRReadCommand,
619   BuildPPAssertCommand,
620   BuildPPEnableCommand,
621   BuildPPLockCommand,
622   BuildFinalizePPCommand,
623   BuildStartupCommand,
624   BuildSaveStateCommand,
625   BuildResumeCommand,
626   BuildSelftestfullCommand,
627   BuildContinueSelfTestCommand,
628   BuildReadPubekCommand,
629   BuildForceClearCommand,
630   BuildPhysicalDisableCommand,
631   BuildPhysicalEnableCommand,
632   BuildPhysicalSetDeactivatedCommand,
633   BuildGetFlagsCommand,
634   BuildGetSTClearFlagsCommand,
635   BuildGetSpaceInfoCommand,
636   BuildGetOwnershipCommand,
637   BuildGetRandomCommand,
638   BuildExtendCommand,
639   BuildGetVersionValCommand,
640   BuildIFXFieldUpgradeInfoRequest2Command,
641   BuildOIAPCommand,
642   BuildOSAPCommand,
643   BuildTakeOwnershipCommand,
644   BuildCreateDelegationFamilyCommand,
645   BuildReadDelegationFamilyTableCommand,
646 };
647 
FreeFields(Field * fld)648 static void FreeFields(Field* fld) {
649   if (fld != NULL) {
650     Field* next_field = fld->next;
651     free(fld);
652     FreeFields(next_field);
653   }
654 }
655 
FreeCommands(Command * cmd)656 static void FreeCommands(Command* cmd) {
657   if (cmd != NULL) {
658     Command* next_command = cmd->next;
659     FreeFields(cmd->fields);
660     free(cmd);
661     FreeCommands(next_command);
662   }
663 }
664 
main(void)665 int main(void) {
666   Command* commands = NULL;
667   int i;
668   for (i = 0; i < sizeof(builders) / sizeof(builders[0]); i++) {
669     Command* cmd = builders[i]();
670     cmd->next = commands;
671     commands = cmd;
672   }
673 
674   printf("/* This file is automatically generated */\n\n");
675   OutputCommands(commands);
676   printf("const int kWriteInfoLength = %d;\n", (int) sizeof(TPM_WRITE_INFO));
677 
678   FreeCommands(commands);
679   return 0;
680 }
681