Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Side by Side Diff: utility/tlcl_generator.c

Issue 2919010: Add tpm lite to vboot reference (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « utility/Makefile ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
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 <stddef.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <tss/tcs.h>
18
19 #include "tlcl.h"
20 #include "tlcl_internal.h"
21 #include "tpmextras.h"
22 #include "utility.h"
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) {
57 Field* fld = (Field*) Malloc(sizeof(Field));
58 if (cmd->fields != NULL) {
59 Field* fn = cmd->fields;
60 assert(offset > fn->offset);
61 }
62 fld->next = cmd->fields;
63 cmd->fields = fld;
64 fld->name = name;
65 fld->visible = 1;
66 fld->offset = offset;
67 }
68
69 /* Adds a constant field with its value. The fields must be added at
70 * increasing offsets.
71 */
72 static void AddInitializedField(Command* cmd, int offset,
73 int size, uint32_t value) {
74 Field* fld = (Field*) Malloc(sizeof(Field));
75 fld->next = cmd->fields;
76 cmd->fields = fld;
77 fld->name = NULL;
78 fld->visible = 0;
79 fld->size = size;
80 fld->offset = offset;
81 fld->value = value;
82 }
83
84 /* Create a structure representing a TPM command datagram.
85 */
86 Command* newCommand(TPM_COMMAND_CODE code, int size) {
87 Command* cmd = (Command*) Malloc(sizeof(Command));
88 cmd->size = size;
89 AddInitializedField(cmd, 0, sizeof(TPM_TAG), TPM_TAG_RQU_COMMAND);
90 AddInitializedField(cmd, sizeof(TPM_TAG), sizeof(uint32_t), size);
91 AddInitializedField(cmd, sizeof(TPM_TAG) + sizeof(uint32_t),
92 sizeof(TPM_COMMAND_CODE), code);
93 return cmd;
94 }
95
96 /* The TPM_PCR_SELECTION structure in /usr/include/tss/tpm.h contains a pointer
97 * instead of an array[3] of bytes, so we need to adjust sizes and offsets
98 * accordingly.
99 */
100 #define PCR_SELECTION_FIX (3 - sizeof(char *))
101
102 /* BuildXXX builds TPM command XXX.
103 */
104 Command* BuildDefineSpaceCommand(void) {
105 int nv_data_public = kTpmRequestHeaderLength;
106 int nv_index = nv_data_public + offsetof(TPM_NV_DATA_PUBLIC, nvIndex);
107 int nv_pcr_info_read = nv_data_public +
108 offsetof(TPM_NV_DATA_PUBLIC, pcrInfoRead);
109 /*
110 * Here we need to carefully add PCR_SELECTION_FIX (or twice that much) in
111 * all the places where the offset calculation would be wrong without it.
112 * The mismatch occurs in the TPM_PCR_SELECTION structure, and it must be
113 * accounted for in all the structures that include it, directly or
114 * indirectly.
115 */
116 int read_locality = nv_pcr_info_read +
117 offsetof(TPM_PCR_INFO_SHORT, localityAtRelease) + PCR_SELECTION_FIX;
118 int nv_pcr_info_write = nv_data_public +
119 offsetof(TPM_NV_DATA_PUBLIC, pcrInfoWrite) + PCR_SELECTION_FIX;
120 int write_locality = nv_pcr_info_write +
121 offsetof(TPM_PCR_INFO_SHORT, localityAtRelease) + PCR_SELECTION_FIX;
122 int nv_permission = nv_data_public +
123 offsetof(TPM_NV_DATA_PUBLIC, permission) + 2 * PCR_SELECTION_FIX;
124 int nv_permission_tag =
125 nv_permission + offsetof(TPM_NV_ATTRIBUTES, tag);
126 int nv_permission_attributes =
127 nv_permission + offsetof(TPM_NV_ATTRIBUTES, attributes);
128 int nv_datasize = nv_data_public +
129 offsetof(TPM_NV_DATA_PUBLIC, dataSize) + 2 * PCR_SELECTION_FIX;
130
131 int size = kTpmRequestHeaderLength + sizeof(TPM_NV_DATA_PUBLIC) +
132 2 * PCR_SELECTION_FIX + kEncAuthLength;
133 Command* cmd = newCommand(TPM_ORD_NV_DefineSpace, size);
134 cmd->name = "tpm_nv_definespace_cmd";
135
136 AddVisibleField(cmd, "index", nv_index);
137 AddVisibleField(cmd, "perm", nv_permission_attributes);
138 AddVisibleField(cmd, "size", nv_datasize);
139
140 AddInitializedField(cmd, nv_data_public, sizeof(uint16_t),
141 TPM_TAG_NV_DATA_PUBLIC);
142 AddInitializedField(cmd, nv_pcr_info_read, sizeof(uint16_t), 3);
143 AddInitializedField(cmd, read_locality, sizeof(TPM_LOCALITY_SELECTION),
144 TPM_ALL_LOCALITIES);
145 AddInitializedField(cmd, nv_pcr_info_write, sizeof(uint16_t), 3);
146 AddInitializedField(cmd, write_locality, sizeof(TPM_LOCALITY_SELECTION),
147 TPM_ALL_LOCALITIES);
148 AddInitializedField(cmd, nv_permission_tag, sizeof(TPM_STRUCTURE_TAG),
149 TPM_TAG_NV_ATTRIBUTES);
150 return cmd;
151 }
152
153 /* BuildXXX builds TPM command XXX.
154 */
155 Command* BuildWriteCommand(void) {
156 Command* cmd = newCommand(TPM_ORD_NV_WriteValue, 0);
157 cmd->name = "tpm_nv_write_cmd";
158 cmd->max_size = TPM_LARGE_ENOUGH_COMMAND_SIZE;
159 AddVisibleField(cmd, "index", kTpmRequestHeaderLength);
160 AddVisibleField(cmd, "length", kTpmRequestHeaderLength + 8);
161 AddVisibleField(cmd, "data", kTpmRequestHeaderLength + 12);
162 return cmd;
163 }
164
165 Command* BuildReadCommand(void) {
166 int size = kTpmRequestHeaderLength + kTpmReadInfoLength;
167 Command* cmd = newCommand(TPM_ORD_NV_ReadValue, size);
168 cmd->name = "tpm_nv_read_cmd";
169 AddVisibleField(cmd, "index", kTpmRequestHeaderLength);
170 AddVisibleField(cmd, "length", kTpmRequestHeaderLength + 8);
171 return cmd;
172 }
173
174 Command* BuildPPAssertCommand(void) {
175 int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE);
176 Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size);
177 cmd->name = "tpm_ppassert_cmd";
178 AddInitializedField(cmd, kTpmRequestHeaderLength,
179 sizeof(TPM_PHYSICAL_PRESENCE),
180 TPM_PHYSICAL_PRESENCE_PRESENT);
181 return cmd;
182 }
183
184 Command* BuildPPLockCommand(void) {
185 int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE);
186 Command* cmd = newCommand(TSC_ORD_PhysicalPresence, size);
187 cmd->name = "tpm_pplock_cmd";
188 AddInitializedField(cmd, kTpmRequestHeaderLength,
189 sizeof(TPM_PHYSICAL_PRESENCE),
190 TPM_PHYSICAL_PRESENCE_LOCK);
191 return cmd;
192 }
193
194 Command* BuildStartupCommand(void) {
195 int size = kTpmRequestHeaderLength + sizeof(TPM_PHYSICAL_PRESENCE);
196 Command* cmd = newCommand(TPM_ORD_Startup, size);
197 cmd->name = "tpm_startup_cmd";
198 AddInitializedField(cmd, kTpmRequestHeaderLength,
199 sizeof(TPM_STARTUP_TYPE),
200 TPM_ST_CLEAR);
201 return cmd;
202 }
203
204 Command* BuildSelftestfullCommand(void) {
205 int size = kTpmRequestHeaderLength;
206 Command* cmd = newCommand(TPM_ORD_SelfTestFull, size);
207 cmd->name = "tpm_selftestfull_cmd";
208 return cmd;
209 }
210
211 Command* BuildContinueSelfTestCommand(void) {
212 int size = kTpmRequestHeaderLength;
213 Command* cmd = newCommand(TPM_ORD_ContinueSelfTest, size);
214 cmd->name = "tpm_continueselftest_cmd";
215 return cmd;
216 }
217
218 Command* BuildReadPubekCommand(void) {
219 int size = kTpmRequestHeaderLength + sizeof(TPM_NONCE);
220 Command* cmd = newCommand(TPM_ORD_ReadPubek, size);
221 cmd->name = "tpm_readpubek_cmd";
222 return cmd;
223 }
224
225 Command* BuildForceClearCommand(void) {
226 int size = kTpmRequestHeaderLength;
227 Command* cmd = newCommand(TPM_ORD_ForceClear, size);
228 cmd->name = "tpm_forceclear_cmd";
229 return cmd;
230 }
231
232 Command* BuildPhysicalEnableCommand(void) {
233 int size = kTpmRequestHeaderLength;
234 Command* cmd = newCommand(TPM_ORD_PhysicalEnable, size);
235 cmd->name = "tpm_physicalenable_cmd";
236 return cmd;
237 }
238
239 Command* BuildPhysicalDisableCommand(void) {
240 int size = kTpmRequestHeaderLength;
241 Command* cmd = newCommand(TPM_ORD_PhysicalDisable, size);
242 cmd->name = "tpm_physicaldisable_cmd";
243 return cmd;
244 }
245
246 Command* BuildPhysicalSetDeactivatedCommand(void) {
247 int size = kTpmRequestHeaderLength + sizeof(uint8_t);
248 Command* cmd = newCommand(TPM_ORD_PhysicalSetDeactivated, size);
249 cmd->name = "tpm_physicalsetdeactivated_cmd";
250 AddVisibleField(cmd, "deactivated", kTpmRequestHeaderLength);
251 return cmd;
252 }
253
254 Command* BuildExtendCommand(void) {
255 int size = kTpmRequestHeaderLength + sizeof(uint32_t) + kPcrDigestLength;
256 Command* cmd = newCommand(TPM_ORD_Extend, size);
257 cmd->name = "tpm_extend_cmd";
258 AddVisibleField(cmd, "pcrNum", kTpmRequestHeaderLength);
259 AddVisibleField(cmd, "inDigest", kTpmRequestHeaderLength + sizeof(uint32_t));
260 return cmd;
261 }
262
263 Command* BuildGetFlagsCommand(void) {
264 int size = (kTpmRequestHeaderLength +
265 sizeof(TPM_CAPABILITY_AREA) + /* capArea */
266 sizeof(uint32_t) + /* subCapSize */
267 sizeof(uint32_t)); /* subCap */
268
269 Command* cmd = newCommand(TPM_ORD_GetCapability, size);
270 cmd->name = "tpm_getflags_cmd";
271 AddInitializedField(cmd, kTpmRequestHeaderLength,
272 sizeof(TPM_CAPABILITY_AREA), TPM_CAP_FLAG);
273 AddInitializedField(cmd, kTpmRequestHeaderLength +
274 sizeof(TPM_CAPABILITY_AREA),
275 sizeof(uint32_t), sizeof(uint32_t));
276 AddInitializedField(cmd, kTpmRequestHeaderLength +
277 sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t),
278 sizeof(uint32_t), TPM_CAP_FLAG_PERMANENT);
279 return cmd;
280 }
281
282 Command* BuildGetPermissionsCommand(void) {
283 int size = (kTpmRequestHeaderLength +
284 sizeof(TPM_CAPABILITY_AREA) + /* capArea */
285 sizeof(uint32_t) + /* subCapSize */
286 sizeof(uint32_t)); /* subCap */
287
288 Command* cmd = newCommand(TPM_ORD_GetCapability, size);
289 cmd->name = "tpm_getpermissions_cmd";
290 AddInitializedField(cmd, kTpmRequestHeaderLength,
291 sizeof(TPM_CAPABILITY_AREA), TPM_CAP_NV_INDEX);
292 AddInitializedField(cmd, kTpmRequestHeaderLength +
293 sizeof(TPM_CAPABILITY_AREA),
294 sizeof(uint32_t), sizeof(uint32_t));
295 AddVisibleField(cmd, "index", kTpmRequestHeaderLength +
296 sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t));
297 return cmd;
298 }
299
300 /* Output the fields of a structure.
301 */
302 void OutputFields(Field* fld) {
303 /*
304 * Field order is reversed.
305 */
306 if (fld != NULL) {
307 OutputFields(fld->next);
308 if (fld->visible) {
309 printf(" uint8_t* %s;\n", fld->name);
310 }
311 }
312 }
313
314 /* Outputs a structure initializer.
315 */
316 int OutputBytes_(Command* cmd, Field* fld) {
317 int cursor = 0;
318 int i;
319 /*
320 * Field order is reversed.
321 */
322 if (fld != NULL) {
323 cursor = OutputBytes_(cmd, fld->next);
324 } else {
325 return 0;
326 }
327 if (!fld->visible) {
328 /*
329 * Catch up missing fields.
330 */
331 assert(fld->offset >= cursor);
332 for (i = 0; i < fld->offset - cursor; i++) {
333 printf("0, ");
334 }
335 cursor = fld->offset;
336 switch (fld->size) {
337 case 1:
338 printf("0x%x, ", fld->value);
339 cursor += 1;
340 break;
341 case 2:
342 printf("0x%x, 0x%x, ", fld->value >> 8, fld->value & 0xff);
343 cursor += 2;
344 break;
345 case 4:
346 printf("0x%x, 0x%x, 0x%x, 0x%x, ", fld->value >> 24,
347 (fld->value >> 16) & 0xff,
348 (fld->value >> 8) & 0xff,
349 fld->value & 0xff);
350 cursor += 4;
351 break;
352 default:
353 error("invalid field size %d\n", fld->size);
354 break;
355 }
356 }
357 return cursor;
358 }
359
360 /* Helper to output a structure initializer.
361 */
362 void OutputBytes(Command* cmd) {
363 (void) OutputBytes_(cmd, cmd->fields);
364 }
365
366 void OutputFieldPointers(Command* cmd, Field* fld) {
367 if (fld == NULL) {
368 return;
369 } else {
370 OutputFieldPointers(cmd, fld->next);
371 if (fld->visible) {
372 printf("%s.buffer + %d, ", cmd->name, fld->offset);
373 }
374 }
375 }
376
377 /* Outputs the structure initializers for all commands.
378 */
379 void OutputCommands(Command* cmd) {
380 if (cmd == NULL) {
381 return;
382 } else {
383 printf("struct {\n uint8_t buffer[%d];\n",
384 cmd->size == 0 ? cmd->max_size : cmd->size);
385 OutputFields(cmd->fields);
386 printf("} %s = {{", cmd->name);
387 OutputBytes(cmd);
388 printf("},\n");
389 OutputFieldPointers(cmd, cmd->fields);
390 printf("};\n\n");
391 }
392 OutputCommands(cmd->next);
393 }
394
395 Command* (*builders[])(void) = {
396 BuildDefineSpaceCommand,
397 BuildWriteCommand,
398 BuildReadCommand,
399 BuildPPAssertCommand,
400 BuildPPLockCommand,
401 BuildStartupCommand,
402 BuildSelftestfullCommand,
403 BuildContinueSelfTestCommand,
404 BuildReadPubekCommand,
405 BuildForceClearCommand,
406 BuildPhysicalDisableCommand,
407 BuildPhysicalEnableCommand,
408 BuildPhysicalSetDeactivatedCommand,
409 BuildGetFlagsCommand,
410 BuildGetPermissionsCommand,
411 BuildExtendCommand,
412 };
413
414 static void FreeFields(Field* fld) {
415 if (fld != NULL) {
416 Field* next_field = fld->next;
417 Free(fld);
418 FreeFields(next_field);
419 }
420 }
421
422 static void FreeCommands(Command* cmd) {
423 if (cmd != NULL) {
424 Command* next_command = cmd->next;
425 Free(cmd);
426 FreeFields(cmd->fields);
427 FreeCommands(next_command);
428 }
429 }
430
431 int main(void) {
432 Command* commands = NULL;
433 int i;
434 for (i = 0; i < sizeof(builders) / sizeof(builders[0]); i++) {
435 Command* cmd = builders[i]();
436 cmd->next = commands;
437 commands = cmd;
438 }
439
440 printf("/* This file is automatically generated */\n\n");
441 OutputCommands(commands);
442 printf("const int kWriteInfoLength = %d;\n", (int) sizeof(TPM_WRITE_INFO));
443 printf("const int kNvDataPublicPermissionsOffset = %d;\n",
444 (int) (offsetof(TPM_NV_DATA_PUBLIC, permission) +
445 2 * PCR_SELECTION_FIX +
446 offsetof(TPM_NV_ATTRIBUTES, attributes)));
447
448 FreeCommands(commands);
449 return 0;
450 }
OLDNEW
« no previous file with comments | « utility/Makefile ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698