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