summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres Morales <anmorales@google.com>2015-03-06 10:55:18 -0800
committerAndres Morales <anmorales@google.com>2015-03-09 12:36:11 -0700
commit99482129e592892ef40613195d2cbcd640e031cd (patch)
tree5e74836445d23e8fad437885de90b4eb2a544e14
parentb2abaa89b8090c7f14048d4404a3eb146f709a6a (diff)
downloadgatekeeper-99482129e592892ef40613195d2cbcd640e031cd.tar.gz
SoftKeyguard module
hw module piping for sw based keyguard Change-Id: I335e09180e59b4d4e4fdbd1c35970d58cded3b1b
-rw-r--r--Android.mk1
-rw-r--r--include/keyguard/keyguard_messages.h6
-rw-r--r--include/keyguard/soft_keyguard_device.h81
-rw-r--r--softkeyguard/Android.mk32
-rw-r--r--softkeyguard/module.cpp21
-rw-r--r--softkeyguard/soft_keyguard_device.cpp151
-rw-r--r--tests/Android.mk5
-rw-r--r--tests/keyguard_device_test.cpp91
8 files changed, 386 insertions, 2 deletions
diff --git a/Android.mk b/Android.mk
index 8f5dc03..1c4916c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -31,3 +31,4 @@ LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_SHARED_LIBRARY)
+include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/include/keyguard/keyguard_messages.h b/include/keyguard/keyguard_messages.h
index 5851d26..eb8a43c 100644
--- a/include/keyguard/keyguard_messages.h
+++ b/include/keyguard/keyguard_messages.h
@@ -35,6 +35,12 @@ struct SizedBuffer {
SizedBuffer() {
length = 0;
}
+
+ /*
+ * Constructs a SizedBuffer out of a pointer and a length
+ * Takes ownership of the buf pointer, and deallocates it
+ * when destructed.
+ */
SizedBuffer(uint8_t *buf, size_t len) {
buffer.reset(buf);
length = len;
diff --git a/include/keyguard/soft_keyguard_device.h b/include/keyguard/soft_keyguard_device.h
new file mode 100644
index 0000000..6da20de
--- /dev/null
+++ b/include/keyguard/soft_keyguard_device.h
@@ -0,0 +1,81 @@
+/*
+ * 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 SYSTEM_SOFT_KEYGUARD_DEVICE_H_
+#define SYSTEM_SOFT_KEYGUARD_DEVICE_H_
+
+#include <keyguard/soft_keyguard.h>
+#include <hardware/keyguard.h>
+#include <UniquePtr.h>
+
+namespace keyguard {
+
+/**
+ * Software based Keyguard implementation
+ *
+ * IMPORTANT MAINTAINER NOTE: Pointers to instances of this class must be castable to hw_device_t
+ * and keyguard. This means it must remain a standard layout class (no virtual functions and
+ * no data members which aren't standard layout), and device_ must be the first data member.
+ * Assertions in the constructor validate compliance with those constraints.
+ */
+class SoftKeyguardDevice {
+public:
+ SoftKeyguardDevice(const hw_module_t *module);
+
+ hw_device_t *hw_device();
+
+private:
+ static int close_device(hw_device_t* dev);
+
+ // Wrappers to translate the keyguard 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.
+ */
+ static int enroll(const struct keyguard_device *dev, uint32_t uid,
+ const uint8_t *password_payload, size_t password_payload_length,
+ uint8_t **enrolled_password_handle, size_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 verification_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
+ */
+ static int verify(const struct keyguard_device *dev, uint32_t uid,
+ const uint8_t *enrolled_password_handle, size_t enrolled_password_handle_length,
+ const uint8_t *provided_password, size_t provided_password_length,
+ uint8_t **verification_token, size_t *verification_token_length);
+
+ keyguard_device device_;
+ UniquePtr<Keyguard> impl_;
+};
+
+} // namespace keyguard
+
+#endif //SYSTEM_SOFT_KEYGUARD_DEVICE_H_
diff --git a/softkeyguard/Android.mk b/softkeyguard/Android.mk
new file mode 100644
index 0000000..9eb67a4
--- /dev/null
+++ b/softkeyguard/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2012 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.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+ifeq ($(USE_32_BIT_KEYSTORE), true)
+LOCAL_MULTILIB := 32
+endif
+LOCAL_MODULE := keyguard.default
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+ module.cpp \
+ soft_keyguard_device.cpp
+LOCAL_CFLAGS = -fvisibility=hidden -Wall -Werror
+LOCAL_SHARED_LIBRARIES := libcrypto libkeyguard
+LOCAL_STATIC_LIBRARIES := libscrypt_static
+LOCAL_C_INCLUDES := external/scrypt/lib/crypto
+LOCAL_MODULE_TAGS := optional
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+include $(BUILD_SHARED_LIBRARY)
diff --git a/softkeyguard/module.cpp b/softkeyguard/module.cpp
new file mode 100644
index 0000000..b41ee9d
--- /dev/null
+++ b/softkeyguard/module.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2012 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<keyguard/soft_keyguard_device.h>
+
+extern struct keyguard_module soft_keyguard_device_module;
+
+struct keyguard_module HAL_MODULE_INFO_SYM __attribute__((visibility("default")))
+ = soft_keyguard_device_module;
diff --git a/softkeyguard/soft_keyguard_device.cpp b/softkeyguard/soft_keyguard_device.cpp
new file mode 100644
index 0000000..6422531
--- /dev/null
+++ b/softkeyguard/soft_keyguard_device.cpp
@@ -0,0 +1,151 @@
+/*
+ * 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 <keyguard/soft_keyguard_device.h>
+
+__attribute__((visibility("default")))
+int softkeyguard_device_open(const hw_module_t *module, const char *name, hw_device_t **device) {
+ if (device == NULL || strcmp(name, HARDWARE_KEYGUARD) != 0)
+ return -EINVAL;
+
+ keyguard::SoftKeyguardDevice *dev = new keyguard::SoftKeyguardDevice(module);
+ if (dev == NULL)
+ return -ENOMEM;
+
+ *device = reinterpret_cast<hw_device_t *>(dev);
+ return 0;
+}
+
+
+static struct hw_module_methods_t keyguard_module_methods = {
+ .open = softkeyguard_device_open,
+};
+
+__attribute__((visibility("default")))
+struct keyguard_module soft_keyguard_device_module = {
+ .common =
+ {
+ .tag = HARDWARE_MODULE_TAG,
+ .module_api_version = KEYGUARD_MODULE_API_VERSION_0_1,
+ .hal_api_version = HARDWARE_HAL_API_VERSION,
+ .id = KEYGUARD_HARDWARE_MODULE_ID,
+ .name = "Keyguard SCrypt HAL",
+ .author = "The Android Open Source Project",
+ .methods = &keyguard_module_methods,
+ .dso = 0,
+ .reserved = {},
+ },
+};
+
+namespace keyguard {
+
+SoftKeyguardDevice::SoftKeyguardDevice(const hw_module_t *module)
+ : impl_(new SoftKeyguard()) {
+#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
+ static_assert(std::is_standard_layout<SoftKeyguardDevice>::value,
+ "SoftKeyguardDevice must be standard layout");
+ static_assert(offsetof(SoftKeyguardDevice, device_) == 0,
+ "device_ must be the first member of KeymasterOpenSsl");
+ static_assert(offsetof(SoftKeyguardDevice, device_.common) == 0,
+ "common must be the first member of keymaster_device");
+#else
+ assert(reinterpret_cast<keyguard_device*>(this) == &device_);
+ assert(reinterpret_cast<hw_device_t*>(this) == &(device_.common));
+#endif
+
+ memset(&device_, 0, sizeof(device_));
+ device_.common.tag = HARDWARE_DEVICE_TAG;
+ device_.common.version = 1;
+ device_.common.module = const_cast<hw_module_t *>(module);
+ device_.common.close = close_device;
+
+ device_.verify = verify;
+ device_.enroll = enroll;
+}
+
+hw_device_t *SoftKeyguardDevice::hw_device() {
+ return &device_.common;
+}
+
+static inline SoftKeyguardDevice *convert_device(const struct keyguard_device *dev) {
+ return reinterpret_cast<SoftKeyguardDevice *>(const_cast<keyguard_device *>(dev));
+}
+
+/* static */
+int SoftKeyguardDevice::close_device(hw_device_t* dev) {
+ delete reinterpret_cast<SoftKeyguardDevice *>(dev);
+ return 0;
+}
+
+int SoftKeyguardDevice::enroll(const struct keyguard_device *dev, uint32_t uid,
+ const uint8_t *password_payload, size_t password_payload_length,
+ uint8_t **enrolled_password_handle, size_t *enrolled_password_handle_length) {
+
+ if (dev == NULL ||
+ enrolled_password_handle == NULL || enrolled_password_handle_length == NULL)
+ return -EINVAL;
+
+ uint8_t *local_password_payload = new uint8_t[password_payload_length];
+ memcpy(local_password_payload, password_payload, password_payload_length);
+
+ SizedBuffer provided_password(local_password_payload, password_payload_length);
+ EnrollRequest request(uid, &provided_password);
+ EnrollResponse response;
+
+ convert_device(dev)->impl_->Enroll(request, &response);
+
+ if (response.error != KG_ERROR_OK)
+ return -EINVAL;
+
+ *enrolled_password_handle = response.enrolled_password_handle.buffer.release();
+ *enrolled_password_handle_length = response.enrolled_password_handle.length;
+ return 0;
+}
+
+int SoftKeyguardDevice::verify(const struct keyguard_device *dev, uint32_t uid,
+ const uint8_t *enrolled_password_handle, size_t enrolled_password_handle_length,
+ const uint8_t *provided_password, size_t provided_password_length,
+ uint8_t **verification_token, size_t *verification_token_length) {
+
+ if (dev == NULL || enrolled_password_handle == NULL ||
+ provided_password == NULL) {
+ return -EINVAL;
+ }
+
+ uint8_t *local_provided_password = new uint8_t[provided_password_length];
+ uint8_t *local_enrolled_password = new uint8_t[enrolled_password_handle_length];
+ memcpy(local_provided_password, provided_password, provided_password_length);
+ memcpy(local_enrolled_password, enrolled_password_handle, enrolled_password_handle_length);
+
+ SizedBuffer password_handle(local_enrolled_password,
+ enrolled_password_handle_length);
+ SizedBuffer provided(local_provided_password, provided_password_length);
+ VerifyRequest request(uid, &password_handle, &provided);
+ VerifyResponse response;
+
+ convert_device(dev)->impl_->Verify(request, &response);
+
+ if (response.error != KG_ERROR_OK)
+ return -EINVAL;
+
+ if (verification_token != NULL && verification_token_length != NULL) {
+ *verification_token = response.verification_token.buffer.release();
+ *verification_token_length = response.verification_token.length;
+ }
+
+ return 0;
+}
+};
diff --git a/tests/Android.mk b/tests/Android.mk
index cca7038..fff72ca 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -20,10 +20,11 @@ include $(CLEAR_VARS)
LOCAL_MODULE := keyguard-unit-tests
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_CFLAGS += -g -Wall -Werror -std=gnu++11 -Wno-missing-field-initializers
-LOCAL_SHARED_LIBRARIES := libkeyguard libcrypto
+LOCAL_SHARED_LIBRARIES := libkeyguard libcrypto libhardware
LOCAL_STATIC_LIBRARIES := libscrypt_static
LOCAL_C_INCLUDES := external/scrypt/lib/crypto
LOCAL_SRC_FILES := \
keyguard_messages_test.cpp \
- keyguard_test.cpp
+ keyguard_test.cpp \
+ keyguard_device_test.cpp
include $(BUILD_NATIVE_TEST)
diff --git a/tests/keyguard_device_test.cpp b/tests/keyguard_device_test.cpp
new file mode 100644
index 0000000..0bc7db9
--- /dev/null
+++ b/tests/keyguard_device_test.cpp
@@ -0,0 +1,91 @@
+/*
+ * 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 <gtest/gtest.h>
+#include <hardware/keyguard.h>
+
+using ::testing::Test;
+
+class KeyguardDeviceTest : public virtual Test {
+public:
+ KeyguardDeviceTest() {}
+ virtual ~KeyguardDeviceTest() {}
+
+ virtual void SetUp() {
+ keyguard_device_initialize(&device);
+ }
+
+ virtual void TearDown() {
+ keyguard_close(device);
+ }
+
+ static void keyguard_device_initialize(keyguard_device_t **dev) {
+ int ret;
+ const hw_module_t *mod;
+ ret = hw_get_module_by_class(KEYGUARD_HARDWARE_MODULE_ID, NULL, &mod);
+
+ ASSERT_EQ(0, ret);
+
+ ret = keyguard_open(mod, dev);
+
+ ASSERT_EQ(0, ret);
+ }
+
+ keyguard_device_t *device;
+};
+
+TEST_F(KeyguardDeviceTest, EnrollAndVerify) {
+ size_t password_len = 50;
+ uint8_t password_payload[password_len];
+ uint8_t *password_handle;
+ size_t password_handle_length;
+ uint8_t *auth_token;
+ size_t auth_token_len;
+ int ret;
+
+ ret = device->enroll(device, 0, password_payload, password_len,
+ &password_handle, &password_handle_length);
+
+ ASSERT_EQ(0, ret);
+
+ ret = device->verify(device, 0, password_handle, password_handle_length,
+ password_payload, password_len, &auth_token, &auth_token_len);
+
+ ASSERT_EQ(0, ret);
+}
+
+TEST_F(KeyguardDeviceTest, EnrollAndVerifyBadPassword) {
+ size_t password_len = 50;
+ uint8_t password_payload[password_len];
+ uint8_t *password_handle;
+ size_t password_handle_length;
+ uint8_t *auth_token = NULL;
+ size_t auth_token_len;
+ int ret;
+
+ ret = device->enroll(device, 0, password_payload, password_len,
+ &password_handle, &password_handle_length);
+
+ ASSERT_EQ(0, ret);
+
+ password_payload[0] = 4;
+
+ ret = device->verify(device, 0, password_handle, password_handle_length,
+ password_payload, password_len, &auth_token, &auth_token_len);
+
+ ASSERT_NE(0, ret);
+ ASSERT_EQ(NULL, auth_token);
+}
+