From 43773f6c42191841fbd030e298e223e3e27206e1 Mon Sep 17 00:00:00 2001 From: Janis Danisevskis Date: Tue, 4 Jun 2019 17:01:25 -0700 Subject: [PATCH] Added HIDL based software implementation of gatekeeper This patch adds a HIDL based software implementation of gatekeeper based on libgatekeeper. Also adds OWNER files to the vts test and default implementation directories. Test: Manually tested in emulator. Changing passwords and login worked. VtsHalGatekeeperV1_0TargetTest gatekeeper-software-device-unit-tests Change-Id: I632aeb6677640c133ec1b79e72568840adbc0550 Merged-In: I632aeb6677640c133ec1b79e72568840adbc0550 --- gatekeeper/1.0/default/OWNERS | 2 + gatekeeper/1.0/software/Android.bp | 28 +++ gatekeeper/1.0/software/OWNERS | 2 + gatekeeper/1.0/software/SoftGateKeeper.h | 171 +++++++++++++++++ .../1.0/software/SoftGateKeeperDevice.cpp | 114 +++++++++++ .../1.0/software/SoftGateKeeperDevice.h | 80 ++++++++ ...ardware.gatekeeper@1.0-service.software.rc | 4 + ...rdware.gatekeeper@1.0-service.software.xml | 11 ++ gatekeeper/1.0/software/service.cpp | 39 ++++ gatekeeper/1.0/software/tests/Android.bp | 34 ++++ .../1.0/software/tests/gatekeeper_test.cpp | 178 ++++++++++++++++++ gatekeeper/1.0/vts/OWNERS | 3 + 12 files changed, 666 insertions(+) create mode 100644 gatekeeper/1.0/default/OWNERS create mode 100644 gatekeeper/1.0/software/Android.bp create mode 100644 gatekeeper/1.0/software/OWNERS create mode 100644 gatekeeper/1.0/software/SoftGateKeeper.h create mode 100644 gatekeeper/1.0/software/SoftGateKeeperDevice.cpp create mode 100644 gatekeeper/1.0/software/SoftGateKeeperDevice.h create mode 100644 gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc create mode 100644 gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml create mode 100644 gatekeeper/1.0/software/service.cpp create mode 100644 gatekeeper/1.0/software/tests/Android.bp create mode 100644 gatekeeper/1.0/software/tests/gatekeeper_test.cpp create mode 100644 gatekeeper/1.0/vts/OWNERS diff --git a/gatekeeper/1.0/default/OWNERS b/gatekeeper/1.0/default/OWNERS new file mode 100644 index 0000000000..335660da3b --- /dev/null +++ b/gatekeeper/1.0/default/OWNERS @@ -0,0 +1,2 @@ +jdanis@google.com +swillden@google.com diff --git a/gatekeeper/1.0/software/Android.bp b/gatekeeper/1.0/software/Android.bp new file mode 100644 index 0000000000..148c98938f --- /dev/null +++ b/gatekeeper/1.0/software/Android.bp @@ -0,0 +1,28 @@ +cc_binary { + name: "android.hardware.gatekeeper@1.0-service.software", + defaults: ["hidl_defaults"], + relative_install_path: "hw", + vendor: true, + init_rc: ["android.hardware.gatekeeper@1.0-service.software.rc"], + + srcs: [ + "service.cpp", + "SoftGateKeeperDevice.cpp", + ], + + shared_libs: [ + "android.hardware.gatekeeper@1.0", + "libbase", + "libhardware", + "libhidlbase", + "libhidltransport", + "libutils", + "liblog", + "libcrypto", + "libgatekeeper", + ], + + static_libs: ["libscrypt_static"], + + vintf_fragments: ["android.hardware.gatekeeper@1.0-service.software.xml"], +} diff --git a/gatekeeper/1.0/software/OWNERS b/gatekeeper/1.0/software/OWNERS new file mode 100644 index 0000000000..335660da3b --- /dev/null +++ b/gatekeeper/1.0/software/OWNERS @@ -0,0 +1,2 @@ +jdanis@google.com +swillden@google.com diff --git a/gatekeeper/1.0/software/SoftGateKeeper.h b/gatekeeper/1.0/software/SoftGateKeeper.h new file mode 100644 index 0000000000..3276d1ebbd --- /dev/null +++ b/gatekeeper/1.0/software/SoftGateKeeper.h @@ -0,0 +1,171 @@ +/* + * 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. + * + */ + +#ifndef SOFT_GATEKEEPER_H_ +#define SOFT_GATEKEEPER_H_ + +extern "C" { +#include +#include + +#include +} + +#include +#include + +#include +#include +#include + +namespace gatekeeper { + +struct fast_hash_t { + uint64_t salt; + uint8_t digest[SHA256_DIGEST_LENGTH]; +}; + +class SoftGateKeeper : public GateKeeper { + public: + static const uint32_t SIGNATURE_LENGTH_BYTES = 32; + + // scrypt params + static const uint64_t N = 16384; + static const uint32_t r = 8; + static const uint32_t p = 1; + + static const int MAX_UINT_32_CHARS = 11; + + SoftGateKeeper() { + key_.reset(new uint8_t[SIGNATURE_LENGTH_BYTES]); + memset(key_.get(), 0, SIGNATURE_LENGTH_BYTES); + } + + virtual ~SoftGateKeeper() {} + + virtual bool GetAuthTokenKey(const uint8_t** auth_token_key, uint32_t* length) const { + if (auth_token_key == NULL || length == NULL) return false; + *auth_token_key = key_.get(); + *length = SIGNATURE_LENGTH_BYTES; + return true; + } + + virtual void GetPasswordKey(const uint8_t** password_key, uint32_t* length) { + if (password_key == NULL || length == NULL) return; + *password_key = key_.get(); + *length = SIGNATURE_LENGTH_BYTES; + } + + virtual void ComputePasswordSignature(uint8_t* signature, uint32_t signature_length, + const uint8_t*, uint32_t, const uint8_t* password, + uint32_t password_length, salt_t salt) const { + if (signature == NULL) return; + crypto_scrypt(password, password_length, reinterpret_cast(&salt), sizeof(salt), N, + r, p, signature, signature_length); + } + + virtual void GetRandom(void* random, uint32_t requested_length) const { + if (random == NULL) return; + RAND_pseudo_bytes((uint8_t*)random, requested_length); + } + + virtual void ComputeSignature(uint8_t* signature, uint32_t signature_length, const uint8_t*, + uint32_t, const uint8_t*, const uint32_t) const { + if (signature == NULL) return; + memset(signature, 0, signature_length); + } + + virtual uint64_t GetMillisecondsSinceBoot() const { + struct timespec time; + int res = clock_gettime(CLOCK_BOOTTIME, &time); + if (res < 0) return 0; + return (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000); + } + + virtual bool IsHardwareBacked() const { return false; } + + virtual bool GetFailureRecord(uint32_t uid, secure_id_t user_id, failure_record_t* record, + bool /* secure */) { + failure_record_t* stored = &failure_map_[uid]; + if (user_id != stored->secure_user_id) { + stored->secure_user_id = user_id; + stored->last_checked_timestamp = 0; + stored->failure_counter = 0; + } + memcpy(record, stored, sizeof(*record)); + return true; + } + + virtual bool ClearFailureRecord(uint32_t uid, secure_id_t user_id, bool /* secure */) { + failure_record_t* stored = &failure_map_[uid]; + stored->secure_user_id = user_id; + stored->last_checked_timestamp = 0; + stored->failure_counter = 0; + return true; + } + + virtual bool WriteFailureRecord(uint32_t uid, failure_record_t* record, bool /* secure */) { + failure_map_[uid] = *record; + return true; + } + + fast_hash_t ComputeFastHash(const SizedBuffer& password, uint64_t salt) { + fast_hash_t fast_hash; + size_t digest_size = password.size() + sizeof(salt); + std::unique_ptr digest(new uint8_t[digest_size]); + memcpy(digest.get(), &salt, sizeof(salt)); + memcpy(digest.get() + sizeof(salt), password.Data(), password.size()); + + SHA256(digest.get(), digest_size, (uint8_t*)&fast_hash.digest); + + fast_hash.salt = salt; + return fast_hash; + } + + bool VerifyFast(const fast_hash_t& fast_hash, const SizedBuffer& password) { + fast_hash_t computed = ComputeFastHash(password, fast_hash.salt); + return memcmp(computed.digest, fast_hash.digest, SHA256_DIGEST_LENGTH) == 0; + } + + bool DoVerify(const password_handle_t* expected_handle, const SizedBuffer& password) { + uint64_t user_id = android::base::get_unaligned(&expected_handle->user_id); + FastHashMap::const_iterator it = fast_hash_map_.find(user_id); + if (it != fast_hash_map_.end() && VerifyFast(it->second, password)) { + return true; + } else { + if (GateKeeper::DoVerify(expected_handle, password)) { + uint64_t salt; + GetRandom(&salt, sizeof(salt)); + fast_hash_map_[user_id] = ComputeFastHash(password, salt); + return true; + } + } + + return false; + } + + private: + typedef std::unordered_map FailureRecordMap; + typedef std::unordered_map FastHashMap; + + std::unique_ptr key_; + FailureRecordMap failure_map_; + FastHashMap fast_hash_map_; +}; +} // namespace gatekeeper + +#endif // SOFT_GATEKEEPER_H_ diff --git a/gatekeeper/1.0/software/SoftGateKeeperDevice.cpp b/gatekeeper/1.0/software/SoftGateKeeperDevice.cpp new file mode 100644 index 0000000000..d7a0b46ee6 --- /dev/null +++ b/gatekeeper/1.0/software/SoftGateKeeperDevice.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 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 "SoftGateKeeperDevice.h" +#include "SoftGateKeeper.h" + +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode; +using ::gatekeeper::EnrollRequest; +using ::gatekeeper::EnrollResponse; +using ::gatekeeper::ERROR_INVALID; +using ::gatekeeper::ERROR_MEMORY_ALLOCATION_FAILED; +using ::gatekeeper::ERROR_NONE; +using ::gatekeeper::ERROR_RETRY; +using ::gatekeeper::SizedBuffer; +using ::gatekeeper::VerifyRequest; +using ::gatekeeper::VerifyResponse; + +#include + +namespace android { + +inline SizedBuffer hidl_vec2sized_buffer(const hidl_vec& vec) { + if (vec.size() == 0 || vec.size() > std::numeric_limits::max()) return {}; + auto dummy = new uint8_t[vec.size()]; + std::copy(vec.begin(), vec.end(), dummy); + return {dummy, static_cast(vec.size())}; +} + +Return SoftGateKeeperDevice::enroll(uint32_t uid, + const hidl_vec& currentPasswordHandle, + const hidl_vec& currentPassword, + const hidl_vec& desiredPassword, + enroll_cb _hidl_cb) { + if (desiredPassword.size() == 0) { + _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}}); + return {}; + } + + EnrollRequest request(uid, hidl_vec2sized_buffer(currentPasswordHandle), + hidl_vec2sized_buffer(desiredPassword), + hidl_vec2sized_buffer(currentPassword)); + EnrollResponse response; + impl_->Enroll(request, &response); + + if (response.error == ERROR_RETRY) { + _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}}); + } else if (response.error != ERROR_NONE) { + _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}}); + } else { + hidl_vec new_handle(response.enrolled_password_handle.Data(), + response.enrolled_password_handle.Data() + + response.enrolled_password_handle.size()); + _hidl_cb({GatekeeperStatusCode::STATUS_OK, response.retry_timeout, new_handle}); + } + return {}; +} + +Return SoftGateKeeperDevice::verify( + uint32_t uid, uint64_t challenge, + const ::android::hardware::hidl_vec& enrolledPasswordHandle, + const ::android::hardware::hidl_vec& providedPassword, verify_cb _hidl_cb) { + if (enrolledPasswordHandle.size() == 0) { + _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}}); + return {}; + } + + VerifyRequest request(uid, challenge, hidl_vec2sized_buffer(enrolledPasswordHandle), + hidl_vec2sized_buffer(providedPassword)); + VerifyResponse response; + + impl_->Verify(request, &response); + + if (response.error == ERROR_RETRY) { + _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}}); + } else if (response.error != ERROR_NONE) { + _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}}); + } else { + hidl_vec auth_token( + response.auth_token.Data(), + response.auth_token.Data() + response.auth_token.size()); + + _hidl_cb({response.request_reenroll ? GatekeeperStatusCode::STATUS_REENROLL + : GatekeeperStatusCode::STATUS_OK, + response.retry_timeout, auth_token}); + } + return {}; +} + +Return SoftGateKeeperDevice::deleteUser(uint32_t /*uid*/, deleteUser_cb _hidl_cb) { + _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}}); + return {}; +} + +Return SoftGateKeeperDevice::deleteAllUsers(deleteAllUsers_cb _hidl_cb) { + _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}}); + return {}; +} + +} // namespace android diff --git a/gatekeeper/1.0/software/SoftGateKeeperDevice.h b/gatekeeper/1.0/software/SoftGateKeeperDevice.h new file mode 100644 index 0000000000..17b474e4aa --- /dev/null +++ b/gatekeeper/1.0/software/SoftGateKeeperDevice.h @@ -0,0 +1,80 @@ +/* + * 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. + */ + +#ifndef SOFT_GATEKEEPER_DEVICE_H_ +#define SOFT_GATEKEEPER_DEVICE_H_ + +#include +#include + +#include +#include "SoftGateKeeper.h" + +namespace android { + +/** + * Software based GateKeeper implementation + */ +class SoftGateKeeperDevice : public ::android::hardware::gatekeeper::V1_0::IGatekeeper { + public: + SoftGateKeeperDevice() { impl_.reset(new ::gatekeeper::SoftGateKeeper()); } + + // Wrappers to translate the gatekeeper HAL API to the Kegyuard Messages API. + + /** + * Enrolls password_payload, which should be derived from a user selected pin or password, + * with the authentication factor private key used only for enrolling authentication + * factor data. + * + * Returns: 0 on success or an error code less than 0 on error. + * On error, enrolled_password_handle will not be allocated. + */ + ::android::hardware::Return enroll( + uint32_t uid, const ::android::hardware::hidl_vec& currentPasswordHandle, + const ::android::hardware::hidl_vec& currentPassword, + const ::android::hardware::hidl_vec& desiredPassword, + enroll_cb _hidl_cb) override; + + /** + * Verifies provided_password matches enrolled_password_handle. + * + * Implementations of this module may retain the result of this call + * to attest to the recency of authentication. + * + * On success, writes the address of a verification token to auth_token, + * usable to attest password verification to other trusted services. Clients + * may pass NULL for this value. + * + * Returns: 0 on success or an error code less than 0 on error + * On error, verification token will not be allocated + */ + ::android::hardware::Return verify( + uint32_t uid, uint64_t challenge, + const ::android::hardware::hidl_vec& enrolledPasswordHandle, + const ::android::hardware::hidl_vec& providedPassword, + verify_cb _hidl_cb) override; + + ::android::hardware::Return deleteUser(uint32_t uid, deleteUser_cb _hidl_cb) override; + + ::android::hardware::Return deleteAllUsers(deleteAllUsers_cb _hidl_cb) override; + + private: + std::unique_ptr<::gatekeeper::SoftGateKeeper> impl_; +}; + +} // namespace android + +#endif // SOFT_GATEKEEPER_DEVICE_H_ diff --git a/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc new file mode 100644 index 0000000000..60cb96c915 --- /dev/null +++ b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc @@ -0,0 +1,4 @@ +service vendor.gatekeeper-1-0 /vendor/bin/hw/android.hardware.gatekeeper@1.0-service.software + class hal + user system + group system diff --git a/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml new file mode 100644 index 0000000000..19714a83b7 --- /dev/null +++ b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml @@ -0,0 +1,11 @@ + + + android.hardware.gatekeeper + hwbinder + 1.0 + + IGatekeeper + default + + + diff --git a/gatekeeper/1.0/software/service.cpp b/gatekeeper/1.0/software/service.cpp new file mode 100644 index 0000000000..a48a964c08 --- /dev/null +++ b/gatekeeper/1.0/software/service.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 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. + */ +#define LOG_TAG "android.hardware.gatekeeper@1.0-service" + +#include +#include + +#include + +#include "SoftGateKeeperDevice.h" + +// Generated HIDL files +using android::SoftGateKeeperDevice; +using android::hardware::gatekeeper::V1_0::IGatekeeper; + +int main() { + ::android::hardware::configureRpcThreadpool(1, true /* willJoinThreadpool */); + android::sp gatekeeper(new SoftGateKeeperDevice()); + auto status = gatekeeper->registerAsService(); + if (status != android::OK) { + LOG(FATAL) << "Could not register service for Gatekeeper 1.0 (software) (" << status << ")"; + } + + android::hardware::joinRpcThreadpool(); + return -1; // Should never get here. +} diff --git a/gatekeeper/1.0/software/tests/Android.bp b/gatekeeper/1.0/software/tests/Android.bp new file mode 100644 index 0000000000..3f0300dc18 --- /dev/null +++ b/gatekeeper/1.0/software/tests/Android.bp @@ -0,0 +1,34 @@ +// +// Copyright (C) 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. +// + +cc_test { + name: "gatekeeper-software-device-unit-tests", + + cflags: [ + "-g", + "-Wall", + "-Werror", + "-Wno-missing-field-initializers", + ], + shared_libs: [ + "libgatekeeper", + "libcrypto", + "libbase", + ], + static_libs: ["libscrypt_static"], + + srcs: ["gatekeeper_test.cpp"], +} diff --git a/gatekeeper/1.0/software/tests/gatekeeper_test.cpp b/gatekeeper/1.0/software/tests/gatekeeper_test.cpp new file mode 100644 index 0000000000..bf4a8bc5fa --- /dev/null +++ b/gatekeeper/1.0/software/tests/gatekeeper_test.cpp @@ -0,0 +1,178 @@ +/* + * 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); +} diff --git a/gatekeeper/1.0/vts/OWNERS b/gatekeeper/1.0/vts/OWNERS new file mode 100644 index 0000000000..738c71025a --- /dev/null +++ b/gatekeeper/1.0/vts/OWNERS @@ -0,0 +1,3 @@ +jdanis@google.com +swillden@google.com +guangzhu@google.com