aboutsummaryrefslogtreecommitdiff
path: root/NV_Certify.c
blob: 36ec53b10f3423b8c0cbeea5f9b3803a99a54e83 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// 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;

   // See if the range to be certified is out of the bounds of the defined
   // Index
   if((in->size + in->offset) > nvIndex.publicArea.dataSize)
       return TPM_RC_NV_RANGE;

// 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;
}