// 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 "Attest_spt_fp.h"
#include "NV_spt_fp.h"
#include "NV_Certify_fp.h"
//
//
//     Error Returns                     Meaning
//
//     TPM_RC_NV_AUTHORIZATION           the authorization was valid but the authorizing entity (authHandle) is
//                                       not allowed to read from the Index referenced by nvIndex
//     TPM_RC_KEY                        signHandle does not reference a signing key
//     TPM_RC_NV_LOCKED                  Index referenced by nvIndex is locked for reading
//     TPM_RC_NV_RANGE                   offset plus size extends outside of the data range of the Index
//                                       referenced by nvIndex
//     TPM_RC_NV_UNINITIALIZED           Index referenced by nvIndex has not been written
//     TPM_RC_SCHEME                     inScheme is not an allowed value for the key definition
//
TPM_RC
TPM2_NV_Certify(
   NV_Certify_In     *in,                 // IN: input parameter list
   NV_Certify_Out    *out                 // OUT: output parameter list
   )
{
   TPM_RC                    result;
   NV_INDEX                  nvIndex;
   TPMS_ATTEST               certifyInfo;

   // Attestation command may cause the orderlyState to be cleared due to
   // the reporting of clock info. If this is the case, check if NV is
   // available first
   if(gp.orderlyState != SHUTDOWN_NONE)
   {
       // The command needs NV update. Check if NV is available.
       // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
       // this point
       result = NvIsAvailable();
       if(result != TPM_RC_SUCCESS)
           return result;
   }

// Input Validation

   // Get NV index info
   NvGetIndexInfo(in->nvIndex, &nvIndex);

   // Common access checks. A TPM_RC_NV_AUTHORIZATION or TPM_RC_NV_LOCKED
   // error may be returned at this point
   result = NvReadAccessChecks(in->authHandle, in->nvIndex);
   if(result != TPM_RC_SUCCESS)
       return result;

    // make sure that the selection is within the range of the Index (cast to avoid
    // any wrap issues with addition)
    if((UINT32)in->size + (UINT32)in->offset > (UINT32)nvIndex.publicArea.dataSize)
        return TPM_RC_NV_RANGE;

    // Make sure the data will fit the return buffer.
    // NOTE: This check may be modified if the output buffer will not hold the
    // maximum sized NV buffer as part of the certified data. The difference in
    // size could be substantial if the signature scheme was produced a large
    // signature (e.g., RSA 4096).
    if(in->size > MAX_NV_BUFFER_SIZE)
        return TPM_RC_VALUE + RC_NV_Certify_size;


// Command Output

  // Filling in attest information
  // Common fields
  // FillInAttestInfo can return TPM_RC_SCHEME or TPM_RC_KEY
  result = FillInAttestInfo(in->signHandle,
                            &in->inScheme,
                            &in->qualifyingData,
                            &certifyInfo);
  if(result != TPM_RC_SUCCESS)
  {
      if(result == TPM_RC_KEY)
          return TPM_RC_KEY + RC_NV_Certify_signHandle;
      else
          return RcSafeAddToResult(result, RC_NV_Certify_inScheme);
  }
  // NV certify specific fields
  // Attestation type
  certifyInfo.type = TPM_ST_ATTEST_NV;

  // Get the name of the index
  certifyInfo.attested.nv.indexName.t.size =
      NvGetName(in->nvIndex, &certifyInfo.attested.nv.indexName.t.name);

  // Set the return size
  certifyInfo.attested.nv.nvContents.t.size = in->size;

  // Set the offset
  certifyInfo.attested.nv.offset = in->offset;

  // Perform the read
  NvGetIndexData(in->nvIndex, &nvIndex,
                 in->offset, in->size,
                 certifyInfo.attested.nv.nvContents.t.buffer);

  // Sign attestation structure. A NULL signature will be returned if
  // signHandle is TPM_RH_NULL. SignAttestInfo() may return TPM_RC_VALUE,
  // TPM_RC_SCHEME or TPM_RC_ATTRUBUTES.
  // Note: SignAttestInfo may return TPM_RC_ATTRIBUTES if the key is not a
  // signing key but that was checked above. TPM_RC_VALUE would mean that the
  // data to sign is too large but the data to sign is a digest
  result = SignAttestInfo(in->signHandle,
                          &in->inScheme,
                          &certifyInfo,
                          &in->qualifyingData,
                          &out->certifyInfo,
                          &out->signature);
  if(result != TPM_RC_SUCCESS)
      return result;

  // orderly state should be cleared because of the reporting of clock info
  // if signing happens
  if(in->signHandle != TPM_RH_NULL)
      g_clearOrderly = TRUE;

   return TPM_RC_SUCCESS;
}
