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