blob: 511a78dbb4b050f21add41f24d4f89e1dcc1fe66 [file] [log] [blame]
Shawn Willden489dfe12015-03-17 10:13:27 -06001/*
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
Janis Danisevskis8f737ad2017-11-21 12:30:15 -080019#include <endian.h>
Shawn Willden489dfe12015-03-17 10:13:27 -060020#include <keymaster/logger.h>
21
22#include "../auth_token_table.h"
23
24using std::vector;
25
Janis Danisevskis8f737ad2017-11-21 12:30:15 -080026namespace keystore {
Shawn Willden489dfe12015-03-17 10:13:27 -060027namespace test {
28
Shawn Willden0329a822017-12-04 13:55:14 -070029class StdoutLogger : public ::keymaster::Logger {
Shawn Willden489dfe12015-03-17 10:13:27 -060030 public:
31 StdoutLogger() { set_instance(this); }
32
33 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
59StdoutLogger logger;
60
61TEST(AuthTokenTableTest, Create) {
62 AuthTokenTable table;
63}
64
Shawn Willdenbb22a6c2017-12-06 19:35:28 -070065static HardwareAuthToken make_token(uint64_t rsid, uint64_t ssid = 0, uint64_t challenge = 0,
66 uint64_t timestamp = 0) {
Shawn Willden0329a822017-12-04 13:55:14 -070067 HardwareAuthToken token;
68 token.userId = rsid;
69 token.authenticatorId = ssid;
70 token.authenticatorType = HardwareAuthenticatorType::PASSWORD;
71 token.challenge = challenge;
72 token.timestamp = timestamp;
Shawn Willden489dfe12015-03-17 10:13:27 -060073 return token;
74}
75
76static AuthorizationSet make_set(uint64_t rsid, uint32_t timeout = 10000) {
77 AuthorizationSetBuilder builder;
Shawn Willden0329a822017-12-04 13:55:14 -070078 builder.Authorization(TAG_USER_AUTH_TYPE, HardwareAuthenticatorType::PASSWORD)
Shawn Willden489dfe12015-03-17 10:13:27 -060079 .Authorization(TAG_USER_SECURE_ID, rsid);
80 // Use timeout == 0 to indicate tags that require auth per operation.
Shawn Willden0329a822017-12-04 13:55:14 -070081 if (timeout != 0) builder.Authorization(TAG_AUTH_TIMEOUT, timeout);
Janis Danisevskis8f737ad2017-11-21 12:30:15 -080082 return builder;
Shawn Willden489dfe12015-03-17 10:13:27 -060083}
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.
87static time_t monotonic_clock() {
88 static time_t time = 0;
89 return time++;
90}
91
92TEST(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
Janis Danisevskis8f737ad2017-11-21 12:30:15 -080099 const HardwareAuthToken* found;
Shawn Willden489dfe12015-03-17 10:13:27 -0600100
Shawn Willden0329a822017-12-04 13:55:14 -0700101 ASSERT_EQ(AuthTokenTable::OK,
102 table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800103 EXPECT_EQ(1U, found->userId);
104 EXPECT_EQ(2U, found->authenticatorId);
Shawn Willden489dfe12015-03-17 10:13:27 -0600105
Shawn Willden0329a822017-12-04 13:55:14 -0700106 ASSERT_EQ(AuthTokenTable::OK,
107 table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800108 EXPECT_EQ(1U, found->userId);
109 EXPECT_EQ(2U, found->authenticatorId);
Shawn Willden489dfe12015-03-17 10:13:27 -0600110
Shawn Willden0329a822017-12-04 13:55:14 -0700111 ASSERT_EQ(AuthTokenTable::OK,
112 table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800113 EXPECT_EQ(3U, found->userId);
114 EXPECT_EQ(4U, found->authenticatorId);
Shawn Willden489dfe12015-03-17 10:13:27 -0600115
Shawn Willden0329a822017-12-04 13:55:14 -0700116 ASSERT_EQ(AuthTokenTable::OK,
117 table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0, &found));
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800118 EXPECT_EQ(3U, found->userId);
119 EXPECT_EQ(4U, found->authenticatorId);
Shawn Willden489dfe12015-03-17 10:13:27 -0600120
121 ASSERT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800122 table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600123}
124
Shawn Willden43b4ad12015-04-16 17:09:33 -0600125TEST(AuthTokenTableTest, FlushTable) {
126 AuthTokenTable table(3, monotonic_clock);
127
128 table.AddAuthenticationToken(make_token(1));
129 table.AddAuthenticationToken(make_token(2));
130 table.AddAuthenticationToken(make_token(3));
131
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800132 const HardwareAuthToken* found;
Shawn Willden43b4ad12015-04-16 17:09:33 -0600133
134 // All three should be in the table.
135 EXPECT_EQ(3U, table.size());
Shawn Willden0329a822017-12-04 13:55:14 -0700136 EXPECT_EQ(AuthTokenTable::OK,
137 table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
138 EXPECT_EQ(AuthTokenTable::OK,
139 table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
140 EXPECT_EQ(AuthTokenTable::OK,
141 table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
Shawn Willden43b4ad12015-04-16 17:09:33 -0600142
143 table.Clear();
144 EXPECT_EQ(0U, table.size());
145}
146
Shawn Willden489dfe12015-03-17 10:13:27 -0600147TEST(AuthTokenTableTest, TableOverflow) {
148 AuthTokenTable table(3, monotonic_clock);
149
150 table.AddAuthenticationToken(make_token(1));
151 table.AddAuthenticationToken(make_token(2));
152 table.AddAuthenticationToken(make_token(3));
153
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800154 const HardwareAuthToken* found;
Shawn Willden489dfe12015-03-17 10:13:27 -0600155
156 // All three should be in the table.
157 EXPECT_EQ(3U, table.size());
Shawn Willden0329a822017-12-04 13:55:14 -0700158 EXPECT_EQ(AuthTokenTable::OK,
159 table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
160 EXPECT_EQ(AuthTokenTable::OK,
161 table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
162 EXPECT_EQ(AuthTokenTable::OK,
163 table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600164
165 table.AddAuthenticationToken(make_token(4));
166
167 // Oldest should be gone.
168 EXPECT_EQ(3U, table.size());
169 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800170 table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600171
172 // Others should be there, including the new one (4). Search for it first, then the others, so
173 // 4 becomes the least recently used.
Shawn Willden0329a822017-12-04 13:55:14 -0700174 EXPECT_EQ(AuthTokenTable::OK,
175 table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0, &found));
176 EXPECT_EQ(AuthTokenTable::OK,
177 table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
178 EXPECT_EQ(AuthTokenTable::OK,
179 table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600180
181 table.AddAuthenticationToken(make_token(5));
182
183 // 5 should have replaced 4.
184 EXPECT_EQ(3U, table.size());
185 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800186 table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700187 EXPECT_EQ(AuthTokenTable::OK,
188 table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
189 EXPECT_EQ(AuthTokenTable::OK,
190 table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0, &found));
191 EXPECT_EQ(AuthTokenTable::OK,
192 table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600193
194 table.AddAuthenticationToken(make_token(6));
195 table.AddAuthenticationToken(make_token(7));
196
197 // 2 and 5 should be gone
198 EXPECT_EQ(3U, table.size());
199 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800200 table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600201 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800202 table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700203 EXPECT_EQ(AuthTokenTable::OK,
204 table.FindAuthorization(make_set(6), KeyPurpose::SIGN, 0, &found));
205 EXPECT_EQ(AuthTokenTable::OK,
206 table.FindAuthorization(make_set(7), KeyPurpose::SIGN, 0, &found));
207 EXPECT_EQ(AuthTokenTable::OK,
208 table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600209
210 table.AddAuthenticationToken(make_token(8));
211 table.AddAuthenticationToken(make_token(9));
212 table.AddAuthenticationToken(make_token(10));
213
214 // Only the three most recent should be there.
215 EXPECT_EQ(3U, table.size());
216 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800217 table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600218 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800219 table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600220 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800221 table.FindAuthorization(make_set(3), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600222 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800223 table.FindAuthorization(make_set(4), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600224 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800225 table.FindAuthorization(make_set(5), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600226 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800227 table.FindAuthorization(make_set(6), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600228 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800229 table.FindAuthorization(make_set(7), KeyPurpose::SIGN, 0, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700230 EXPECT_EQ(AuthTokenTable::OK,
231 table.FindAuthorization(make_set(8), KeyPurpose::SIGN, 0, &found));
232 EXPECT_EQ(AuthTokenTable::OK,
233 table.FindAuthorization(make_set(9), KeyPurpose::SIGN, 0, &found));
Shawn Willden47d26162016-03-16 08:32:39 -0600234 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800235 table.FindAuthorization(make_set(10), KeyPurpose::SIGN, 0, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600236}
237
238TEST(AuthTokenTableTest, AuthenticationNotRequired) {
239 AuthTokenTable table;
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800240 const HardwareAuthToken* found;
Shawn Willden489dfe12015-03-17 10:13:27 -0600241
242 EXPECT_EQ(AuthTokenTable::AUTH_NOT_REQUIRED,
Shawn Willden0329a822017-12-04 13:55:14 -0700243 table.FindAuthorization(AuthorizationSetBuilder().Authorization(TAG_NO_AUTH_REQUIRED),
244 KeyPurpose::SIGN, 0 /* no challenge */, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600245}
246
247TEST(AuthTokenTableTest, OperationHandleNotFound) {
248 AuthTokenTable table;
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800249 const HardwareAuthToken* found;
Shawn Willden489dfe12015-03-17 10:13:27 -0600250
251 table.AddAuthenticationToken(make_token(1, 0, 1, 5));
252 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800253 table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
Shawn Willden489dfe12015-03-17 10:13:27 -0600254 2 /* non-matching challenge */, &found));
Shawn Willden47d26162016-03-16 08:32:39 -0600255 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800256 table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
Shawn Willden47d26162016-03-16 08:32:39 -0600257 1 /* matching challenge */, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600258 table.MarkCompleted(1);
Shawn Willden47d26162016-03-16 08:32:39 -0600259 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800260 table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
Shawn Willden47d26162016-03-16 08:32:39 -0600261 1 /* used challenge */, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600262}
263
264TEST(AuthTokenTableTest, OperationHandleRequired) {
265 AuthTokenTable table;
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800266 const HardwareAuthToken* found;
Shawn Willden489dfe12015-03-17 10:13:27 -0600267
268 table.AddAuthenticationToken(make_token(1));
Shawn Willden47d26162016-03-16 08:32:39 -0600269 EXPECT_EQ(AuthTokenTable::OP_HANDLE_REQUIRED,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800270 table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
Shawn Willden47d26162016-03-16 08:32:39 -0600271 0 /* no op handle */, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600272}
273
274TEST(AuthTokenTableTest, AuthSidChanged) {
275 AuthTokenTable table;
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800276 const HardwareAuthToken* found;
Shawn Willden489dfe12015-03-17 10:13:27 -0600277
278 table.AddAuthenticationToken(make_token(1, 3, /* op handle */ 1));
279 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_WRONG_SID,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800280 table.FindAuthorization(make_set(2, 0 /* no timeout */), KeyPurpose::SIGN,
Shawn Willden47d26162016-03-16 08:32:39 -0600281 1 /* op handle */, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600282}
283
284TEST(AuthTokenTableTest, TokenExpired) {
285 AuthTokenTable table(5, monotonic_clock);
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800286 const HardwareAuthToken* found;
Shawn Willden489dfe12015-03-17 10:13:27 -0600287
288 auto key_info = make_set(1, 5 /* five second timeout */);
289
290 // monotonic_clock "ticks" one second each time it's called, which is once per request, so the
291 // sixth request should fail, since key_info says the key is good for five seconds.
292 //
293 // Note that this tests the decision of the AuthTokenTable to reject a request it knows is
294 // expired. An additional check of the secure timestamp (in the token) will be made by
295 // keymaster when the found token is passed to it.
296 table.AddAuthenticationToken(make_token(1, 0));
Shawn Willden47d26162016-03-16 08:32:39 -0600297 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800298 table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
Shawn Willden47d26162016-03-16 08:32:39 -0600299 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800300 table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
Shawn Willden47d26162016-03-16 08:32:39 -0600301 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800302 table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
Shawn Willden47d26162016-03-16 08:32:39 -0600303 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800304 table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
Shawn Willden47d26162016-03-16 08:32:39 -0600305 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800306 table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600307 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_EXPIRED,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800308 table.FindAuthorization(key_info, KeyPurpose::SIGN, 0 /* no op handle */, &found));
Shawn Willden489dfe12015-03-17 10:13:27 -0600309}
310
311TEST(AuthTokenTableTest, MarkNonexistentEntryCompleted) {
312 AuthTokenTable table;
313 // Marking a nonexistent entry completed is ignored. This test is mainly for code coverage.
314 table.MarkCompleted(1);
315}
316
317TEST(AuthTokenTableTest, SupersededEntries) {
318 AuthTokenTable table;
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800319 const HardwareAuthToken* found;
Shawn Willden489dfe12015-03-17 10:13:27 -0600320
321 // Add two identical tokens, without challenges. The second should supersede the first, based
322 // on timestamp (fourth arg to make_token).
323 table.AddAuthenticationToken(make_token(1, 0, 0, 0));
324 table.AddAuthenticationToken(make_token(1, 0, 0, 1));
325 EXPECT_EQ(1U, table.size());
Shawn Willden0329a822017-12-04 13:55:14 -0700326 EXPECT_EQ(AuthTokenTable::OK,
327 table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
328 EXPECT_EQ(1U, found->timestamp);
Shawn Willden489dfe12015-03-17 10:13:27 -0600329
330 // Add a third token, this with a different RSID. It should not be superseded.
331 table.AddAuthenticationToken(make_token(2, 0, 0, 2));
332 EXPECT_EQ(2U, table.size());
333
334 // Add two more, superseding each of the two in the table.
335 table.AddAuthenticationToken(make_token(1, 0, 0, 3));
336 table.AddAuthenticationToken(make_token(2, 0, 0, 4));
337 EXPECT_EQ(2U, table.size());
Shawn Willden0329a822017-12-04 13:55:14 -0700338 EXPECT_EQ(AuthTokenTable::OK,
339 table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0, &found));
340 EXPECT_EQ(3U, found->timestamp);
341 EXPECT_EQ(AuthTokenTable::OK,
342 table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0, &found));
343 EXPECT_EQ(4U, found->timestamp);
Shawn Willden489dfe12015-03-17 10:13:27 -0600344
345 // Add another, this one with a challenge value. It should supersede the old one since it is
346 // newer, and matches other than the challenge.
347 table.AddAuthenticationToken(make_token(1, 0, 1, 5));
348 EXPECT_EQ(2U, table.size());
349
350 // And another, also with a challenge. Because of the challenge values, the one just added
351 // cannot be superseded.
352 table.AddAuthenticationToken(make_token(1, 0, 2, 6));
353 EXPECT_EQ(3U, table.size());
354
355 // Should be able to find each of them, by specifying their challenge, with a key that is not
356 // timed (timed keys don't care about challenges).
357 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800358 table.FindAuthorization(make_set(1, 0 /* no timeout*/), KeyPurpose::SIGN,
Shawn Willden47d26162016-03-16 08:32:39 -0600359 1 /* challenge */, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700360 EXPECT_EQ(5U, found->timestamp);
Shawn Willden489dfe12015-03-17 10:13:27 -0600361 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800362 table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
Shawn Willden47d26162016-03-16 08:32:39 -0600363 2 /* challenge */, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700364 EXPECT_EQ(6U, found->timestamp);
Shawn Willden489dfe12015-03-17 10:13:27 -0600365
366 // Add another, without a challenge, and the same timestamp as the last one. This new one
367 // actually could be considered already-superseded, but the table doesn't handle that case,
368 // since it seems unlikely to occur in practice.
369 table.AddAuthenticationToken(make_token(1, 0, 0, 6));
370 EXPECT_EQ(4U, table.size());
Shawn Willden47d26162016-03-16 08:32:39 -0600371 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800372 table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700373 EXPECT_EQ(6U, found->timestamp);
Shawn Willden489dfe12015-03-17 10:13:27 -0600374
375 // Add another without a challenge but an increased timestamp. This should supersede the
376 // previous challenge-free entry.
377 table.AddAuthenticationToken(make_token(1, 0, 0, 7));
378 EXPECT_EQ(4U, table.size());
379 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800380 table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
Shawn Willden47d26162016-03-16 08:32:39 -0600381 2 /* challenge */, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700382 EXPECT_EQ(6U, found->timestamp);
Shawn Willden47d26162016-03-16 08:32:39 -0600383 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800384 table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700385 EXPECT_EQ(7U, found->timestamp);
Shawn Willden489dfe12015-03-17 10:13:27 -0600386
387 // Mark the entry with challenge 2 as complete. Since there's a newer challenge-free entry, the
388 // challenge entry will be superseded.
389 table.MarkCompleted(2);
390 EXPECT_EQ(3U, table.size());
391 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800392 table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
Shawn Willden47d26162016-03-16 08:32:39 -0600393 2 /* challenge */, &found));
394 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800395 table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700396 EXPECT_EQ(7U, found->timestamp);
Shawn Willden489dfe12015-03-17 10:13:27 -0600397
398 // Add another SID 1 entry with a challenge. It supersedes the previous SID 1 entry with
399 // no challenge (timestamp 7), but not the one with challenge 1 (timestamp 5).
400 table.AddAuthenticationToken(make_token(1, 0, 3, 8));
401 EXPECT_EQ(3U, table.size());
402
403 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800404 table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
Shawn Willden47d26162016-03-16 08:32:39 -0600405 1 /* challenge */, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700406 EXPECT_EQ(5U, found->timestamp);
Shawn Willden489dfe12015-03-17 10:13:27 -0600407
408 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800409 table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
Shawn Willden47d26162016-03-16 08:32:39 -0600410 3 /* challenge */, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700411 EXPECT_EQ(8U, found->timestamp);
Shawn Willden489dfe12015-03-17 10:13:27 -0600412
413 // SID 2 entry is still there.
Shawn Willden47d26162016-03-16 08:32:39 -0600414 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800415 table.FindAuthorization(make_set(2), KeyPurpose::SIGN, 0 /* challenge */, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700416 EXPECT_EQ(4U, found->timestamp);
Shawn Willden489dfe12015-03-17 10:13:27 -0600417
418 // Mark the entry with challenge 3 as complete. Since the older challenge 1 entry is
419 // incomplete, nothing is superseded.
420 table.MarkCompleted(3);
421 EXPECT_EQ(3U, table.size());
422
423 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800424 table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
Shawn Willden47d26162016-03-16 08:32:39 -0600425 1 /* challenge */, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700426 EXPECT_EQ(5U, found->timestamp);
Shawn Willden489dfe12015-03-17 10:13:27 -0600427
Shawn Willden47d26162016-03-16 08:32:39 -0600428 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800429 table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700430 EXPECT_EQ(8U, found->timestamp);
Shawn Willden489dfe12015-03-17 10:13:27 -0600431
432 // Mark the entry with challenge 1 as complete. Since there's a newer one (with challenge 3,
433 // completed), the challenge 1 entry is superseded and removed.
434 table.MarkCompleted(1);
435 EXPECT_EQ(2U, table.size());
436 EXPECT_EQ(AuthTokenTable::AUTH_TOKEN_NOT_FOUND,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800437 table.FindAuthorization(make_set(1, 0 /* no timeout */), KeyPurpose::SIGN,
Shawn Willden47d26162016-03-16 08:32:39 -0600438 1 /* challenge */, &found));
439 EXPECT_EQ(AuthTokenTable::OK,
Janis Danisevskis8f737ad2017-11-21 12:30:15 -0800440 table.FindAuthorization(make_set(1), KeyPurpose::SIGN, 0 /* challenge */, &found));
Shawn Willden0329a822017-12-04 13:55:14 -0700441 EXPECT_EQ(8U, found->timestamp);
Shawn Willden489dfe12015-03-17 10:13:27 -0600442}
443
Shawn Willden489dfe12015-03-17 10:13:27 -0600444} // namespace test
Shawn Willden0329a822017-12-04 13:55:14 -0700445} // namespace keystore