• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }