1 // This file was extracted from the TCG Published
2 // Trusted Platform Module Library
3 // Part 3: Commands
4 // Family "2.0"
5 // Level 00 Revision 01.16
6 // October 30, 2014
7 
8 #include "InternalRoutines.h"
9 #include "PolicyLocality_fp.h"
10 //
11 //     Limit a policy to a specific locality
12 //
13 //     Error Returns                       Meaning
14 //
15 //     TPM_RC_RANGE                        all the locality values selected by locality have been disabled by
16 //                                         previous TPM2_PolicyLocality() calls.
17 //
18 TPM_RC
TPM2_PolicyLocality(PolicyLocality_In * in)19 TPM2_PolicyLocality(
20     PolicyLocality_In        *in                 // IN: input parameter list
21     )
22 {
23     SESSION        *session;
24     BYTE            marshalBuffer[sizeof(TPMA_LOCALITY)];
25     BYTE            prevSetting[sizeof(TPMA_LOCALITY)];
26     UINT32          marshalSize;
27     BYTE           *buffer;
28     INT32           bufferSize;
29     TPM_CC          commandCode = TPM_CC_PolicyLocality;
30     HASH_STATE      hashState;
31 
32 // Input Validation
33 
34     // Get pointer to the session structure
35     session = SessionGet(in->policySession);
36 
37     // Get new locality setting in canonical form
38     buffer = marshalBuffer;
39     bufferSize = sizeof(TPMA_LOCALITY);
40     marshalSize = TPMA_LOCALITY_Marshal(&in->locality, &buffer, &bufferSize);
41 
42     // Its an error if the locality parameter is zero
43     if(marshalBuffer[0] == 0)
44         return TPM_RC_RANGE + RC_PolicyLocality_locality;
45 
46     // Get existing locality setting in canonical form
47     buffer = prevSetting;
48     bufferSize = sizeof(TPMA_LOCALITY);
49     TPMA_LOCALITY_Marshal(&session->commandLocality, &buffer, &bufferSize);
50 
51     // If the locality has previously been set
52     if(    prevSetting[0] != 0
53         // then the current locality setting and the requested have to be the same
54         // type (that is, either both normal or both extended
55         && ((prevSetting[0] < 32) != (marshalBuffer[0] < 32)))
56         return TPM_RC_RANGE + RC_PolicyLocality_locality;
57 
58     // See if the input is a regular or extended locality
59     if(marshalBuffer[0] < 32)
60     {
61         // if there was no previous setting, start with all normal localities
62         // enabled
63         if(prevSetting[0] == 0)
64             prevSetting[0] = 0x1F;
65 
66          // AND the new setting with the previous setting and store it in prevSetting
67          prevSetting[0] &= marshalBuffer[0];
68 
69          // The result setting can not be 0
70          if(prevSetting[0] == 0)
71           return TPM_RC_RANGE + RC_PolicyLocality_locality;
72   }
73   else
74   {
75       // for extended locality
76       // if the locality has already been set, then it must match the
77       if(prevSetting[0] != 0 && prevSetting[0] != marshalBuffer[0])
78           return TPM_RC_RANGE + RC_PolicyLocality_locality;
79 
80       // Setting is OK
81       prevSetting[0] = marshalBuffer[0];
82 
83   }
84 
85 // Internal Data Update
86 
87   // Update policy hash
88   // policyDigestnew = hash(policyDigestold || TPM_CC_PolicyLocality || locality)
89   // Start hash
90   CryptStartHash(session->authHashAlg, &hashState);
91 
92   // add old digest
93   CryptUpdateDigest2B(&hashState, &session->u2.policyDigest.b);
94 
95   // add commandCode
96   CryptUpdateDigestInt(&hashState, sizeof(TPM_CC), &commandCode);
97 
98   // add input locality
99   CryptUpdateDigest(&hashState, marshalSize, marshalBuffer);
100 
101   // complete the digest
102   CryptCompleteHash2B(&hashState, &session->u2.policyDigest.b);
103 
104   // update session locality by unmarshal function. The function must succeed
105   // because both input and existing locality setting have been validated.
106   buffer = prevSetting;
107   TPMA_LOCALITY_Unmarshal(&session->commandLocality, &buffer,
108                           (INT32 *) &marshalSize);
109 
110    return TPM_RC_SUCCESS;
111 }
112