/* * Copyright 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include "../SoftGateKeeper.h" using ::gatekeeper::EnrollRequest; using ::gatekeeper::EnrollResponse; using ::gatekeeper::secure_id_t; using ::gatekeeper::SizedBuffer; using ::gatekeeper::SoftGateKeeper; using ::gatekeeper::VerifyRequest; using ::gatekeeper::VerifyResponse; using ::testing::Test; static SizedBuffer makePasswordBuffer(int init = 0) { constexpr const uint32_t pw_buffer_size = 16; auto pw_buffer = new uint8_t[pw_buffer_size]; memset(pw_buffer, init, pw_buffer_size); return {pw_buffer, pw_buffer_size}; } static SizedBuffer makeAndInitializeSizedBuffer(const uint8_t* data, uint32_t size) { auto buffer = new uint8_t[size]; memcpy(buffer, data, size); return {buffer, size}; } static SizedBuffer copySizedBuffer(const SizedBuffer& rhs) { return makeAndInitializeSizedBuffer(rhs.Data(), rhs.size()); } static void do_enroll(SoftGateKeeper& gatekeeper, EnrollResponse* response) { EnrollRequest request(0, {}, makePasswordBuffer(), {}); gatekeeper.Enroll(request, response); } TEST(GateKeeperTest, EnrollSuccess) { SoftGateKeeper gatekeeper; EnrollResponse response; do_enroll(gatekeeper, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); } TEST(GateKeeperTest, EnrollBogusData) { SoftGateKeeper gatekeeper; EnrollResponse response; EnrollRequest request(0, {}, {}, {}); gatekeeper.Enroll(request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error); } TEST(GateKeeperTest, VerifySuccess) { SoftGateKeeper gatekeeper; EnrollResponse enroll_response; do_enroll(gatekeeper, &enroll_response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); VerifyRequest request(0, 1, std::move(enroll_response.enrolled_password_handle), makePasswordBuffer()); VerifyResponse response; gatekeeper.Verify(request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); auto auth_token = response.auth_token.Data(); ASSERT_NE(nullptr, auth_token); ASSERT_EQ((uint32_t)HW_AUTH_PASSWORD, ntohl(auth_token->authenticator_type)); ASSERT_EQ((uint64_t)1, auth_token->challenge); ASSERT_NE(~((uint32_t)0), auth_token->timestamp); ASSERT_NE((uint64_t)0, auth_token->user_id); ASSERT_NE((uint64_t)0, auth_token->authenticator_id); } TEST(GateKeeperTest, TrustedReEnroll) { SoftGateKeeper gatekeeper; EnrollResponse enroll_response; // do_enroll enrolls an all 0 password do_enroll(gatekeeper, &enroll_response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); // verify first password VerifyRequest request(0, 0, copySizedBuffer(enroll_response.enrolled_password_handle), makePasswordBuffer()); VerifyResponse response; gatekeeper.Verify(request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); auto auth_token = response.auth_token.Data(); ASSERT_NE(nullptr, auth_token); secure_id_t secure_id = auth_token->user_id; // enroll new password EnrollRequest enroll_request(0, std::move(enroll_response.enrolled_password_handle), makePasswordBuffer(1) /* new password */, makePasswordBuffer() /* old password */); gatekeeper.Enroll(enroll_request, &enroll_response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); // verify new password VerifyRequest new_request(0, 0, std::move(enroll_response.enrolled_password_handle), makePasswordBuffer(1)); gatekeeper.Verify(new_request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); ASSERT_NE(nullptr, response.auth_token.Data()); ASSERT_EQ(secure_id, response.auth_token.Data()->user_id); } TEST(GateKeeperTest, UntrustedReEnroll) { SoftGateKeeper gatekeeper; SizedBuffer provided_password; EnrollResponse enroll_response; // do_enroll enrolls an all 0 password provided_password = makePasswordBuffer(); do_enroll(gatekeeper, &enroll_response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); // verify first password VerifyRequest request(0, 0, std::move(enroll_response.enrolled_password_handle), std::move(provided_password)); VerifyResponse response; gatekeeper.Verify(request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); auto auth_token = response.auth_token.Data(); ASSERT_NE(nullptr, auth_token); secure_id_t secure_id = auth_token->user_id; EnrollRequest enroll_request(0, {}, makePasswordBuffer(1), {}); gatekeeper.Enroll(enroll_request, &enroll_response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); // verify new password VerifyRequest new_request(0, 0, std::move(enroll_response.enrolled_password_handle), makePasswordBuffer(1)); gatekeeper.Verify(new_request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); ASSERT_NE(nullptr, response.auth_token.Data()); ASSERT_NE(secure_id, response.auth_token.Data()->user_id); } TEST(GateKeeperTest, VerifyBogusData) { SoftGateKeeper gatekeeper; VerifyResponse response; VerifyRequest request(0, 0, {}, {}); gatekeeper.Verify(request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error); }