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 Sign unit tests.
17 /*! \file */
18 #include <climits>
19 
20 #include "gtest/gtest.h"
21 
22 #include "epid/common-testhelper/epid2params_wrapper-testhelper.h"
23 #include "epid/common-testhelper/epid_params-testhelper.h"
24 #include "epid/common-testhelper/errors-testhelper.h"
25 #include "epid/common-testhelper/prng-testhelper.h"
26 #include "epid/member/tpm2/unittests/tpm2-testhelper.h"
27 
28 extern "C" {
29 #include "epid/common/src/hashsize.h"
30 #include "epid/common/src/memory.h"
31 #include "epid/member/tpm2/commit.h"
32 #include "epid/member/tpm2/load_external.h"
33 #include "epid/member/tpm2/sign.h"
34 }
35 
36 namespace {
37 //////////////////////////////////////////////////////////////////////////
38 // Tpm2Sign Tests
39 // Verify signature computed by TPM ECDAA scheme:
40 // sign_k ?= digest mod p
41 // point^sign_s ?= random_exp * private_exp^sign_k
IsSignatureValid(void const * digest,size_t digest_len,FfElement const * sign_k,FfElement const * sign_s,EcPoint const * point,EcPoint const * private_exp,EcPoint const * random_exp,HashAlg hash_alg)42 bool IsSignatureValid(void const* digest, size_t digest_len,
43                       FfElement const* sign_k, FfElement const* sign_s,
44                       EcPoint const* point, EcPoint const* private_exp,
45                       EcPoint const* random_exp, HashAlg hash_alg) {
46   (void)hash_alg;
47 
48   Epid20Params params;
49 
50   BigNumObj digest_bn(digest_len);
51   THROW_ON_EPIDERR(ReadBigNum(digest, digest_len, digest_bn));
52   FfElementObj t(&params.fp);
53   THROW_ON_EPIDERR(InitFfElementFromBn(params.fp, digest_bn, t));
54   FpElemStr t_str, sign_k_str;
55   THROW_ON_EPIDERR(WriteFfElement(params.fp, t, &t_str, sizeof(t_str)));
56   THROW_ON_EPIDERR(
57       WriteFfElement(params.fp, sign_k, &sign_k_str, sizeof(sign_k_str)));
58   if (!(t_str == sign_k_str)) return false;
59 
60   BigNumStr exp;
61   // v1 = p2^s
62   EcPointObj v1(&params.G1);
63   THROW_ON_EPIDERR(WriteFfElement(params.fp, sign_s, &exp, sizeof(exp)));
64   THROW_ON_EPIDERR(EcExp(params.G1, point, &exp, v1));
65   // v2 = k^sign_k
66   EcPointObj v2(&params.G1);
67   THROW_ON_EPIDERR(WriteFfElement(params.fp, sign_k, &exp, sizeof(exp)));
68   THROW_ON_EPIDERR(EcExp(params.G1, private_exp, &exp, v2));
69   // v2 = l * k^digest
70   THROW_ON_EPIDERR(EcMul(params.G1, random_exp, v2, v2));
71   // v1 ?= v2
72   G1ElemStr v1_str, v2_str;
73   THROW_ON_EPIDERR(WriteEcPoint(params.G1, v1, &v1_str, sizeof(v1_str)));
74   THROW_ON_EPIDERR(WriteEcPoint(params.G1, v2, &v2_str, sizeof(v2_str)));
75   return v1_str == v2_str;
76 }
77 
TEST_F(EpidTpm2Test,SignProducesValidSignature)78 TEST_F(EpidTpm2Test, SignProducesValidSignature) {
79   Epid20Params params;
80 
81   // create TPM context
82   Prng my_prng;
83   Epid2ParamsObj epid2params;
84   FpElemStr f = this->kMemberFValue;
85   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, &f, epid2params);
86   THROW_ON_EPIDERR(Tpm2SetHashAlg(tpm, kSha256));
87   // load f value
88   EXPECT_EQ(kEpidNoErr, Tpm2LoadExternal(tpm, &f));
89 
90   // commit(P1=p2, P2=p2) => k = p2^f, l = p2^r, e = p2^r
91   FfElementObj y2(&params.fq, this->kY2Sha256Str);
92   EcPointObj p2(&params.G1, kP2Sha256Str);
93   EcPointObj p2_exp_f(&params.G1, kP2Sha256ExpF);
94 
95   EcPointObj k(&params.G1), l(&params.G1), e(&params.G1);
96   uint16_t counter = 0;
97   EXPECT_EQ(kEpidNoErr,
98             Tpm2Commit(tpm, p2, this->kS2Sha256.data(), this->kS2Sha256.size(),
99                        y2, k, l, e, &counter));
100 
101   // sign(digest) => sign_k = sign_k, sign_s = r + c * f,
102   //   where c = H(sign_k||digest)
103   FfElementObj sign_k(&params.fp), sign_s(&params.fp);
104   EXPECT_EQ(kEpidNoErr,
105             Tpm2Sign(tpm, this->kDigestSha256, sizeof(this->kDigestSha256),
106                      counter, sign_k, sign_s));
107 
108   EXPECT_TRUE(IsSignatureValid(this->kDigestSha256, sizeof(this->kDigestSha256),
109                                sign_k, sign_s, p2, k, l, kSha256));
110 }
111 
TEST_F(EpidTpm2Test,SignProducesValidSignatureTwoTimes)112 TEST_F(EpidTpm2Test, SignProducesValidSignatureTwoTimes) {
113   Epid20Params params;
114 
115   // create TPM context
116   Prng my_prng;
117   Epid2ParamsObj epid2params;
118   FpElemStr f = this->kMemberFValue;
119   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, &f, epid2params);
120   THROW_ON_EPIDERR(Tpm2SetHashAlg(tpm, kSha256));
121   // load f value
122   EXPECT_EQ(kEpidNoErr, Tpm2LoadExternal(tpm, &f));
123 
124   // commit(P1=p2, P2=p2) => k = p2^f, l = p2^r, e = p2^r
125   FfElementObj y2(&params.fq, this->kY2Sha256Str);
126   EcPointObj p2(&params.G1, kP2Sha256Str);
127   EcPointObj p2_exp_f(&params.G1, kP2Sha256ExpF);
128 
129   EcPointObj k1(&params.G1), l1(&params.G1), e1(&params.G1);
130   EcPointObj k2(&params.G1), l2(&params.G1), e2(&params.G1);
131   uint16_t ctr1 = 0, ctr2 = 0;
132   EXPECT_EQ(kEpidNoErr,
133             Tpm2Commit(tpm, p2, this->kS2Sha256.data(), this->kS2Sha256.size(),
134                        y2, k1, l1, e1, &ctr1));
135   EXPECT_EQ(kEpidNoErr,
136             Tpm2Commit(tpm, p2, this->kS2Sha256.data(), this->kS2Sha256.size(),
137                        y2, k2, l2, e2, &ctr2));
138 
139   // sign(digest) => sign_k = sign_k, sign_s = r + c * f,
140   //   where c = H(sign_k||digest)
141   FfElementObj sign_k1(&params.fp), sign_s1(&params.fp);
142   FfElementObj sign_k2(&params.fp), sign_s2(&params.fp);
143   EXPECT_EQ(kEpidNoErr,
144             Tpm2Sign(tpm, this->kDigestSha256, sizeof(this->kDigestSha256),
145                      ctr1, sign_k1, sign_s1));
146   EXPECT_EQ(kEpidNoErr,
147             Tpm2Sign(tpm, this->kDigestSha256, sizeof(this->kDigestSha256),
148                      ctr2, sign_k2, sign_s2));
149 
150   EXPECT_TRUE(IsSignatureValid(this->kDigestSha256, sizeof(this->kDigestSha256),
151                                sign_k1, sign_s1, p2, k1, l1, kSha256));
152   EXPECT_TRUE(IsSignatureValid(this->kDigestSha256, sizeof(this->kDigestSha256),
153                                sign_k2, sign_s2, p2, k2, l2, kSha256));
154 }
155 
TEST_F(EpidTpm2Test,SignFailsGivenNullParameters)156 TEST_F(EpidTpm2Test, SignFailsGivenNullParameters) {
157   Epid20Params params;
158   EcPointObj k(&params.G1), l(&params.G1), e(&params.G1);
159   FfElementObj sig_k(&params.fp), sig_s(&params.fp);
160   uint16_t counter = 0;
161 
162   Prng my_prng;
163   Epid2ParamsObj epid2params;
164   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, &this->kMemberFValue, epid2params);
165   THROW_ON_EPIDERR(Tpm2SetHashAlg(tpm, kSha256));
166   THROW_ON_EPIDERR(Tpm2LoadExternal(tpm, &this->kMemberFValue));
167   THROW_ON_EPIDERR(
168       Tpm2Commit(tpm, nullptr, nullptr, 0, nullptr, k, l, e, &counter));
169 
170   EXPECT_EQ(kEpidBadArgErr,
171             Tpm2Sign(nullptr, this->kDigestSha256, sizeof(this->kDigestSha256),
172                      counter, sig_k, sig_s));
173   EXPECT_EQ(kEpidBadArgErr, Tpm2Sign(tpm, nullptr, sizeof(this->kDigestSha256),
174                                      counter, sig_k, sig_s));
175   EXPECT_EQ(kEpidBadArgErr,
176             Tpm2Sign(tpm, this->kDigestSha256, sizeof(this->kDigestSha256),
177                      counter, sig_k, nullptr));
178 }
179 
TEST_F(EpidTpm2Test,SignFailsGivenInvalidDigestLen)180 TEST_F(EpidTpm2Test, SignFailsGivenInvalidDigestLen) {
181   Epid20Params params;
182   EcPointObj k(&params.G1), l(&params.G1), e(&params.G1);
183   FfElementObj sig_k(&params.fp), sig_s(&params.fp);
184   uint16_t counter = 0;
185 
186   Prng my_prng;
187   Epid2ParamsObj epid2params;
188   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, &this->kMemberFValue, epid2params);
189   THROW_ON_EPIDERR(Tpm2SetHashAlg(tpm, kSha256));
190   THROW_ON_EPIDERR(Tpm2LoadExternal(tpm, &this->kMemberFValue));
191   THROW_ON_EPIDERR(
192       Tpm2Commit(tpm, nullptr, nullptr, 0, nullptr, k, l, e, &counter));
193 
194   uint8_t digest[EPID_SHA256_DIGEST_BITSIZE / CHAR_BIT + 1] = {0};
195   EXPECT_EQ(kEpidBadArgErr, Tpm2Sign(tpm, digest, 0, counter, sig_k, sig_s));
196   EXPECT_EQ(kEpidBadArgErr,
197             Tpm2Sign(tpm, digest, EPID_SHA256_DIGEST_BITSIZE / CHAR_BIT + 1,
198                      counter, sig_k, sig_s));
199   EXPECT_EQ(kEpidBadArgErr,
200             Tpm2Sign(tpm, digest, EPID_SHA256_DIGEST_BITSIZE / CHAR_BIT - 1,
201                      counter, sig_k, sig_s));
202 }
203 
TEST_F(EpidTpm2Test,SignFailsGivenUnrecognizedCounter)204 TEST_F(EpidTpm2Test, SignFailsGivenUnrecognizedCounter) {
205   Epid20Params params;
206   EcPointObj k(&params.G1), l(&params.G1), e(&params.G1);
207   FfElementObj sig_k(&params.fp), sig_s(&params.fp);
208   uint16_t counter = 0;
209   uint16_t zero = 0;
210   uint16_t one = 1;
211   uint16_t minus_one = (uint16_t)-1;
212 
213   Prng my_prng;
214   Epid2ParamsObj epid2params;
215   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, &this->kMemberFValue, epid2params);
216   THROW_ON_EPIDERR(Tpm2SetHashAlg(tpm, kSha256));
217   THROW_ON_EPIDERR(Tpm2LoadExternal(tpm, &this->kMemberFValue));
218 
219   EXPECT_EQ(kEpidBadArgErr,
220             Tpm2Sign(tpm, this->kDigestSha256, sizeof(this->kDigestSha256),
221                      zero, sig_k, sig_s));
222   EXPECT_EQ(kEpidBadArgErr,
223             Tpm2Sign(tpm, this->kDigestSha256, sizeof(this->kDigestSha256), one,
224                      sig_k, sig_s));
225   EXPECT_EQ(kEpidBadArgErr,
226             Tpm2Sign(tpm, this->kDigestSha256, sizeof(this->kDigestSha256),
227                      minus_one, sig_k, sig_s));
228 
229   THROW_ON_EPIDERR(
230       Tpm2Commit(tpm, nullptr, nullptr, 0, nullptr, k, l, e, &counter));
231 
232   uint16_t counter_plus_1 = counter + 1;
233   EXPECT_EQ(kEpidBadArgErr,
234             Tpm2Sign(tpm, this->kDigestSha256, sizeof(this->kDigestSha256),
235                      counter_plus_1, sig_k, sig_s));
236   THROW_ON_EPIDERR(Tpm2ReleaseCounter(tpm, counter));
237 }
238 
TEST_F(EpidTpm2Test,SignFailsGivenPreviouslyUsedCounter)239 TEST_F(EpidTpm2Test, SignFailsGivenPreviouslyUsedCounter) {
240   Epid20Params params;
241   EcPointObj k(&params.G1), l(&params.G1), e(&params.G1);
242   FfElementObj sig_k(&params.fp), sig_s(&params.fp);
243   uint16_t counter = 0;
244 
245   Prng my_prng;
246   Epid2ParamsObj epid2params;
247   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, &this->kMemberFValue, epid2params);
248   THROW_ON_EPIDERR(Tpm2SetHashAlg(tpm, kSha256));
249   THROW_ON_EPIDERR(Tpm2LoadExternal(tpm, &this->kMemberFValue));
250   THROW_ON_EPIDERR(
251       Tpm2Commit(tpm, nullptr, nullptr, 0, nullptr, k, l, e, &counter));
252 
253   EXPECT_EQ(kEpidNoErr,
254             Tpm2Sign(tpm, this->kDigestSha256, sizeof(this->kDigestSha256),
255                      counter, sig_k, sig_s));
256   EXPECT_EQ(kEpidBadArgErr,
257             Tpm2Sign(tpm, this->kDigestSha256, sizeof(this->kDigestSha256),
258                      counter, sig_k, sig_s));
259 }
260 
TEST_F(EpidTpm2Test,SignFailsIfKeyNotSet)261 TEST_F(EpidTpm2Test, SignFailsIfKeyNotSet) {
262   Epid20Params params;
263   EcPointObj k(&params.G1), l(&params.G1), e(&params.G1);
264   FfElementObj sig_k(&params.fp), sig_s(&params.fp);
265   uint16_t counter = 0;
266 
267   Prng my_prng;
268   Epid2ParamsObj epid2params;
269   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, nullptr, epid2params);
270 
271   EXPECT_EQ(kEpidBadArgErr,
272             Tpm2Sign(tpm, this->kDigestSha256, sizeof(this->kDigestSha256),
273                      counter, sig_k, sig_s));
274 }
275 
276 //////////////////////////////////////////////////////////////////////////
277 // Tpm2ReleaseCounter Tests
TEST_F(EpidTpm2Test,ReleaseCounterFailsGivenNullPtr)278 TEST_F(EpidTpm2Test, ReleaseCounterFailsGivenNullPtr) {
279   // create TPM context
280   Prng my_prng;
281   Epid2ParamsObj epid2params;
282   FpElemStr f = this->kMemberFValue;
283   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, &f, epid2params);
284   uint16_t ctr = 0;
285 
286   EXPECT_EQ(kEpidBadArgErr, Tpm2ReleaseCounter(nullptr, ctr));
287 }
TEST_F(EpidTpm2Test,ReleaseCounterSuccessfullyReleasesCounter)288 TEST_F(EpidTpm2Test, ReleaseCounterSuccessfullyReleasesCounter) {
289   Epid20Params params;
290 
291   // create TPM context
292   Prng my_prng;
293   Epid2ParamsObj epid2params;
294   FpElemStr f = this->kMemberFValue;
295   Tpm2CtxObj tpm(&Prng::Generate, &my_prng, &f, epid2params);
296   THROW_ON_EPIDERR(Tpm2SetHashAlg(tpm, kSha256));
297   // load f value
298   EXPECT_EQ(kEpidNoErr, Tpm2LoadExternal(tpm, &f));
299 
300   // commit(P1=p2, P2=p2) => k = p2^f, l = p2^r, e = p2^r
301   FfElementObj y2(&params.fq, this->kY2Sha256Str);
302   EcPointObj p2(&params.G1, kP2Sha256Str);
303   EcPointObj p2_exp_f(&params.G1, kP2Sha256ExpF);
304 
305   EcPointObj k(&params.G1), l(&params.G1), e(&params.G1);
306   uint16_t counter = 0;
307   EXPECT_EQ(kEpidNoErr,
308             Tpm2Commit(tpm, p2, this->kS2Sha256.data(), this->kS2Sha256.size(),
309                        y2, k, l, e, &counter));
310   EXPECT_EQ(kEpidNoErr, Tpm2ReleaseCounter(tpm, counter));
311 
312   // sign(digest) => sign_k = sign_k, sign_s = r + c * f,
313   //   where c = H(sign_k||digest)
314   FfElementObj sign_k(&params.fp), sign_s(&params.fp);
315   EXPECT_EQ(kEpidBadArgErr,
316             Tpm2Sign(tpm, this->kDigestSha256, sizeof(this->kDigestSha256),
317                      counter, sign_k, sign_s));
318 }
319 
320 }  // namespace
321