• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*############################################################################
2 # Copyright 2017 Intel Corporation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #     http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 ############################################################################*/
16 
17 /*!
18  * \file
19  * \brief TSS NV API implementation.
20  */
21 
22 #include "epid/member/tpm2/nv.h"
23 #include <tss2/tss.h>
24 #include "epid/common/src/memory.h"
25 #include "epid/member/tpm2/ibm_tss/printtss.h"
26 #include "epid/member/tpm2/ibm_tss/state.h"
27 
Tpm2NvUndefineSpace(Tpm2Ctx * ctx,uint32_t nv_index)28 EpidStatus Tpm2NvUndefineSpace(Tpm2Ctx* ctx, uint32_t nv_index) {
29   TPM_RC rc = 0;
30   NV_UndefineSpace_In in;
31   TPMI_SH_AUTH_SESSION sessionHandle0 = TPM_RS_PW;
32   if (!ctx) {
33     return kEpidBadArgErr;
34   }
35   if ((nv_index >> 24) != TPM_HT_NV_INDEX) {
36     return kEpidBadArgErr;
37   }
38 
39   in.authHandle = TPM_RH_OWNER;
40   // the NV Index to remove from NV space
41   in.nvIndex = nv_index;
42   rc = TSS_Execute(ctx->tss, NULL, (COMMAND_PARAMETERS*)&in, NULL,
43                    TPM_CC_NV_UndefineSpace, sessionHandle0, NULL, 0,
44                    TPM_RH_NULL, NULL, 0);
45   if (rc != TPM_RC_SUCCESS) {
46     print_tpm2_response_code("TPM2_NV_UndefineSpace", rc);
47     return kEpidBadArgErr;
48   }
49   return kEpidNoErr;
50 }
51 
Tpm2NvDefineSpace(Tpm2Ctx * ctx,uint32_t nv_index,size_t size)52 EpidStatus Tpm2NvDefineSpace(Tpm2Ctx* ctx, uint32_t nv_index, size_t size) {
53   TPM_RC rc = 0;
54   NV_DefineSpace_In in = {0};
55   TPMI_SH_AUTH_SESSION sessionHandle0 = TPM_RS_PW;
56   if (!ctx || size == 0 || size > MAX_NV_BUFFER_SIZE) {
57     return kEpidBadArgErr;
58   }
59   if ((nv_index >> 24) != TPM_HT_NV_INDEX) {
60     return kEpidBadArgErr;
61   }
62 
63   in.authHandle = TPM_RH_OWNER;
64   // the handle of the data area
65   in.publicInfo.nvPublic.nvIndex = nv_index;
66   // hash algorithm used to compute the name of the Index and used for the
67   // authPolicy
68   in.publicInfo.nvPublic.nameAlg = TPM_ALG_SHA256;
69   in.publicInfo.nvPublic.attributes.val = TPMA_NVA_NO_DA | TPMA_NVA_AUTHWRITE |
70                                           TPMA_NVA_AUTHREAD | TPMA_NVA_ORDINARY;
71   // the size of the data area
72   in.publicInfo.nvPublic.dataSize = (uint16_t)size;
73   rc = TSS_Execute(ctx->tss, NULL, (COMMAND_PARAMETERS*)&in, NULL,
74                    TPM_CC_NV_DefineSpace, sessionHandle0, NULL, 0, TPM_RH_NULL,
75                    NULL, 0);
76   if (rc != TPM_RC_SUCCESS) {
77     print_tpm2_response_code("TPM2_NV_DefineSpace", rc);
78     if (rc == TPM_RC_NV_DEFINED) {
79       return kEpidDuplicateErr;
80     }
81     return kEpidBadArgErr;
82   }
83   return kEpidNoErr;
84 }
85 
Tpm2NvRead(Tpm2Ctx * ctx,uint32_t nv_index,size_t size,uint16_t offset,void * data)86 EpidStatus Tpm2NvRead(Tpm2Ctx* ctx, uint32_t nv_index, size_t size,
87                       uint16_t offset, void* data) {
88   TPM_RC rc = 0;
89   NV_Read_In in;
90   NV_Read_Out out;
91   TPMI_SH_AUTH_SESSION sessionHandle0 = TPM_RS_PW;
92   int done = FALSE;
93   // bytes read so far
94   uint16_t bytes_read_so_far = 0;
95 
96   if (!ctx || !data || size == 0 || size > MAX_NV_BUFFER_SIZE) {
97     return kEpidBadArgErr;
98   }
99   if ((nv_index >> 24) != TPM_HT_NV_INDEX) {
100     return kEpidBadArgErr;
101   }
102 
103   if ((nv_index >> 24) != TPM_HT_NV_INDEX) {
104     return kEpidBadArgErr;
105   }
106   // Authorization handle
107   in.authHandle = nv_index;
108   in.nvIndex = nv_index;
109   in.offset = offset;
110   while ((rc == TPM_RC_SUCCESS) && !done) {
111     in.offset = offset + bytes_read_so_far;
112     if ((uint32_t)(size - bytes_read_so_far) < MAX_NV_BUFFER_SIZE) {
113       // last chunk
114       in.size = (uint16_t)size - bytes_read_so_far;
115     } else {
116       // next chunk
117       in.size = MAX_NV_BUFFER_SIZE;
118     }
119     rc = TSS_Execute(ctx->tss, (RESPONSE_PARAMETERS*)&out,
120                      (COMMAND_PARAMETERS*)&in, NULL, TPM_CC_NV_Read,
121                      sessionHandle0, NULL, 0, TPM_RH_NULL, NULL, 0);
122     if (rc == TPM_RC_SUCCESS) {
123       // copy the results to the read buffer
124       memcpy_S((uint8_t*)data + bytes_read_so_far, size - bytes_read_so_far,
125                out.data.b.buffer, out.data.b.size);
126       bytes_read_so_far += out.data.b.size;
127       if (bytes_read_so_far == size) {
128         done = TRUE;
129       }
130     } else {
131       print_tpm2_response_code("TPM2_NV_Read", rc);
132     }
133   }
134   if (rc != TPM_RC_SUCCESS) {
135     return kEpidBadArgErr;
136   }
137   return kEpidNoErr;
138 }
139 
Tpm2NvWrite(Tpm2Ctx * ctx,uint32_t nv_index,size_t size,uint16_t offset,void const * data)140 EpidStatus Tpm2NvWrite(Tpm2Ctx* ctx, uint32_t nv_index, size_t size,
141                        uint16_t offset, void const* data) {
142   TPM_RC rc = TPM_RC_SUCCESS;
143   NV_Write_In in = {0};
144   TPMI_SH_AUTH_SESSION sessionHandle0 = TPM_RS_PW;
145   if (!ctx || !data || size == 0 || size > MAX_NV_BUFFER_SIZE) {
146     return kEpidBadArgErr;
147   }
148   if ((nv_index >> 24) != TPM_HT_NV_INDEX) {
149     return kEpidBadArgErr;
150   }
151 
152   in.authHandle = nv_index;
153   in.data.b.size = (uint16_t)size;
154   memcpy(in.data.b.buffer, data, size);
155   in.nvIndex = nv_index;
156   // beginning offset
157   in.offset = offset;
158   rc = TSS_Execute(ctx->tss, NULL, (COMMAND_PARAMETERS*)&in, NULL,
159                    TPM_CC_NV_Write, sessionHandle0, NULL, 0, TPM_RH_NULL, NULL,
160                    0);
161   if (rc != TPM_RC_SUCCESS) {
162     print_tpm2_response_code("TPM2_NV_Write", rc);
163     return kEpidBadArgErr;
164   }
165   return kEpidNoErr;
166 }
167