• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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