• 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 //** Includes, Defines, and Types
36 #define     TPM_FAIL_C
37 #include    "Tpm.h"
38 #include    <assert.h>
39 
40 // On MS C compiler, can save the alignment state and set the alignment to 1 for
41 // the duration of the TpmTypes.h include.  This will avoid a lot of alignment
42 // warnings from the compiler for the unaligned structures. The alignment of the
43 // structures is not important as this function does not use any of the structures
44 // in TpmTypes.h and only include it for the #defines of the capabilities,
45 // properties, and command code values.
46 #include "TpmTypes.h"
47 
48 //** Typedefs
49 // These defines are used primarily for sizing of the local response buffer.
50 typedef struct
51 {
52     TPM_ST          tag;
53     UINT32          size;
54     TPM_RC          code;
55 } HEADER;
56 
57 typedef struct
58 {
59     BYTE            tag[sizeof(TPM_ST)];
60     BYTE            size[sizeof(UINT32)];
61     BYTE            code[sizeof(TPM_RC)];
62 } PACKED_HEADER;
63 
64 typedef struct
65 {
66     BYTE             size[sizeof(UINT16)];
67     struct
68     {
69         BYTE         function[sizeof(UINT32)];
70         BYTE         line[sizeof(UINT32)];
71         BYTE         code[sizeof(UINT32)];
72     } values;
73     BYTE             returnCode[sizeof(TPM_RC)];
74 } GET_TEST_RESULT_PARAMETERS;
75 
76 typedef struct
77 {
78     BYTE         moreData[sizeof(TPMI_YES_NO)];
79     BYTE         capability[sizeof(TPM_CAP)]; // Always TPM_CAP_TPM_PROPERTIES
80     BYTE         tpmProperty[sizeof(TPML_TAGGED_TPM_PROPERTY)];
81 } GET_CAPABILITY_PARAMETERS;
82 
83 typedef struct
84 {
85     BYTE         header[sizeof(PACKED_HEADER)];
86     BYTE         getTestResult[sizeof(GET_TEST_RESULT_PARAMETERS)];
87 } TEST_RESPONSE;
88 
89 typedef struct
90 {
91     BYTE         header[sizeof(PACKED_HEADER)];
92     BYTE         getCap[sizeof(GET_CAPABILITY_PARAMETERS)];
93 } CAPABILITY_RESPONSE;
94 
95 typedef union
96 {
97     BYTE         test[sizeof(TEST_RESPONSE)];
98     BYTE         cap[sizeof(CAPABILITY_RESPONSE)];
99 } RESPONSES;
100 
101 // Buffer to hold the responses. This may be a little larger than
102 // required due to padding that a compiler might add.
103 // Note: This is not in Global.c because of the specialized data definitions above.
104 // Since the data contained in this structure is not relevant outside of the
105 // execution of a single command (when the TPM is in failure mode. There is no
106 // compelling reason to move all the typedefs to Global.h and this structure
107 // to Global.c.
108 #ifndef __IGNORE_STATE__ // Don't define this value
109 static BYTE response[sizeof(RESPONSES)];
110 #endif
111 
112 //** Local Functions
113 
114 //*** MarshalUint16()
115 // Function to marshal a 16 bit value to the output buffer.
116 static INT32
MarshalUint16(UINT16 integer,BYTE ** buffer)117 MarshalUint16(
118     UINT16          integer,
119     BYTE            **buffer
120     )
121 {
122     UINT16_TO_BYTE_ARRAY(integer, *buffer);
123     *buffer += 2;
124     return 2;
125 }
126 
127 //*** MarshalUint32()
128 // Function to marshal a 32 bit value to the output buffer.
129 static INT32
MarshalUint32(UINT32 integer,BYTE ** buffer)130 MarshalUint32(
131     UINT32           integer,
132     BYTE            **buffer
133     )
134 {
135     UINT32_TO_BYTE_ARRAY(integer, *buffer);
136     *buffer += 4;
137     return 4;
138 }
139 
140 //***Unmarshal32()
Unmarshal32(UINT32 * target,BYTE ** buffer,INT32 * size)141 static BOOL Unmarshal32(
142     UINT32          *target,
143     BYTE            **buffer,
144     INT32           *size
145     )
146 {
147     if((*size -= 4) < 0)
148         return FALSE;
149     *target = BYTE_ARRAY_TO_UINT32(*buffer);
150     *buffer += 4;
151     return TRUE;
152 }
153 
154 //***Unmarshal16()
Unmarshal16(UINT16 * target,BYTE ** buffer,INT32 * size)155 static BOOL Unmarshal16(
156     UINT16          *target,
157     BYTE           **buffer,
158     INT32           *size
159 )
160 {
161     if((*size -= 2) < 0)
162         return FALSE;
163     *target = BYTE_ARRAY_TO_UINT16(*buffer);
164     *buffer += 2;
165     return TRUE;
166 }
167 
168 //** Public Functions
169 
170 //*** SetForceFailureMode()
171 // This function is called by the simulator to enable failure mode testing.
172 #if SIMULATION
173 LIB_EXPORT void
SetForceFailureMode(void)174 SetForceFailureMode(
175     void
176     )
177 {
178     g_forceFailureMode = TRUE;
179     return;
180 }
181 #endif
182 
183 //*** TpmLogFailure()
184 // This function saves the failure values when the code will continue to operate. It
185 // if similar to TpmFail() but returns to the caller. The assumption is that the
186 // caller will propagate a failure back up the stack.
187 void
TpmLogFailure(const char * function,int line,int code)188 TpmLogFailure(
189 #if FAIL_TRACE
190     const char      *function,
191     int              line,
192 #endif
193     int              code
194 )
195 {
196     // Save the values that indicate where the error occurred.
197     // On a 64-bit machine, this may truncate the address of the string
198     // of the function name where the error occurred.
199 #if FAIL_TRACE
200     s_failFunction = (UINT32)(ptrdiff_t)function;
201     s_failLine = line;
202 #else
203     s_failFunction = 0;
204     s_failLine = 0;
205 #endif
206     s_failCode = code;
207 
208     // We are in failure mode
209     g_inFailureMode = TRUE;
210 
211     return;
212 }
213 
214 //*** TpmFail()
215 // This function is called by TPM.lib when a failure occurs. It will set up the
216 // failure values to be returned on TPM2_GetTestResult().
217 NORETURN void
TpmFail(const char * function,int line,int code)218 TpmFail(
219 #if FAIL_TRACE
220     const char      *function,
221     int              line,
222 #endif
223     int              code
224     )
225 {
226     // Save the values that indicate where the error occurred.
227     // On a 64-bit machine, this may truncate the address of the string
228     // of the function name where the error occurred.
229 #if FAIL_TRACE
230     s_failFunction = (UINT32)(ptrdiff_t)function;
231     s_failLine = line;
232 #else
233     s_failFunction = (UINT32)(ptrdiff_t)NULL;
234     s_failLine = 0;
235 #endif
236     s_failCode = code;
237 
238     // We are in failure mode
239     g_inFailureMode = TRUE;
240 
241     // if asserts are enabled, then do an assert unless the failure mode code
242     // is being tested.
243 #if SIMULATION
244 #   ifndef NDEBUG
245     assert(g_forceFailureMode);
246 #   endif
247     // Clear this flag
248     g_forceFailureMode = FALSE;
249 #endif
250     // Jump to the failure mode code.
251     // Note: only get here if asserts are off or if we are testing failure mode
252     _plat__Fail();
253 }
254 
255 //*** TpmFailureMode(
256 // This function is called by the interface code when the platform is in failure
257 // mode.
258 void
TpmFailureMode(unsigned int inRequestSize,unsigned char * inRequest,unsigned int * outResponseSize,unsigned char ** outResponse)259 TpmFailureMode(
260     unsigned int     inRequestSize,     // IN: command buffer size
261     unsigned char   *inRequest,         // IN: command buffer
262     unsigned int    *outResponseSize,   // OUT: response buffer size
263     unsigned char   **outResponse       // OUT: response buffer
264     )
265 {
266     UINT32           marshalSize;
267     UINT32           capability;
268     HEADER           header;    // unmarshaled command header
269     UINT32           pt;    // unmarshaled property type
270     UINT32           count; // unmarshaled property count
271     UINT8           *buffer = inRequest;
272     INT32            size = inRequestSize;
273 
274     // If there is no command buffer, then just return TPM_RC_FAILURE
275     if(inRequestSize == 0 || inRequest == NULL)
276         goto FailureModeReturn;
277     // If the header is not correct for TPM2_GetCapability() or
278     // TPM2_GetTestResult() then just return the in failure mode response;
279     if(! (Unmarshal16(&header.tag,  &buffer, &size)
280        && Unmarshal32(&header.size, &buffer, &size)
281        && Unmarshal32(&header.code, &buffer, &size)))
282         goto FailureModeReturn;
283     if(header.tag != TPM_ST_NO_SESSIONS
284        || header.size < 10)
285         goto FailureModeReturn;
286     switch(header.code)
287     {
288         case TPM_CC_GetTestResult:
289             // make sure that the command size is correct
290             if(header.size != 10)
291                 goto FailureModeReturn;
292             buffer = &response[10];
293             marshalSize = MarshalUint16(3 * sizeof(UINT32), &buffer);
294             marshalSize += MarshalUint32(s_failFunction, &buffer);
295             marshalSize += MarshalUint32(s_failLine, &buffer);
296             marshalSize += MarshalUint32(s_failCode, &buffer);
297             if(s_failCode == FATAL_ERROR_NV_UNRECOVERABLE)
298                 marshalSize += MarshalUint32(TPM_RC_NV_UNINITIALIZED, &buffer);
299             else
300                 marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer);
301             break;
302         case TPM_CC_GetCapability:
303             // make sure that the size of the command is exactly the size
304             // returned for the capability, property, and count
305             if(header.size != (10 + (3 * sizeof(UINT32)))
306                     // also verify that this is requesting TPM properties
307                || !Unmarshal32(&capability, &buffer, &size)
308                || capability != TPM_CAP_TPM_PROPERTIES
309                || !Unmarshal32(&pt, &buffer, &size)
310                || !Unmarshal32(&count, &buffer, &size))
311                 goto FailureModeReturn;
312             // If in failure mode because of an unrecoverable read error, and the
313             // property is 0 and the count is 0, then this is an indication to
314             // re-manufacture the TPM. Do the re-manufacture but stay in failure
315             // mode until the TPM is reset.
316             // Note: this behavior is not required by the specification and it is
317             // OK to leave the TPM permanently bricked due to an unrecoverable NV
318             // error.
319             if(count == 0 && pt == 0 && s_failCode == FATAL_ERROR_NV_UNRECOVERABLE)
320             {
321                 g_manufactured = FALSE;
322                 TPM_Manufacture(0);
323             }
324             if(count > 0)
325                 count = 1;
326             else if(pt > TPM_PT_FIRMWARE_VERSION_2)
327                 count = 0;
328             if(pt < TPM_PT_MANUFACTURER)
329                 pt = TPM_PT_MANUFACTURER;
330             // set up for return
331             buffer = &response[10];
332             // if the request was for a PT less than the last one
333             // then we indicate more, otherwise, not.
334             if(pt < TPM_PT_FIRMWARE_VERSION_2)
335                 *buffer++ = YES;
336             else
337                 *buffer++ = NO;
338             marshalSize = 1;
339 
340             // indicate the capability type
341             marshalSize += MarshalUint32(capability, &buffer);
342             // indicate the number of values that are being returned (0 or 1)
343             marshalSize += MarshalUint32(count, &buffer);
344             // indicate the property
345             marshalSize += MarshalUint32(pt, &buffer);
346 
347             if(count > 0)
348                 switch(pt)
349                 {
350                     case TPM_PT_MANUFACTURER:
351                     // the vendor ID unique to each TPM manufacturer
352 #ifdef  MANUFACTURER
353                         pt = *(UINT32*)MANUFACTURER;
354 #else
355                         pt = 0;
356 #endif
357                         break;
358                     case TPM_PT_VENDOR_STRING_1:
359                         // the first four characters of the vendor ID string
360 #ifdef  VENDOR_STRING_1
361                         pt = *(UINT32*)VENDOR_STRING_1;
362 #else
363                         pt = 0;
364 #endif
365                         break;
366                     case TPM_PT_VENDOR_STRING_2:
367                         // the second four characters of the vendor ID string
368 #ifdef  VENDOR_STRING_2
369                         pt = *(UINT32*)VENDOR_STRING_2;
370 #else
371                         pt = 0;
372 #endif
373                         break;
374                     case TPM_PT_VENDOR_STRING_3:
375                         // the third four characters of the vendor ID string
376 #ifdef  VENDOR_STRING_3
377                         pt = *(UINT32*)VENDOR_STRING_3;
378 #else
379                         pt = 0;
380 #endif
381                         break;
382                     case TPM_PT_VENDOR_STRING_4:
383                         // the fourth four characters of the vendor ID string
384 #ifdef  VENDOR_STRING_4
385                         pt = *(UINT32*)VENDOR_STRING_4;
386 #else
387                         pt = 0;
388 #endif
389                         break;
390                     case TPM_PT_VENDOR_TPM_TYPE:
391                         // vendor-defined value indicating the TPM model
392                         // We just make up a number here
393                         pt = 1;
394                         break;
395                     case TPM_PT_FIRMWARE_VERSION_1:
396                         // the more significant 32-bits of a vendor-specific value
397                         // indicating the version of the firmware
398 #ifdef  FIRMWARE_V1
399                         pt = FIRMWARE_V1;
400 #else
401                         pt = 0;
402 #endif
403                         break;
404                     default: // TPM_PT_FIRMWARE_VERSION_2:
405                         // the less significant 32-bits of a vendor-specific value
406                         // indicating the version of the firmware
407 #ifdef  FIRMWARE_V2
408                         pt = FIRMWARE_V2;
409 #else
410                         pt = 0;
411 #endif
412                         break;
413                 }
414             marshalSize += MarshalUint32(pt, &buffer);
415             break;
416         default: // default for switch (cc)
417             goto FailureModeReturn;
418     }
419     // Now do the header
420     buffer = response;
421     marshalSize = marshalSize + 10; // Add the header size to the
422                                     // stuff already marshaled
423     MarshalUint16(TPM_ST_NO_SESSIONS, &buffer); // structure tag
424     MarshalUint32(marshalSize, &buffer);  // responseSize
425     MarshalUint32(TPM_RC_SUCCESS, &buffer); // response code
426 
427     *outResponseSize = marshalSize;
428     *outResponse = (unsigned char *)&response;
429     return;
430 FailureModeReturn:
431     buffer = response;
432     marshalSize = MarshalUint16(TPM_ST_NO_SESSIONS, &buffer);
433     marshalSize += MarshalUint32(10, &buffer);
434     marshalSize += MarshalUint32(TPM_RC_FAILURE, &buffer);
435     *outResponseSize = marshalSize;
436     *outResponse = (unsigned char *)response;
437     return;
438 }
439 
440 //*** UnmarshalFail()
441 // This is a stub that is used to catch an attempt to unmarshal an entry
442 // that is not defined. Don't ever expect this to be called but...
443 void
UnmarshalFail(void * type,BYTE ** buffer,INT32 * size)444 UnmarshalFail(
445     void            *type,
446     BYTE            **buffer,
447     INT32           *size
448     )
449 {
450     NOT_REFERENCED(type);
451     NOT_REFERENCED(buffer);
452     NOT_REFERENCED(size);
453     FAIL(FATAL_ERROR_INTERNAL);
454 }