1 /*
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
27 #include <hardware/hw_auth_token.h>
28
29 #include <android/log.h>
30 #include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
31 #include <android/hardware/gatekeeper/1.0/types.h>
32
33 #include <log/log.h>
34
35 #include <VtsHalHidlTargetTestBase.h>
36
37 using ::android::hardware::hidl_string;
38 using ::android::hardware::hidl_vec;
39 using ::android::hardware::gatekeeper::V1_0::IGatekeeper;
40 using ::android::hardware::gatekeeper::V1_0::GatekeeperResponse;
41 using ::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode;
42 using ::android::hardware::Return;
43 using ::android::hardware::Void;
44 using ::android::sp;
45
46 struct GatekeeperRequest {
47 uint32_t uid;
48 uint64_t challenge;
49 hidl_vec<uint8_t> curPwdHandle;
50 hidl_vec<uint8_t> curPwd;
51 hidl_vec<uint8_t> newPwd;
GatekeeperRequestGatekeeperRequest52 GatekeeperRequest() : uid(0), challenge(0) {}
53 };
54
55 // ASSERT_* macros generate return "void" internally
56 // we have to use EXPECT_* if we return anything but "void"
toAuthToken(GatekeeperResponse & rsp)57 static const hw_auth_token_t *toAuthToken(GatekeeperResponse &rsp) {
58 const hw_auth_token_t *auth_token =
59 reinterpret_cast<hw_auth_token_t *>(rsp.data.data());
60 const size_t auth_token_size = rsp.data.size();
61
62 EXPECT_NE(nullptr, auth_token);
63 EXPECT_EQ(sizeof(hw_auth_token_t), auth_token_size);
64
65 if (auth_token != nullptr && auth_token_size >= sizeof(*auth_token)) {
66 // these are in network order: translate to host
67 uint32_t auth_type = ntohl(auth_token->authenticator_type);
68 uint64_t auth_tstamp = ntohq(auth_token->timestamp);
69
70 EXPECT_EQ(HW_AUTH_PASSWORD, auth_type);
71 EXPECT_NE(UINT64_C(~0), auth_tstamp);
72 EXPECT_EQ(HW_AUTH_TOKEN_VERSION, auth_token->version);
73 // EXPECT_NE(UINT64_C(0), auth_token->authenticator_id);
74 ALOGI("Authenticator ID: %016" PRIX64, auth_token->authenticator_id);
75 EXPECT_NE(UINT32_C(0), auth_token->user_id);
76 }
77 return auth_token;
78 }
79
80 // The main test class for Gatekeeper HIDL HAL.
81 class GatekeeperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
82 protected:
setUid(uint32_t uid)83 void setUid(uint32_t uid) { uid_ = uid; }
84
doEnroll(GatekeeperRequest & req,GatekeeperResponse & rsp)85 void doEnroll(GatekeeperRequest &req, GatekeeperResponse &rsp) {
86 while (true) {
87 auto ret = gatekeeper_->enroll(
88 uid_, req.curPwdHandle, req.curPwd, req.newPwd,
89 [&rsp](const GatekeeperResponse &cbRsp) { rsp = cbRsp; });
90 ASSERT_TRUE(ret.isOk());
91 if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
92 ALOGI("%s: got retry code; retrying in 1 sec", __func__);
93 sleep(1);
94 }
95 }
96
doVerify(GatekeeperRequest & req,GatekeeperResponse & rsp)97 void doVerify(GatekeeperRequest &req, GatekeeperResponse &rsp) {
98 while (true) {
99 auto ret = gatekeeper_->verify(
100 uid_, req.challenge, req.curPwdHandle, req.newPwd,
101 [&rsp](const GatekeeperResponse &cb_rsp) { rsp = cb_rsp; });
102 ASSERT_TRUE(ret.isOk());
103 if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
104 ALOGI("%s: got retry code; retrying in 1 sec", __func__);
105 sleep(1);
106 }
107 }
108
doDeleteUser(GatekeeperResponse & rsp)109 void doDeleteUser(GatekeeperResponse &rsp) {
110 while (true) {
111 auto ret = gatekeeper_->deleteUser(
112 uid_, [&rsp](const GatekeeperResponse &cb_rsp) { rsp = cb_rsp; });
113 ASSERT_TRUE(ret.isOk());
114 if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
115 ALOGI("%s: got retry code; retrying in 1 sec", __func__);
116 sleep(1);
117 }
118 }
119
doDeleteAllUsers(GatekeeperResponse & rsp)120 void doDeleteAllUsers(GatekeeperResponse &rsp) {
121 while (true) {
122 auto ret = gatekeeper_->deleteAllUsers(
123 [&rsp](const GatekeeperResponse &cb_rsp) { rsp = cb_rsp; });
124 ASSERT_TRUE(ret.isOk());
125 if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
126 ALOGI("%s: got retry code; retrying in 1 sec", __func__);
127 sleep(1);
128 }
129 }
130
generatePassword(hidl_vec<uint8_t> & password,uint8_t seed)131 void generatePassword(hidl_vec<uint8_t> &password, uint8_t seed) {
132 password.resize(16);
133 memset(password.data(), seed, password.size());
134 }
135
checkEnroll(GatekeeperResponse & rsp,bool expectSuccess)136 void checkEnroll(GatekeeperResponse &rsp, bool expectSuccess) {
137 if (expectSuccess) {
138 EXPECT_EQ(GatekeeperStatusCode::STATUS_OK, rsp.code);
139 EXPECT_NE(nullptr, rsp.data.data());
140 EXPECT_GT(rsp.data.size(), UINT32_C(0));
141 } else {
142 EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, rsp.code);
143 EXPECT_EQ(UINT32_C(0), rsp.data.size());
144 }
145 }
146
checkVerify(GatekeeperResponse & rsp,uint64_t challenge,bool expectSuccess)147 void checkVerify(GatekeeperResponse &rsp, uint64_t challenge,
148 bool expectSuccess) {
149 if (expectSuccess) {
150 EXPECT_GE(rsp.code, GatekeeperStatusCode::STATUS_OK);
151 EXPECT_LE(rsp.code, GatekeeperStatusCode::STATUS_REENROLL);
152
153 const hw_auth_token_t *auth_token = toAuthToken(rsp);
154 ASSERT_NE(nullptr, auth_token);
155 EXPECT_EQ(challenge, auth_token->challenge);
156 } else {
157 EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, rsp.code);
158 EXPECT_EQ(UINT32_C(0), rsp.data.size());
159 }
160 }
161
enrollNewPassword(hidl_vec<uint8_t> & password,GatekeeperResponse & rsp,bool expectSuccess)162 void enrollNewPassword(hidl_vec<uint8_t> &password, GatekeeperResponse &rsp,
163 bool expectSuccess) {
164 GatekeeperRequest req;
165 req.newPwd.setToExternal(password.data(), password.size());
166 doEnroll(req, rsp);
167 checkEnroll(rsp, expectSuccess);
168 }
169
verifyPassword(hidl_vec<uint8_t> & password,hidl_vec<uint8_t> & passwordHandle,uint64_t challenge,GatekeeperResponse & verifyRsp,bool expectSuccess)170 void verifyPassword(hidl_vec<uint8_t> &password,
171 hidl_vec<uint8_t> &passwordHandle, uint64_t challenge,
172 GatekeeperResponse &verifyRsp, bool expectSuccess) {
173 GatekeeperRequest verifyReq;
174
175 // build verify request for the same password (we want it to succeed)
176 verifyReq.newPwd = password;
177 // use enrolled password handle we've got
178 verifyReq.curPwdHandle = passwordHandle;
179 verifyReq.challenge = challenge;
180 doVerify(verifyReq, verifyRsp);
181 checkVerify(verifyRsp, challenge, expectSuccess);
182 }
183
184 protected:
185 sp<IGatekeeper> gatekeeper_;
186 uint32_t uid_;
187
188 public:
GatekeeperHidlTest()189 GatekeeperHidlTest() : uid_(0) {}
SetUp()190 virtual void SetUp() override {
191 GatekeeperResponse rsp;
192 gatekeeper_ = ::testing::VtsHalHidlTargetTestBase::getService<IGatekeeper>();
193 ASSERT_NE(nullptr, gatekeeper_.get());
194 doDeleteAllUsers(rsp);
195 }
196
TearDown()197 virtual void TearDown() override {
198 GatekeeperResponse rsp;
199 doDeleteAllUsers(rsp);
200 }
201 };
202
203 /**
204 * Ensure we can enroll new password
205 */
TEST_F(GatekeeperHidlTest,EnrollSuccess)206 TEST_F(GatekeeperHidlTest, EnrollSuccess) {
207 hidl_vec<uint8_t> password;
208 GatekeeperResponse rsp;
209 ALOGI("Testing Enroll (expected success)");
210 generatePassword(password, 0);
211 enrollNewPassword(password, rsp, true);
212 ALOGI("Testing Enroll done");
213 }
214
215 /**
216 * Ensure we can not enroll empty password
217 */
TEST_F(GatekeeperHidlTest,EnrollNoPassword)218 TEST_F(GatekeeperHidlTest, EnrollNoPassword) {
219 hidl_vec<uint8_t> password;
220 GatekeeperResponse rsp;
221 ALOGI("Testing Enroll (expected failure)");
222 enrollNewPassword(password, rsp, false);
223 ALOGI("Testing Enroll done");
224 }
225
226 /**
227 * Ensure we can successfully verify previously enrolled password
228 */
TEST_F(GatekeeperHidlTest,VerifySuccess)229 TEST_F(GatekeeperHidlTest, VerifySuccess) {
230 GatekeeperResponse enrollRsp;
231 GatekeeperResponse verifyRsp;
232 hidl_vec<uint8_t> password;
233
234 ALOGI("Testing Enroll+Verify (expected success)");
235 generatePassword(password, 0);
236 enrollNewPassword(password, enrollRsp, true);
237 verifyPassword(password, enrollRsp.data, 1, verifyRsp, true);
238 ALOGI("Testing Enroll+Verify done");
239 }
240
241 /**
242 * Ensure we can securely update password (keep the same
243 * secure user_id) if we prove we know old password
244 */
TEST_F(GatekeeperHidlTest,TrustedReenroll)245 TEST_F(GatekeeperHidlTest, TrustedReenroll) {
246 GatekeeperResponse enrollRsp;
247 GatekeeperRequest reenrollReq;
248 GatekeeperResponse reenrollRsp;
249 GatekeeperResponse verifyRsp;
250 GatekeeperResponse reenrollVerifyRsp;
251 hidl_vec<uint8_t> password;
252 hidl_vec<uint8_t> newPassword;
253
254 generatePassword(password, 0);
255
256 ALOGI("Testing Trusted Reenroll (expected success)");
257 enrollNewPassword(password, enrollRsp, true);
258 verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
259 ALOGI("Primary Enroll+Verify done");
260
261 generatePassword(newPassword, 1);
262 reenrollReq.newPwd.setToExternal(newPassword.data(), newPassword.size());
263 reenrollReq.curPwd.setToExternal(password.data(), password.size());
264 reenrollReq.curPwdHandle.setToExternal(enrollRsp.data.data(),
265 enrollRsp.data.size());
266
267 doEnroll(reenrollReq, reenrollRsp);
268 checkEnroll(reenrollRsp, true);
269 verifyPassword(newPassword, reenrollRsp.data, 0, reenrollVerifyRsp, true);
270 ALOGI("Trusted ReEnroll+Verify done");
271
272 const hw_auth_token_t *first = toAuthToken(verifyRsp);
273 const hw_auth_token_t *second = toAuthToken(reenrollVerifyRsp);
274 if (first != nullptr && second != nullptr) {
275 EXPECT_EQ(first->user_id, second->user_id);
276 }
277 ALOGI("Testing Trusted Reenroll done");
278 }
279
280 /**
281 * Ensure we can update password (and get new
282 * secure user_id) if we don't know old password
283 */
TEST_F(GatekeeperHidlTest,UntrustedReenroll)284 TEST_F(GatekeeperHidlTest, UntrustedReenroll) {
285 GatekeeperResponse enrollRsp;
286 GatekeeperResponse reenrollRsp;
287 GatekeeperResponse verifyRsp;
288 GatekeeperResponse reenrollVerifyRsp;
289 hidl_vec<uint8_t> password;
290 hidl_vec<uint8_t> newPassword;
291
292 ALOGI("Testing Untrusted Reenroll (expected success)");
293 generatePassword(password, 0);
294 enrollNewPassword(password, enrollRsp, true);
295 verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
296 ALOGI("Primary Enroll+Verify done");
297
298 generatePassword(newPassword, 1);
299 enrollNewPassword(newPassword, reenrollRsp, true);
300 verifyPassword(newPassword, reenrollRsp.data, 0, reenrollVerifyRsp, true);
301 ALOGI("Untrusted ReEnroll+Verify done");
302
303 const hw_auth_token_t *first = toAuthToken(verifyRsp);
304 const hw_auth_token_t *second = toAuthToken(reenrollVerifyRsp);
305 if (first != nullptr && second != nullptr) {
306 EXPECT_NE(first->user_id, second->user_id);
307 }
308 ALOGI("Testing Untrusted Reenroll done");
309 }
310
311 /**
312 * Ensure we dont get successful verify with invalid data
313 */
TEST_F(GatekeeperHidlTest,VerifyNoData)314 TEST_F(GatekeeperHidlTest, VerifyNoData) {
315 hidl_vec<uint8_t> password;
316 hidl_vec<uint8_t> passwordHandle;
317 GatekeeperResponse verifyRsp;
318
319 ALOGI("Testing Verify (expected failure)");
320 verifyPassword(password, passwordHandle, 0, verifyRsp, false);
321 EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, verifyRsp.code);
322 ALOGI("Testing Verify done");
323 }
324
325 /**
326 * Ensure we can not verify password after we enrolled it and then deleted user
327 */
TEST_F(GatekeeperHidlTest,DeleteUserTest)328 TEST_F(GatekeeperHidlTest, DeleteUserTest) {
329 hidl_vec<uint8_t> password;
330 GatekeeperResponse enrollRsp;
331 GatekeeperResponse verifyRsp;
332 GatekeeperResponse delRsp;
333 ALOGI("Testing deleteUser (expected success)");
334 setUid(10001);
335 generatePassword(password, 0);
336 enrollNewPassword(password, enrollRsp, true);
337 verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
338 ALOGI("Enroll+Verify done");
339 doDeleteUser(delRsp);
340 EXPECT_EQ(UINT32_C(0), delRsp.data.size());
341 EXPECT_TRUE(delRsp.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
342 delRsp.code == GatekeeperStatusCode::STATUS_OK);
343 ALOGI("DeleteUser done");
344 if (delRsp.code == GatekeeperStatusCode::STATUS_OK) {
345 verifyPassword(password, enrollRsp.data, 0, verifyRsp, false);
346 EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, verifyRsp.code);
347 ALOGI("Verify after Delete done (must fail)");
348 }
349 ALOGI("Testing deleteUser done: rsp=%" PRIi32, delRsp.code);
350 }
351
352 /**
353 * Ensure we can not delete a user that does not exist
354 */
TEST_F(GatekeeperHidlTest,DeleteInvalidUserTest)355 TEST_F(GatekeeperHidlTest, DeleteInvalidUserTest) {
356 hidl_vec<uint8_t> password;
357 GatekeeperResponse enrollRsp;
358 GatekeeperResponse verifyRsp;
359 GatekeeperResponse delRsp1;
360 GatekeeperResponse delRsp2;
361 ALOGI("Testing deleteUser (expected failure)");
362 setUid(10002);
363 generatePassword(password, 0);
364 enrollNewPassword(password, enrollRsp, true);
365 verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
366 ALOGI("Enroll+Verify done");
367
368 // Delete the user
369 doDeleteUser(delRsp1);
370 EXPECT_EQ(UINT32_C(0), delRsp1.data.size());
371 EXPECT_TRUE(delRsp1.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
372 delRsp1.code == GatekeeperStatusCode::STATUS_OK);
373
374 // Delete the user again
375 doDeleteUser(delRsp2);
376 EXPECT_EQ(UINT32_C(0), delRsp2.data.size());
377 EXPECT_TRUE(delRsp2.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
378 delRsp2.code == GatekeeperStatusCode::ERROR_GENERAL_FAILURE);
379 ALOGI("DeleteUser done");
380 ALOGI("Testing deleteUser done: rsp=%" PRIi32, delRsp2.code);
381 }
382
383 /**
384 * Ensure we can not verify passwords after we enrolled them and then deleted
385 * all users
386 */
TEST_F(GatekeeperHidlTest,DeleteAllUsersTest)387 TEST_F(GatekeeperHidlTest, DeleteAllUsersTest) {
388 struct UserData {
389 uint32_t userId;
390 hidl_vec<uint8_t> password;
391 GatekeeperResponse enrollRsp;
392 GatekeeperResponse verifyRsp;
393 UserData(int id) { userId = id; }
394 } users[3]{10001, 10002, 10003};
395 GatekeeperResponse delAllRsp;
396 ALOGI("Testing deleteAllUsers (expected success)");
397
398 // enroll multiple users
399 for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
400 setUid(users[i].userId);
401 generatePassword(users[i].password, (i % 255) + 1);
402 enrollNewPassword(users[i].password, users[i].enrollRsp, true);
403 }
404 ALOGI("Multiple users enrolled");
405
406 // verify multiple users
407 for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
408 setUid(users[i].userId);
409 verifyPassword(users[i].password, users[i].enrollRsp.data, 0,
410 users[i].verifyRsp, true);
411 }
412 ALOGI("Multiple users verified");
413
414 doDeleteAllUsers(delAllRsp);
415 EXPECT_EQ(UINT32_C(0), delAllRsp.data.size());
416 EXPECT_TRUE(delAllRsp.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
417 delAllRsp.code == GatekeeperStatusCode::STATUS_OK);
418 ALOGI("All users deleted");
419
420 if (delAllRsp.code == GatekeeperStatusCode::STATUS_OK) {
421 // verify multiple users after they are deleted; all must fail
422 for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
423 setUid(users[i].userId);
424 verifyPassword(users[i].password, users[i].enrollRsp.data, 0,
425 users[i].verifyRsp, false);
426 EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE,
427 users[i].verifyRsp.code);
428 }
429 ALOGI("Multiple users verified after delete (all must fail)");
430 }
431
432 ALOGI("Testing deleteAllUsers done: rsp=%" PRIi32, delAllRsp.code);
433 }
434
main(int argc,char ** argv)435 int main(int argc, char **argv) {
436 ::testing::InitGoogleTest(&argc, argv);
437 int status = RUN_ALL_TESTS();
438 ALOGI("Test result = %d", status);
439 return status;
440 }
441