/* * 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 <arpa/inet.h> #include <iostream> #include <gtest/gtest.h> #include <UniquePtr.h> #include <hardware/hw_auth_token.h> #include "../SoftGateKeeper.h" using ::gatekeeper::SizedBuffer; using ::testing::Test; using ::gatekeeper::EnrollRequest; using ::gatekeeper::EnrollResponse; using ::gatekeeper::VerifyRequest; using ::gatekeeper::VerifyResponse; using ::gatekeeper::SoftGateKeeper; using ::gatekeeper::secure_id_t; static void do_enroll(SoftGateKeeper &gatekeeper, EnrollResponse *response) { SizedBuffer password; password.buffer.reset(new uint8_t[16]); password.length = 16; memset(password.buffer.get(), 0, 16); EnrollRequest request(0, NULL, &password, NULL); 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; SizedBuffer password; EnrollResponse response; EnrollRequest request(0, NULL, &password, NULL); gatekeeper.Enroll(request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error); } TEST(GateKeeperTest, VerifySuccess) { SoftGateKeeper gatekeeper; SizedBuffer provided_password; EnrollResponse enroll_response; provided_password.buffer.reset(new uint8_t[16]); provided_password.length = 16; memset(provided_password.buffer.get(), 0, 16); do_enroll(gatekeeper, &enroll_response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); VerifyRequest request(0, 1, &enroll_response.enrolled_password_handle, &provided_password); VerifyResponse response; gatekeeper.Verify(request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); hw_auth_token_t *auth_token = reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get()); 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; SizedBuffer provided_password; EnrollResponse enroll_response; SizedBuffer password_handle; // do_enroll enrolls an all 0 password provided_password.buffer.reset(new uint8_t[16]); provided_password.length = 16; memset(provided_password.buffer.get(), 0, 16); do_enroll(gatekeeper, &enroll_response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); // keep a copy of the handle password_handle.buffer.reset(new uint8_t[enroll_response.enrolled_password_handle.length]); password_handle.length = enroll_response.enrolled_password_handle.length; memcpy(password_handle.buffer.get(), enroll_response.enrolled_password_handle.buffer.get(), password_handle.length); // verify first password VerifyRequest request(0, 0, &enroll_response.enrolled_password_handle, &provided_password); VerifyResponse response; gatekeeper.Verify(request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); hw_auth_token_t *auth_token = reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get()); secure_id_t secure_id = auth_token->user_id; // enroll new password provided_password.buffer.reset(new uint8_t[16]); provided_password.length = 16; memset(provided_password.buffer.get(), 0, 16); SizedBuffer password; password.buffer.reset(new uint8_t[16]); memset(password.buffer.get(), 1, 16); password.length = 16; EnrollRequest enroll_request(0, &password_handle, &password, &provided_password); gatekeeper.Enroll(enroll_request, &enroll_response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); // verify new password password.buffer.reset(new uint8_t[16]); memset(password.buffer.get(), 1, 16); password.length = 16; VerifyRequest new_request(0, 0, &enroll_response.enrolled_password_handle, &password); gatekeeper.Verify(new_request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); ASSERT_EQ(secure_id, reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get())->user_id); } TEST(GateKeeperTest, UntrustedReEnroll) { SoftGateKeeper gatekeeper; SizedBuffer provided_password; EnrollResponse enroll_response; // do_enroll enrolls an all 0 password provided_password.buffer.reset(new uint8_t[16]); provided_password.length = 16; memset(provided_password.buffer.get(), 0, 16); do_enroll(gatekeeper, &enroll_response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); // verify first password VerifyRequest request(0, 0, &enroll_response.enrolled_password_handle, &provided_password); VerifyResponse response; gatekeeper.Verify(request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); hw_auth_token_t *auth_token = reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get()); secure_id_t secure_id = auth_token->user_id; // enroll new password SizedBuffer password; password.buffer.reset(new uint8_t[16]); memset(password.buffer.get(), 1, 16); password.length = 16; EnrollRequest enroll_request(0, NULL, &password, NULL); gatekeeper.Enroll(enroll_request, &enroll_response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error); // verify new password password.buffer.reset(new uint8_t[16]); memset(password.buffer.get(), 1, 16); password.length = 16; VerifyRequest new_request(0, 0, &enroll_response.enrolled_password_handle, &password); gatekeeper.Verify(new_request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error); ASSERT_NE(secure_id, reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get())->user_id); } TEST(GateKeeperTest, VerifyBogusData) { SoftGateKeeper gatekeeper; SizedBuffer provided_password; SizedBuffer password_handle; VerifyResponse response; VerifyRequest request(0, 0, &provided_password, &password_handle); gatekeeper.Verify(request, &response); ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error); }