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 "PolicyAuthorize_fp.h"
10 #include "Policy_spt_fp.h"
11 //
12 //
13 //     Error Returns                     Meaning
14 //
15 //     TPM_RC_HASH                       hash algorithm in keyName is not supported
16 //     TPM_RC_SIZE                       keyName is not the correct size for its hash algorithm
17 //     TPM_RC_VALUE                      the current policyDigest of policySession does not match
18 //                                       approvedPolicy; or checkTicket doesn't match the provided values
19 //
20 TPM_RC
TPM2_PolicyAuthorize(PolicyAuthorize_In * in)21 TPM2_PolicyAuthorize(
22    PolicyAuthorize_In    *in                   // IN: input parameter list
23    )
24 {
25    SESSION                     *session;
26    TPM2B_DIGEST                 authHash;
27    HASH_STATE                   hashState;
28    TPMT_TK_VERIFIED             ticket;
29    TPM_ALG_ID                   hashAlg;
30    UINT16                       digestSize;
31 
32 // Input Validation
33 
34    // Get pointer to the session structure
35    session = SessionGet(in->policySession);
36 
37    // Extract from the Name of the key, the algorithm used to compute it's Name
38    hashAlg = BYTE_ARRAY_TO_UINT16(in->keySign.t.name);
39 
40    // 'keySign' parameter needs to use a supported hash algorithm, otherwise
41    // can't tell how large the digest should be
42    digestSize = CryptGetHashDigestSize(hashAlg);
43    if(digestSize == 0)
44        return TPM_RC_HASH + RC_PolicyAuthorize_keySign;
45 
46    if(digestSize != (in->keySign.t.size - 2))
47        return TPM_RC_SIZE + RC_PolicyAuthorize_keySign;
48 
49    //If this is a trial policy, skip all validations
50    if(session->attributes.isTrialPolicy == CLEAR)
51    {
52        // Check that "approvedPolicy" matches the current value of the
53        // policyDigest in policy session
54        if(!Memory2BEqual(&session->u2.policyDigest.b,
55                          &in->approvedPolicy.b))
56            return TPM_RC_VALUE + RC_PolicyAuthorize_approvedPolicy;
57 
58          // Validate ticket TPMT_TK_VERIFIED
59          // Compute aHash. The authorizing object sign a digest
60          // aHash := hash(approvedPolicy || policyRef).
61          // Start hash
62          authHash.t.size = CryptStartHash(hashAlg, &hashState);
63 
64          // add approvedPolicy
65          CryptUpdateDigest2B(&hashState, &in->approvedPolicy.b);
66 
67       // add policyRef
68       CryptUpdateDigest2B(&hashState, &in->policyRef.b);
69 
70       // complete hash
71       CryptCompleteHash2B(&hashState, &authHash.b);
72 
73       // re-compute TPMT_TK_VERIFIED
74       TicketComputeVerified(in->checkTicket.hierarchy, &authHash,
75                             &in->keySign, &ticket);
76 
77       // Compare ticket digest. If not match, return error
78       if(!Memory2BEqual(&in->checkTicket.digest.b, &ticket.digest.b))
79           return TPM_RC_VALUE+ RC_PolicyAuthorize_checkTicket;
80   }
81 
82 // Internal Data Update
83 
84   // Set policyDigest to zero digest
85   MemorySet(session->u2.policyDigest.t.buffer, 0,
86             session->u2.policyDigest.t.size);
87 
88   // Update policyDigest
89   PolicyContextUpdate(TPM_CC_PolicyAuthorize, &in->keySign, &in->policyRef,
90                       NULL, 0, session);
91 
92   return TPM_RC_SUCCESS;
93 
94 }
95