/* Microsoft Reference Implementation for TPM 2.0 | |
* | |
* The copyright in this software is being made available under the BSD License, | |
* included below. This software may be subject to other third party and | |
* contributor rights, including patent rights, and no such rights are granted | |
* under this license. | |
* | |
* Copyright (c) Microsoft Corporation | |
* | |
* All rights reserved. | |
* | |
* BSD License | |
* | |
* Redistribution and use in source and binary forms, with or without modification, | |
* are permitted provided that the following conditions are met: | |
* | |
* Redistributions of source code must retain the above copyright notice, this list | |
* of conditions and the following disclaimer. | |
* | |
* Redistributions in binary form must reproduce the above copyright notice, this | |
* list of conditions and the following disclaimer in the documentation and/or other | |
* materials provided with the distribution. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" | |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | |
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
//** Introduction | |
/* | |
This clause contains the functions used for ticket computations. | |
*/ | |
//** Includes | |
#include "Tpm.h" | |
//** Functions | |
//*** TicketIsSafe() | |
// This function indicates if producing a ticket is safe. | |
// It checks if the leading bytes of an input buffer is TPM_GENERATED_VALUE | |
// or its substring of canonical form. If so, it is not safe to produce ticket | |
// for an input buffer claiming to be TPM generated buffer | |
// return type: BOOL | |
// TRUE It is safe to produce ticket | |
// FALSE It is not safe to produce ticket | |
BOOL | |
TicketIsSafe( | |
TPM2B *buffer | |
) | |
{ | |
TPM_GENERATED valueToCompare = TPM_GENERATED_VALUE; | |
BYTE bufferToCompare[sizeof(valueToCompare)]; | |
BYTE *marshalBuffer; | |
// | |
// If the buffer size is less than the size of TPM_GENERATED_VALUE, assume | |
// it is not safe to generate a ticket | |
if(buffer->size < sizeof(valueToCompare)) | |
return FALSE; | |
marshalBuffer = bufferToCompare; | |
TPM_GENERATED_Marshal(&valueToCompare, &marshalBuffer, NULL); | |
if(MemoryEqual(buffer->buffer, bufferToCompare, sizeof(valueToCompare))) | |
return FALSE; | |
else | |
return TRUE; | |
} | |
//*** TicketComputeVerified() | |
// This function creates a TPMT_TK_VERIFIED ticket. | |
/*(See part 2 specification) | |
// The ticket is computed as: | |
// HMAC(proof, (TPM_ST_VERIFIED | digest | keyName)) | |
// Where: | |
// HMAC() an HMAC using the hash of proof | |
// proof a TPM secret value associated with the hierarchy | |
// associated with keyName | |
// TPM_ST_VERIFIED a value to differentiate the tickets | |
// digest the signed digest | |
// keyName the Name of the key that signed digest | |
*/ | |
void | |
TicketComputeVerified( | |
TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket | |
TPM2B_DIGEST *digest, // IN: digest | |
TPM2B_NAME *keyName, // IN: name of key that signed the values | |
TPMT_TK_VERIFIED *ticket // OUT: verified ticket | |
) | |
{ | |
TPM2B_PROOF *proof; | |
HMAC_STATE hmacState; | |
// | |
// Fill in ticket fields | |
ticket->tag = TPM_ST_VERIFIED; | |
ticket->hierarchy = hierarchy; | |
proof = HierarchyGetProof(hierarchy); | |
// Start HMAC using the proof value of the hierarchy as the HMAC key | |
ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, | |
&proof->b); | |
// TPM_ST_VERIFIED | |
CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag); | |
// digest | |
CryptDigestUpdate2B(&hmacState.hashState, &digest->b); | |
// key name | |
CryptDigestUpdate2B(&hmacState.hashState, &keyName->b); | |
// done | |
CryptHmacEnd2B(&hmacState, &ticket->digest.b); | |
return; | |
} | |
//*** TicketComputeAuth() | |
// This function creates a TPMT_TK_AUTH ticket. | |
/*(See part 2 specification) | |
// The ticket is computed as: | |
// HMAC(proof, (type || timeout || timeEpoch || cpHash | |
// || policyRef || keyName)) | |
// where: | |
// HMAC() an HMAC using the hash of proof | |
// proof a TPM secret value associated with the hierarchy of the key | |
// associated with keyName. | |
// type a value to differentiate the tickets. It could be either | |
// TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED | |
// timeout TPM-specific value indicating when the authorization expires | |
// timeEpoch TPM-specific value indicating the epoch for the timeout | |
// cpHash optional hash (digest only) of the authorized command | |
// policyRef optional reference to a policy value | |
// keyName name of the key that signed the authorization | |
*/ | |
void | |
TicketComputeAuth( | |
TPM_ST type, // IN: the type of ticket. | |
TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket | |
UINT64 timeout, // IN: timeout | |
BOOL expiresOnReset,// IN: flag to indicate if ticket expires on | |
// TPM Reset | |
TPM2B_DIGEST *cpHashA, // IN: input cpHashA | |
TPM2B_NONCE *policyRef, // IN: input policyRef | |
TPM2B_NAME *entityName, // IN: name of entity | |
TPMT_TK_AUTH *ticket // OUT: Created ticket | |
) | |
{ | |
TPM2B_PROOF *proof; | |
HMAC_STATE hmacState; | |
// | |
// Get proper proof | |
proof = HierarchyGetProof(hierarchy); | |
// Fill in ticket fields | |
ticket->tag = type; | |
ticket->hierarchy = hierarchy; | |
// Start HMAC with hierarchy proof as the HMAC key | |
ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, | |
&proof->b); | |
// TPM_ST_AUTH_SECRET or TPM_ST_AUTH_SIGNED, | |
CryptDigestUpdateInt(&hmacState, sizeof(UINT16), ticket->tag); | |
// cpHash | |
CryptDigestUpdate2B(&hmacState.hashState, &cpHashA->b); | |
// policyRef | |
CryptDigestUpdate2B(&hmacState.hashState, &policyRef->b); | |
// keyName | |
CryptDigestUpdate2B(&hmacState.hashState, &entityName->b); | |
// timeout | |
CryptDigestUpdateInt(&hmacState, sizeof(timeout), timeout); | |
if(timeout != 0) | |
{ | |
// epoch | |
CryptDigestUpdateInt(&hmacState.hashState, sizeof(CLOCK_NONCE), | |
g_timeEpoch); | |
// reset count | |
if(expiresOnReset) | |
CryptDigestUpdateInt(&hmacState.hashState, sizeof(gp.totalResetCount), | |
gp.totalResetCount); | |
} | |
// done | |
CryptHmacEnd2B(&hmacState, &ticket->digest.b); | |
return; | |
} | |
//*** TicketComputeHashCheck() | |
// This function creates a TPMT_TK_HASHCHECK ticket. | |
/*(See part 2 specification) | |
// The ticket is computed as: | |
// HMAC(proof, (TPM_ST_HASHCHECK || digest )) | |
// where: | |
// HMAC() an HMAC using the hash of proof | |
// proof a TPM secret value associated with the hierarchy | |
// TPM_ST_HASHCHECK | |
// a value to differentiate the tickets | |
// digest the digest of the data | |
*/ | |
void | |
TicketComputeHashCheck( | |
TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy constant for ticket | |
TPM_ALG_ID hashAlg, // IN: the hash algorithm for 'digest' | |
TPM2B_DIGEST *digest, // IN: input digest | |
TPMT_TK_HASHCHECK *ticket // OUT: Created ticket | |
) | |
{ | |
TPM2B_PROOF *proof; | |
HMAC_STATE hmacState; | |
// | |
// Get proper proof | |
proof = HierarchyGetProof(hierarchy); | |
// Fill in ticket fields | |
ticket->tag = TPM_ST_HASHCHECK; | |
ticket->hierarchy = hierarchy; | |
// Start HMAC using hierarchy proof as HMAC key | |
ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, | |
&proof->b); | |
// TPM_ST_HASHCHECK | |
CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag); | |
// hash algorithm | |
CryptDigestUpdateInt(&hmacState, sizeof(hashAlg), hashAlg); | |
// digest | |
CryptDigestUpdate2B(&hmacState.hashState, &digest->b); | |
// done | |
CryptHmacEnd2B(&hmacState, &ticket->digest.b); | |
return; | |
} | |
//*** TicketComputeCreation() | |
// This function creates a TPMT_TK_CREATION ticket. | |
/*(See part 2 specification) | |
// The ticket is computed as: | |
// HMAC(proof, (TPM_ST_CREATION || Name || hash(TPMS_CREATION_DATA))) | |
// Where: | |
// HMAC() an HMAC using the hash of proof | |
// proof a TPM secret value associated with the hierarchy associated with Name | |
// TPM_ST_VERIFIED a value to differentiate the tickets | |
// Name the Name of the object to which the creation data is to be associated | |
// TPMS_CREATION_DATA the creation data structure associated with Name | |
*/ | |
void | |
TicketComputeCreation( | |
TPMI_RH_HIERARCHY hierarchy, // IN: hierarchy for ticket | |
TPM2B_NAME *name, // IN: object name | |
TPM2B_DIGEST *creation, // IN: creation hash | |
TPMT_TK_CREATION *ticket // OUT: created ticket | |
) | |
{ | |
TPM2B_PROOF *proof; | |
HMAC_STATE hmacState; | |
// Get proper proof | |
proof = HierarchyGetProof(hierarchy); | |
// Fill in ticket fields | |
ticket->tag = TPM_ST_CREATION; | |
ticket->hierarchy = hierarchy; | |
// Start HMAC using hierarchy proof as HMAC key | |
ticket->digest.t.size = CryptHmacStart2B(&hmacState, CONTEXT_INTEGRITY_HASH_ALG, | |
&proof->b); | |
// TPM_ST_CREATION | |
CryptDigestUpdateInt(&hmacState, sizeof(TPM_ST), ticket->tag); | |
// name if provided | |
if(name != NULL) | |
CryptDigestUpdate2B(&hmacState.hashState, &name->b); | |
// creation hash | |
CryptDigestUpdate2B(&hmacState.hashState, &creation->b); | |
// Done | |
CryptHmacEnd2B(&hmacState, &ticket->digest.b); | |
return; | |
} |