mirror of
https://github.com/stefanberger/libtpms
synced 2026-08-11 20:59:34 +00:00
Sync: Have PolicyContextUpdate return TPM_RC
Split-out those TPM 2 command functions that need to be adapted due to the functions they call returning an error code. Split them out into their own files so they can be synchronized easier. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
parent
60783bd058
commit
2c01c2d865
@ -258,7 +258,12 @@ libtpms_tpm2_la_SOURCES = \
|
||||
tpm2/PlatformData.c \
|
||||
tpm2/PlatformPcr.c \
|
||||
tpm2/Policy_spt.c \
|
||||
tpm2/PolicyAuthorize.c \
|
||||
tpm2/PolicyAuthorizeNV.c \
|
||||
tpm2/PolicyPCR.c \
|
||||
tpm2/PolicySecret.c \
|
||||
tpm2/PolicySigned.c \
|
||||
tpm2/PolicyTicket.c \
|
||||
tpm2/PolicyTransportSPDM.c \
|
||||
tpm2/Power.c \
|
||||
tpm2/PowerPlat.c \
|
||||
|
||||
@ -58,385 +58,6 @@
|
||||
/* */
|
||||
/********************************************************************************/
|
||||
|
||||
#include "Tpm.h"
|
||||
#include "Policy_spt_fp.h"
|
||||
#include "PolicySigned_fp.h"
|
||||
#include "RuntimeProfile_fp.h"
|
||||
|
||||
#if CC_PolicySigned // Conditional expansion of this file
|
||||
|
||||
/*(See part 3 specification)
|
||||
// Include an asymmetrically signed authorization to the policy evaluation
|
||||
*/
|
||||
// Return Type: TPM_RC
|
||||
// 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_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
|
||||
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;
|
||||
UINT64 authTimeout = 0;
|
||||
// Input Validation
|
||||
// Set up local pointers
|
||||
session = SessionGet(in->policySession); // the session structure
|
||||
pAssert_RC(session);
|
||||
|
||||
// Only do input validation if this is not a trial policy session
|
||||
if(session->attributes.isTrialPolicy == CLEAR)
|
||||
{
|
||||
authTimeout = ComputeAuthTimeout(session, in->expiration, &in->nonceTPM);
|
||||
|
||||
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 authorization
|
||||
// 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 = CryptHashStart(&hashState, CryptGetSignHashAlg(&in->auth));
|
||||
// If there is no digest size, then we don't have a verification function
|
||||
// for this algorithm (e.g. TPM_ALG_ECDAA) so indicate that it is a
|
||||
// bad scheme.
|
||||
if(authHash.t.size == 0)
|
||||
return TPM_RCS_SCHEME + RC_PolicySigned_auth;
|
||||
|
||||
// nonceTPM
|
||||
CryptDigestUpdate2B(&hashState, &in->nonceTPM.b);
|
||||
|
||||
// expiration
|
||||
CryptDigestUpdateInt(&hashState, sizeof(UINT32), in->expiration);
|
||||
|
||||
// cpHashA
|
||||
CryptDigestUpdate2B(&hashState, &in->cpHashA.b);
|
||||
|
||||
// policyRef
|
||||
CryptDigestUpdate2B(&hashState, &in->policyRef.b);
|
||||
|
||||
// Complete digest
|
||||
CryptHashEnd2B(&hashState, &authHash.b);
|
||||
|
||||
// Validate Signature. A TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE
|
||||
// error may be returned at this point
|
||||
result = CryptValidateSignature(in->authObject, &authHash, &in->auth);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return RcSafeAddToResult(result, RC_PolicySigned_auth);
|
||||
}
|
||||
// Internal Data Update
|
||||
// Update policy with input policyRef and name of authorization key
|
||||
// These values are updated even if the session is a trial session
|
||||
PolicyContextUpdate(TPM_CC_PolicySigned,
|
||||
EntityGetName(in->authObject, &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)
|
||||
{
|
||||
BOOL expiresOnReset = (in->nonceTPM.t.size == 0);
|
||||
// Compute policy ticket
|
||||
authTimeout &= ~EXPIRATION_BIT;
|
||||
|
||||
result = TicketComputeAuth(TPM_ST_AUTH_SIGNED,
|
||||
EntityGetHierarchy(in->authObject),
|
||||
authTimeout,
|
||||
expiresOnReset,
|
||||
&in->cpHashA,
|
||||
&in->policyRef,
|
||||
&entityName,
|
||||
&out->policyTicket);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
|
||||
// Generate timeout buffer. The format of output timeout buffer is
|
||||
// TPM-specific.
|
||||
// Note: In this implementation, the timeout buffer value is computed after
|
||||
// the ticket is produced so, when the ticket is checked, the expiration
|
||||
// flag needs to be extracted before the ticket is checked.
|
||||
// In the Windows compatible version, the least-significant bit of the
|
||||
// timeout value is used as a flag to indicate if the authorization expires
|
||||
// on reset. The flag is the MSb.
|
||||
out->timeout.t.size = sizeof(authTimeout);
|
||||
if(expiresOnReset)
|
||||
authTimeout |= EXPIRATION_BIT;
|
||||
UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generate a null ticket.
|
||||
// timeout buffer is null
|
||||
out->timeout.t.size = 0;
|
||||
|
||||
// authorization 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;
|
||||
}
|
||||
|
||||
#endif // CC_PolicySigned
|
||||
|
||||
|
||||
#include "Tpm.h"
|
||||
#include "PolicySecret_fp.h"
|
||||
|
||||
#if CC_PolicySecret // Conditional expansion of this file
|
||||
|
||||
# include "Policy_spt_fp.h"
|
||||
# include "NV_spt_fp.h"
|
||||
|
||||
/*(See part 3 specification)
|
||||
// Add a secret-based authorization to the policy evaluation
|
||||
*/
|
||||
// Return Type: TPM_RC
|
||||
// TPM_RC_CPHASH cpHash for policy was previously set to a
|
||||
// value that is not the same as 'cpHashA'
|
||||
// TPM_RC_EXPIRED 'expiration' indicates a time in the past
|
||||
// TPM_RC_NONCE 'nonceTPM' does not match the nonce associated
|
||||
// with 'policySession'
|
||||
// TPM_RC_SIZE 'cpHashA' is not the size of a digest for the
|
||||
// hash associated with 'policySession'
|
||||
TPM_RC
|
||||
TPM2_PolicySecret(PolicySecret_In* in, // IN: input parameter list
|
||||
PolicySecret_Out* out // OUT: output parameter list
|
||||
)
|
||||
{
|
||||
TPM_RC result;
|
||||
SESSION* session;
|
||||
TPM2B_NAME entityName;
|
||||
UINT64 authTimeout = 0;
|
||||
|
||||
# if CC_ReadOnlyControl
|
||||
// Don't allow on PIN PASS or PIN FAIL indices when in Read-Only mode
|
||||
if(gc.readOnly && NvIsPinCountedIndex(in->authHandle))
|
||||
return TPM_RC_READ_ONLY;
|
||||
# endif // CC_ReadOnlyControl
|
||||
|
||||
// Input Validation
|
||||
// Get pointer to the session structure
|
||||
session = SessionGet(in->policySession);
|
||||
pAssert_RC(session);
|
||||
|
||||
//Only do input validation if this is not a trial policy session
|
||||
if(session->attributes.isTrialPolicy == CLEAR)
|
||||
{
|
||||
authTimeout = ComputeAuthTimeout(session, in->expiration, &in->nonceTPM);
|
||||
|
||||
result = PolicyParameterChecks(session,
|
||||
authTimeout,
|
||||
&in->cpHashA,
|
||||
&in->nonceTPM,
|
||||
RC_PolicySecret_nonceTPM,
|
||||
RC_PolicySecret_cpHashA,
|
||||
RC_PolicySecret_expiration);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
// Internal Data Update
|
||||
// Update policy context with input policyRef and name of authorizing key
|
||||
// This value is computed even for trial sessions. Possibly update the cpHash
|
||||
PolicyContextUpdate(TPM_CC_PolicySecret,
|
||||
EntityGetName(in->authHandle, &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
|
||||
&& !NvIsPinPassIndex(in->authHandle))
|
||||
{
|
||||
BOOL expiresOnReset = (in->nonceTPM.t.size == 0);
|
||||
// Compute policy ticket
|
||||
authTimeout &= ~EXPIRATION_BIT;
|
||||
result = TicketComputeAuth(TPM_ST_AUTH_SECRET,
|
||||
EntityGetHierarchy(in->authHandle),
|
||||
authTimeout,
|
||||
expiresOnReset,
|
||||
&in->cpHashA,
|
||||
&in->policyRef,
|
||||
&entityName,
|
||||
&out->policyTicket);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
|
||||
// Generate timeout buffer. The format of output timeout buffer is
|
||||
// TPM-specific.
|
||||
// Note: In this implementation, the timeout buffer value is computed after
|
||||
// the ticket is produced so, when the ticket is checked, the expiration
|
||||
// flag needs to be extracted before the ticket is checked.
|
||||
out->timeout.t.size = sizeof(authTimeout);
|
||||
// In the Windows compatible version, the least-significant bit of the
|
||||
// timeout value is used as a flag to indicate if the authorization expires
|
||||
// on reset. The flag is the MSb.
|
||||
if(expiresOnReset)
|
||||
authTimeout |= EXPIRATION_BIT;
|
||||
UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// timeout buffer is null
|
||||
out->timeout.t.size = 0;
|
||||
|
||||
// authorization ticket is null
|
||||
out->policyTicket.tag = TPM_ST_AUTH_SECRET;
|
||||
out->policyTicket.hierarchy = TPM_RH_NULL;
|
||||
out->policyTicket.digest.t.size = 0;
|
||||
}
|
||||
return TPM_RC_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // CC_PolicySecret
|
||||
|
||||
#include "Tpm.h"
|
||||
#include "PolicyTicket_fp.h"
|
||||
|
||||
#if CC_PolicyTicket // Conditional expansion of this file
|
||||
|
||||
# include "Policy_spt_fp.h"
|
||||
|
||||
/*(See part 3 specification)
|
||||
// Include ticket to the policy evaluation
|
||||
*/
|
||||
// Return Type: TPM_RC
|
||||
// TPM_RC_CPHASH policy's cpHash was previously set to a different
|
||||
// value
|
||||
// TPM_RC_EXPIRED 'timeout' value in the ticket is in the past and the
|
||||
// ticket has expired
|
||||
// TPM_RC_SIZE 'timeout' or 'cpHash' has invalid size for the
|
||||
// TPM_RC_TICKET 'ticket' is not valid
|
||||
TPM_RC
|
||||
TPM2_PolicyTicket(PolicyTicket_In* in // IN: input parameter list
|
||||
)
|
||||
{
|
||||
TPM_RC result;
|
||||
SESSION* session;
|
||||
UINT64 authTimeout;
|
||||
TPMT_TK_AUTH ticketToCompare;
|
||||
TPM_CC commandCode = TPM_CC_PolicySecret;
|
||||
BOOL expiresOnReset;
|
||||
// Input Validation
|
||||
|
||||
// Get pointer to the session structure
|
||||
session = SessionGet(in->policySession);
|
||||
pAssert_RC(session);
|
||||
|
||||
// NOTE: A trial policy session is not allowed to use this command.
|
||||
// A ticket is used in place of a previously given authorization. Since
|
||||
// a trial policy doesn't actually authenticate, the validated
|
||||
// ticket is not necessary and, in place of using a ticket, one
|
||||
// should use the intended authorization for which the ticket
|
||||
// would be a substitute.
|
||||
if(session->attributes.isTrialPolicy)
|
||||
return TPM_RCS_ATTRIBUTES + RC_PolicyTicket_policySession;
|
||||
// Restore timeout data. The format of timeout buffer is TPM-specific.
|
||||
// In this implementation, the most significant bit of the timeout value is
|
||||
// used as the flag to indicate that the ticket expires on TPM Reset or
|
||||
// TPM Restart. The flag has to be removed before the parameters and ticket
|
||||
// are checked.
|
||||
if(in->timeout.t.size != sizeof(UINT64))
|
||||
return TPM_RCS_SIZE + RC_PolicyTicket_timeout;
|
||||
authTimeout = BYTE_ARRAY_TO_UINT64(in->timeout.t.buffer);
|
||||
|
||||
// extract the flag
|
||||
expiresOnReset = (authTimeout & EXPIRATION_BIT) != 0;
|
||||
authTimeout &= ~EXPIRATION_BIT;
|
||||
|
||||
// Do the normal checks on the cpHashA and timeout values
|
||||
result = PolicyParameterChecks(session,
|
||||
authTimeout,
|
||||
&in->cpHashA,
|
||||
NULL, // no nonce
|
||||
0, // no bad nonce return
|
||||
RC_PolicyTicket_cpHashA,
|
||||
RC_PolicyTicket_timeout);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
// Validate Ticket
|
||||
// Re-generate policy ticket by input parameters
|
||||
result = TicketComputeAuth(in->ticket.tag,
|
||||
in->ticket.hierarchy,
|
||||
authTimeout,
|
||||
expiresOnReset,
|
||||
&in->cpHashA,
|
||||
&in->policyRef,
|
||||
&in->authName,
|
||||
&ticketToCompare);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
|
||||
// Compare generated digest with input ticket digest
|
||||
if(!MemoryEqual2B(&in->ticket.digest.b, &ticketToCompare.digest.b))
|
||||
return TPM_RCS_TICKET + RC_PolicyTicket_ticket;
|
||||
|
||||
// Internal Data Update
|
||||
|
||||
// Is this ticket to take the place of a TPM2_PolicySigned() or
|
||||
// a TPM2_PolicySecret()?
|
||||
if(in->ticket.tag == TPM_ST_AUTH_SIGNED)
|
||||
commandCode = TPM_CC_PolicySigned;
|
||||
else if(in->ticket.tag == TPM_ST_AUTH_SECRET)
|
||||
commandCode = TPM_CC_PolicySecret;
|
||||
else
|
||||
// There could only be two possible tag values. Any other value should
|
||||
// be caught by the ticket validation process.
|
||||
FAIL(FATAL_ERROR_INTERNAL);
|
||||
|
||||
// Update policy context
|
||||
PolicyContextUpdate(commandCode,
|
||||
&in->authName,
|
||||
&in->policyRef,
|
||||
&in->cpHashA,
|
||||
authTimeout,
|
||||
session);
|
||||
|
||||
return TPM_RC_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // CC_PolicyTicket
|
||||
|
||||
#include "Tpm.h"
|
||||
#include "PolicyOR_fp.h"
|
||||
@ -1138,105 +759,6 @@ TPM2_PolicyDuplicationSelect(
|
||||
#endif // CC_PolicyDuplicationSelect
|
||||
|
||||
|
||||
#include "Tpm.h"
|
||||
#include "PolicyAuthorize_fp.h"
|
||||
|
||||
#if CC_PolicyAuthorize // Conditional expansion of this file
|
||||
|
||||
# include "Policy_spt_fp.h"
|
||||
|
||||
/*(See part 3 specification)
|
||||
// Change policy by a signature from authority
|
||||
*/
|
||||
// Return Type: TPM_RC
|
||||
// TPM_RC_HASH hash algorithm in 'keyName' is not supported
|
||||
// TPM_RC_SIZE 'keyName' is not the correct size for its hash algorithm
|
||||
// TPM_RC_VALUE the current policyDigest of 'policySession' does not
|
||||
// match 'approvedPolicy'; or 'checkTicket' doesn't match
|
||||
// the provided values
|
||||
TPM_RC
|
||||
TPM2_PolicyAuthorize(PolicyAuthorize_In* in // IN: input parameter list
|
||||
)
|
||||
{
|
||||
TPM_RC result = TPM_RC_SUCCESS;
|
||||
SESSION* session;
|
||||
TPM2B_DIGEST authHash;
|
||||
HASH_STATE hashState;
|
||||
TPMT_TK_VERIFIED ticket;
|
||||
TPM_ALG_ID hashAlg;
|
||||
UINT16 digestSize;
|
||||
// Input Validation
|
||||
|
||||
// Get pointer to the session structure
|
||||
session = SessionGet(in->policySession);
|
||||
pAssert_RC(session);
|
||||
|
||||
if(in->keySign.t.size < 2)
|
||||
{
|
||||
return TPM_RCS_SIZE + RC_PolicyAuthorize_keySign;
|
||||
}
|
||||
|
||||
// Extract from the Name of the key, the algorithm used to compute its Name
|
||||
hashAlg = BYTE_ARRAY_TO_UINT16(in->keySign.t.name);
|
||||
|
||||
// 'keySign' parameter needs to use a supported hash algorithm, otherwise
|
||||
// can't tell how large the digest should be
|
||||
if(!CryptHashIsValidAlg(hashAlg, FALSE))
|
||||
return TPM_RCS_HASH + RC_PolicyAuthorize_keySign;
|
||||
|
||||
digestSize = CryptHashGetDigestSize(hashAlg);
|
||||
if(digestSize != (in->keySign.t.size - 2))
|
||||
return TPM_RCS_SIZE + RC_PolicyAuthorize_keySign;
|
||||
|
||||
//If this is a trial policy, skip all validations
|
||||
if(session->attributes.isTrialPolicy == CLEAR)
|
||||
{
|
||||
// Check that "approvedPolicy" matches the current value of the
|
||||
// policyDigest in policy session
|
||||
if(!MemoryEqual2B(&session->u2.policyDigest.b, &in->approvedPolicy.b))
|
||||
return TPM_RCS_VALUE + RC_PolicyAuthorize_approvedPolicy;
|
||||
|
||||
// Validate ticket TPMT_TK_VERIFIED
|
||||
// Compute aHash. The authorizing object sign a digest
|
||||
// aHash := hash(approvedPolicy || policyRef).
|
||||
// Start hash
|
||||
authHash.t.size = CryptHashStart(&hashState, hashAlg);
|
||||
|
||||
// add approvedPolicy
|
||||
CryptDigestUpdate2B(&hashState, &in->approvedPolicy.b);
|
||||
|
||||
// add policyRef
|
||||
CryptDigestUpdate2B(&hashState, &in->policyRef.b);
|
||||
|
||||
// complete hash
|
||||
CryptHashEnd2B(&hashState, &authHash.b);
|
||||
|
||||
// re-compute TPMT_TK_VERIFIED
|
||||
result = TicketComputeVerified(in->checkTicket.hierarchy, &authHash,
|
||||
&in->keySign, &ticket);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
|
||||
// Compare ticket digest. If not match, return error
|
||||
if(!MemoryEqual2B(&in->checkTicket.digest.b, &ticket.digest.b))
|
||||
return TPM_RCS_VALUE + RC_PolicyAuthorize_checkTicket;
|
||||
}
|
||||
|
||||
// Internal Data Update
|
||||
|
||||
// Set policyDigest to zero digest
|
||||
PolicyDigestClear(session);
|
||||
|
||||
// Update policyDigest
|
||||
PolicyContextUpdate(
|
||||
TPM_CC_PolicyAuthorize, &in->keySign, &in->policyRef, NULL, 0, session);
|
||||
|
||||
return TPM_RC_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // CC_PolicyAuthorize
|
||||
|
||||
|
||||
#include "Tpm.h"
|
||||
#include "PolicyAuthValue_fp.h"
|
||||
|
||||
@ -1479,96 +1001,6 @@ TPM2_PolicyTemplate(PolicyTemplate_In* in // IN: input parameter list
|
||||
|
||||
#endif // CC_PolicyTemplate
|
||||
|
||||
#include "Tpm.h"
|
||||
|
||||
#if CC_PolicyAuthorizeNV // Conditional expansion of this file
|
||||
|
||||
# include "PolicyAuthorizeNV_fp.h"
|
||||
# include "Policy_spt_fp.h"
|
||||
# include "Marshal.h"
|
||||
|
||||
/*(See part 3 specification)
|
||||
// Change policy by a signature from authority
|
||||
*/
|
||||
// Return Type: TPM_RC
|
||||
// TPM_RC_HASH hash algorithm in 'keyName' is not supported or is not
|
||||
// the same as the hash algorithm of the policy session
|
||||
// TPM_RC_SIZE 'keyName' is not the correct size for its hash algorithm
|
||||
// TPM_RC_VALUE the current policyDigest of 'policySession' does not
|
||||
// match 'approvedPolicy'; or 'checkTicket' doesn't match
|
||||
// the provided values
|
||||
TPM_RC
|
||||
TPM2_PolicyAuthorizeNV(PolicyAuthorizeNV_In* in)
|
||||
{
|
||||
SESSION* session;
|
||||
TPM_RC result;
|
||||
NV_REF locator;
|
||||
NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
|
||||
TPM2B_NAME name;
|
||||
TPMT_HA policyInNv = {
|
||||
.hashAlg = 0, // libpms added: Coverity
|
||||
};
|
||||
BYTE nvTemp[sizeof(TPMT_HA)];
|
||||
BYTE* buffer = nvTemp;
|
||||
INT32 size;
|
||||
// Input Validation
|
||||
// Get pointer to the session structure
|
||||
session = SessionGet(in->policySession);
|
||||
pAssert_RC(session);
|
||||
|
||||
// Skip checks if this is a trial policy
|
||||
if(!session->attributes.isTrialPolicy)
|
||||
{
|
||||
// Check the authorizations for reading
|
||||
// Common read access checks. NvReadAccessChecks() returns
|
||||
// TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED
|
||||
// error may be returned at this point
|
||||
result = NvReadAccessChecks(
|
||||
in->authHandle, in->nvIndex, nvIndex->publicArea.attributes);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
|
||||
// Read the contents of the index into a temp buffer
|
||||
size = MIN(nvIndex->publicArea.dataSize, sizeof(TPMT_HA));
|
||||
NvGetIndexData(nvIndex, locator, 0, (UINT16)size, nvTemp);
|
||||
|
||||
// Unmarshal the contents of the buffer into the internal format of a
|
||||
// TPMT_HA so that the hash and digest elements can be accessed from the
|
||||
// structure rather than the byte array that is in the Index (written by
|
||||
// user of the Index).
|
||||
result = TPMT_HA_Unmarshal(&policyInNv, &buffer, &size, FALSE);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
|
||||
// Verify that the hash is the same
|
||||
if(policyInNv.hashAlg != session->authHashAlg)
|
||||
return TPM_RC_HASH;
|
||||
|
||||
// See if the contents of the digest in the Index matches the value
|
||||
// in the policy
|
||||
if(!MemoryEqual(&policyInNv.digest,
|
||||
&session->u2.policyDigest.t.buffer,
|
||||
session->u2.policyDigest.t.size))
|
||||
return TPM_RC_VALUE;
|
||||
}
|
||||
|
||||
// Internal Data Update
|
||||
|
||||
// Set policyDigest to zero digest
|
||||
PolicyDigestClear(session);
|
||||
|
||||
// Update policyDigest
|
||||
PolicyContextUpdate(TPM_CC_PolicyAuthorizeNV,
|
||||
EntityGetName(in->nvIndex, &name),
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
session);
|
||||
|
||||
return TPM_RC_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // CC_PolicyAuthorizeNV
|
||||
|
||||
#include "Tpm.h"
|
||||
#include "PolicyCapability_fp.h"
|
||||
|
||||
98
src/tpm2/PolicyAuthorize.c
Normal file
98
src/tpm2/PolicyAuthorize.c
Normal file
@ -0,0 +1,98 @@
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include "Tpm.h"
|
||||
#include "PolicyAuthorize_fp.h"
|
||||
|
||||
#if CC_PolicyAuthorize // Conditional expansion of this file
|
||||
|
||||
# include "Policy_spt_fp.h"
|
||||
|
||||
/*(See part 3 specification)
|
||||
// Change policy by a signature from authority
|
||||
*/
|
||||
// Return Type: TPM_RC
|
||||
// TPM_RC_HASH hash algorithm in 'keyName' is not supported
|
||||
// TPM_RC_SIZE 'keyName' is not the correct size for its hash algorithm
|
||||
// TPM_RC_VALUE the current policyDigest of 'policySession' does not
|
||||
// match 'approvedPolicy'; or 'checkTicket' doesn't match
|
||||
// the provided values
|
||||
TPM_RC
|
||||
TPM2_PolicyAuthorize(PolicyAuthorize_In* in // IN: input parameter list
|
||||
)
|
||||
{
|
||||
TPM_RC result = TPM_RC_SUCCESS;
|
||||
SESSION* session;
|
||||
TPM2B_DIGEST authHash;
|
||||
HASH_STATE hashState;
|
||||
TPMT_TK_VERIFIED ticket;
|
||||
TPM_ALG_ID hashAlg;
|
||||
UINT16 digestSize;
|
||||
|
||||
// Input Validation
|
||||
|
||||
// Get pointer to the session structure
|
||||
session = SessionGet(in->policySession);
|
||||
pAssert_RC(session);
|
||||
|
||||
if(in->keySign.t.size < 2)
|
||||
{
|
||||
return TPM_RCS_SIZE + RC_PolicyAuthorize_keySign;
|
||||
}
|
||||
|
||||
// Extract from the Name of the key, the algorithm used to compute its Name
|
||||
hashAlg = BYTE_ARRAY_TO_UINT16(in->keySign.t.name);
|
||||
|
||||
// 'keySign' parameter needs to use a supported hash algorithm, otherwise
|
||||
// can't tell how large the digest should be
|
||||
if(!CryptHashIsValidAlg(hashAlg, FALSE))
|
||||
return TPM_RCS_HASH + RC_PolicyAuthorize_keySign;
|
||||
|
||||
digestSize = CryptHashGetDigestSize(hashAlg);
|
||||
if(digestSize != (in->keySign.t.size - 2))
|
||||
return TPM_RCS_SIZE + RC_PolicyAuthorize_keySign;
|
||||
|
||||
//If this is a trial policy, skip all validations
|
||||
if(session->attributes.isTrialPolicy == CLEAR)
|
||||
{
|
||||
// Check that "approvedPolicy" matches the current value of the
|
||||
// policyDigest in policy session
|
||||
if(!MemoryEqual2B(&session->u2.policyDigest.b, &in->approvedPolicy.b))
|
||||
return TPM_RCS_VALUE + RC_PolicyAuthorize_approvedPolicy;
|
||||
|
||||
// Validate ticket TPMT_TK_VERIFIED
|
||||
// Compute aHash. The authorizing object sign a digest
|
||||
// aHash := hash(approvedPolicy || policyRef).
|
||||
// Start hash
|
||||
authHash.t.size = CryptHashStart(&hashState, hashAlg);
|
||||
|
||||
// add approvedPolicy
|
||||
CryptDigestUpdate2B(&hashState, &in->approvedPolicy.b);
|
||||
|
||||
// add policyRef
|
||||
CryptDigestUpdate2B(&hashState, &in->policyRef.b);
|
||||
|
||||
// complete hash
|
||||
CryptHashEnd2B(&hashState, &authHash.b);
|
||||
|
||||
// re-compute TPMT_TK_VERIFIED
|
||||
result = TicketComputeVerified(
|
||||
in->checkTicket.hierarchy, &authHash, &in->keySign, &ticket);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
|
||||
// Compare ticket digest. If not match, return error
|
||||
if(!MemoryEqual2B(&in->checkTicket.digest.b, &ticket.digest.b))
|
||||
return TPM_RCS_VALUE + RC_PolicyAuthorize_checkTicket;
|
||||
}
|
||||
|
||||
// Internal Data Update
|
||||
|
||||
// Set policyDigest to zero digest
|
||||
PolicyDigestClear(session);
|
||||
|
||||
// Update policyDigest
|
||||
return PolicyContextUpdate(
|
||||
TPM_CC_PolicyAuthorize, &in->keySign, &in->policyRef, NULL, 0, session);
|
||||
}
|
||||
|
||||
#endif // CC_PolicyAuthorize
|
||||
91
src/tpm2/PolicyAuthorizeNV.c
Normal file
91
src/tpm2/PolicyAuthorizeNV.c
Normal file
@ -0,0 +1,91 @@
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include "Tpm.h"
|
||||
|
||||
#if CC_PolicyAuthorizeNV // Conditional expansion of this file
|
||||
|
||||
# include "PolicyAuthorizeNV_fp.h"
|
||||
# include "Policy_spt_fp.h"
|
||||
# include "Marshal.h"
|
||||
|
||||
/*(See part 3 specification)
|
||||
// Change policy by a signature from authority
|
||||
*/
|
||||
// Return Type: TPM_RC
|
||||
// TPM_RC_HASH hash algorithm in 'keyName' is not supported or is not
|
||||
// the same as the hash algorithm of the policy session
|
||||
// TPM_RC_SIZE 'keyName' is not the correct size for its hash algorithm
|
||||
// TPM_RC_VALUE the current policyDigest of 'policySession' does not
|
||||
// match 'approvedPolicy'; or 'checkTicket' doesn't match
|
||||
// the provided values
|
||||
TPM_RC
|
||||
TPM2_PolicyAuthorizeNV(PolicyAuthorizeNV_In* in)
|
||||
{
|
||||
SESSION* session;
|
||||
TPM_RC result;
|
||||
NV_REF locator;
|
||||
NV_INDEX* nvIndex = NvGetIndexInfo(in->nvIndex, &locator);
|
||||
TPM2B_NAME name;
|
||||
TPMT_HA policyInNv = {
|
||||
.hashAlg = 0, // libpms added: Coverity
|
||||
};
|
||||
BYTE nvTemp[sizeof(TPMT_HA)];
|
||||
BYTE* buffer = nvTemp;
|
||||
INT32 size;
|
||||
|
||||
// Input Validation
|
||||
// Get pointer to the session structure
|
||||
session = SessionGet(in->policySession);
|
||||
pAssert_RC(session);
|
||||
|
||||
// Skip checks if this is a trial policy
|
||||
if(!session->attributes.isTrialPolicy)
|
||||
{
|
||||
// Check the authorizations for reading
|
||||
// Common read access checks. NvReadAccessChecks() returns
|
||||
// TPM_RC_NV_AUTHORIZATION, TPM_RC_NV_LOCKED, or TPM_RC_NV_UNINITIALIZED
|
||||
// error may be returned at this point
|
||||
result = NvReadAccessChecks(
|
||||
in->authHandle, in->nvIndex, nvIndex->publicArea.attributes);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
|
||||
// Read the contents of the index into a temp buffer
|
||||
size = MIN(nvIndex->publicArea.dataSize, sizeof(TPMT_HA));
|
||||
NvGetIndexData(nvIndex, locator, 0, (UINT16)size, nvTemp);
|
||||
|
||||
// Unmarshal the contents of the buffer into the internal format of a
|
||||
// TPMT_HA so that the hash and digest elements can be accessed from the
|
||||
// structure rather than the byte array that is in the Index (written by
|
||||
// user of the Index).
|
||||
result = TPMT_HA_Unmarshal(&policyInNv, &buffer, &size, FALSE);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
|
||||
// Verify that the hash is the same
|
||||
if(policyInNv.hashAlg != session->authHashAlg)
|
||||
return TPM_RC_HASH;
|
||||
|
||||
// See if the contents of the digest in the Index matches the value
|
||||
// in the policy
|
||||
if(!MemoryEqual(&policyInNv.digest,
|
||||
&session->u2.policyDigest.t.buffer,
|
||||
session->u2.policyDigest.t.size))
|
||||
return TPM_RC_VALUE;
|
||||
}
|
||||
|
||||
// Internal Data Update
|
||||
|
||||
// Set policyDigest to zero digest
|
||||
PolicyDigestClear(session);
|
||||
|
||||
// Update policyDigest
|
||||
return PolicyContextUpdate(TPM_CC_PolicyAuthorizeNV,
|
||||
EntityGetName(in->nvIndex, &name),
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
session);
|
||||
}
|
||||
|
||||
#endif // CC_PolicyAuthorize
|
||||
120
src/tpm2/PolicySecret.c
Normal file
120
src/tpm2/PolicySecret.c
Normal file
@ -0,0 +1,120 @@
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include "Tpm.h"
|
||||
#include "PolicySecret_fp.h"
|
||||
|
||||
#if CC_PolicySecret // Conditional expansion of this file
|
||||
|
||||
# include "Policy_spt_fp.h"
|
||||
# include "NV_spt_fp.h"
|
||||
|
||||
/*(See part 3 specification)
|
||||
// Add a secret-based authorization to the policy evaluation
|
||||
*/
|
||||
// Return Type: TPM_RC
|
||||
// TPM_RC_CPHASH cpHash for policy was previously set to a
|
||||
// value that is not the same as 'cpHashA'
|
||||
// TPM_RC_EXPIRED 'expiration' indicates a time in the past
|
||||
// TPM_RC_NONCE 'nonceTPM' does not match the nonce associated
|
||||
// with 'policySession'
|
||||
// TPM_RC_SIZE 'cpHashA' is not the size of a digest for the
|
||||
// hash associated with 'policySession'
|
||||
TPM_RC
|
||||
TPM2_PolicySecret(PolicySecret_In* in, // IN: input parameter list
|
||||
PolicySecret_Out* out // OUT: output parameter list
|
||||
)
|
||||
{
|
||||
TPM_RC result;
|
||||
SESSION* session;
|
||||
TPM2B_NAME entityName;
|
||||
UINT64 authTimeout = 0;
|
||||
// Input Validation
|
||||
|
||||
# if CC_ReadOnlyControl
|
||||
// Don't allow on PIN PASS or PIN FAIL indices when in Read-Only mode
|
||||
if(gc.readOnly && NvIsPinCountedIndex(in->authHandle))
|
||||
return TPM_RC_READ_ONLY;
|
||||
# endif // CC_ReadOnlyControl
|
||||
|
||||
// Get pointer to the session structure
|
||||
session = SessionGet(in->policySession);
|
||||
pAssert_RC(session);
|
||||
|
||||
//Only do input validation if this is not a trial policy session
|
||||
if(session->attributes.isTrialPolicy == CLEAR)
|
||||
{
|
||||
authTimeout = ComputeAuthTimeout(session, in->expiration, &in->nonceTPM);
|
||||
|
||||
result = PolicyParameterChecks(session,
|
||||
authTimeout,
|
||||
&in->cpHashA,
|
||||
&in->nonceTPM,
|
||||
RC_PolicySecret_nonceTPM,
|
||||
RC_PolicySecret_cpHashA,
|
||||
RC_PolicySecret_expiration);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
// Internal Data Update
|
||||
// Update policy context with input policyRef and name of authorizing key
|
||||
// This value is computed even for trial sessions. Possibly update the cpHash
|
||||
result = PolicyContextUpdate(TPM_CC_PolicySecret,
|
||||
EntityGetName(in->authHandle, &entityName),
|
||||
&in->policyRef,
|
||||
&in->cpHashA,
|
||||
authTimeout,
|
||||
session);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// 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
|
||||
&& !NvIsPinPassIndex(in->authHandle))
|
||||
{
|
||||
BOOL expiresOnReset = (in->nonceTPM.t.size == 0);
|
||||
// Compute policy ticket
|
||||
authTimeout &= ~EXPIRATION_BIT;
|
||||
result = TicketComputeAuth(TPM_ST_AUTH_SECRET,
|
||||
EntityGetHierarchy(in->authHandle),
|
||||
authTimeout,
|
||||
expiresOnReset,
|
||||
&in->cpHashA,
|
||||
&in->policyRef,
|
||||
&entityName,
|
||||
&out->policyTicket);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
|
||||
// Generate timeout buffer. The format of output timeout buffer is
|
||||
// TPM-specific.
|
||||
// Note: In this implementation, the timeout buffer value is computed after
|
||||
// the ticket is produced so, when the ticket is checked, the expiration
|
||||
// flag needs to be extracted before the ticket is checked.
|
||||
out->timeout.t.size = sizeof(authTimeout);
|
||||
// In the Windows compatible version, the least-significant bit of the
|
||||
// timeout value is used as a flag to indicate if the authorization expires
|
||||
// on reset. The flag is the MSb.
|
||||
if(expiresOnReset)
|
||||
authTimeout |= EXPIRATION_BIT;
|
||||
UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// timeout buffer is null
|
||||
out->timeout.t.size = 0;
|
||||
|
||||
// authorization ticket is null
|
||||
out->policyTicket.tag = TPM_ST_AUTH_SECRET;
|
||||
out->policyTicket.hierarchy = TPM_RH_NULL;
|
||||
out->policyTicket.digest.t.size = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // CC_PolicySecret
|
||||
164
src/tpm2/PolicySigned.c
Normal file
164
src/tpm2/PolicySigned.c
Normal file
@ -0,0 +1,164 @@
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include "Tpm.h"
|
||||
#include "Policy_spt_fp.h"
|
||||
#include "PolicySigned_fp.h"
|
||||
|
||||
#if CC_PolicySigned // Conditional expansion of this file
|
||||
|
||||
/*(See part 3 specification)
|
||||
// Include an asymmetrically signed authorization to the policy evaluation
|
||||
*/
|
||||
// Return Type: TPM_RC
|
||||
// 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_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
|
||||
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;
|
||||
UINT64 authTimeout = 0;
|
||||
// Input Validation
|
||||
// Set up local pointers
|
||||
session = SessionGet(in->policySession); // the session structure
|
||||
pAssert_RC(session);
|
||||
|
||||
// Only do input validation if this is not a trial policy session
|
||||
if(session->attributes.isTrialPolicy == CLEAR)
|
||||
{
|
||||
authTimeout = ComputeAuthTimeout(session, in->expiration, &in->nonceTPM);
|
||||
|
||||
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 authorization
|
||||
// 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 = CryptHashStart(&hashState, CryptGetSignHashAlg(&in->auth));
|
||||
// If there is no digest size, then we don't have a verification function
|
||||
// for this algorithm (e.g. TPM_ALG_ECDAA) so indicate that it is a
|
||||
// bad scheme.
|
||||
if(authHash.t.size == 0)
|
||||
return TPM_RCS_SCHEME + RC_PolicySigned_auth;
|
||||
|
||||
// nonceTPM
|
||||
CryptDigestUpdate2B(&hashState, &in->nonceTPM.b);
|
||||
|
||||
// expiration
|
||||
CryptDigestUpdateInt(&hashState, sizeof(UINT32), in->expiration);
|
||||
|
||||
// cpHashA
|
||||
CryptDigestUpdate2B(&hashState, &in->cpHashA.b);
|
||||
|
||||
// policyRef
|
||||
CryptDigestUpdate2B(&hashState, &in->policyRef.b);
|
||||
|
||||
// Complete digest
|
||||
CryptHashEnd2B(&hashState, &authHash.b);
|
||||
|
||||
// Validate Signature. A TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE
|
||||
// error may be returned at this point
|
||||
result = CryptValidateSignature(in->authObject, &authHash, &in->auth);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return RcSafeAddToResult(result, RC_PolicySigned_auth);
|
||||
}
|
||||
// Internal Data Update
|
||||
// Update policy with input policyRef and name of authorization key
|
||||
// These values are updated even if the session is a trial session
|
||||
result = PolicyContextUpdate(TPM_CC_PolicySigned,
|
||||
EntityGetName(in->authObject, &entityName),
|
||||
&in->policyRef,
|
||||
&in->cpHashA,
|
||||
authTimeout,
|
||||
session);
|
||||
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
BOOL expiresOnReset = (in->nonceTPM.t.size == 0);
|
||||
// Compute policy ticket
|
||||
authTimeout &= ~EXPIRATION_BIT;
|
||||
|
||||
result = TicketComputeAuth(TPM_ST_AUTH_SIGNED,
|
||||
EntityGetHierarchy(in->authObject),
|
||||
authTimeout,
|
||||
expiresOnReset,
|
||||
&in->cpHashA,
|
||||
&in->policyRef,
|
||||
&entityName,
|
||||
&out->policyTicket);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
|
||||
// Generate timeout buffer. The format of output timeout buffer is
|
||||
// TPM-specific.
|
||||
// Note: In this implementation, the timeout buffer value is computed after
|
||||
// the ticket is produced so, when the ticket is checked, the expiration
|
||||
// flag needs to be extracted before the ticket is checked.
|
||||
// In the Windows compatible version, the least-significant bit of the
|
||||
// timeout value is used as a flag to indicate if the authorization expires
|
||||
// on reset. The flag is the MSb.
|
||||
out->timeout.t.size = sizeof(authTimeout);
|
||||
if(expiresOnReset)
|
||||
authTimeout |= EXPIRATION_BIT;
|
||||
UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generate a null ticket.
|
||||
// timeout buffer is null
|
||||
out->timeout.t.size = 0;
|
||||
|
||||
// authorization ticket is null
|
||||
out->policyTicket.tag = TPM_ST_AUTH_SIGNED;
|
||||
out->policyTicket.hierarchy = TPM_RH_NULL;
|
||||
out->policyTicket.digest.t.size = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // CC_PolicySigned
|
||||
107
src/tpm2/PolicyTicket.c
Normal file
107
src/tpm2/PolicyTicket.c
Normal file
@ -0,0 +1,107 @@
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
#include "Tpm.h"
|
||||
#include "PolicyTicket_fp.h"
|
||||
|
||||
#if CC_PolicyTicket // Conditional expansion of this file
|
||||
|
||||
# include "Policy_spt_fp.h"
|
||||
|
||||
/*(See part 3 specification)
|
||||
// Include ticket to the policy evaluation
|
||||
*/
|
||||
// Return Type: TPM_RC
|
||||
// TPM_RC_CPHASH policy's cpHash was previously set to a different
|
||||
// value
|
||||
// TPM_RC_EXPIRED 'timeout' value in the ticket is in the past and the
|
||||
// ticket has expired
|
||||
// TPM_RC_SIZE 'timeout' or 'cpHash' has invalid size for the
|
||||
// TPM_RC_TICKET 'ticket' is not valid
|
||||
TPM_RC
|
||||
TPM2_PolicyTicket(PolicyTicket_In* in // IN: input parameter list
|
||||
)
|
||||
{
|
||||
TPM_RC result;
|
||||
SESSION* session;
|
||||
UINT64 authTimeout;
|
||||
TPMT_TK_AUTH ticketToCompare;
|
||||
TPM_CC commandCode = TPM_CC_PolicySecret;
|
||||
BOOL expiresOnReset;
|
||||
|
||||
// Input Validation
|
||||
|
||||
// Get pointer to the session structure
|
||||
session = SessionGet(in->policySession);
|
||||
pAssert_RC(session);
|
||||
|
||||
// NOTE: A trial policy session is not allowed to use this command.
|
||||
// A ticket is used in place of a previously given authorization. Since
|
||||
// a trial policy doesn't actually authenticate, the validated
|
||||
// ticket is not necessary and, in place of using a ticket, one
|
||||
// should use the intended authorization for which the ticket
|
||||
// would be a substitute.
|
||||
if(session->attributes.isTrialPolicy)
|
||||
return TPM_RCS_ATTRIBUTES + RC_PolicyTicket_policySession;
|
||||
// Restore timeout data. The format of timeout buffer is TPM-specific.
|
||||
// In this implementation, the most significant bit of the timeout value is
|
||||
// used as the flag to indicate that the ticket expires on TPM Reset or
|
||||
// TPM Restart. The flag has to be removed before the parameters and ticket
|
||||
// are checked.
|
||||
if(in->timeout.t.size != sizeof(UINT64))
|
||||
return TPM_RCS_SIZE + RC_PolicyTicket_timeout;
|
||||
authTimeout = BYTE_ARRAY_TO_UINT64(in->timeout.t.buffer);
|
||||
|
||||
// extract the flag
|
||||
expiresOnReset = (authTimeout & EXPIRATION_BIT) != 0;
|
||||
authTimeout &= ~EXPIRATION_BIT;
|
||||
|
||||
// Do the normal checks on the cpHashA and timeout values
|
||||
result = PolicyParameterChecks(session,
|
||||
authTimeout,
|
||||
&in->cpHashA,
|
||||
NULL, // no nonce
|
||||
0, // no bad nonce return
|
||||
RC_PolicyTicket_cpHashA,
|
||||
RC_PolicyTicket_timeout);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
// Validate Ticket
|
||||
// Re-generate policy ticket by input parameters
|
||||
result = TicketComputeAuth(in->ticket.tag,
|
||||
in->ticket.hierarchy,
|
||||
authTimeout,
|
||||
expiresOnReset,
|
||||
&in->cpHashA,
|
||||
&in->policyRef,
|
||||
&in->authName,
|
||||
&ticketToCompare);
|
||||
if(result != TPM_RC_SUCCESS)
|
||||
return result;
|
||||
|
||||
// Compare generated digest with input ticket digest
|
||||
if(!MemoryEqual2B(&in->ticket.digest.b, &ticketToCompare.digest.b))
|
||||
return TPM_RCS_TICKET + RC_PolicyTicket_ticket;
|
||||
|
||||
// Internal Data Update
|
||||
|
||||
// Is this ticket to take the place of a TPM2_PolicySigned() or
|
||||
// a TPM2_PolicySecret()?
|
||||
if(in->ticket.tag == TPM_ST_AUTH_SIGNED)
|
||||
commandCode = TPM_CC_PolicySigned;
|
||||
else if(in->ticket.tag == TPM_ST_AUTH_SECRET)
|
||||
commandCode = TPM_CC_PolicySecret;
|
||||
else
|
||||
// There could only be two possible tag values. Any other value should
|
||||
// be caught by the ticket validation process.
|
||||
FAIL(FATAL_ERROR_INTERNAL);
|
||||
|
||||
// Update policy context
|
||||
return PolicyContextUpdate(commandCode,
|
||||
&in->authName,
|
||||
&in->policyRef,
|
||||
&in->cpHashA,
|
||||
authTimeout,
|
||||
session);
|
||||
}
|
||||
|
||||
#endif // CC_PolicyTicket
|
||||
@ -1,63 +1,4 @@
|
||||
/********************************************************************************/
|
||||
/* */
|
||||
/* Policy Command Support */
|
||||
/* Written by Ken Goldman */
|
||||
/* IBM Thomas J. Watson Research Center */
|
||||
/* $Id: Policy_spt.c 1594 2020-03-26 22:15:48Z kgoldman $ */
|
||||
/* */
|
||||
/* Licenses and Notices */
|
||||
/* */
|
||||
/* 1. Copyright Licenses: */
|
||||
/* */
|
||||
/* - Trusted Computing Group (TCG) grants to the user of the source code in */
|
||||
/* this specification (the "Source Code") a worldwide, irrevocable, */
|
||||
/* nonexclusive, royalty free, copyright license to reproduce, create */
|
||||
/* derivative works, distribute, display and perform the Source Code and */
|
||||
/* derivative works thereof, and to grant others the rights granted herein. */
|
||||
/* */
|
||||
/* - The TCG grants to the user of the other parts of the specification */
|
||||
/* (other than the Source Code) the rights to reproduce, distribute, */
|
||||
/* display, and perform the specification solely for the purpose of */
|
||||
/* developing products based on such documents. */
|
||||
/* */
|
||||
/* 2. Source Code Distribution Conditions: */
|
||||
/* */
|
||||
/* - Redistributions of Source Code must retain the above copyright licenses, */
|
||||
/* this list of conditions and the following disclaimers. */
|
||||
/* */
|
||||
/* - Redistributions in binary form must reproduce the above copyright */
|
||||
/* licenses, this list of conditions and the following disclaimers in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
/* */
|
||||
/* 3. Disclaimers: */
|
||||
/* */
|
||||
/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
|
||||
/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
|
||||
/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
|
||||
/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */
|
||||
/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */
|
||||
/* information on specification licensing rights available through TCG */
|
||||
/* membership agreements. */
|
||||
/* */
|
||||
/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */
|
||||
/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */
|
||||
/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */
|
||||
/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */
|
||||
/* */
|
||||
/* - Without limitation, TCG and its members and licensors disclaim all */
|
||||
/* liability, including liability for infringement of any proprietary */
|
||||
/* rights, relating to use of information in this specification and to the */
|
||||
/* implementation of this specification, and TCG disclaims all liability for */
|
||||
/* cost of procurement of substitute goods or services, lost profits, loss */
|
||||
/* of use, loss of data or any incidental, consequential, direct, indirect, */
|
||||
/* or special damages, whether under contract, tort, warranty or otherwise, */
|
||||
/* arising in any way out of use or reliance upon this specification or any */
|
||||
/* information herein. */
|
||||
/* */
|
||||
/* (c) Copyright IBM Corp. and others, 2016 - 2020 */
|
||||
/* */
|
||||
/********************************************************************************/
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
//** Includes
|
||||
#include "Tpm.h"
|
||||
@ -121,7 +62,7 @@ PolicyParameterChecks(SESSION* session,
|
||||
// objectName to it. This will also update the cpHash if it is present.
|
||||
//
|
||||
// Return Type: void
|
||||
void PolicyContextUpdate(
|
||||
TPM_RC PolicyContextUpdate(
|
||||
TPM_CC commandCode, // IN: command code
|
||||
TPM2B_NAME* name, // IN: name of entity
|
||||
TPM2B_NONCE* ref, // IN: the reference data
|
||||
@ -136,8 +77,8 @@ void PolicyContextUpdate(
|
||||
CryptHashStart(&hashState, session->authHashAlg);
|
||||
|
||||
// policyDigest size should always be the digest size of session hash algorithm.
|
||||
pAssert(session->u2.policyDigest.t.size
|
||||
== CryptHashGetDigestSize(session->authHashAlg));
|
||||
pAssert_RC(session->u2.policyDigest.t.size
|
||||
== CryptHashGetDigestSize(session->authHashAlg));
|
||||
|
||||
// add old digest
|
||||
CryptDigestUpdate2B(&hashState, &session->u2.policyDigest.b);
|
||||
@ -186,7 +127,8 @@ void PolicyContextUpdate(
|
||||
if(session->timeout == 0 || session->timeout > policyTimeout)
|
||||
session->timeout = policyTimeout;
|
||||
}
|
||||
return;
|
||||
VERIFY_NOT_FAILED();
|
||||
return TPM_RC_SUCCESS;
|
||||
}
|
||||
//*** ComputeAuthTimeout()
|
||||
// This function is used to determine what the authorization timeout value for
|
||||
|
||||
@ -1,63 +1,4 @@
|
||||
/********************************************************************************/
|
||||
/* */
|
||||
/* */
|
||||
/* Written by Ken Goldman */
|
||||
/* IBM Thomas J. Watson Research Center */
|
||||
/* $Id: Policy_spt_fp.h 1490 2019-07-26 21:13:22Z kgoldman $ */
|
||||
/* */
|
||||
/* Licenses and Notices */
|
||||
/* */
|
||||
/* 1. Copyright Licenses: */
|
||||
/* */
|
||||
/* - Trusted Computing Group (TCG) grants to the user of the source code in */
|
||||
/* this specification (the "Source Code") a worldwide, irrevocable, */
|
||||
/* nonexclusive, royalty free, copyright license to reproduce, create */
|
||||
/* derivative works, distribute, display and perform the Source Code and */
|
||||
/* derivative works thereof, and to grant others the rights granted herein. */
|
||||
/* */
|
||||
/* - The TCG grants to the user of the other parts of the specification */
|
||||
/* (other than the Source Code) the rights to reproduce, distribute, */
|
||||
/* display, and perform the specification solely for the purpose of */
|
||||
/* developing products based on such documents. */
|
||||
/* */
|
||||
/* 2. Source Code Distribution Conditions: */
|
||||
/* */
|
||||
/* - Redistributions of Source Code must retain the above copyright licenses, */
|
||||
/* this list of conditions and the following disclaimers. */
|
||||
/* */
|
||||
/* - Redistributions in binary form must reproduce the above copyright */
|
||||
/* licenses, this list of conditions and the following disclaimers in the */
|
||||
/* documentation and/or other materials provided with the distribution. */
|
||||
/* */
|
||||
/* 3. Disclaimers: */
|
||||
/* */
|
||||
/* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
|
||||
/* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
|
||||
/* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
|
||||
/* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */
|
||||
/* Contact TCG Administration (admin@trustedcomputinggroup.org) for */
|
||||
/* information on specification licensing rights available through TCG */
|
||||
/* membership agreements. */
|
||||
/* */
|
||||
/* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */
|
||||
/* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */
|
||||
/* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */
|
||||
/* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */
|
||||
/* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */
|
||||
/* */
|
||||
/* - Without limitation, TCG and its members and licensors disclaim all */
|
||||
/* liability, including liability for infringement of any proprietary */
|
||||
/* rights, relating to use of information in this specification and to the */
|
||||
/* implementation of this specification, and TCG disclaims all liability for */
|
||||
/* cost of procurement of substitute goods or services, lost profits, loss */
|
||||
/* of use, loss of data or any incidental, consequential, direct, indirect, */
|
||||
/* or special damages, whether under contract, tort, warranty or otherwise, */
|
||||
/* arising in any way out of use or reliance upon this specification or any */
|
||||
/* information herein. */
|
||||
/* */
|
||||
/* (c) Copyright IBM Corp. and others, 2016 */
|
||||
/* */
|
||||
/********************************************************************************/
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
/*(Auto-generated)
|
||||
* Created by TpmPrototypes; Version 3.0 July 18, 2017
|
||||
@ -87,7 +28,7 @@ PolicyParameterChecks(SESSION* session,
|
||||
// objectName to it. This will also update the cpHash if it is present.
|
||||
//
|
||||
// Return Type: void
|
||||
void PolicyContextUpdate(
|
||||
TPM_RC PolicyContextUpdate(
|
||||
TPM_CC commandCode, // IN: command code
|
||||
TPM2B_NAME* name, // IN: name of entity
|
||||
TPM2B_NONCE* ref, // IN: the reference data
|
||||
|
||||
Loading…
Reference in New Issue
Block a user