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 "Policy_spt_fp.h"
10 #include "PolicySigned_fp.h"
11 //
12 //
13 // Error Returns Meaning
14 //
15 // TPM_RC_CPHASH cpHash was previously set to a different value
16 // TPM_RC_EXPIRED expiration indicates a time in the past or expiration is non-zero but no
17 // nonceTPM is present
18 // TPM_RC_HANDLE authObject need to have sensitive portion loaded
19 // TPM_RC_KEY authObject is not a signing scheme
20 // TPM_RC_NONCE nonceTPM is not the nonce associated with the policySession
21 // TPM_RC_SCHEME the signing scheme of auth is not supported by the TPM
22 // TPM_RC_SIGNATURE the signature is not genuine
23 // TPM_RC_SIZE input cpHash has wrong size
24 // TPM_RC_VALUE input policyID or expiration does not match the internal data in policy
25 // session
26 //
27 TPM_RC
TPM2_PolicySigned(PolicySigned_In * in,PolicySigned_Out * out)28 TPM2_PolicySigned(
29 PolicySigned_In *in, // IN: input parameter list
30 PolicySigned_Out *out // OUT: output parameter list
31 )
32 {
33 TPM_RC result = TPM_RC_SUCCESS;
34 SESSION *session;
35 TPM2B_NAME entityName;
36 TPM2B_DIGEST authHash;
37 HASH_STATE hashState;
38 UINT32 expiration = (in->expiration < 0)
39 ? -(in->expiration) : in->expiration;
40 UINT64 authTimeout = 0;
41
42 // Input Validation
43
44 // Set up local pointers
45 session = SessionGet(in->policySession); // the session structure
46
47 // Only do input validation if this is not a trial policy session
48 if(session->attributes.isTrialPolicy == CLEAR)
49 {
50 if(expiration != 0)
51 authTimeout = expiration * 1000 + session->startTime;
52
53 result = PolicyParameterChecks(session, authTimeout,
54 &in->cpHashA, &in->nonceTPM,
55 RC_PolicySigned_nonceTPM,
56 RC_PolicySigned_cpHashA,
57 RC_PolicySigned_expiration);
58 if(result != TPM_RC_SUCCESS)
59 return result;
60
61 // Re-compute the digest being signed
62 /*(See part 3 specification)
63 // The digest is computed as:
64 // aHash := hash ( nonceTPM | expiration | cpHashA | policyRef)
65 // where:
66 // hash() the hash associated with the signed auth
67 // nonceTPM the nonceTPM value from the TPM2_StartAuthSession .
68 // response If the authorization is not limited to this
69 // session, the size of this value is zero.
70 // expiration time limit on authorization set by authorizing object.
71 // This 32-bit value is set to zero if the expiration
72 // time is not being set.
73 // cpHashA hash of the command parameters for the command being
74 // approved using the hash algorithm of the PSAP session.
75 // Set to NULLauth if the authorization is not limited
76 // to a specific command.
77 // policyRef hash of an opaque value determined by the authorizing
78 // object. Set to the NULLdigest if no hash is present.
79 */
80 // Start hash
81 authHash.t.size = CryptStartHash(CryptGetSignHashAlg(&in->auth),
82 &hashState);
83
84 // add nonceTPM
85 CryptUpdateDigest2B(&hashState, &in->nonceTPM.b);
86
87 // add expiration
88 CryptUpdateDigestInt(&hashState, sizeof(UINT32), (BYTE*) &in->expiration);
89
90 // add cpHashA
91 CryptUpdateDigest2B(&hashState, &in->cpHashA.b);
92
93 // add policyRef
94 CryptUpdateDigest2B(&hashState, &in->policyRef.b);
95
96 // Complete digest
97 CryptCompleteHash2B(&hashState, &authHash.b);
98
99 // Validate Signature. A TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE
100 // error may be returned at this point
101 result = CryptVerifySignature(in->authObject, &authHash, &in->auth);
102 if(result != TPM_RC_SUCCESS)
103 return RcSafeAddToResult(result, RC_PolicySigned_auth);
104 }
105 // Internal Data Update
106 // Need the Name of the signing entity
107 entityName.t.size = EntityGetName(in->authObject, &entityName.t.name);
108
109 // Update policy with input policyRef and name of auth key
110 // These values are updated even if the session is a trial session
111 PolicyContextUpdate(TPM_CC_PolicySigned, &entityName, &in->policyRef,
112 &in->cpHashA, authTimeout, session);
113
114 // Command Output
115
116 // Create ticket and timeout buffer if in->expiration < 0 and this is not
117 // a trial session.
118 // NOTE: PolicyParameterChecks() makes sure that nonceTPM is present
119 // when expiration is non-zero.
120 if( in->expiration < 0
121 && session->attributes.isTrialPolicy == CLEAR
122 )
123 {
124 // Generate timeout buffer. The format of output timeout buffer is
125 // TPM-specific.
126 // Note: can't do a direct copy because the output buffer is a byte
127 // array and it may not be aligned to accept a 64-bit value. The method
128 // used has the side-effect of making the returned value a big-endian,
129 // 64-bit value that is byte aligned.
130 out->timeout.t.size = sizeof(UINT64);
131 UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
132
133 // Compute policy ticket
134 TicketComputeAuth(TPM_ST_AUTH_SIGNED, EntityGetHierarchy(in->authObject),
135 authTimeout, &in->cpHashA, &in->policyRef, &entityName,
136 &out->policyTicket);
137 }
138 else
139 {
140 // Generate a null ticket.
141 // timeout buffer is null
142 out->timeout.t.size = 0;
143
144 // auth ticket is null
145 out->policyTicket.tag = TPM_ST_AUTH_SIGNED;
146 out->policyTicket.hierarchy = TPM_RH_NULL;
147 out->policyTicket.digest.t.size = 0;
148 }
149
150 return TPM_RC_SUCCESS;
151 }
152