1 /*
2 * Copyright (C) 2015 The Android Open Source Project
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 #include <gtest/gtest.h>
18
19 #include <endian.h>
20 #include <keymaster/logger.h>
21
22 #include "../auth_token_table.h"
23
24 using std::vector;
25
26 namespace keystore {
27 namespace test {
28
29 class StdoutLogger : public ::keymaster::Logger {
30 public:
StdoutLogger()31 StdoutLogger() { set_instance(this); }
32
log_msg(LogLevel level,const char * fmt,va_list args) const33 int log_msg(LogLevel level, const char* fmt, va_list args) const {
34 int output_len = 0;
35 switch (level) {
36 case DEBUG_LVL:
37 output_len = printf("DEBUG: ");
38 break;
39 case INFO_LVL:
40 output_len = printf("INFO: ");
41 break;
42 case WARNING_LVL:
43 output_len = printf("WARNING: ");
44 break;
45 case ERROR_LVL:
46 output_len = printf("ERROR: ");
47 break;
48 case SEVERE_LVL:
49 output_len = printf("SEVERE: ");
50 break;
51 }
52
53 output_len += vprintf(fmt, args);
54 output_len += printf("\n");
55 return output_len;
56 }
57 };
58
59 StdoutLogger logger;
60
TEST(AuthTokenTableTest,Create)61 TEST(AuthTokenTableTest, Create) {
62 AuthTokenTable table;
63 }
64
make_token(uint64_t rsid,uint64_t ssid=0,uint64_t challenge=0,uint64_t timestamp=0)65 static HardwareAuthToken make_token(uint64_t rsid, uint64_t ssid = 0, uint64_t challenge = 0,
66 uint64_t timestamp = 0) {
67 HardwareAuthToken token;
68 token.userId = rsid;
69 token.authenticatorId = ssid;
70 token.authenticatorType = HardwareAuthenticatorType::PASSWORD;
71 token.challenge = challenge;
72 token.timestamp = timestamp;
73 return token;
74 }
75
make_set(uint64_t rsid,uint32_t timeout=10000)76 static AuthorizationSet make_set(uint64_t rsid, uint32_t timeout = 10000) {
77 AuthorizationSetBuilder builder;
78 builder.Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD)
79 .Authorization(TAG_USER_SECURE_ID, rsid);
80 // Use timeout == 0 to indicate tags that require auth per operation.
81 if (timeout != 0) builder.Authorization(TAG_AUTH_TIMEOUT, timeout);
82 return std::move(builder);
83 }
84
85 // Tests obviously run so fast that a real-time clock with a one-second granularity rarely changes
86 // output during a test run. This test clock "ticks" one second every time it's called.
monotonic_clock()87 static time_t monotonic_clock() {
88 static time_t time = 0;
89 return time++;
90 }
91
TEST(AuthTokenTableTest,SimpleAddAndFindTokens)92 TEST(AuthTokenTableTest, SimpleAddAndFindTokens) {
93 AuthTokenTable table;
94
95 table.AddAuthenticationToken(make_token(1, 2));
96 table.AddAuthenticationToken(make_token(3, 4));
97 EXPECT_EQ(2U, table.size());
98
99 AuthTokenTable::Error rc;
100 HardwareAuthToken found;
101
102 ASSERT_EQ(
103 AuthTokenTable::OK,
104 (std::tie(rc, found) = table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0), rc));
105 EXPECT_EQ(1U, found.userId);
106 EXPECT_EQ(2U, found.authenticatorId);
107
108 ASSERT_EQ(
109 AuthTokenTable::OK,
110 (std::tie(rc, found) = table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0), rc));
111 EXPECT_EQ(1U, found.userId);
112 EXPECT_EQ(2U, found.authenticatorId);
113
114 ASSERT_EQ(
115 AuthTokenTable::OK,
116 (std::tie(rc, found) = table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0), rc));
117 EXPECT_EQ(3U, found.userId);
118 EXPECT_EQ(4U, found.authenticatorId);
119
120 ASSERT_EQ(
121 AuthTokenTable::OK,
122 (std::tie(rc, found) = table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0), rc));
123 EXPECT_EQ(3U, found.userId);
124 EXPECT_EQ(4U, found.authenticatorId);
125
126 ASSERT_EQ(
127 AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
128 (std::tie(rc, found) = table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0), rc));
129 }
130
TEST(AuthTokenTableTest,FlushTable)131 TEST(AuthTokenTableTest, FlushTable) {
132 AuthTokenTable table(3, monotonic_clock);
133
134 table.AddAuthenticationToken(make_token(1));
135 table.AddAuthenticationToken(make_token(2));
136 table.AddAuthenticationToken(make_token(3));
137
138 AuthTokenTable::Error rc;
139 HardwareAuthToken found;
140
141 // All three should be in the table.
142 EXPECT_EQ(3U, table.size());
143 EXPECT_EQ(
144 AuthTokenTable::OK,
145 (std::tie(rc, found) = table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0), rc));
146 EXPECT_EQ(
147 AuthTokenTable::OK,
148 (std::tie(rc, found) = table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0), rc));
149 EXPECT_EQ(
150 AuthTokenTable::OK,
151 (std::tie(rc, found) = table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0), rc));
152
153 table.Clear();
154 EXPECT_EQ(0U, table.size());
155 }
156
TEST(AuthTokenTableTest,TableOverflow)157 TEST(AuthTokenTableTest, TableOverflow) {
158 AuthTokenTable table(3, monotonic_clock);
159
160 table.AddAuthenticationToken(make_token(1));
161 table.AddAuthenticationToken(make_token(2));
162 table.AddAuthenticationToken(make_token(3));
163
164 AuthTokenTable::Error rc;
165 HardwareAuthToken found;
166
167 // All three should be in the table.
168 EXPECT_EQ(3U, table.size());
169 EXPECT_EQ(
170 AuthTokenTable::OK,
171 (std::tie(rc, found) = table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0), rc));
172 EXPECT_EQ(
173 AuthTokenTable::OK,
174 (std::tie(rc, found) = table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0), rc));
175 EXPECT_EQ(
176 AuthTokenTable::OK,
177 (std::tie(rc, found) = table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0), rc));
178
179 table.AddAuthenticationToken(make_token(4));
180
181 // Oldest should be gone.
182 EXPECT_EQ(3U, table.size());
183 EXPECT_EQ(
184 AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
185 (std::tie(rc, found) = table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0), rc));
186
187 // Others should be there, including the new one (4). Search for it first, then the others, so
188 // 4 becomes the least recently used.
189 EXPECT_EQ(
190 AuthTokenTable::OK,
191 (std::tie(rc, found) = table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0), rc));
192 EXPECT_EQ(
193 AuthTokenTable::OK,
194 (std::tie(rc, found) = table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0), rc));
195 EXPECT_EQ(
196 AuthTokenTable::OK,
197 (std::tie(rc, found) = table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0), rc));
198
199 table.AddAuthenticationToken(make_token(5));
200
201 // 5 should have replaced 4.
202 EXPECT_EQ(3U, table.size());
203 EXPECT_EQ(
204 AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
205 (std::tie(rc, found) = table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0), rc));
206 EXPECT_EQ(
207 AuthTokenTable::OK,
208 (std::tie(rc, found) = table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0), rc));
209 EXPECT_EQ(
210 AuthTokenTable::OK,
211 (std::tie(rc, found) = table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0), rc));
212 EXPECT_EQ(
213 AuthTokenTable::OK,
214 (std::tie(rc, found) = table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0), rc));
215
216 table.AddAuthenticationToken(make_token(6));
217 table.AddAuthenticationToken(make_token(7));
218
219 // 2 and 5 should be gone
220 EXPECT_EQ(3U, table.size());
221 EXPECT_EQ(
222 AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
223 (std::tie(rc, found) = table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0), rc));
224 EXPECT_EQ(
225 AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
226 (std::tie(rc, found) = table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0), rc));
227 EXPECT_EQ(
228 AuthTokenTable::OK,
229 (std::tie(rc, found) = table.FindAuthorization(make_set(6), KeyPurpose::SIGN, 0), rc));
230 EXPECT_EQ(
231 AuthTokenTable::OK,
232 (std::tie(rc, found) = table.FindAuthorization(make_set(7), KeyPurpose::SIGN, 0), rc));
233 EXPECT_EQ(
234 AuthTokenTable::OK,
235 (std::tie(rc, found) = table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0), rc));
236
237 table.AddAuthenticationToken(make_token(8));
238 table.AddAuthenticationToken(make_token(9));
239 table.AddAuthenticationToken(make_token(10));
240
241 // Only the three most recent should be there.
242 EXPECT_EQ(3U, table.size());
243 EXPECT_EQ(
244 AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
245 (std::tie(rc, found) = table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0), rc));
246 EXPECT_EQ(
247 AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
248 (std::tie(rc, found) = table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0), rc));
249 EXPECT_EQ(
250 AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
251 (std::tie(rc, found) = table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0), rc));
252 EXPECT_EQ(
253 AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
254 (std::tie(rc, found) = table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0), rc));
255 EXPECT_EQ(
256 AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
257 (std::tie(rc, found) = table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0), rc));
258 EXPECT_EQ(
259 AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
260 (std::tie(rc, found) = table.FindAuthorization(make_set(6), KeyPurpose::SIGN, 0), rc));
261 EXPECT_EQ(
262 AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
263 (std::tie(rc, found) = table.FindAuthorization(make_set(7), KeyPurpose::SIGN, 0), rc));
264 EXPECT_EQ(
265 AuthTokenTable::OK,
266 (std::tie(rc, found) = table.FindAuthorization(make_set(8), KeyPurpose::SIGN, 0), rc));
267 EXPECT_EQ(
268 AuthTokenTable::OK,
269 (std::tie(rc, found) = table.FindAuthorization(make_set(9), KeyPurpose::SIGN, 0), rc));
270 EXPECT_EQ(
271 AuthTokenTable::OK,
272 (std::tie(rc, found) = table.FindAuthorization(make_set(10), KeyPurpose::SIGN, 0), rc));
273 }
274
TEST(AuthTokenTableTest,AuthenticationNotRequired)275 TEST(AuthTokenTableTest, AuthenticationNotRequired) {
276 AuthTokenTable table;
277 AuthTokenTable::Error rc;
278 HardwareAuthToken found;
279
280 EXPECT_EQ(AuthTokenTable::AUTH_NOT_REQUIRED,
281 (std::tie(rc, found) = table.FindAuthorization(
282 AuthorizationSetBuilder().Authorization(TAG_NO_AUTH_REQUIRED), KeyPurpose::SIGN,
283 0 /* no challenge */),
284 rc));
285 }
286
TEST(AuthTokenTableTest,OperationHandleNotFound)287 TEST(AuthTokenTableTest, OperationHandleNotFound) {
288 AuthTokenTable table;
289 AuthTokenTable::Error rc;
290 HardwareAuthToken found;
291
292 table.AddAuthenticationToken(make_token(1, 0, 1, 5));
293 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
294 (std::tie(rc, found) =
295 table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
296 2 /* non-matching challenge */),
297 rc));
298 EXPECT_EQ(AuthTokenTable::OK,
299 (std::tie(rc, found) = table.FindAuthorization(
300 make_set(1, 0 /* no timeout */), KeyPurpose::SIGN, 1 /* matching challenge */),
301 rc));
302 table.MarkCompleted(1);
303 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
304 (std::tie(rc, found) = table.FindAuthorization(
305 make_set(1, 0 /* no timeout */), KeyPurpose::SIGN, 1 /* used challenge */),
306 rc));
307 }
308
TEST(AuthTokenTableTest,OperationHandleRequired)309 TEST(AuthTokenTableTest, OperationHandleRequired) {
310 AuthTokenTable table;
311 AuthTokenTable::Error rc;
312 HardwareAuthToken found;
313
314 table.AddAuthenticationToken(make_token(1));
315 EXPECT_EQ(AuthTokenTable::OP_HANDLE_REQUIRED,
316 (std::tie(rc, found) = table.FindAuthorization(
317 make_set(1, 0 /* no timeout */), KeyPurpose::SIGN, 0 /* no op handle */),
318 rc));
319 }
320
TEST(AuthTokenTableTest,AuthSidChanged)321 TEST(AuthTokenTableTest, AuthSidChanged) {
322 AuthTokenTable table;
323 AuthTokenTable::Error rc;
324 HardwareAuthToken found;
325
326 table.AddAuthenticationToken(make_token(1, 3, /* op handle */ 1));
327 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_WRONG_SID,
328 (std::tie(rc, found) = table.FindAuthorization(make_set(2, 0 /* no timeout */),
329 KeyPurpose::SIGN, 1 /* op handle */),
330 rc));
331 }
332
TEST(AuthTokenTableTest,TokenExpired)333 TEST(AuthTokenTableTest, TokenExpired) {
334 AuthTokenTable table(5, monotonic_clock);
335 AuthTokenTable::Error rc;
336 HardwareAuthToken found;
337
338 auto key_info = make_set(1, 5 /* five second timeout */);
339
340 // monotonic_clock "ticks" one second each time it's called, which is once per request, so the
341 // sixth request should fail, since key_info says the key is good for five seconds.
342 //
343 // Note that this tests the decision of the AuthTokenTable to reject a request it knows is
344 // expired. An additional check of the secure timestamp (in the token) will be made by
345 // keymaster when the found token is passed to it.
346 table.AddAuthenticationToken(make_token(1, 0));
347 EXPECT_EQ(AuthTokenTable::OK, (std::tie(rc, found) = table.FindAuthorization(
348 key_info, KeyPurpose::SIGN, 0 /* no op handle */),
349 rc));
350 EXPECT_EQ(AuthTokenTable::OK, (std::tie(rc, found) = table.FindAuthorization(
351 key_info, KeyPurpose::SIGN, 0 /* no op handle */),
352 rc));
353 EXPECT_EQ(AuthTokenTable::OK, (std::tie(rc, found) = table.FindAuthorization(
354 key_info, KeyPurpose::SIGN, 0 /* no op handle */),
355 rc));
356 EXPECT_EQ(AuthTokenTable::OK, (std::tie(rc, found) = table.FindAuthorization(
357 key_info, KeyPurpose::SIGN, 0 /* no op handle */),
358 rc));
359 EXPECT_EQ(AuthTokenTable::OK, (std::tie(rc, found) = table.FindAuthorization(
360 key_info, KeyPurpose::SIGN, 0 /* no op handle */),
361 rc));
362 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_EXPIRED,
363 (std::tie(rc, found) =
364 table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */),
365 rc));
366 }
367
TEST(AuthTokenTableTest,MarkNonexistentEntryCompleted)368 TEST(AuthTokenTableTest, MarkNonexistentEntryCompleted) {
369 AuthTokenTable table;
370 // Marking a nonexistent entry completed is ignored. This test is mainly for code coverage.
371 table.MarkCompleted(1);
372 }
373
TEST(AuthTokenTableTest,SupersededEntries)374 TEST(AuthTokenTableTest, SupersededEntries) {
375 AuthTokenTable table;
376 AuthTokenTable::Error rc;
377 HardwareAuthToken found;
378
379 // Add two identical tokens, without challenges. The second should supersede the first, based
380 // on timestamp (fourth arg to make_token).
381 table.AddAuthenticationToken(make_token(1, 0, 0, 0));
382 table.AddAuthenticationToken(make_token(1, 0, 0, 1));
383 EXPECT_EQ(1U, table.size());
384 EXPECT_EQ(
385 AuthTokenTable::OK,
386 (std::tie(rc, found) = table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0), rc));
387 EXPECT_EQ(1U, found.timestamp);
388
389 // Add a third token, this with a different RSID. It should not be superseded.
390 table.AddAuthenticationToken(make_token(2, 0, 0, 2));
391 EXPECT_EQ(2U, table.size());
392
393 // Add two more, superseding each of the two in the table.
394 table.AddAuthenticationToken(make_token(1, 0, 0, 3));
395 table.AddAuthenticationToken(make_token(2, 0, 0, 4));
396 EXPECT_EQ(2U, table.size());
397 EXPECT_EQ(
398 AuthTokenTable::OK,
399 (std::tie(rc, found) = table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0), rc));
400 EXPECT_EQ(3U, found.timestamp);
401 EXPECT_EQ(
402 AuthTokenTable::OK,
403 (std::tie(rc, found) = table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0), rc));
404 EXPECT_EQ(4U, found.timestamp);
405
406 // Add another, this one with a challenge value. It should supersede the old one since it is
407 // newer, and matches other than the challenge.
408 table.AddAuthenticationToken(make_token(1, 0, 1, 5));
409 EXPECT_EQ(2U, table.size());
410
411 // And another, also with a challenge. Because of the challenge values, the one just added
412 // cannot be superseded.
413 table.AddAuthenticationToken(make_token(1, 0, 2, 6));
414 EXPECT_EQ(3U, table.size());
415
416 // Should be able to find each of them, by specifying their challenge, with a key that is not
417 // timed (timed keys don't care about challenges).
418 EXPECT_EQ(AuthTokenTable::OK,
419 (std::tie(rc, found) = table.FindAuthorization(make_set(1, 0 /* no timeout*/),
420 KeyPurpose::SIGN, 1 /* challenge */),
421 rc));
422 EXPECT_EQ(5U, found.timestamp);
423 EXPECT_EQ(AuthTokenTable::OK,
424 (std::tie(rc, found) = table.FindAuthorization(make_set(1, 0 /* no timeout */),
425 KeyPurpose::SIGN, 2 /* challenge */),
426 rc));
427 EXPECT_EQ(6U, found.timestamp);
428
429 // Add another, without a challenge, and the same timestamp as the last one. This new one
430 // actually could be considered already-superseded, but the table doesn't handle that case,
431 // since it seems unlikely to occur in practice.
432 table.AddAuthenticationToken(make_token(1, 0, 0, 6));
433 EXPECT_EQ(4U, table.size());
434 EXPECT_EQ(AuthTokenTable::OK, (std::tie(rc, found) = table.FindAuthorization(
435 make_set(1), KeyPurpose::SIGN, 0 /* challenge */),
436 rc));
437 EXPECT_EQ(6U, found.timestamp);
438
439 // Add another without a challenge but an increased timestamp. This should supersede the
440 // previous challenge-free entry.
441 table.AddAuthenticationToken(make_token(1, 0, 0, 7));
442 EXPECT_EQ(4U, table.size());
443 EXPECT_EQ(AuthTokenTable::OK,
444 (std::tie(rc, found) = table.FindAuthorization(make_set(1, 0 /* no timeout */),
445 KeyPurpose::SIGN, 2 /* challenge */),
446 rc));
447 EXPECT_EQ(6U, found.timestamp);
448 EXPECT_EQ(AuthTokenTable::OK, (std::tie(rc, found) = table.FindAuthorization(
449 make_set(1), KeyPurpose::SIGN, 0 /* challenge */),
450 rc));
451 EXPECT_EQ(7U, found.timestamp);
452
453 // Mark the entry with challenge 2 as complete. Since there's a newer challenge-free entry, the
454 // challenge entry will be superseded.
455 table.MarkCompleted(2);
456 EXPECT_EQ(3U, table.size());
457 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
458 (std::tie(rc, found) = table.FindAuthorization(make_set(1, 0 /* no timeout */),
459 KeyPurpose::SIGN, 2 /* challenge */),
460 rc));
461 EXPECT_EQ(AuthTokenTable::OK, (std::tie(rc, found) = table.FindAuthorization(
462 make_set(1), KeyPurpose::SIGN, 0 /* challenge */),
463 rc));
464 EXPECT_EQ(7U, found.timestamp);
465
466 // Add another SID 1 entry with a challenge. It supersedes the previous SID 1 entry with
467 // no challenge (timestamp 7), but not the one with challenge 1 (timestamp 5).
468 table.AddAuthenticationToken(make_token(1, 0, 3, 8));
469 EXPECT_EQ(3U, table.size());
470
471 EXPECT_EQ(AuthTokenTable::OK,
472 (std::tie(rc, found) = table.FindAuthorization(make_set(1, 0 /* no timeout */),
473 KeyPurpose::SIGN, 1 /* challenge */),
474 rc));
475 EXPECT_EQ(5U, found.timestamp);
476
477 EXPECT_EQ(AuthTokenTable::OK,
478 (std::tie(rc, found) = table.FindAuthorization(make_set(1, 0 /* no timeout */),
479 KeyPurpose::SIGN, 3 /* challenge */),
480 rc));
481 EXPECT_EQ(8U, found.timestamp);
482
483 // SID 2 entry is still there.
484 EXPECT_EQ(AuthTokenTable::OK, (std::tie(rc, found) = table.FindAuthorization(
485 make_set(2), KeyPurpose::SIGN, 0 /* challenge */),
486 rc));
487 EXPECT_EQ(4U, found.timestamp);
488
489 // Mark the entry with challenge 3 as complete. Since the older challenge 1 entry is
490 // incomplete, nothing is superseded.
491 table.MarkCompleted(3);
492 EXPECT_EQ(3U, table.size());
493
494 EXPECT_EQ(AuthTokenTable::OK,
495 (std::tie(rc, found) = table.FindAuthorization(make_set(1, 0 /* no timeout */),
496 KeyPurpose::SIGN, 1 /* challenge */),
497 rc));
498 EXPECT_EQ(5U, found.timestamp);
499
500 EXPECT_EQ(AuthTokenTable::OK, (std::tie(rc, found) = table.FindAuthorization(
501 make_set(1), KeyPurpose::SIGN, 0 /* challenge */),
502 rc));
503 EXPECT_EQ(8U, found.timestamp);
504
505 // Mark the entry with challenge 1 as complete. Since there's a newer one (with challenge 3,
506 // completed), the challenge 1 entry is superseded and removed.
507 table.MarkCompleted(1);
508 EXPECT_EQ(2U, table.size());
509 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
510 (std::tie(rc, found) = table.FindAuthorization(make_set(1, 0 /* no timeout */),
511 KeyPurpose::SIGN, 1 /* challenge */),
512 rc));
513 EXPECT_EQ(AuthTokenTable::OK, (std::tie(rc, found) = table.FindAuthorization(
514 make_set(1), KeyPurpose::SIGN, 0 /* challenge */),
515 rc));
516 EXPECT_EQ(8U, found.timestamp);
517 }
518
519 } // namespace test
520 } // namespace keystore
521