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(¶ms.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(¶ms.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(¶ms.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(¶ms.fq, this->kY2Sha256Str);
92 EcPointObj p2(¶ms.G1, kP2Sha256Str);
93 EcPointObj p2_exp_f(¶ms.G1, kP2Sha256ExpF);
94
95 EcPointObj k(¶ms.G1), l(¶ms.G1), e(¶ms.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(¶ms.fp), sign_s(¶ms.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(¶ms.fq, this->kY2Sha256Str);
126 EcPointObj p2(¶ms.G1, kP2Sha256Str);
127 EcPointObj p2_exp_f(¶ms.G1, kP2Sha256ExpF);
128
129 EcPointObj k1(¶ms.G1), l1(¶ms.G1), e1(¶ms.G1);
130 EcPointObj k2(¶ms.G1), l2(¶ms.G1), e2(¶ms.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(¶ms.fp), sign_s1(¶ms.fp);
142 FfElementObj sign_k2(¶ms.fp), sign_s2(¶ms.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(¶ms.G1), l(¶ms.G1), e(¶ms.G1);
159 FfElementObj sig_k(¶ms.fp), sig_s(¶ms.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(¶ms.G1), l(¶ms.G1), e(¶ms.G1);
183 FfElementObj sig_k(¶ms.fp), sig_s(¶ms.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(¶ms.G1), l(¶ms.G1), e(¶ms.G1);
207 FfElementObj sig_k(¶ms.fp), sig_s(¶ms.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(¶ms.G1), l(¶ms.G1), e(¶ms.G1);
242 FfElementObj sig_k(¶ms.fp), sig_s(¶ms.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(¶ms.G1), l(¶ms.G1), e(¶ms.G1);
264 FfElementObj sig_k(¶ms.fp), sig_s(¶ms.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(¶ms.fq, this->kY2Sha256Str);
302 EcPointObj p2(¶ms.G1, kP2Sha256Str);
303 EcPointObj p2_exp_f(¶ms.G1, kP2Sha256ExpF);
304
305 EcPointObj k(¶ms.G1), l(¶ms.G1), e(¶ms.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(¶ms.fp), sign_s(¶ms.fp);
315 EXPECT_EQ(kEpidBadArgErr,
316 Tpm2Sign(tpm, this->kDigestSha256, sizeof(this->kDigestSha256),
317 counter, sign_k, sign_s));
318 }
319
320 } // namespace
321