// 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;
}