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 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