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