diff options
-rw-r--r-- | gatekeeperd/Android.mk | 8 | ||||
-rw-r--r-- | gatekeeperd/SoftGateKeeperDevice.cpp | 100 | ||||
-rw-r--r-- | gatekeeperd/SoftGateKeeperDevice.h | 75 | ||||
-rw-r--r-- | gatekeeperd/gatekeeperd.cpp | 48 |
4 files changed, 216 insertions, 15 deletions
diff --git a/gatekeeperd/Android.mk b/gatekeeperd/Android.mk index f743cc3..be3d6fc 100644 --- a/gatekeeperd/Android.mk +++ b/gatekeeperd/Android.mk @@ -18,14 +18,16 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_CFLAGS := -Wall -Wextra -Werror -Wunused -LOCAL_SRC_FILES := IGateKeeperService.cpp gatekeeperd.cpp +LOCAL_SRC_FILES := SoftGateKeeperDevice.cpp IGateKeeperService.cpp gatekeeperd.cpp LOCAL_MODULE := gatekeeperd LOCAL_SHARED_LIBRARIES := \ libbinder \ + libgatekeeper \ liblog \ libhardware \ libutils \ + libcrypto \ libkeystore_binder -LOCAL_C_INCLUDES := \ - system/gatekeeper/include +LOCAL_STATIC_LIBRARIES := libscrypt_static +LOCAL_C_INCLUDES := external/scrypt/lib/crypto include $(BUILD_EXECUTABLE) diff --git a/gatekeeperd/SoftGateKeeperDevice.cpp b/gatekeeperd/SoftGateKeeperDevice.cpp new file mode 100644 index 0000000..b96bf8d --- /dev/null +++ b/gatekeeperd/SoftGateKeeperDevice.cpp @@ -0,0 +1,100 @@ +/* + * 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 <gatekeeper/soft_gatekeeper.h> + +#include "SoftGateKeeperDevice.h" + +namespace android { + +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) { + + if (enrolled_password_handle == NULL || enrolled_password_handle_length == NULL || + desired_password == NULL || desired_password_length == 0) + return -EINVAL; + + // Current password and current password handle go together + if (current_password_handle == NULL || current_password_handle_length == 0 || + current_password == NULL || current_password_length == 0) { + current_password_handle = NULL; + current_password_handle_length = 0; + current_password = NULL; + current_password_length = 0; + } + + SizedBuffer desired_password_buffer(desired_password_length); + memcpy(desired_password_buffer.buffer.get(), desired_password, desired_password_length); + + SizedBuffer current_password_handle_buffer(current_password_handle_length); + if (current_password_handle) { + memcpy(current_password_handle_buffer.buffer.get(), current_password_handle, + current_password_handle_length); + } + + SizedBuffer current_password_buffer(current_password_length); + if (current_password) { + memcpy(current_password_buffer.buffer.get(), current_password, current_password_length); + } + + EnrollRequest request(uid, ¤t_password_handle_buffer, &desired_password_buffer, + ¤t_password_buffer); + EnrollResponse response; + + impl_->Enroll(request, &response); + + 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 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) { + + if (enrolled_password_handle == NULL || + provided_password == NULL) { + return -EINVAL; + } + + SizedBuffer password_handle_buffer(enrolled_password_handle_length); + memcpy(password_handle_buffer.buffer.get(), enrolled_password_handle, + enrolled_password_handle_length); + SizedBuffer provided_password_buffer(provided_password_length); + memcpy(provided_password_buffer.buffer.get(), provided_password, provided_password_length); + + VerifyRequest request(uid, challenge, &password_handle_buffer, &provided_password_buffer); + VerifyResponse response; + + impl_->Verify(request, &response); + + if (response.error != ERROR_NONE) + return -EINVAL; + + if (auth_token != NULL && auth_token_length != NULL) { + *auth_token = response.auth_token.buffer.release(); + *auth_token_length = response.auth_token.length; + } + + return 0; +} +} // namespace android diff --git a/gatekeeperd/SoftGateKeeperDevice.h b/gatekeeperd/SoftGateKeeperDevice.h new file mode 100644 index 0000000..c0b5047 --- /dev/null +++ b/gatekeeperd/SoftGateKeeperDevice.h @@ -0,0 +1,75 @@ +/* + * 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 <gatekeeper/soft_gatekeeper.h> +#include <UniquePtr.h> + +using namespace gatekeeper; + +namespace android { + +/** + * Software based GateKeeper implementation + */ +class SoftGateKeeperDevice { +public: + SoftGateKeeperDevice() { + impl_.reset(new 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. + */ + 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); +private: + UniquePtr<GateKeeper> impl_; +}; + +} // namespace gatekeeper + +#endif //SOFT_GATEKEEPER_DEVICE_H_ diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp index 75cd225..72c7ba2 100644 --- a/gatekeeperd/gatekeeperd.cpp +++ b/gatekeeperd/gatekeeperd.cpp @@ -38,6 +38,8 @@ #include <hardware/gatekeeper.h> #include <hardware/hw_auth_token.h> +#include "SoftGateKeeperDevice.h" + namespace android { static const String16 KEYGUARD_PERMISSION("android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"); @@ -47,15 +49,18 @@ class GateKeeperProxy : public BnGateKeeperService { public: GateKeeperProxy() { int ret = hw_get_module_by_class(GATEKEEPER_HARDWARE_MODULE_ID, NULL, &module); - if (ret < 0) - LOG_ALWAYS_FATAL_IF(ret < 0, "Unable to find GateKeeper HAL"); - ret = gatekeeper_open(module, &device); - if (ret < 0) - LOG_ALWAYS_FATAL_IF(ret < 0, "Unable to open GateKeeper HAL"); + if (ret < 0) { + ALOGW("falling back to software GateKeeper"); + soft_device.reset(new SoftGateKeeperDevice()); + } else { + ret = gatekeeper_open(module, &device); + if (ret < 0) + LOG_ALWAYS_FATAL_IF(ret < 0, "Unable to open GateKeeper HAL"); + } } virtual ~GateKeeperProxy() { - gatekeeper_close(device); + if (device) gatekeeper_close(device); } void store_sid(uint32_t uid, uint64_t sid) { @@ -111,11 +116,22 @@ public: // need a desired password to enroll if (desired_password_length == 0) return -EINVAL; - int ret = device->enroll(device, uid, - current_password_handle, current_password_handle_length, - current_password, current_password_length, - desired_password, desired_password_length, - enrolled_password_handle, enrolled_password_handle_length); + + int ret; + if (device) { + ret = device->enroll(device, uid, + current_password_handle, current_password_handle_length, + current_password, current_password_length, + desired_password, desired_password_length, + enrolled_password_handle, enrolled_password_handle_length); + } else { + ret = soft_device->enroll(uid, + current_password_handle, current_password_handle_length, + current_password, current_password_length, + desired_password, desired_password_length, + enrolled_password_handle, enrolled_password_handle_length); + } + if (ret >= 0) { gatekeeper::password_handle_t *handle = reinterpret_cast<gatekeeper::password_handle_t *>(*enrolled_password_handle); @@ -150,9 +166,16 @@ public: if ((enrolled_password_handle_length | provided_password_length) == 0) return -EINVAL; - int ret = device->verify(device, uid, challenge, + int ret; + if (device) { + ret = device->verify(device, uid, challenge, enrolled_password_handle, enrolled_password_handle_length, provided_password, provided_password_length, auth_token, auth_token_length); + } else { + ret = soft_device->verify(uid, challenge, + enrolled_password_handle, enrolled_password_handle_length, + provided_password, provided_password_length, auth_token, auth_token_length); + } if (ret >= 0 && *auth_token != NULL && *auth_token_length > 0) { // TODO: cache service? @@ -214,6 +237,7 @@ public: private: gatekeeper_device_t *device; + UniquePtr<SoftGateKeeperDevice> soft_device; const hw_module_t *module; }; }// namespace android |