blob: ff4eba78bc438bada4934408eeda01a7f21ccb6e [file] [log] [blame]
/* 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.
*/
#include "Tpm.h"
#include "NV_DefineSpace_fp.h"
#ifdef TPM_CC_NV_DefineSpace // Conditional expansion of this file
/*(See part 3 specification)
// Define a NV index space
*/
// return type: TPM_RC
// TPM_RC_HIERARCHY for authorizations using TPM_RH_PLATFORM
// phEnable_NV is clear preventing access to NV
// data in the platform hierarchy.
// TPM_RC_ATTRIBUTES attributes of the index are not consistent
// TPM_RC_NV_DEFINED index already exists
// TPM_RC_NV_SPACE insufficient space for the index
// TPM_RC_SIZE 'auth->size' or 'publicInfo->authPolicy.size' is
// larger than the digest size of
// 'publicInfo->nameAlg'; or 'publicInfo->dataSize'
// is not consistent with 'publicInfo->attributes'
// (this includes the case when the index is
// larger than a MAX_NV_BUFFER_SIZE but the
// TPMA_NV_WRITEALL attribute is SET)
TPM_RC
TPM2_NV_DefineSpace(
NV_DefineSpace_In *in // IN: input parameter list
)
{
TPMA_NV attributes = in->publicInfo.nvPublic.attributes;
UINT16 nameSize;
nameSize = CryptHashGetDigestSize(in->publicInfo.nvPublic.nameAlg);
// Input Validation
// Checks not specific to type
// If the UndefineSpaceSpecial command is not implemented, then can't have
// an index that can only be deleted with policy
#if CC_NV_UndefineSpaceSpecial == NO
if(IsNv_TPMA_NV_POLICY_DELETE(attributes))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
#endif
// check that the authPolicy consistent with hash algorithm
if(in->publicInfo.nvPublic.authPolicy.t.size != 0
&& in->publicInfo.nvPublic.authPolicy.t.size != nameSize)
return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
// make sure that the authValue is not too large
if(MemoryRemoveTrailingZeros(&in->auth)
> CryptHashGetDigestSize(in->publicInfo.nvPublic.nameAlg))
return TPM_RCS_SIZE + RC_NV_DefineSpace_auth;
// If an index is being created by the owner and shEnable is
// clear, then we would not reach this point because ownerAuth
// can't be given when shEnable is CLEAR. However, if phEnable
// is SET but phEnableNV is CLEAR, we have to check here
if(in->authHandle == TPM_RH_PLATFORM && gc.phEnableNV == CLEAR)
return TPM_RCS_HIERARCHY + RC_NV_DefineSpace_authHandle;
// Attribute checks
// Eliminate the unsupported types
switch(NV_ATTRIBUTES_TO_TYPE(attributes))
{
#if CC_NV_Increment == YES
case TPM_NT_COUNTER:
#endif
#if CC_NV_SetBits == YES
case TPM_NT_BITS:
#endif
#if CC_NV_Extend == YES
case TPM_NT_EXTEND:
#endif
#if CC_PolicySecret == YES && defined TPM_NT_PIN_PASS
case TPM_NT_PIN_PASS:
case TPM_NT_PIN_FAIL:
#endif
case TPM_NT_ORDINARY:
break;
default:
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
break;
}
// Check that the sizes are OK based on the type
switch(NV_ATTRIBUTES_TO_TYPE(attributes))
{
case TPM_NT_ORDINARY:
// Can't exceed the allowed size for the implementation
if(in->publicInfo.nvPublic.dataSize > MAX_NV_INDEX_SIZE)
return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
break;
case TPM_NT_EXTEND:
if(in->publicInfo.nvPublic.dataSize != nameSize)
return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
break;
default:
// Everything else needs a size of 8
if(in->publicInfo.nvPublic.dataSize != 8)
return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
break;
}
// Handle other specifics
switch(NV_ATTRIBUTES_TO_TYPE(attributes))
{
case TPM_NT_COUNTER:
// Counter can't have TPMA_NV_CLEAR_STCLEAR SET (don't clear counters)
if(IsNv_TPMA_NV_CLEAR_STCLEAR(attributes))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
break;
#ifdef TPM_NT_PIN_FAIL
case TPM_NT_PIN_FAIL:
// NV_NO_DA must be SET and AUTHWRITE must be CLEAR
// NOTE: As with a PIN_PASS index, the authValue of the index is not
// available until the index is written. If AUTHWRITE is the only way to
// write then index, it could never be written. Rather than go through
// all of the other possible ways to write the Index, it is simply
// prohibited to write the index with the authValue. Other checks
// below will insure that there seems to be a way to write the index
// (i.e., with platform authorization , owner authorization,
// or with policyAuth.)
// It is not allowed to create a PIN Index that can't be modified.
if(!IsNv_TPMA_NV_NO_DA(attributes))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
#endif
#ifdef TPM_NT_PIN_PASS
case TPM_NT_PIN_PASS:
// AUTHWRITE must be CLEAR (see note above to TPM_NT_PIN_FAIL)
if(IsNv_TPMA_NV_AUTHWRITE(attributes)
|| IsNv_TPMA_NV_GLOBALLOCK(attributes)
|| IsNv_TPMA_NV_WRITEDEFINE(attributes))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
#endif // this comes before break because PIN_FAIL falls through
break;
default:
break;
}
// Locks may not be SET and written cannot be SET
if(IsNv_TPMA_NV_WRITTEN(attributes)
|| IsNv_TPMA_NV_WRITELOCKED(attributes)
|| IsNv_TPMA_NV_READLOCKED(attributes))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// There must be a way to read the index.
if(!IsNv_TPMA_NV_OWNERREAD(attributes)
&& !IsNv_TPMA_NV_PPREAD(attributes)
&& !IsNv_TPMA_NV_AUTHREAD(attributes)
&& !IsNv_TPMA_NV_POLICYREAD(attributes))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// There must be a way to write the index
if(!IsNv_TPMA_NV_OWNERWRITE(attributes)
&& !IsNv_TPMA_NV_PPWRITE(attributes)
&& !IsNv_TPMA_NV_AUTHWRITE(attributes)
&& !IsNv_TPMA_NV_POLICYWRITE(attributes))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// An index with TPMA_NV_CLEAR_STCLEAR can't have TPMA_NV_WRITEDEFINE SET
if(IsNv_TPMA_NV_CLEAR_STCLEAR(attributes)
&& IsNv_TPMA_NV_WRITEDEFINE(attributes))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// Make sure that the creator of the index can delete the index
if((IsNv_TPMA_NV_PLATFORMCREATE(attributes)
&& in->authHandle == TPM_RH_OWNER)
|| (!IsNv_TPMA_NV_PLATFORMCREATE(attributes)
&& in->authHandle == TPM_RH_PLATFORM))
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_authHandle;
// If TPMA_NV_POLICY_DELETE is SET, then the index must be defined by
// the platform
if(IsNv_TPMA_NV_POLICY_DELETE(attributes)
&& TPM_RH_PLATFORM != in->authHandle)
return TPM_RCS_ATTRIBUTES + RC_NV_DefineSpace_publicInfo;
// Make sure that the TPMA_NV_WRITEALL is not set if the index size is larger
// than the allowed NV buffer size.
if(in->publicInfo.nvPublic.dataSize > MAX_NV_BUFFER_SIZE
&& IsNv_TPMA_NV_WRITEALL(attributes))
return TPM_RCS_SIZE + RC_NV_DefineSpace_publicInfo;
// And finally, see if the index is already defined.
if(NvIndexIsDefined(in->publicInfo.nvPublic.nvIndex))
return TPM_RC_NV_DEFINED;
// Internal Data Update
// define the space. A TPM_RC_NV_SPACE error may be returned at this point
return NvDefineIndex(&in->publicInfo.nvPublic, &in->auth);
}
#endif // CC_NV_DefineSpace