blob: 618624e1d47c5dae8a6f37df4f5291ffe566e625 [file] [log] [blame]
Alexey Polyudov96f4a892016-11-22 14:18:01 -08001/*
2 * Copyright (C) 2016 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#define LOG_TAG "gatekeeper_hidl_hal_test"
18
19#include <algorithm>
20#include <cmath>
21#include <string>
22#include <vector>
23
24#include <inttypes.h>
25#include <unistd.h>
26
nelsonli79aada22019-11-20 15:11:04 +080027#include <gtest/gtest.h>
Alexey Polyudov96f4a892016-11-22 14:18:01 -080028#include <hardware/hw_auth_token.h>
nelsonli79aada22019-11-20 15:11:04 +080029#include <hidl/GtestPrinter.h>
30#include <hidl/ServiceManagement.h>
Alexey Polyudov96f4a892016-11-22 14:18:01 -080031
Yifan Hongf9d30342016-11-30 13:45:34 -080032#include <android/log.h>
Alexey Polyudov96f4a892016-11-22 14:18:01 -080033#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
34#include <android/hardware/gatekeeper/1.0/types.h>
35
Steven Moreland3eb7df72017-04-06 12:15:23 -070036#include <log/log.h>
37
Alexey Polyudov96f4a892016-11-22 14:18:01 -080038using ::android::hardware::hidl_string;
39using ::android::hardware::hidl_vec;
40using ::android::hardware::gatekeeper::V1_0::IGatekeeper;
41using ::android::hardware::gatekeeper::V1_0::GatekeeperResponse;
42using ::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode;
43using ::android::hardware::Return;
44using ::android::hardware::Void;
45using ::android::sp;
46
47struct GatekeeperRequest {
48 uint32_t uid;
49 uint64_t challenge;
50 hidl_vec<uint8_t> curPwdHandle;
51 hidl_vec<uint8_t> curPwd;
52 hidl_vec<uint8_t> newPwd;
53 GatekeeperRequest() : uid(0), challenge(0) {}
54};
55
56// ASSERT_* macros generate return "void" internally
57// we have to use EXPECT_* if we return anything but "void"
58static const hw_auth_token_t *toAuthToken(GatekeeperResponse &rsp) {
59 const hw_auth_token_t *auth_token =
60 reinterpret_cast<hw_auth_token_t *>(rsp.data.data());
61 const size_t auth_token_size = rsp.data.size();
62
63 EXPECT_NE(nullptr, auth_token);
64 EXPECT_EQ(sizeof(hw_auth_token_t), auth_token_size);
65
66 if (auth_token != nullptr && auth_token_size >= sizeof(*auth_token)) {
67 // these are in network order: translate to host
68 uint32_t auth_type = ntohl(auth_token->authenticator_type);
69 uint64_t auth_tstamp = ntohq(auth_token->timestamp);
70
71 EXPECT_EQ(HW_AUTH_PASSWORD, auth_type);
72 EXPECT_NE(UINT64_C(~0), auth_tstamp);
73 EXPECT_EQ(HW_AUTH_TOKEN_VERSION, auth_token->version);
74 // EXPECT_NE(UINT64_C(0), auth_token->authenticator_id);
75 ALOGI("Authenticator ID: %016" PRIX64, auth_token->authenticator_id);
76 EXPECT_NE(UINT32_C(0), auth_token->user_id);
77 }
78 return auth_token;
79}
80
81// The main test class for Gatekeeper HIDL HAL.
nelsonli79aada22019-11-20 15:11:04 +080082class GatekeeperHidlTest : public ::testing::TestWithParam<std::string> {
Alexey Polyudov96f4a892016-11-22 14:18:01 -080083 protected:
84 void setUid(uint32_t uid) { uid_ = uid; }
85
86 void doEnroll(GatekeeperRequest &req, GatekeeperResponse &rsp) {
87 while (true) {
88 auto ret = gatekeeper_->enroll(
89 uid_, req.curPwdHandle, req.curPwd, req.newPwd,
90 [&rsp](const GatekeeperResponse &cbRsp) { rsp = cbRsp; });
Steven Morelandb6438422017-01-03 17:06:57 -080091 ASSERT_TRUE(ret.isOk());
Alexey Polyudov96f4a892016-11-22 14:18:01 -080092 if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
93 ALOGI("%s: got retry code; retrying in 1 sec", __func__);
94 sleep(1);
95 }
96 }
97
98 void doVerify(GatekeeperRequest &req, GatekeeperResponse &rsp) {
99 while (true) {
100 auto ret = gatekeeper_->verify(
101 uid_, req.challenge, req.curPwdHandle, req.newPwd,
102 [&rsp](const GatekeeperResponse &cb_rsp) { rsp = cb_rsp; });
Steven Morelandb6438422017-01-03 17:06:57 -0800103 ASSERT_TRUE(ret.isOk());
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800104 if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
105 ALOGI("%s: got retry code; retrying in 1 sec", __func__);
106 sleep(1);
107 }
108 }
109
110 void doDeleteUser(GatekeeperResponse &rsp) {
111 while (true) {
112 auto ret = gatekeeper_->deleteUser(
113 uid_, [&rsp](const GatekeeperResponse &cb_rsp) { rsp = cb_rsp; });
Steven Morelandb6438422017-01-03 17:06:57 -0800114 ASSERT_TRUE(ret.isOk());
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800115 if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
116 ALOGI("%s: got retry code; retrying in 1 sec", __func__);
117 sleep(1);
118 }
119 }
120
121 void doDeleteAllUsers(GatekeeperResponse &rsp) {
122 while (true) {
123 auto ret = gatekeeper_->deleteAllUsers(
124 [&rsp](const GatekeeperResponse &cb_rsp) { rsp = cb_rsp; });
Steven Morelandb6438422017-01-03 17:06:57 -0800125 ASSERT_TRUE(ret.isOk());
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800126 if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
127 ALOGI("%s: got retry code; retrying in 1 sec", __func__);
128 sleep(1);
129 }
130 }
131
132 void generatePassword(hidl_vec<uint8_t> &password, uint8_t seed) {
133 password.resize(16);
134 memset(password.data(), seed, password.size());
135 }
136
137 void checkEnroll(GatekeeperResponse &rsp, bool expectSuccess) {
138 if (expectSuccess) {
139 EXPECT_EQ(GatekeeperStatusCode::STATUS_OK, rsp.code);
140 EXPECT_NE(nullptr, rsp.data.data());
141 EXPECT_GT(rsp.data.size(), UINT32_C(0));
142 } else {
143 EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, rsp.code);
144 EXPECT_EQ(UINT32_C(0), rsp.data.size());
145 }
146 }
147
148 void checkVerify(GatekeeperResponse &rsp, uint64_t challenge,
149 bool expectSuccess) {
150 if (expectSuccess) {
151 EXPECT_GE(rsp.code, GatekeeperStatusCode::STATUS_OK);
152 EXPECT_LE(rsp.code, GatekeeperStatusCode::STATUS_REENROLL);
153
154 const hw_auth_token_t *auth_token = toAuthToken(rsp);
155 ASSERT_NE(nullptr, auth_token);
156 EXPECT_EQ(challenge, auth_token->challenge);
157 } else {
158 EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, rsp.code);
159 EXPECT_EQ(UINT32_C(0), rsp.data.size());
160 }
161 }
162
163 void enrollNewPassword(hidl_vec<uint8_t> &password, GatekeeperResponse &rsp,
164 bool expectSuccess) {
165 GatekeeperRequest req;
166 req.newPwd.setToExternal(password.data(), password.size());
167 doEnroll(req, rsp);
168 checkEnroll(rsp, expectSuccess);
169 }
170
171 void verifyPassword(hidl_vec<uint8_t> &password,
172 hidl_vec<uint8_t> &passwordHandle, uint64_t challenge,
173 GatekeeperResponse &verifyRsp, bool expectSuccess) {
174 GatekeeperRequest verifyReq;
175
176 // build verify request for the same password (we want it to succeed)
177 verifyReq.newPwd = password;
178 // use enrolled password handle we've got
179 verifyReq.curPwdHandle = passwordHandle;
180 verifyReq.challenge = challenge;
181 doVerify(verifyReq, verifyRsp);
182 checkVerify(verifyRsp, challenge, expectSuccess);
183 }
184
185 protected:
186 sp<IGatekeeper> gatekeeper_;
187 uint32_t uid_;
188
189 public:
190 GatekeeperHidlTest() : uid_(0) {}
191 virtual void SetUp() override {
192 GatekeeperResponse rsp;
nelsonli79aada22019-11-20 15:11:04 +0800193 gatekeeper_ = IGatekeeper::getService(GetParam());
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800194 ASSERT_NE(nullptr, gatekeeper_.get());
195 doDeleteAllUsers(rsp);
196 }
197
198 virtual void TearDown() override {
199 GatekeeperResponse rsp;
200 doDeleteAllUsers(rsp);
201 }
202};
203
204/**
205 * Ensure we can enroll new password
206 */
nelsonli79aada22019-11-20 15:11:04 +0800207TEST_P(GatekeeperHidlTest, EnrollSuccess) {
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800208 hidl_vec<uint8_t> password;
209 GatekeeperResponse rsp;
210 ALOGI("Testing Enroll (expected success)");
211 generatePassword(password, 0);
212 enrollNewPassword(password, rsp, true);
213 ALOGI("Testing Enroll done");
214}
215
216/**
217 * Ensure we can not enroll empty password
218 */
nelsonli79aada22019-11-20 15:11:04 +0800219TEST_P(GatekeeperHidlTest, EnrollNoPassword) {
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800220 hidl_vec<uint8_t> password;
221 GatekeeperResponse rsp;
222 ALOGI("Testing Enroll (expected failure)");
223 enrollNewPassword(password, rsp, false);
224 ALOGI("Testing Enroll done");
225}
226
227/**
228 * Ensure we can successfully verify previously enrolled password
229 */
nelsonli79aada22019-11-20 15:11:04 +0800230TEST_P(GatekeeperHidlTest, VerifySuccess) {
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800231 GatekeeperResponse enrollRsp;
232 GatekeeperResponse verifyRsp;
233 hidl_vec<uint8_t> password;
234
235 ALOGI("Testing Enroll+Verify (expected success)");
236 generatePassword(password, 0);
237 enrollNewPassword(password, enrollRsp, true);
238 verifyPassword(password, enrollRsp.data, 1, verifyRsp, true);
Marco Nelissen111feb12021-06-14 11:29:21 -0700239
240 ALOGI("Testing unenrolled password doesn't verify");
241 generatePassword(password, 1);
242 verifyPassword(password, enrollRsp.data, 1, verifyRsp, false);
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800243 ALOGI("Testing Enroll+Verify done");
244}
245
246/**
247 * Ensure we can securely update password (keep the same
248 * secure user_id) if we prove we know old password
249 */
nelsonli79aada22019-11-20 15:11:04 +0800250TEST_P(GatekeeperHidlTest, TrustedReenroll) {
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800251 GatekeeperResponse enrollRsp;
252 GatekeeperRequest reenrollReq;
253 GatekeeperResponse reenrollRsp;
254 GatekeeperResponse verifyRsp;
255 GatekeeperResponse reenrollVerifyRsp;
256 hidl_vec<uint8_t> password;
257 hidl_vec<uint8_t> newPassword;
258
259 generatePassword(password, 0);
260
261 ALOGI("Testing Trusted Reenroll (expected success)");
262 enrollNewPassword(password, enrollRsp, true);
263 verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
264 ALOGI("Primary Enroll+Verify done");
265
266 generatePassword(newPassword, 1);
267 reenrollReq.newPwd.setToExternal(newPassword.data(), newPassword.size());
268 reenrollReq.curPwd.setToExternal(password.data(), password.size());
269 reenrollReq.curPwdHandle.setToExternal(enrollRsp.data.data(),
270 enrollRsp.data.size());
271
272 doEnroll(reenrollReq, reenrollRsp);
273 checkEnroll(reenrollRsp, true);
274 verifyPassword(newPassword, reenrollRsp.data, 0, reenrollVerifyRsp, true);
275 ALOGI("Trusted ReEnroll+Verify done");
276
277 const hw_auth_token_t *first = toAuthToken(verifyRsp);
278 const hw_auth_token_t *second = toAuthToken(reenrollVerifyRsp);
279 if (first != nullptr && second != nullptr) {
280 EXPECT_EQ(first->user_id, second->user_id);
281 }
282 ALOGI("Testing Trusted Reenroll done");
283}
284
285/**
286 * Ensure we can update password (and get new
287 * secure user_id) if we don't know old password
288 */
nelsonli79aada22019-11-20 15:11:04 +0800289TEST_P(GatekeeperHidlTest, UntrustedReenroll) {
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800290 GatekeeperResponse enrollRsp;
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800291 GatekeeperResponse reenrollRsp;
292 GatekeeperResponse verifyRsp;
293 GatekeeperResponse reenrollVerifyRsp;
294 hidl_vec<uint8_t> password;
295 hidl_vec<uint8_t> newPassword;
296
297 ALOGI("Testing Untrusted Reenroll (expected success)");
298 generatePassword(password, 0);
299 enrollNewPassword(password, enrollRsp, true);
300 verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
301 ALOGI("Primary Enroll+Verify done");
302
303 generatePassword(newPassword, 1);
304 enrollNewPassword(newPassword, reenrollRsp, true);
305 verifyPassword(newPassword, reenrollRsp.data, 0, reenrollVerifyRsp, true);
306 ALOGI("Untrusted ReEnroll+Verify done");
307
308 const hw_auth_token_t *first = toAuthToken(verifyRsp);
309 const hw_auth_token_t *second = toAuthToken(reenrollVerifyRsp);
310 if (first != nullptr && second != nullptr) {
311 EXPECT_NE(first->user_id, second->user_id);
312 }
Marco Nelissen103fb4f2021-02-01 12:35:28 -0800313 // the old enrollment should be invalid now
314 verifyPassword(password, enrollRsp.data, 0, verifyRsp, false);
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800315 ALOGI("Testing Untrusted Reenroll done");
316}
317
318/**
319 * Ensure we dont get successful verify with invalid data
320 */
nelsonli79aada22019-11-20 15:11:04 +0800321TEST_P(GatekeeperHidlTest, VerifyNoData) {
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800322 hidl_vec<uint8_t> password;
323 hidl_vec<uint8_t> passwordHandle;
324 GatekeeperResponse verifyRsp;
325
326 ALOGI("Testing Verify (expected failure)");
327 verifyPassword(password, passwordHandle, 0, verifyRsp, false);
328 EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, verifyRsp.code);
329 ALOGI("Testing Verify done");
330}
331
332/**
333 * Ensure we can not verify password after we enrolled it and then deleted user
334 */
nelsonli79aada22019-11-20 15:11:04 +0800335TEST_P(GatekeeperHidlTest, DeleteUserTest) {
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800336 hidl_vec<uint8_t> password;
337 GatekeeperResponse enrollRsp;
338 GatekeeperResponse verifyRsp;
339 GatekeeperResponse delRsp;
340 ALOGI("Testing deleteUser (expected success)");
341 setUid(10001);
342 generatePassword(password, 0);
343 enrollNewPassword(password, enrollRsp, true);
344 verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
345 ALOGI("Enroll+Verify done");
346 doDeleteUser(delRsp);
347 EXPECT_EQ(UINT32_C(0), delRsp.data.size());
348 EXPECT_TRUE(delRsp.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
349 delRsp.code == GatekeeperStatusCode::STATUS_OK);
350 ALOGI("DeleteUser done");
351 if (delRsp.code == GatekeeperStatusCode::STATUS_OK) {
352 verifyPassword(password, enrollRsp.data, 0, verifyRsp, false);
353 EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, verifyRsp.code);
354 ALOGI("Verify after Delete done (must fail)");
355 }
356 ALOGI("Testing deleteUser done: rsp=%" PRIi32, delRsp.code);
357}
358
359/**
Ryan Campbellb7a77542017-02-22 11:15:35 -0800360 * Ensure we can not delete a user that does not exist
361 */
nelsonli79aada22019-11-20 15:11:04 +0800362TEST_P(GatekeeperHidlTest, DeleteInvalidUserTest) {
Ryan Campbellb7a77542017-02-22 11:15:35 -0800363 hidl_vec<uint8_t> password;
364 GatekeeperResponse enrollRsp;
365 GatekeeperResponse verifyRsp;
366 GatekeeperResponse delRsp1;
367 GatekeeperResponse delRsp2;
368 ALOGI("Testing deleteUser (expected failure)");
369 setUid(10002);
370 generatePassword(password, 0);
371 enrollNewPassword(password, enrollRsp, true);
372 verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
373 ALOGI("Enroll+Verify done");
374
375 // Delete the user
376 doDeleteUser(delRsp1);
377 EXPECT_EQ(UINT32_C(0), delRsp1.data.size());
378 EXPECT_TRUE(delRsp1.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
379 delRsp1.code == GatekeeperStatusCode::STATUS_OK);
380
381 // Delete the user again
382 doDeleteUser(delRsp2);
383 EXPECT_EQ(UINT32_C(0), delRsp2.data.size());
384 EXPECT_TRUE(delRsp2.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
385 delRsp2.code == GatekeeperStatusCode::ERROR_GENERAL_FAILURE);
386 ALOGI("DeleteUser done");
387 ALOGI("Testing deleteUser done: rsp=%" PRIi32, delRsp2.code);
388}
389
390/**
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800391 * Ensure we can not verify passwords after we enrolled them and then deleted
392 * all users
393 */
nelsonli79aada22019-11-20 15:11:04 +0800394TEST_P(GatekeeperHidlTest, DeleteAllUsersTest) {
Alexey Polyudov96f4a892016-11-22 14:18:01 -0800395 struct UserData {
396 uint32_t userId;
397 hidl_vec<uint8_t> password;
398 GatekeeperResponse enrollRsp;
399 GatekeeperResponse verifyRsp;
400 UserData(int id) { userId = id; }
401 } users[3]{10001, 10002, 10003};
402 GatekeeperResponse delAllRsp;
403 ALOGI("Testing deleteAllUsers (expected success)");
404
405 // enroll multiple users
406 for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
407 setUid(users[i].userId);
408 generatePassword(users[i].password, (i % 255) + 1);
409 enrollNewPassword(users[i].password, users[i].enrollRsp, true);
410 }
411 ALOGI("Multiple users enrolled");
412
413 // verify multiple users
414 for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
415 setUid(users[i].userId);
416 verifyPassword(users[i].password, users[i].enrollRsp.data, 0,
417 users[i].verifyRsp, true);
418 }
419 ALOGI("Multiple users verified");
420
421 doDeleteAllUsers(delAllRsp);
422 EXPECT_EQ(UINT32_C(0), delAllRsp.data.size());
423 EXPECT_TRUE(delAllRsp.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
424 delAllRsp.code == GatekeeperStatusCode::STATUS_OK);
425 ALOGI("All users deleted");
426
427 if (delAllRsp.code == GatekeeperStatusCode::STATUS_OK) {
428 // verify multiple users after they are deleted; all must fail
429 for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
430 setUid(users[i].userId);
431 verifyPassword(users[i].password, users[i].enrollRsp.data, 0,
432 users[i].verifyRsp, false);
433 EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE,
434 users[i].verifyRsp.code);
435 }
436 ALOGI("Multiple users verified after delete (all must fail)");
437 }
438
439 ALOGI("Testing deleteAllUsers done: rsp=%" PRIi32, delAllRsp.code);
440}
441
Dan Shiba4d5322020-07-28 13:09:30 -0700442GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GatekeeperHidlTest);
nelsonli79aada22019-11-20 15:11:04 +0800443INSTANTIATE_TEST_SUITE_P(
444 PerInstance, GatekeeperHidlTest,
445 testing::ValuesIn(android::hardware::getAllHalInstanceNames(IGatekeeper::descriptor)),
446 android::hardware::PrintInstanceNameToString);