aboutsummaryrefslogtreecommitdiff
path: root/PolicySigned.c
blob: 14bb1676f839eae29824989f6ec54ef53db53ef6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// This file was extracted from the TCG Published
// Trusted Platform Module Library
// Part 3: Commands
// Family "2.0"
// Level 00 Revision 01.16
// October 30, 2014

#include "InternalRoutines.h"
#include "Policy_spt_fp.h"
#include "PolicySigned_fp.h"
//
//
//     Error Returns                     Meaning
//
//     TPM_RC_CPHASH                     cpHash was previously set to a different value
//     TPM_RC_EXPIRED                    expiration indicates a time in the past or expiration is non-zero but no
//                                       nonceTPM is present
//     TPM_RC_HANDLE                     authObject need to have sensitive portion loaded
//     TPM_RC_KEY                        authObject is not a signing scheme
//     TPM_RC_NONCE                      nonceTPM is not the nonce associated with the policySession
//     TPM_RC_SCHEME                     the signing scheme of auth is not supported by the TPM
//     TPM_RC_SIGNATURE                  the signature is not genuine
//     TPM_RC_SIZE                       input cpHash has wrong size
//     TPM_RC_VALUE                      input policyID or expiration does not match the internal data in policy
//                                       session
//
TPM_RC
TPM2_PolicySigned(
   PolicySigned_In       *in,                  // IN: input parameter list
   PolicySigned_Out      *out                  // OUT: output parameter list
   )
{
   TPM_RC                     result = TPM_RC_SUCCESS;
   SESSION                   *session;
   TPM2B_NAME                 entityName;
   TPM2B_DIGEST               authHash;
   HASH_STATE                 hashState;
   UINT32                     expiration = (in->expiration < 0)
                                           ? -(in->expiration) : in->expiration;
   UINT64                     authTimeout = 0;

// Input Validation

   // Set up local pointers
   session = SessionGet(in->policySession);               // the session structure

   // Only do input validation if this is not a trial policy session
   if(session->attributes.isTrialPolicy == CLEAR)
   {
       if(expiration != 0)
           authTimeout = expiration * 1000 + session->startTime;

       result = PolicyParameterChecks(session, authTimeout,
                                       &in->cpHashA, &in->nonceTPM,
                                       RC_PolicySigned_nonceTPM,
                                       RC_PolicySigned_cpHashA,
                                       RC_PolicySigned_expiration);
       if(result != TPM_RC_SUCCESS)
           return result;

       // Re-compute the digest being signed
       /*(See part 3 specification)
       // The digest is computed as:
       //     aHash := hash ( nonceTPM | expiration | cpHashA | policyRef)
       // where:
       //      hash()      the hash associated with the signed auth
       //      nonceTPM    the nonceTPM value from the TPM2_StartAuthSession .
       //                  response If the authorization is not limited to this
       //                  session, the size of this value is zero.
       //      expiration time limit on authorization set by authorizing object.
       //                  This 32-bit value is set to zero if the expiration
       //                  time is not being set.
       //      cpHashA     hash of the command parameters for the command being
       //                  approved using the hash algorithm of the PSAP session.
       //                  Set to NULLauth if the authorization is not limited
       //                  to a specific command.
       //      policyRef   hash of an opaque value determined by the authorizing
       //                  object. Set to the NULLdigest if no hash is present.
       */
       // Start hash
       authHash.t.size = CryptStartHash(CryptGetSignHashAlg(&in->auth),
                                        &hashState);

       // add nonceTPM
       CryptUpdateDigest2B(&hashState, &in->nonceTPM.b);

       // add expiration
       CryptUpdateDigestInt(&hashState, sizeof(UINT32), (BYTE*) &in->expiration);

       // add cpHashA
       CryptUpdateDigest2B(&hashState, &in->cpHashA.b);

       // add policyRef
       CryptUpdateDigest2B(&hashState, &in->policyRef.b);

       // Complete digest
       CryptCompleteHash2B(&hashState, &authHash.b);

       // Validate Signature. A TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE
       // error may be returned at this point
       result = CryptVerifySignature(in->authObject, &authHash, &in->auth);
       if(result != TPM_RC_SUCCESS)
           return RcSafeAddToResult(result, RC_PolicySigned_auth);
   }
// Internal Data Update
   // Need the Name of the signing entity
   entityName.t.size = EntityGetName(in->authObject, &entityName.t.name);

   // Update policy with input policyRef and name of auth key
   // These values are updated even if the session is a trial session
   PolicyContextUpdate(TPM_CC_PolicySigned, &entityName, &in->policyRef,
                       &in->cpHashA, authTimeout, session);

// Command Output

   // Create ticket and timeout buffer if in->expiration < 0 and this is not
   // a trial session.
   // NOTE: PolicyParameterChecks() makes sure that nonceTPM is present
   // when expiration is non-zero.
   if(   in->expiration < 0
      && session->attributes.isTrialPolicy == CLEAR
     )
   {
       // Generate timeout buffer. The format of output timeout buffer is
       // TPM-specific.
       // Note: can't do a direct copy because the output buffer is a byte
       // array and it may not be aligned to accept a 64-bit value. The method
       // used has the side-effect of making the returned value a big-endian,
       // 64-bit value that is byte aligned.
       out->timeout.t.size = sizeof(UINT64);
       UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);

       // Compute policy ticket
       TicketComputeAuth(TPM_ST_AUTH_SIGNED, EntityGetHierarchy(in->authObject),
                         authTimeout, &in->cpHashA, &in->policyRef, &entityName,
                         &out->policyTicket);
   }
   else
   {
       // Generate a null ticket.
       // timeout buffer is null
       out->timeout.t.size = 0;

       // auth ticket is null
       out->policyTicket.tag = TPM_ST_AUTH_SIGNED;
       out->policyTicket.hierarchy = TPM_RH_NULL;
       out->policyTicket.digest.t.size = 0;
   }

   return TPM_RC_SUCCESS;
}