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 #include "Tpm.h"
36 #include "Policy_spt_fp.h"
37 #include "PolicySigned_fp.h"
38
39 #if CC_PolicySigned // Conditional expansion of this file
40
41 /*(See part 3 specification)
42 // Include an asymmetrically signed authorization to the policy evaluation
43 */
44 // Return Type: TPM_RC
45 // TPM_RC_CPHASH cpHash was previously set to a different value
46 // TPM_RC_EXPIRED 'expiration' indicates a time in the past or
47 // 'expiration' is non-zero but no nonceTPM is present
48 // TPM_RC_NONCE 'nonceTPM' is not the nonce associated with the
49 // 'policySession'
50 // TPM_RC_SCHEME the signing scheme of 'auth' is not supported by the
51 // TPM
52 // TPM_RC_SIGNATURE the signature is not genuine
53 // TPM_RC_SIZE input cpHash has wrong size
54 TPM_RC
TPM2_PolicySigned(PolicySigned_In * in,PolicySigned_Out * out)55 TPM2_PolicySigned(
56 PolicySigned_In *in, // IN: input parameter list
57 PolicySigned_Out *out // OUT: output parameter list
58 )
59 {
60 TPM_RC result = TPM_RC_SUCCESS;
61 SESSION *session;
62 TPM2B_NAME entityName;
63 TPM2B_DIGEST authHash;
64 HASH_STATE hashState;
65 UINT64 authTimeout = 0;
66 // Input Validation
67 // Set up local pointers
68 session = SessionGet(in->policySession); // the session structure
69
70 // Only do input validation if this is not a trial policy session
71 if(session->attributes.isTrialPolicy == CLEAR)
72 {
73 authTimeout = ComputeAuthTimeout(session, in->expiration, &in->nonceTPM);
74
75 result = PolicyParameterChecks(session, authTimeout,
76 &in->cpHashA, &in->nonceTPM,
77 RC_PolicySigned_nonceTPM,
78 RC_PolicySigned_cpHashA,
79 RC_PolicySigned_expiration);
80 if(result != TPM_RC_SUCCESS)
81 return result;
82 // Re-compute the digest being signed
83 /*(See part 3 specification)
84 // The digest is computed as:
85 // aHash := hash ( nonceTPM | expiration | cpHashA | policyRef)
86 // where:
87 // hash() the hash associated with the signed authorization
88 // nonceTPM the nonceTPM value from the TPM2_StartAuthSession .
89 // response If the authorization is not limited to this
90 // session, the size of this value is zero.
91 // expiration time limit on authorization set by authorizing object.
92 // This 32-bit value is set to zero if the expiration
93 // time is not being set.
94 // cpHashA hash of the command parameters for the command being
95 // approved using the hash algorithm of the PSAP session.
96 // Set to NULLauth if the authorization is not limited
97 // to a specific command.
98 // policyRef hash of an opaque value determined by the authorizing
99 // object. Set to the NULLdigest if no hash is present.
100 */
101 // Start hash
102 authHash.t.size = CryptHashStart(&hashState,
103 CryptGetSignHashAlg(&in->auth));
104 // If there is no digest size, then we don't have a verification function
105 // for this algorithm (e.g. TPM_ALG_ECDAA) so indicate that it is a
106 // bad scheme.
107 if(authHash.t.size == 0)
108 return TPM_RCS_SCHEME + RC_PolicySigned_auth;
109
110 // nonceTPM
111 CryptDigestUpdate2B(&hashState, &in->nonceTPM.b);
112
113 // expiration
114 CryptDigestUpdateInt(&hashState, sizeof(UINT32), in->expiration);
115
116 // cpHashA
117 CryptDigestUpdate2B(&hashState, &in->cpHashA.b);
118
119 // policyRef
120 CryptDigestUpdate2B(&hashState, &in->policyRef.b);
121
122 // Complete digest
123 CryptHashEnd2B(&hashState, &authHash.b);
124
125 // Validate Signature. A TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE
126 // error may be returned at this point
127 result = CryptValidateSignature(in->authObject, &authHash, &in->auth);
128 if(result != TPM_RC_SUCCESS)
129 return RcSafeAddToResult(result, RC_PolicySigned_auth);
130 }
131 // Internal Data Update
132 // Update policy with input policyRef and name of authorization key
133 // These values are updated even if the session is a trial session
134 PolicyContextUpdate(TPM_CC_PolicySigned,
135 EntityGetName(in->authObject, &entityName),
136 &in->policyRef,
137 &in->cpHashA, authTimeout, session);
138 // Command Output
139 // Create ticket and timeout buffer if in->expiration < 0 and this is not
140 // a trial session.
141 // NOTE: PolicyParameterChecks() makes sure that nonceTPM is present
142 // when expiration is non-zero.
143 if(in->expiration < 0
144 && session->attributes.isTrialPolicy == CLEAR)
145 {
146 BOOL expiresOnReset = (in->nonceTPM.t.size == 0);
147 // Compute policy ticket
148 authTimeout &= ~EXPIRATION_BIT;
149
150 TicketComputeAuth(TPM_ST_AUTH_SIGNED, EntityGetHierarchy(in->authObject),
151 authTimeout, expiresOnReset, &in->cpHashA, &in->policyRef,
152 &entityName, &out->policyTicket);
153 // Generate timeout buffer. The format of output timeout buffer is
154 // TPM-specific.
155 // Note: In this implementation, the timeout buffer value is computed after
156 // the ticket is produced so, when the ticket is checked, the expiration
157 // flag needs to be extracted before the ticket is checked.
158 // In the Windows compatible version, the least-significant bit of the
159 // timeout value is used as a flag to indicate if the authorization expires
160 // on reset. The flag is the MSb.
161 out->timeout.t.size = sizeof(authTimeout);
162 if(expiresOnReset)
163 authTimeout |= EXPIRATION_BIT;
164 UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
165 }
166 else
167 {
168 // Generate a null ticket.
169 // timeout buffer is null
170 out->timeout.t.size = 0;
171
172 // authorization ticket is null
173 out->policyTicket.tag = TPM_ST_AUTH_SIGNED;
174 out->policyTicket.hierarchy = TPM_RH_NULL;
175 out->policyTicket.digest.t.size = 0;
176 }
177 return TPM_RC_SUCCESS;
178 }
179
180 #endif // CC_PolicySigned