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 /// TPM non volatile memory API unit tests.
17 /*! \file */
18 #include <array>
19 #include <cstring>
20 #include "gtest/gtest.h"
21 
22 #include "epid/common-testhelper/epid2params_wrapper-testhelper.h"
23 #include "epid/common-testhelper/errors-testhelper.h"
24 #include "epid/common-testhelper/prng-testhelper.h"
25 #include "epid/member/tpm2/unittests/tpm2-testhelper.h"
26 
27 extern "C" {
28 #include "epid/member/tpm2/nv.h"
29 }
30 
operator ==(MembershipCredential const & lhs,MembershipCredential const & rhs)31 bool operator==(MembershipCredential const& lhs,
32                 MembershipCredential const& rhs) {
33   return 0 == std::memcmp(&lhs, &rhs, sizeof(lhs));
34 }
35 
36 namespace {
37 
TEST(NvTest,CanStoreMembershipCredential)38 TEST(NvTest, CanStoreMembershipCredential) {
39   // Demonstrate NV API usage
40   Prng my_prng;
41   Epid2ParamsObj epid2params;
42   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
43   uint32_t nv_index = 0x01000000;
44 
45   MembershipCredential const credential = {
46       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47        0x00, 0x00, 0x00, 0x01},  // group id
48       {{{{0x46, 0xc9, 0x69, 0xee, 0xf4, 0x68, 0xe1, 0x5f, 0xac, 0xbf, 0xdd,
49           0x77, 0xeb, 0x4c, 0xaf, 0x8a, 0x87, 0x68, 0x3f, 0x4e, 0xda, 0xf2,
50           0x96, 0xec, 0x57, 0x08, 0x90, 0xe8, 0x19, 0x62, 0x54, 0xdb}}},
51        {{{0x1e, 0x52, 0x23, 0x16, 0x91, 0xe4, 0xa8, 0x1d, 0x9a, 0x1b, 0x8a,
52           0xad, 0x0a, 0xcf, 0x36, 0x4f, 0xae, 0x43, 0xde, 0x62, 0xff, 0xa6,
53           0x4b, 0xa8, 0x16, 0x24, 0x98, 0x80, 0x82, 0x80, 0x37, 0x77}}}},  // A
54       {{{0x0a, 0x30, 0xae, 0x43, 0xa1, 0xe0, 0xd7, 0xdf, 0x10, 0x5e, 0xaf,
55          0xd8, 0x5a, 0x61, 0x10, 0x86, 0xd0, 0x9d, 0xb9, 0xe4, 0x46, 0xdd,
56          0xb7, 0x1b, 0x00, 0x14, 0x7c, 0x6b, 0x13, 0x72, 0xc3, 0x77}}}  // x
57   };
58   MembershipCredential data = {0};
59 
60   // probe is nv_index is defined
61   if (kEpidNoErr != Tpm2NvRead(tpm, nv_index, sizeof(data), 0, &data)) {
62     EXPECT_EQ(kEpidNoErr,
63               Tpm2NvDefineSpace(tpm, nv_index, sizeof(MembershipCredential)));
64   }
65   // write
66   EXPECT_EQ(kEpidNoErr,
67             Tpm2NvWrite(tpm, nv_index, sizeof(credential), 0, &credential));
68 
69   // read
70   EXPECT_EQ(kEpidNoErr, Tpm2NvRead(tpm, nv_index, sizeof(data), 0, &data));
71   EXPECT_EQ(credential, data);
72   THROW_ON_EPIDERR(Tpm2NvUndefineSpace(tpm, nv_index));
73 }
74 
TEST(NvTest,CanUseOffset)75 TEST(NvTest, CanUseOffset) {
76   Prng my_prng;
77   Epid2ParamsObj epid2params;
78   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
79   uint32_t nv_index = 0x01000000;
80 
81   std::array<uint8_t, 3> const data1_src = {1, 2, 3};
82   std::array<uint8_t, 5> const data2_src = {4, 5, 6, 7, 8};
83   std::array<uint8_t, 3> data1_dst = {0};
84   std::array<uint8_t, 5> data2_dst = {0};
85 
86   THROW_ON_EPIDERR(
87       Tpm2NvDefineSpace(tpm, nv_index, data1_src.size() + data2_src.size()));
88 
89   EXPECT_EQ(kEpidNoErr,
90             Tpm2NvWrite(tpm, nv_index, data1_src.size(), 0, data1_src.data()));
91   EXPECT_EQ(kEpidNoErr,
92             Tpm2NvWrite(tpm, nv_index, data2_src.size(),
93                         (uint16_t)data1_src.size(), data2_src.data()));
94 
95   EXPECT_EQ(kEpidNoErr,
96             Tpm2NvRead(tpm, nv_index, data1_dst.size(), 0, data1_dst.data()));
97   EXPECT_EQ(data1_src, data1_dst);
98 
99   EXPECT_EQ(kEpidNoErr,
100             Tpm2NvRead(tpm, nv_index, data2_dst.size(),
101                        (uint16_t)data1_dst.size(), data2_dst.data()));
102   EXPECT_EQ(data2_src, data2_dst);
103   THROW_ON_EPIDERR(Tpm2NvUndefineSpace(tpm, nv_index));
104 }
105 
106 //////////////////////////////////////////////////////////////////////////
107 // Tpm2NvDefineSpace Tests
TEST(NvTest,NvDefineSpaceFailsGivenNullParameters)108 TEST(NvTest, NvDefineSpaceFailsGivenNullParameters) {
109   uint32_t nv_index = 0x01000000;
110   EXPECT_EQ(kEpidBadArgErr,
111             Tpm2NvDefineSpace(nullptr, nv_index, sizeof(MembershipCredential)));
112 }
113 
TEST(NvTest,NvDefineSpaceCanAllocateSpace)114 TEST(NvTest, NvDefineSpaceCanAllocateSpace) {
115   Prng my_prng;
116   Epid2ParamsObj epid2params;
117   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
118   uint32_t nv_index = 0x01000000;
119   EXPECT_EQ(kEpidNoErr,
120             Tpm2NvDefineSpace(tpm, nv_index, sizeof(MembershipCredential)));
121   THROW_ON_EPIDERR(Tpm2NvUndefineSpace(tpm, nv_index));
122 }
123 
TEST(NvTest,NvDefineSpaceCatchReDefinition)124 TEST(NvTest, NvDefineSpaceCatchReDefinition) {
125   Prng my_prng;
126   Epid2ParamsObj epid2params;
127   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
128   uint32_t nv_index = 0x01000002;
129   EXPECT_EQ(kEpidNoErr,
130             Tpm2NvDefineSpace(tpm, nv_index, sizeof(MembershipCredential)));
131   EXPECT_EQ(kEpidDuplicateErr,
132             Tpm2NvDefineSpace(tpm, nv_index, sizeof(MembershipCredential)));
133   THROW_ON_EPIDERR(Tpm2NvUndefineSpace(tpm, nv_index));
134 }
135 
136 //////////////////////////////////////////////////////////////////////////
137 // Tpm2NvUndefineSpace Tests
TEST(NvTest,NvUndefineSpaceFailsGivenNullParameters)138 TEST(NvTest, NvUndefineSpaceFailsGivenNullParameters) {
139   uint32_t nv_index = 0x01000000;
140   EXPECT_EQ(kEpidBadArgErr, Tpm2NvUndefineSpace(nullptr, nv_index));
141 }
142 
TEST(NvTest,NvUndefineSpaceCanDeallocateSpace)143 TEST(NvTest, NvUndefineSpaceCanDeallocateSpace) {
144   Prng my_prng;
145   Epid2ParamsObj epid2params;
146   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
147   uint32_t nv_index = 0x01000000;
148   MembershipCredential data = {0};
149   THROW_ON_EPIDERR(Tpm2NvDefineSpace(tpm, nv_index, sizeof(data)));
150   EXPECT_EQ(kEpidNoErr, Tpm2NvUndefineSpace(tpm, nv_index));
151   EXPECT_EQ(kEpidBadArgErr, Tpm2NvRead(tpm, nv_index, sizeof(data), 0, &data));
152 }
153 
TEST(NvTest,NvUndefineSpaceCatchReDefinition)154 TEST(NvTest, NvUndefineSpaceCatchReDefinition) {
155   Prng my_prng;
156   Epid2ParamsObj epid2params;
157   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
158   uint32_t nv_index = 0x01000000;
159   MembershipCredential const data = {0};
160   EXPECT_EQ(kEpidNoErr, Tpm2NvDefineSpace(tpm, nv_index, sizeof(data)));
161   EXPECT_EQ(kEpidNoErr, Tpm2NvUndefineSpace(tpm, nv_index));
162   EXPECT_EQ(kEpidBadArgErr, Tpm2NvUndefineSpace(tpm, nv_index));
163 }
164 
165 //////////////////////////////////////////////////////////////////////////
166 // Tpm2NvWrite Tests
TEST(NvTest,NvWriteFailsGivenNullParameters)167 TEST(NvTest, NvWriteFailsGivenNullParameters) {
168   Prng my_prng;
169   Epid2ParamsObj epid2params;
170   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
171   uint32_t nv_index = 0x01000000;
172   THROW_ON_EPIDERR(
173       Tpm2NvDefineSpace(tpm, nv_index, sizeof(MembershipCredential)));
174 
175   MembershipCredential const data = {0};
176   EXPECT_EQ(kEpidBadArgErr,
177             Tpm2NvWrite(nullptr, nv_index, sizeof(data), 0, &data));
178   EXPECT_EQ(kEpidBadArgErr,
179             Tpm2NvWrite(tpm, nv_index, sizeof(data), 0, nullptr));
180   THROW_ON_EPIDERR(Tpm2NvUndefineSpace(tpm, nv_index));
181 }
182 
TEST(NvTest,NvWriteCanWrite)183 TEST(NvTest, NvWriteCanWrite) {
184   Prng my_prng;
185   Epid2ParamsObj epid2params;
186   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
187   uint32_t nv_index = 0x01000000;
188   THROW_ON_EPIDERR(
189       Tpm2NvDefineSpace(tpm, nv_index, sizeof(MembershipCredential)));
190 
191   MembershipCredential const data = {0};
192   EXPECT_EQ(kEpidNoErr, Tpm2NvWrite(tpm, nv_index, sizeof(data), 0, &data));
193   EXPECT_EQ(kEpidNoErr, Tpm2NvWrite(tpm, nv_index, sizeof(data) - 1, 1, &data));
194   THROW_ON_EPIDERR(Tpm2NvUndefineSpace(tpm, nv_index));
195 }
196 
TEST(NvTest,NvWriteFailsGivenOverflow)197 TEST(NvTest, NvWriteFailsGivenOverflow) {
198   Prng my_prng;
199   Epid2ParamsObj epid2params;
200   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
201   uint32_t nv_index = 0x01000000;
202   THROW_ON_EPIDERR(
203       Tpm2NvDefineSpace(tpm, nv_index, sizeof(MembershipCredential)));
204 
205   MembershipCredential const data = {0};
206   EXPECT_EQ(kEpidBadArgErr, Tpm2NvWrite(tpm, nv_index, sizeof(data), 1, &data));
207   EXPECT_EQ(kEpidBadArgErr,
208             Tpm2NvWrite(tpm, nv_index, sizeof(data) + 1, 1, &data));
209   EXPECT_EQ(kEpidBadArgErr,
210             Tpm2NvWrite(tpm, nv_index, 1, sizeof(MembershipCredential), &data));
211   THROW_ON_EPIDERR(Tpm2NvUndefineSpace(tpm, nv_index));
212 }
213 
TEST(NvTest,NvWriteFailsGivenInvalidLength)214 TEST(NvTest, NvWriteFailsGivenInvalidLength) {
215   Prng my_prng;
216   Epid2ParamsObj epid2params;
217   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
218   uint32_t nv_index = 0x01000000;
219   THROW_ON_EPIDERR(
220       Tpm2NvDefineSpace(tpm, nv_index, sizeof(MembershipCredential)));
221 
222   MembershipCredential const data = {0};
223   EXPECT_EQ(kEpidBadArgErr, Tpm2NvWrite(tpm, nv_index, 0, 0, &data));
224   THROW_ON_EPIDERR(Tpm2NvUndefineSpace(tpm, nv_index));
225 }
226 
TEST(NvTest,NvWriteFailsGivenIndexUndefined)227 TEST(NvTest, NvWriteFailsGivenIndexUndefined) {
228   Prng my_prng;
229   Epid2ParamsObj epid2params;
230   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
231   uint32_t nv_index = 0x01000003;
232 
233   MembershipCredential const data = {0};
234   EXPECT_EQ(kEpidBadArgErr, Tpm2NvWrite(tpm, nv_index, 1, 0, &data));
235 }
236 
237 //////////////////////////////////////////////////////////////////////////
238 // Tpm2NvRead Tests
TEST(NvTest,NvReadFailsGivenNullParameters)239 TEST(NvTest, NvReadFailsGivenNullParameters) {
240   Prng my_prng;
241   Epid2ParamsObj epid2params;
242   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
243   uint32_t nv_index = 0x01000000;
244   THROW_ON_EPIDERR(
245       Tpm2NvDefineSpace(tpm, nv_index, sizeof(MembershipCredential)));
246 
247   MembershipCredential data = {0};
248   EXPECT_EQ(kEpidBadArgErr,
249             Tpm2NvRead(nullptr, nv_index, sizeof(data), 0, &data));
250   EXPECT_EQ(kEpidBadArgErr,
251             Tpm2NvRead(tpm, nv_index, sizeof(data), 0, nullptr));
252   THROW_ON_EPIDERR(Tpm2NvUndefineSpace(tpm, nv_index));
253 }
254 
TEST(NvTest,NvReadCanRead)255 TEST(NvTest, NvReadCanRead) {
256   Prng my_prng;
257   Epid2ParamsObj epid2params;
258   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
259   uint32_t nv_index = 0x01000000;
260   std::vector<uint8_t> const data_src = {1, 2, 3, 4, 5, 6, 7, 8};
261   std::vector<uint8_t> data_dst(data_src.size());
262   THROW_ON_EPIDERR(Tpm2NvDefineSpace(tpm, nv_index, data_src.size()));
263   THROW_ON_EPIDERR(
264       Tpm2NvWrite(tpm, nv_index, data_src.size(), 0, data_src.data()));
265 
266   EXPECT_EQ(kEpidNoErr, Tpm2NvRead(tpm, nv_index, 3, 0, data_dst.data()));
267   EXPECT_EQ(kEpidNoErr, Tpm2NvRead(tpm, nv_index, data_src.size() - 3, 3,
268                                    data_dst.data() + 3));
269   THROW_ON_EPIDERR(Tpm2NvUndefineSpace(tpm, nv_index));
270   EXPECT_EQ(data_src, data_dst);
271 }
272 
TEST(NvTest,NvReadFailIfWriteWasNotCalled)273 TEST(NvTest, NvReadFailIfWriteWasNotCalled) {
274   Prng my_prng;
275   Epid2ParamsObj epid2params;
276   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
277   uint32_t nv_index = 0x01000000;
278   THROW_ON_EPIDERR(
279       Tpm2NvDefineSpace(tpm, nv_index, sizeof(MembershipCredential)));
280 
281   MembershipCredential data = {0};
282   EXPECT_EQ(kEpidBadArgErr, Tpm2NvRead(tpm, nv_index, sizeof(data), 0, &data));
283   THROW_ON_EPIDERR(Tpm2NvUndefineSpace(tpm, nv_index));
284 }
285 
TEST(NvTest,NvReadFailsGivenOverflow)286 TEST(NvTest, NvReadFailsGivenOverflow) {
287   Prng my_prng;
288   Epid2ParamsObj epid2params;
289   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
290   uint32_t nv_index = 0x01000000;
291   THROW_ON_EPIDERR(
292       Tpm2NvDefineSpace(tpm, nv_index, sizeof(MembershipCredential)));
293 
294   MembershipCredential data = {0};
295   EXPECT_EQ(kEpidBadArgErr, Tpm2NvRead(tpm, nv_index, sizeof(data), 1, &data));
296   EXPECT_EQ(kEpidBadArgErr,
297             Tpm2NvRead(tpm, nv_index, sizeof(data) + 1, 0, &data));
298   EXPECT_EQ(kEpidBadArgErr,
299             Tpm2NvRead(tpm, nv_index, 1, sizeof(MembershipCredential), &data));
300   THROW_ON_EPIDERR(Tpm2NvUndefineSpace(tpm, nv_index));
301 }
302 
TEST(NvTest,NvReadFailsGivenInvalidLength)303 TEST(NvTest, NvReadFailsGivenInvalidLength) {
304   Prng my_prng;
305   Epid2ParamsObj epid2params;
306   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
307   uint32_t nv_index = 0x01000000;
308   THROW_ON_EPIDERR(
309       Tpm2NvDefineSpace(tpm, nv_index, sizeof(MembershipCredential)));
310 
311   MembershipCredential data = {0};
312   EXPECT_EQ(kEpidBadArgErr, Tpm2NvRead(tpm, nv_index, 0, 0, &data));
313   THROW_ON_EPIDERR(Tpm2NvUndefineSpace(tpm, nv_index));
314 }
315 
TEST(NvTest,NvReadFailsGivenIndexUndefined)316 TEST(NvTest, NvReadFailsGivenIndexUndefined) {
317   Prng my_prng;
318   Epid2ParamsObj epid2params;
319   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
320   uint32_t nv_index = 0x01000003;
321 
322   MembershipCredential data = {0};
323   EXPECT_EQ(kEpidBadArgErr, Tpm2NvRead(tpm, nv_index, 1, 0, &data));
324 }
325 
326 }  // namespace
327