1 // This file was extracted from the TCG Published
2 // Trusted Platform Module Library
3 // Part 4: Supporting Routines
4 // Family "2.0"
5 // Level 00 Revision 01.16
6 // October 30, 2014
7 
8 #include "InternalRoutines.h"
9 #include "PP_fp.h"
10 
11 //
12 //
13 //             Functions
14 //
15 //             PhysicalPresencePreInstall_Init()
16 //
17 //       This function is used to initialize the array of commands that require confirmation with physical presence.
18 //       The array is an array of bits that has a correspondence with the command code.
19 //       This command should only ever be executable in a manufacturing setting or in a simulation.
20 //
21 void
PhysicalPresencePreInstall_Init(void)22 PhysicalPresencePreInstall_Init(
23      void
24      )
25 {
26      // Clear all the PP commands
27      MemorySet(&gp.ppList, 0,
28 //
29                 ((TPM_CC_PP_LAST - TPM_CC_PP_FIRST + 1) + 7) / 8);
30    // TPM_CC_PP_Commands always requires PP
31    if(CommandIsImplemented(TPM_CC_PP_Commands))
32        PhysicalPresenceCommandSet(TPM_CC_PP_Commands);
33    // Write PP list to NV
34    NvWriteReserved(NV_PP_LIST, &gp.ppList);
35    return;
36 }
37 //
38 //
39 //          PhysicalPresenceCommandSet()
40 //
41 //     This function is used to indicate a command that requires PP confirmation.
42 //
43 void
PhysicalPresenceCommandSet(TPM_CC commandCode)44 PhysicalPresenceCommandSet(
45    TPM_CC               commandCode       // IN: command code
46    )
47 {
48    UINT32         bitPos;
49    // Assume command is implemented. It should be checked before this
50    // function is called
51    pAssert(CommandIsImplemented(commandCode));
52    // If the command is not a PP command, ignore it
53    if(commandCode < TPM_CC_PP_FIRST || commandCode > TPM_CC_PP_LAST)
54        return;
55    bitPos = commandCode - TPM_CC_PP_FIRST;
56    // Set bit
57    gp.ppList[bitPos/8] |= 1 << (bitPos % 8);
58    return;
59 }
60 //
61 //
62 //          PhysicalPresenceCommandClear()
63 //
64 //     This function is used to indicate a command that no longer requires PP confirmation.
65 //
66 void
PhysicalPresenceCommandClear(TPM_CC commandCode)67 PhysicalPresenceCommandClear(
68    TPM_CC               commandCode       // IN: command code
69    )
70 {
71    UINT32         bitPos;
72    // Assume command is implemented. It should be checked before this
73    // function is called
74    pAssert(CommandIsImplemented(commandCode));
75    // If the command is not a PP command, ignore it
76    if(commandCode < TPM_CC_PP_FIRST || commandCode > TPM_CC_PP_LAST)
77        return;
78    // if the input code is TPM_CC_PP_Commands, it can not be cleared
79    if(commandCode == TPM_CC_PP_Commands)
80        return;
81    bitPos = commandCode - TPM_CC_PP_FIRST;
82      // Set bit
83      gp.ppList[bitPos/8] |= (1 << (bitPos % 8));
84      // Flip it to off
85      gp.ppList[bitPos/8] ^= (1 << (bitPos % 8));
86      return;
87 }
88 //
89 //
90 //           PhysicalPresenceIsRequired()
91 //
92 //      This function indicates if PP confirmation is required for a command.
93 //
94 //      Return Value                      Meaning
95 //
96 //      TRUE                              if physical presence is required
97 //      FALSE                             if physical presence is not required
98 //
99 BOOL
PhysicalPresenceIsRequired(TPM_CC commandCode)100 PhysicalPresenceIsRequired(
101      TPM_CC             commandCode           // IN: command code
102      )
103 {
104      UINT32        bitPos;
105      // if the input commandCode is not a PP command, return FALSE
106      if(commandCode < TPM_CC_PP_FIRST || commandCode > TPM_CC_PP_LAST)
107          return FALSE;
108      bitPos = commandCode - TPM_CC_PP_FIRST;
109      // Check the bit map. If the bit is SET, PP authorization is required
110      return ((gp.ppList[bitPos/8] & (1 << (bitPos % 8))) != 0);
111 }
112 //
113 //
114 //           PhysicalPresenceCapGetCCList()
115 //
116 //      This function returns a list of commands that require PP confirmation. The list starts from the first
117 //      implemented command that has a command code that the same or greater than commandCode.
118 //
119 //      Return Value                      Meaning
120 //
121 //      YES                               if there are more command codes available
122 //      NO                                all the available command codes have been returned
123 //
124 TPMI_YES_NO
PhysicalPresenceCapGetCCList(TPM_CC commandCode,UINT32 count,TPML_CC * commandList)125 PhysicalPresenceCapGetCCList(
126      TPM_CC             commandCode,          // IN: start command code
127      UINT32             count,                // IN: count of returned TPM_CC
128      TPML_CC           *commandList           // OUT: list of TPM_CC
129      )
130 {
131      TPMI_YES_NO       more = NO;
132      UINT32            i;
133      // Initialize output handle list
134      commandList->count = 0;
135      // The maximum count of command we may return is MAX_CAP_CC
136      if(count > MAX_CAP_CC) count = MAX_CAP_CC;
137      // Collect PP commands
138      for(i = commandCode; i <= TPM_CC_PP_LAST; i++)
139      {
140          if(PhysicalPresenceIsRequired(i))
141          {
142              if(commandList->count < count)
143              {
144                  // If we have not filled up the return list, add this command
145                  // code to it
146                  commandList->commandCodes[commandList->count] = i;
147                  commandList->count++;
148              }
149              else
150              {
151                  // If the return list is full but we still have PP command
152                  // available, report this and stop iterating
153                  more = YES;
154                  break;
155              }
156          }
157      }
158      return more;
159 }
160