// 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 "HMAC_fp.h"
//
//
// Error Returns Meaning
//
// TPM_RC_ATTRIBUTES key referenced by handle is not a signing key or is a restricted key
// TPM_RC_TYPE key referenced by handle is not an HMAC key
// TPM_RC_VALUE hashAlg is not compatible with the hash algorithm of the scheme of
// the object referenced by handle
//
TPM_RC
TPM2_HMAC(
HMAC_In *in, // IN: input parameter list
HMAC_Out *out // OUT: output parameter list
)
{
HMAC_STATE hmacState;
OBJECT *hmacObject;
TPMI_ALG_HASH hashAlg;
TPMT_PUBLIC *publicArea;
// Input Validation
// Get HMAC key object and public area pointers
hmacObject = ObjectGet(in->handle);
publicArea = &hmacObject->publicArea;
// Make sure that the key is an HMAC key
if(publicArea->type != TPM_ALG_KEYEDHASH)
return TPM_RC_TYPE + RC_HMAC_handle;
// and that it is unrestricted
if(publicArea->objectAttributes.restricted == SET)
return TPM_RC_ATTRIBUTES + RC_HMAC_handle;
// and that it is a signing key
if(publicArea->objectAttributes.sign != SET)
return TPM_RC_KEY + RC_HMAC_handle;
// See if the key has a default
if(publicArea->parameters.keyedHashDetail.scheme.scheme == TPM_ALG_NULL)
// it doesn't so use the input value
hashAlg = in->hashAlg;
else
{
// key has a default so use it
hashAlg
= publicArea->parameters.keyedHashDetail.scheme.details.hmac.hashAlg;
// and verify that the input was either the TPM_ALG_NULL or the default
if(in->hashAlg != TPM_ALG_NULL && in->hashAlg != hashAlg)
hashAlg = TPM_ALG_NULL;
}
// if we ended up without a hash algorith then return an error
if(hashAlg == TPM_ALG_NULL)
return TPM_RC_VALUE + RC_HMAC_hashAlg;
// Command Output
// Start HMAC stack
out->outHMAC.t.size = CryptStartHMAC2B(hashAlg,
&hmacObject->sensitive.sensitive.bits.b,
&hmacState);
// Adding HMAC data
CryptUpdateDigest2B(&hmacState, &in->buffer.b);
// Complete HMAC
CryptCompleteHMAC2B(&hmacState, &out->outHMAC.b);
return TPM_RC_SUCCESS;
}