From 125f7bb3eef36d9d9c96f8048e70f84c4a764d21 Mon Sep 17 00:00:00 2001 From: Tellen Yu Date: Wed, 06 Sep 2017 07:29:57 +0000 Subject: VTS: use software gatekeeper instead of trusty [1/1] PD# NONE use software gatekeeper simulate hardware gatekeeper, because, our platform don't use it Change-Id: Idbe7f7aac2b2606bae8e5d5d5e949d7b0eeb96f1 --- diff --git a/Android.mk b/Android.mk index ad5ca02..dc0165b 100644 --- a/Android.mk +++ b/Android.mk @@ -29,9 +29,16 @@ LOCAL_MODULE := gatekeeper.amlogic LOCAL_MODULE_RELATIVE_PATH := hw LOCAL_SRC_FILES := \ - module.cpp \ - trusty_gatekeeper_ipc.c \ - trusty_gatekeeper.cpp + GKPModule.cpp \ + trusty/trusty_gatekeeper_ipc.c \ + trusty/trusty_gatekeeper.cpp \ + soft/SoftGateKeeperDevice.cpp + +LOCAL_STATIC_LIBRARIES := libscrypt_static +LOCAL_C_INCLUDES := \ + external/boringssl/src/include/ \ + external/scrypt/lib/crypto \ + system/core/base/include LOCAL_CLFAGS = -fvisibility=hidden -Wall -Werror @@ -39,8 +46,13 @@ LOCAL_SHARED_LIBRARIES := \ libgatekeeper \ liblog \ libcutils \ - libtrusty + libtrusty \ + libcrypto LOCAL_MODULE_TAGS := optional +ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26 && echo OK),OK) +LOCAL_PROPRIETARY_MODULE := true +endif + include $(BUILD_SHARED_LIBRARY) diff --git a/module.cpp b/GKPModule.cpp index 0ee3c2f..15ed4d8 100644 --- a/module.cpp +++ b/GKPModule.cpp @@ -20,26 +20,36 @@ #include #include -#include "trusty_gatekeeper.h" +#include "trusty/trusty_gatekeeper.h" +#include "soft/SoftGateKeeperDevice.h" using gatekeeper::TrustyGateKeeperDevice; +using android::SoftGateKeeperDevice; -static int trusty_gatekeeper_open(const hw_module_t *module, const char *name, +static int gatekeeper_open(const hw_module_t *module, const char *name, hw_device_t **device) { if (strcmp(name, HARDWARE_GATEKEEPER) != 0) { return -EINVAL; } - TrustyGateKeeperDevice *gatekeeper = new TrustyGateKeeperDevice(module); - if (gatekeeper == NULL) return -ENOMEM; - *device = gatekeeper->hw_device(); + //trusty gatekeeper don't implement, so use software instead of + if (true) { + SoftGateKeeperDevice *gatekeeper = new SoftGateKeeperDevice(module); + if (gatekeeper == NULL) return -ENOMEM; + *device = gatekeeper->sw_device(); + } + else { + TrustyGateKeeperDevice *gatekeeper = new TrustyGateKeeperDevice(module); + if (gatekeeper == NULL) return -ENOMEM; + *device = gatekeeper->hw_device(); + } return 0; } static struct hw_module_methods_t gatekeeper_module_methods = { - .open = trusty_gatekeeper_open, + .open = gatekeeper_open, }; struct gatekeeper_module HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = { @@ -48,8 +58,8 @@ struct gatekeeper_module HAL_MODULE_INFO_SYM __attribute__((visibility("default" .module_api_version = GATEKEEPER_MODULE_API_VERSION_0_1, .hal_api_version = HARDWARE_HAL_API_VERSION, .id = GATEKEEPER_HARDWARE_MODULE_ID, - .name = "Trusty GateKeeper HAL", - .author = "The Android Open Source Project", + .name = "AML GateKeeper HAL", + .author = "aml", .methods = &gatekeeper_module_methods, .dso = 0, .reserved = {} diff --git a/soft/SoftGateKeeper.h b/soft/SoftGateKeeper.h new file mode 100644 index 0000000..cb02a6f --- a/dev/null +++ b/soft/SoftGateKeeper.h @@ -0,0 +1,182 @@ +/* + * 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; + uint8_t *auth_token_key_copy = new uint8_t[SIGNATURE_LENGTH_BYTES]; + memcpy(auth_token_key_copy, key_.get(), SIGNATURE_LENGTH_BYTES); + + *auth_token_key = auth_token_key_copy; + *length = SIGNATURE_LENGTH_BYTES; + return true; + } + + virtual void GetPasswordKey(const uint8_t **password_key, uint32_t *length) { + if (password_key == NULL || length == NULL) return; + uint8_t *password_key_copy = new uint8_t[SIGNATURE_LENGTH_BYTES]; + memcpy(password_key_copy, key_.get(), SIGNATURE_LENGTH_BYTES); + + *password_key = password_key_copy; + *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.length + sizeof(salt); + std::unique_ptr digest(new uint8_t[digest_size]); + memcpy(digest.get(), &salt, sizeof(salt)); + memcpy(digest.get() + sizeof(salt), password.buffer.get(), password.length); + + 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; + + UniquePtr key_; + FailureRecordMap failure_map_; + FastHashMap fast_hash_map_; +}; +} + +#endif // SOFT_GATEKEEPER_H_ diff --git a/trusty_gatekeeper.cpp b/soft/SoftGateKeeperDevice.cpp index b3fbfa9..ea52688 100644 --- a/trusty_gatekeeper.cpp +++ b/soft/SoftGateKeeperDevice.cpp @@ -14,80 +14,50 @@ * limitations under the License. */ -#define LOG_TAG "TrustyGateKeeper" - #include #include #include +#include "SoftGateKeeper.h" +#include "SoftGateKeeperDevice.h" -#include - -#include - -#include "trusty_gatekeeper.h" -#include "trusty_gatekeeper_ipc.h" -#include "gatekeeper_ipc.h" - -namespace gatekeeper { - -const uint32_t SEND_BUF_SIZE = 8192; -const uint32_t RECV_BUF_SIZE = 8192; - -TrustyGateKeeperDevice::TrustyGateKeeperDevice(const hw_module_t *module) { -#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) - static_assert(std::is_standard_layout::value, - "TrustyGateKeeperDevice must be standard layout"); - static_assert(offsetof(TrustyGateKeeperDevice, device_) == 0, - "device_ must be the first member of TrustyGateKeeperDevice"); - static_assert(offsetof(TrustyGateKeeperDevice, device_.common) == 0, - "common must be the first member of gatekeeper_device"); -#else - assert(reinterpret_cast(this) == &device_); - assert(reinterpret_cast(this) == &(device_.common)); -#endif - - memset(&device_, 0, sizeof(device_)); - device_.common.tag = HARDWARE_DEVICE_TAG; - device_.common.version = 1; - device_.common.module = const_cast(module); - device_.common.close = close_device; - - device_.enroll = enroll; - device_.verify = verify; - device_.delete_user = nullptr; - device_.delete_all_users = nullptr; - - int rc = trusty_gatekeeper_connect(); - if (rc < 0) { - ALOGE("Error initializing trusty session: %d", rc); - } +namespace android { - error_ = rc; +SoftGateKeeperDevice::SoftGateKeeperDevice(const hw_module_t *module) { + assert(reinterpret_cast(this) == &deviceSoft); + assert(reinterpret_cast(this) == &(deviceSoft.common)); -} + memset(&deviceSoft, 0, sizeof(deviceSoft)); + deviceSoft.common.tag = HARDWARE_DEVICE_TAG; + deviceSoft.common.version = 1; + deviceSoft.common.module = const_cast(module); + deviceSoft.common.close = close_device; -hw_device_t* TrustyGateKeeperDevice::hw_device() { - return &device_.common; + deviceSoft.enroll = enroll; + deviceSoft.verify = verify; + deviceSoft.delete_user = nullptr; + deviceSoft.delete_all_users = nullptr; + + implSoft.reset(new SoftGateKeeper()); } -int TrustyGateKeeperDevice::close_device(hw_device_t* dev) { - delete reinterpret_cast(dev); +int SoftGateKeeperDevice::close_device(hw_device_t* dev) { + delete reinterpret_cast(dev); return 0; } -TrustyGateKeeperDevice::~TrustyGateKeeperDevice() { - trusty_gatekeeper_disconnect(); +SoftGateKeeperDevice::~SoftGateKeeperDevice() { + } -int TrustyGateKeeperDevice::Enroll(uint32_t uid, const uint8_t *current_password_handle, - uint32_t current_password_handle_length, const uint8_t *current_password, - uint32_t current_password_length, const uint8_t *desired_password, - uint32_t desired_password_length, uint8_t **enrolled_password_handle, - uint32_t *enrolled_password_handle_length) { +hw_device_t* SoftGateKeeperDevice::sw_device() { + return &deviceSoft.common; +} - if (error_ != 0) { - return error_; - } +int SoftGateKeeperDevice::Enroll(uint32_t uid, + const uint8_t *current_password_handle, uint32_t current_password_handle_length, + const uint8_t *current_password, uint32_t current_password_length, + const uint8_t *desired_password, uint32_t desired_password_length, + uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) { SizedBuffer desired_password_buffer(desired_password_length); memcpy(desired_password_buffer.buffer.get(), desired_password, desired_password_length); @@ -107,28 +77,24 @@ int TrustyGateKeeperDevice::Enroll(uint32_t uid, const uint8_t *current_password ¤t_password_buffer); EnrollResponse response; - gatekeeper_error_t error = Send(request, &response); + implSoft->Enroll(request, &response); - if (error == ERROR_RETRY) { + if (response.error == ERROR_RETRY) { return response.retry_timeout; - } else if (error != ERROR_NONE) { + } else if (response.error != ERROR_NONE) { return -EINVAL; } *enrolled_password_handle = response.enrolled_password_handle.buffer.release(); *enrolled_password_handle_length = response.enrolled_password_handle.length; - - return 0; } -int TrustyGateKeeperDevice::Verify(uint32_t uid, uint64_t challenge, - const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length, - const uint8_t *provided_password, uint32_t provided_password_length, - uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll) { - if (error_ != 0) { - return error_; - } +int SoftGateKeeperDevice::Verify(uint32_t uid, + uint64_t challenge, const uint8_t *enrolled_password_handle, + uint32_t enrolled_password_handle_length, const uint8_t *provided_password, + uint32_t provided_password_length, uint8_t **auth_token, uint32_t *auth_token_length, + bool *request_reenroll) { SizedBuffer password_handle_buffer(enrolled_password_handle_length); memcpy(password_handle_buffer.buffer.get(), enrolled_password_handle, @@ -139,11 +105,11 @@ int TrustyGateKeeperDevice::Verify(uint32_t uid, uint64_t challenge, VerifyRequest request(uid, challenge, &password_handle_buffer, &provided_password_buffer); VerifyResponse response; - gatekeeper_error_t error = Send(request, &response); + implSoft->Verify(request, &response); - if (error == ERROR_RETRY) { + if (response.error == ERROR_RETRY) { return response.retry_timeout; - } else if (error != ERROR_NONE) { + } else if (response.error != ERROR_NONE) { return -EINVAL; } @@ -159,35 +125,12 @@ int TrustyGateKeeperDevice::Verify(uint32_t uid, uint64_t challenge, return 0; } -gatekeeper_error_t TrustyGateKeeperDevice::Send(uint32_t command, const GateKeeperMessage& request, - GateKeeperMessage *response) { - uint32_t request_size = request.GetSerializedSize(); - if (request_size > SEND_BUF_SIZE) - return ERROR_INVALID; - uint8_t send_buf[SEND_BUF_SIZE]; - request.Serialize(send_buf, send_buf + request_size); - - // Send it - uint8_t recv_buf[RECV_BUF_SIZE]; - uint32_t response_size = RECV_BUF_SIZE; - int rc = trusty_gatekeeper_call(command, send_buf, request_size, recv_buf, &response_size); - if (rc < 0) { - ALOGE("error (%d) calling gatekeeper TA", rc); - return ERROR_INVALID; - } - - const gatekeeper_message *msg = reinterpret_cast(recv_buf); - const uint8_t *payload = msg->payload; - - return response->Deserialize(payload, payload + response_size); -} - -static inline TrustyGateKeeperDevice *convert_device(const gatekeeper_device *dev) { - return reinterpret_cast(const_cast(dev)); +static inline SoftGateKeeperDevice *convert_device(const gatekeeper_device *dev) { + return reinterpret_cast(const_cast(dev)); } /* static */ -int TrustyGateKeeperDevice::enroll(const struct gatekeeper_device *dev, uint32_t uid, +int SoftGateKeeperDevice::enroll(const struct gatekeeper_device *dev, uint32_t uid, const uint8_t *current_password_handle, uint32_t current_password_handle_length, const uint8_t *current_password, uint32_t current_password_length, const uint8_t *desired_password, uint32_t desired_password_length, @@ -214,7 +157,7 @@ int TrustyGateKeeperDevice::enroll(const struct gatekeeper_device *dev, uint32_t } /* static */ -int TrustyGateKeeperDevice::verify(const struct gatekeeper_device *dev, uint32_t uid, +int SoftGateKeeperDevice::verify(const struct gatekeeper_device *dev, uint32_t uid, uint64_t challenge, const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length, const uint8_t *provided_password, uint32_t provided_password_length, uint8_t **auth_token, uint32_t *auth_token_length, @@ -229,4 +172,4 @@ int TrustyGateKeeperDevice::verify(const struct gatekeeper_device *dev, uint32_t enrolled_password_handle_length, provided_password, provided_password_length, auth_token, auth_token_length, request_reenroll); } -}; +} // namespace android diff --git a/soft/SoftGateKeeperDevice.h b/soft/SoftGateKeeperDevice.h new file mode 100644 index 0000000..ae71b8c --- a/dev/null +++ b/soft/SoftGateKeeperDevice.h @@ -0,0 +1,93 @@ +/* + * 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 "SoftGateKeeper.h" + +#include + +using namespace gatekeeper; + +namespace android { + +/** + * Software based GateKeeper implementation + */ +class SoftGateKeeperDevice { +public: + SoftGateKeeperDevice(const hw_module_t *module); + ~SoftGateKeeperDevice(); + + hw_device_t* sw_device(); + + // 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. + */ + int Enroll(uint32_t uid, + const uint8_t *current_password_handle, uint32_t current_password_handle_length, + const uint8_t *current_password, uint32_t current_password_length, + const uint8_t *desired_password, uint32_t desired_password_length, + uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length); + + /** + * 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 + */ + int Verify(uint32_t uid, uint64_t challenge, + const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length, + const uint8_t *provided_password, uint32_t provided_password_length, + uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll); + + static int enroll(const struct gatekeeper_device *dev, uint32_t uid, + const uint8_t *current_password_handle, uint32_t current_password_handle_length, + const uint8_t *current_password, uint32_t current_password_length, + const uint8_t *desired_password, uint32_t desired_password_length, + uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length); + + static int verify(const struct gatekeeper_device *dev, uint32_t uid, uint64_t challenge, + const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length, + const uint8_t *provided_password, uint32_t provided_password_length, + uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll); + + static int close_device(hw_device_t* dev); + + gatekeeper_device deviceSoft; +private: + UniquePtr implSoft; +}; + +} // namespace gatekeeper + +#endif //SOFT_GATEKEEPER_DEVICE_H_ diff --git a/gatekeeper_ipc.h b/trusty/gatekeeper_ipc.h index b05dcd8..b05dcd8 100644 --- a/gatekeeper_ipc.h +++ b/trusty/gatekeeper_ipc.h diff --git a/trusty_gatekeeper.cpp b/trusty/trusty_gatekeeper.cpp index b3fbfa9..b3fbfa9 100644 --- a/trusty_gatekeeper.cpp +++ b/trusty/trusty_gatekeeper.cpp diff --git a/trusty_gatekeeper.h b/trusty/trusty_gatekeeper.h index 2becc49..2becc49 100644 --- a/trusty_gatekeeper.h +++ b/trusty/trusty_gatekeeper.h diff --git a/trusty_gatekeeper_ipc.c b/trusty/trusty_gatekeeper_ipc.c index f67944b..f67944b 100644 --- a/trusty_gatekeeper_ipc.c +++ b/trusty/trusty_gatekeeper_ipc.c diff --git a/trusty_gatekeeper_ipc.h b/trusty/trusty_gatekeeper_ipc.h index f8de7f8..f8de7f8 100644 --- a/trusty_gatekeeper_ipc.h +++ b/trusty/trusty_gatekeeper_ipc.h -- cgit