1 /* Microsoft Reference Implementation for TPM 2.0
2 *
3 * The copyright in this software is being made available under the BSD License,
4 * included below. This software may be subject to other third party and
5 * contributor rights, including patent rights, and no such rights are granted
6 * under this license.
7 *
8 * Copyright (c) Microsoft Corporation
9 *
10 * All rights reserved.
11 *
12 * BSD License
13 *
14 * Redistribution and use in source and binary forms, with or without modification,
15 * are permitted provided that the following conditions are met:
16 *
17 * Redistributions of source code must retain the above copyright notice, this list
18 * of conditions and the following disclaimer.
19 *
20 * Redistributions in binary form must reproduce the above copyright notice, this
21 * list of conditions and the following disclaimer in the documentation and/or
22 * other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 //* Includes and Typedefs
37 #include "Tpm.h"
38 #include "Marshal.h"
39
40 #if TABLE_DRIVEN_DISPATCH
41
42 typedef TPM_RC(NoFlagFunction)(void *target, BYTE **buffer, INT32 *size);
43 typedef TPM_RC(FlagFunction)(void *target, BYTE **buffer, INT32 *size, BOOL flag);
44
45 typedef FlagFunction *UNMARSHAL_t;
46
47 typedef INT16(MarshalFunction)(void *source, BYTE **buffer, INT32 *size);
48 typedef MarshalFunction *MARSHAL_t;
49
50 typedef TPM_RC(COMMAND_NO_ARGS)(void);
51 typedef TPM_RC(COMMAND_IN_ARG)(void *in);
52 typedef TPM_RC(COMMAND_OUT_ARG)(void *out);
53 typedef TPM_RC(COMMAND_INOUT_ARG)(void *in, void *out);
54
55 typedef union COMMAND_t
56 {
57 COMMAND_NO_ARGS *noArgs;
58 COMMAND_IN_ARG *inArg;
59 COMMAND_OUT_ARG *outArg;
60 COMMAND_INOUT_ARG *inOutArg;
61 } COMMAND_t;
62
63 // This structure is used by ParseHandleBuffer() and CommandDispatcher(). The
64 // parameters in this structure are unique for each command. The parameters are:
65 // command holds the address of the command processing function that is called
66 // by Command Dispatcher
67 // inSize This is the size of the command-dependent input structure. The
68 // input structure holds the unmarshaled handles and command
69 // parameters. If the command takes no arguments (handles or
70 // parameters) then inSize will have a value of 0.
71 // outSize This is the size of the command-dependent output structure. The
72 // output structure holds the results of the command in an unmarshaled
73 // form. When command processing is completed, these values are
74 // marshaled into the output buffer. It is always the case that the
75 // unmarshaled version of an output structure is larger then the
76 // marshaled version. This is because the marshaled version contains
77 // the exact same number of significant bytes but with padding removed.
78 // typesOffsets This parameter points to the list of data types that are to be
79 // marshaled or unmarshaled. The list of types follows the 'offsets'
80 // array. The offsets array is variable sized so the typesOffset filed
81 // is necessary for the handle and command processing to be able to
82 // find the types that are being handled. The 'offsets' array may be
83 // empty. The 'types' structure is described below.
84 // offsets This is an array of offsets of each of the parameters in the
85 // command or response. When processing the command parameters (not
86 // handles) the list contains the offset of the next parameter. For
87 // example, if the first command parameter has a size of 4 and there is
88 // a second command parameter, then the offset would be 4, indicating
89 // that the second parameter starts at 4. If the second parameter has
90 // a size of 8, and there is a third parameter, then the second entry
91 // in offsets is 12 (4 for the first parameter and 8 for the second).
92 // An offset value of 0 in the list indicates the start of the response
93 // parameter list. When CommandDispatcher hits this value, it will stop
94 // unmarshaling the parameters and call 'command'. If a command has no
95 // response parameters and only one command parameter, then offsets can
96 // be an empty list.
97
98 typedef struct COMMAND_DESCRIPTOR_t
99 {
100 COMMAND_t command; // Address of the command
101 UINT16 inSize; // Maximum size of the input structure
102 UINT16 outSize; // Maximum size of the output structure
103 UINT16 typesOffset; // address of the types field
104 UINT16 offsets[1];
105 } COMMAND_DESCRIPTOR_t;
106
107 // The 'types' list is an encoded byte array. The byte value has two parts. The most
108 // significant bit is used when a parameter takes a flag and indicates if the flag
109 // should be SET or not. The remaining 7 bits are an index into an array of
110 // addresses of marshaling and unmarshaling functions.
111 // The array of functions is divided into 6 sections with a value assigned
112 // to denote the start of that section (and the end of the previous section). The
113 // defined offset values for each section are:
114 // 0 unmarshaling for handles that do not take flags
115 // HANDLE_FIRST_FLAG_TYPE unmarshaling for handles that take flags
116 // PARAMETER_FIRST_TYPE unmarshaling for parameters that do not take flags
117 // PARAMETER_FIRST_FLAG_TYPE unmarshaling for parameters that take flags
118 // PARAMETER_LAST_TYPE + 1 marshaling for handles
119 // RESPONSE_PARAMETER_FIRST_TYPE marshaling for parameters
120 // RESPONSE_PARAMETER_LAST_TYPE is the last value in the list of marshaling and
121 // unmarshaling functions.
122 //
123 // The types list is constructed with a byte of 0xff at the end of the command
124 // parameters and with an 0xff at the end of the response parameters.
125
126 #if COMPRESSED_LISTS
127 # define PAD_LIST 0
128 #else
129 # define PAD_LIST 1
130 #endif
131 #define _COMMAND_TABLE_DISPATCH_
132 #include "CommandDispatchData.h"
133
134 #define TEST_COMMAND TPM_CC_Startup
135
136 #define NEW_CC
137
138 #else
139
140 #include "Commands.h"
141
142 #endif
143
144 //* Marshal/Unmarshal Functions
145
146 //** ParseHandleBuffer()
147 // This is the table-driven version of the handle buffer unmarshaling code
148 TPM_RC
ParseHandleBuffer(COMMAND * command)149 ParseHandleBuffer(
150 COMMAND *command
151 )
152 {
153 TPM_RC result;
154 #if TABLE_DRIVEN_DISPATCH
155 COMMAND_DESCRIPTOR_t *desc;
156 BYTE *types;
157 BYTE type;
158 BYTE dType;
159
160 // Make sure that nothing strange has happened
161 pAssert(command->index
162 < sizeof(s_CommandDataArray) / sizeof(COMMAND_DESCRIPTOR_t *));
163 // Get the address of the descriptor for this command
164 desc = s_CommandDataArray[command->index];
165
166 pAssert(desc != NULL);
167 // Get the associated list of unmarshaling data types.
168 types = &((BYTE *)desc)[desc->typesOffset];
169
170 // if(s_ccAttr[commandIndex].commandIndex == TEST_COMMAND)
171 // commandIndex = commandIndex;
172 // No handles yet
173 command->handleNum = 0;
174
175 // Get the first type value
176 for(type = *types++;
177 // check each byte to make sure that we have not hit the start
178 // of the parameters
179 (dType = (type & 0x7F)) < PARAMETER_FIRST_TYPE;
180 // get the next type
181 type = *types++)
182 {
183 #if TABLE_DRIVEN_MARSHAL
184 marshalIndex_t index;
185 index = unmarshalArray[dType] | ((type & 0x80) ? NULL_FLAG : 0);
186 result = Unmarshal(index, &(command->handles[command->handleNum]),
187 &command->parameterBuffer, &command->parameterSize);
188
189 #else
190 // See if unmarshaling of this handle type requires a flag
191 if(dType < HANDLE_FIRST_FLAG_TYPE)
192 {
193 // Look up the function to do the unmarshaling
194 NoFlagFunction *f = (NoFlagFunction *)unmarshalArray[dType];
195 // call it
196 result = f(&(command->handles[command->handleNum]),
197 &command->parameterBuffer,
198 &command->parameterSize);
199 }
200 else
201 {
202 // Look up the function
203 FlagFunction *f = unmarshalArray[dType];
204
205 // Call it setting the flag to the appropriate value
206 result = f(&(command->handles[command->handleNum]),
207 &command->parameterBuffer,
208 &command->parameterSize, (type & 0x80) != 0);
209 }
210 #endif
211
212 // Got a handle
213 // We do this first so that the match for the handle offset of the
214 // response code works correctly.
215 command->handleNum += 1;
216 if(result != TPM_RC_SUCCESS)
217 // if the unmarshaling failed, return the response code with the
218 // handle indication set
219 return result + TPM_RC_H + (command->handleNum * TPM_RC_1);
220 }
221 #else
222 BYTE **handleBufferStart = &command->parameterBuffer;
223 INT32 *bufferRemainingSize = &command->parameterSize;
224 TPM_HANDLE *handles = &command->handles[0];
225 UINT32 *handleCount = &command->handleNum;
226 *handleCount = 0;
227 switch(command->code)
228 {
229 #include "HandleProcess.h"
230 #undef handles
231 default:
232 FAIL(FATAL_ERROR_INTERNAL);
233 break;
234 }
235 #endif
236 return TPM_RC_SUCCESS;
237 }
238
239 //** CommandDispatcher()
240 // Function to unmarshal the command parameters, call the selected action code, and
241 // marshal the response parameters.
242 TPM_RC
CommandDispatcher(COMMAND * command)243 CommandDispatcher(
244 COMMAND *command
245 )
246 {
247 #if !TABLE_DRIVEN_DISPATCH
248 TPM_RC result;
249 BYTE **paramBuffer = &command->parameterBuffer;
250 INT32 *paramBufferSize = &command->parameterSize;
251 BYTE **responseBuffer = &command->responseBuffer;
252 INT32 *respParmSize = &command->parameterSize;
253 INT32 rSize;
254 TPM_HANDLE *handles = &command->handles[0];
255 //
256 command->handleNum = 0; // The command-specific code knows how
257 // many handles there are. This is for
258 // cataloging the number of response
259 // handles
260 MemoryIoBufferAllocationReset(); // Initialize so that allocation will
261 // work properly
262 switch(GetCommandCode(command->index))
263 {
264 #include "CommandDispatcher.h"
265
266 default:
267 FAIL(FATAL_ERROR_INTERNAL);
268 break;
269 }
270 Exit:
271 MemoryIoBufferZero();
272 return result;
273 #else
274 COMMAND_DESCRIPTOR_t *desc;
275 BYTE *types;
276 BYTE type;
277 UINT16 *offsets;
278 UINT16 offset = 0;
279 UINT32 maxInSize;
280 BYTE *commandIn;
281 INT32 maxOutSize;
282 BYTE *commandOut;
283 COMMAND_t cmd;
284 TPM_HANDLE *handles;
285 UINT32 hasInParameters = 0;
286 BOOL hasOutParameters = FALSE;
287 UINT32 pNum = 0;
288 BYTE dType; // dispatch type
289 TPM_RC result;
290 //
291 // Get the address of the descriptor for this command
292 pAssert(command->index
293 < sizeof(s_CommandDataArray) / sizeof(COMMAND_DESCRIPTOR_t *));
294 desc = s_CommandDataArray[command->index];
295
296 // Get the list of parameter types for this command
297 pAssert(desc != NULL);
298 types = &((BYTE *)desc)[desc->typesOffset];
299
300 // Get a pointer to the list of parameter offsets
301 offsets = &desc->offsets[0];
302 // pointer to handles
303 handles = command->handles;
304
305 // Get the size required to hold all the unmarshaled parameters for this command
306 maxInSize = desc->inSize;
307 // and the size of the output parameter structure returned by this command
308 maxOutSize = desc->outSize;
309
310 MemoryIoBufferAllocationReset();
311 // Get a buffer for the input parameters
312 commandIn = MemoryGetInBuffer(maxInSize);
313 // And the output parameters
314 commandOut = (BYTE *)MemoryGetOutBuffer((UINT32)maxOutSize);
315
316 // Get the address of the action code dispatch
317 cmd = desc->command;
318
319 // Copy any handles into the input buffer
320 for(type = *types++; (type & 0x7F) < PARAMETER_FIRST_TYPE; type = *types++)
321 {
322 // 'offset' was initialized to zero so the first unmarshaling will always
323 // be to the start of the data structure
324 *(TPM_HANDLE *)&(commandIn[offset]) = *handles++;
325 // This check is used so that we don't have to add an additional offset
326 // value to the offsets list to correspond to the stop value in the
327 // command parameter list.
328 if(*types != 0xFF)
329 offset = *offsets++;
330 // maxInSize -= sizeof(TPM_HANDLE);
331 hasInParameters++;
332 }
333 // Exit loop with type containing the last value read from types
334 // maxInSize has the amount of space remaining in the command action input
335 // buffer. Make sure that we don't have more data to unmarshal than is going to
336 // fit.
337
338 // type contains the last value read from types so it is not necessary to
339 // reload it, which is good because *types now points to the next value
340 for(; (dType = (type & 0x7F)) <= PARAMETER_LAST_TYPE; type = *types++)
341 {
342 pNum++;
343 #if TABLE_DRIVEN_MARSHAL
344 {
345 marshalIndex_t index = unmarshalArray[dType];
346 index |= (type & 0x80) ? NULL_FLAG : 0;
347 result = Unmarshal(index, &commandIn[offset], &command->parameterBuffer,
348 &command->parameterSize);
349 }
350 #else
351 if(dType < PARAMETER_FIRST_FLAG_TYPE)
352 {
353 NoFlagFunction *f = (NoFlagFunction *)unmarshalArray[dType];
354 result = f(&commandIn[offset], &command->parameterBuffer,
355 &command->parameterSize);
356 }
357 else
358 {
359 FlagFunction *f = unmarshalArray[dType];
360 result = f(&commandIn[offset], &command->parameterBuffer,
361 &command->parameterSize,
362 (type & 0x80) != 0);
363 }
364 #endif
365 if(result != TPM_RC_SUCCESS)
366 {
367 result += TPM_RC_P + (TPM_RC_1 * pNum);
368 goto Exit;
369 }
370 // This check is used so that we don't have to add an additional offset
371 // value to the offsets list to correspond to the stop value in the
372 // command parameter list.
373 if(*types != 0xFF)
374 offset = *offsets++;
375 hasInParameters++;
376 }
377 // Should have used all the bytes in the input
378 if(command->parameterSize != 0)
379 {
380 result = TPM_RC_SIZE;
381 goto Exit;
382 }
383
384 // The command parameter unmarshaling stopped when it hit a value that was out
385 // of range for unmarshaling values and left *types pointing to the first
386 // marshaling type. If that type happens to be the STOP value, then there
387 // are no response parameters. So, set the flag to indicate if there are
388 // output parameters.
389 hasOutParameters = *types != 0xFF;
390
391 // There are four cases for calling, with and without input parameters and with
392 // and without output parameters.
393 if(hasInParameters > 0)
394 {
395 if(hasOutParameters)
396 result = cmd.inOutArg(commandIn, commandOut);
397 else
398 result = cmd.inArg(commandIn);
399 }
400 else
401 {
402 if(hasOutParameters)
403 result = cmd.outArg(commandOut);
404 else
405 result = cmd.noArgs();
406 }
407 if(result != TPM_RC_SUCCESS)
408 goto Exit;
409
410 // Offset in the marshaled output structure
411 offset = 0;
412
413 // Process the return handles, if any
414 command->handleNum = 0;
415
416 // Could make this a loop to process output handles but there is only ever
417 // one handle in the outputs (for now).
418 type = *types++;
419 if((dType = (type & 0x7F)) < RESPONSE_PARAMETER_FIRST_TYPE)
420 {
421 // The out->handle value was referenced as TPM_HANDLE in the
422 // action code so it has to be properly aligned.
423 command->handles[command->handleNum++] =
424 *((TPM_HANDLE *)&(commandOut[offset]));
425 maxOutSize -= sizeof(UINT32);
426 type = *types++;
427 offset = *offsets++;
428 }
429 // Use the size of the command action output buffer as the maximum for the
430 // number of bytes that can get marshaled. Since the marshaling code has
431 // no pointers to data, all of the data being returned has to be in the
432 // command action output buffer. If we try to marshal more bytes than
433 // could fit into the output buffer, we need to fail.
434 for(;(dType = (type & 0x7F)) <= RESPONSE_PARAMETER_LAST_TYPE
435 && !g_inFailureMode; type = *types++)
436 {
437 #if TABLE_DRIVEN_MARSHAL
438 marshalIndex_t index = marshalArray[dType];
439 command->parameterSize += Marshal(index, &commandOut[offset],
440 &command->responseBuffer,
441 &maxOutSize);
442 #else
443 const MARSHAL_t f = marshalArray[dType];
444
445 command->parameterSize += f(&commandOut[offset],
446 &command->responseBuffer,
447 &maxOutSize);
448 #endif
449 offset = *offsets++;
450 }
451 result = (maxOutSize < 0) ? TPM_RC_FAILURE : TPM_RC_SUCCESS;
452 Exit:
453 MemoryIoBufferZero();
454 return result;
455 #endif
456 }