libese-hw: restore explicit power off am: d5ef1a2852 am: d6decab1ee am: 9c078aa6bf
am: 40a6bcac46
Change-Id: I44c5e158624513adabd8e2b4896bee863548a31e
diff --git a/esed/Android.bp b/esed/Android.bp
index 53e7da6..c5a2005 100644
--- a/esed/Android.bp
+++ b/esed/Android.bp
@@ -14,6 +14,8 @@
// limitations under the License.
//
+subdirs = ["tests"]
+
cc_defaults {
name: "esed_defaults",
proprietary: true,
@@ -35,13 +37,19 @@
name: "esed",
srcs: [
"esed.cpp",
+ "Weaver.cpp",
+ "OemLock.cpp",
],
init_rc = ["esed.rc"],
defaults: ["esed_defaults"],
shared_libs: [
+ "android.hardware.weaver@1.0",
+ "android.hardware.oemlock@1.0",
"libese",
"libbase",
+ "libese-app-boot",
"libese_cpp_nxp_pn80t_nq_nci",
+ "libese-app-weaver",
"libhidlbase",
"libhidltransport",
"libhwbinder",
diff --git a/esed/OemLock.cpp b/esed/OemLock.cpp
new file mode 100644
index 0000000..4a7974d
--- /dev/null
+++ b/esed/OemLock.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2017 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 "OemLock.h"
+
+#include <vector>
+
+#include <android-base/logging.h>
+#include "../apps/boot/include/ese/app/boot.h"
+#include "ScopedEseConnection.h"
+
+namespace android {
+namespace esed {
+
+// libhidl
+using ::android::hardware::Void;
+
+// Methods from ::android::hardware::oemlock::V1_0::IOemLock follow.
+Return<void> OemLock::getName(getName_cb _hidl_cb) {
+ _hidl_cb(OemLockStatus::OK, {"01"});
+ return Void();
+}
+
+Return<OemLockSecureStatus> OemLock::setOemUnlockAllowedByCarrier(
+ bool allowed, const hidl_vec<uint8_t>& signature) {
+ LOG(INFO) << "Running OemLock::setOemUnlockAllowedByCarrier: " << allowed;
+ ScopedEseConnection ese{mEse};
+ ese.init();
+ // In general, setting the carrier lock to locked is only done in factory,
+ // but there is no reason the HAL could not be used in factory to do it.
+ // As such, the signature would actually be a specially formatted string of
+ // identifiers. Unlocking requires a signature packaged in a simple format
+ // as well.
+ //
+ // See ../apps/boot/README.md for details.
+ std::vector<uint8_t> data(signature);
+ // "allowed" == unlocked == 0.
+ uint8_t lock_byte = allowed ? 0 : 1;
+ // xset expects the lock value as the first byte.
+ data.insert(data.cbegin(), lock_byte);
+
+ // Open SE session for applet
+ EseBootSession session;
+ ese_boot_session_init(&session);
+ EseAppResult res = ese_boot_session_open(mEse.ese_interface(), &session);
+ if (res != ESE_APP_RESULT_OK) {
+ LOG(ERROR) << "Failed to open a boot session: " << res;
+ return OemLockSecureStatus::FAILED;
+ }
+ res = ese_boot_lock_xset(&session, kEseBootLockIdCarrier,
+ data.data(), data.size());
+ if (res != ESE_APP_RESULT_OK) {
+ LOG(ERROR) << "Failed to change lock state (allowed="
+ << allowed << "): " << res;
+ }
+
+ // Try and close the session without perturbing our result value.
+ if (ese_boot_session_close(&session) != ESE_APP_RESULT_OK) {
+ LOG(WARNING) << "Failed to close boot session";
+ }
+
+ if (EseAppResultValue(res) == ESE_APP_RESULT_ERROR_APPLET) {
+ // 0004 and 0005 are invalid signature and invalid nonce respectively.
+ return OemLockSecureStatus::INVALID_SIGNATURE;
+ } else if (res != ESE_APP_RESULT_OK) {
+ return OemLockSecureStatus::FAILED;
+ }
+ return OemLockSecureStatus::OK;
+}
+
+Return<void> OemLock::isOemUnlockAllowedByCarrier(isOemUnlockAllowedByCarrier_cb _hidl_cb) {
+ LOG(VERBOSE) << "Running OemLock::isOemUnlockAllowedByCarrier";
+ ScopedEseConnection ese{mEse};
+ ese.init();
+ // Open SE session for applet
+ EseBootSession session;
+ ese_boot_session_init(&session);
+ EseAppResult res = ese_boot_session_open(mEse.ese_interface(), &session);
+ if (res != ESE_APP_RESULT_OK) {
+ LOG(ERROR) << "Failed to open a boot session: " << res;
+ _hidl_cb(OemLockStatus::FAILED, false);
+ return Void();
+ }
+ std::vector<uint8_t> data;
+ data.resize(1024);
+ uint16_t actualData = 0;
+ res = ese_boot_lock_xget(&session, kEseBootLockIdCarrier,
+ &data[0], data.size(),
+ &actualData);
+ if (res != ESE_APP_RESULT_OK || actualData == 0) {
+ LOG(ERROR) << "Failed to get lock state: " << res;
+ }
+
+ // Try and close the session without perturbing our result value.
+ if (ese_boot_session_close(&session) != ESE_APP_RESULT_OK) {
+ LOG(WARNING) << "Failed to close boot session";
+ }
+
+ if (res != ESE_APP_RESULT_OK) {
+ // Fail closed.
+ _hidl_cb(OemLockStatus::FAILED, false);
+ return Void();
+ }
+ // if data[0] == 1, lock == true, so allowed == false.
+ _hidl_cb(OemLockStatus::OK, data[0] != 0 ? false : true);
+ return Void();
+}
+
+Return<OemLockStatus> OemLock::setOemUnlockAllowedByDevice(bool allowed) {
+ LOG(INFO) << "Running OemLock::setOemUnlockAllowedByDevice: " << allowed;
+ ScopedEseConnection ese{mEse};
+ ese.init();
+ // "allowed" == unlocked == 0.
+ uint8_t lock_byte = allowed ? 0 : 1;
+
+ // Open SE session for applet
+ EseBootSession session;
+ ese_boot_session_init(&session);
+ EseAppResult res = ese_boot_session_open(mEse.ese_interface(), &session);
+ if (res != ESE_APP_RESULT_OK) {
+ LOG(ERROR) << "Failed to open a boot session: " << res;
+ return OemLockStatus::FAILED;
+ }
+ res = ese_boot_lock_set(&session, kEseBootLockIdDevice, lock_byte);
+ if (res != ESE_APP_RESULT_OK) {
+ LOG(ERROR) << "Failed to change device lock state (allowed="
+ << allowed << "): " << res;
+ }
+
+ // Try and close the session without perturbing our result value.
+ if (ese_boot_session_close(&session) != ESE_APP_RESULT_OK) {
+ LOG(WARNING) << "Failed to close boot session";
+ }
+
+ if (res != ESE_APP_RESULT_OK) {
+ return OemLockStatus::FAILED;
+ }
+ return OemLockStatus::OK;
+}
+
+Return<void> OemLock::isOemUnlockAllowedByDevice(isOemUnlockAllowedByDevice_cb _hidl_cb) {
+ LOG(VERBOSE) << "Running OemLock::isOemUnlockAllowedByDevice";
+ ScopedEseConnection ese{mEse};
+ ese.init();
+ // Open SE session for applet
+ EseBootSession session;
+ ese_boot_session_init(&session);
+ EseAppResult res = ese_boot_session_open(mEse.ese_interface(), &session);
+ if (res != ESE_APP_RESULT_OK) {
+ LOG(ERROR) << "Failed to open a boot session: " << res;
+ _hidl_cb(OemLockStatus::FAILED, false);
+ return Void();
+ }
+ uint8_t lock_byte = 0;
+ res = ese_boot_lock_get(&session, kEseBootLockIdDevice, &lock_byte);
+ if (res != ESE_APP_RESULT_OK) {
+ LOG(ERROR) << "Failed to get device lock state: " << res;
+ }
+
+ // Try and close the session without perturbing our result value.
+ if (ese_boot_session_close(&session) != ESE_APP_RESULT_OK) {
+ LOG(WARNING) << "Failed to close boot session";
+ }
+
+ if (res != ESE_APP_RESULT_OK) {
+ // Fail closed.
+ _hidl_cb(OemLockStatus::FAILED, false);
+ return Void();
+ }
+ // if data[0] == 1, lock == true, so allowed == false.
+ _hidl_cb(OemLockStatus::OK, lock_byte != 0 ? false : true);
+ return Void();
+}
+
+} // namespace esed
+} // namespace android
diff --git a/esed/OemLock.h b/esed/OemLock.h
new file mode 100644
index 0000000..3d8fc9d
--- /dev/null
+++ b/esed/OemLock.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 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 ANDROID_ESED_OEMLOCK_H
+#define ANDROID_ESED_OEMLOCK_H
+
+#include <android/hardware/oemlock/1.0/IOemLock.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <esecpp/EseInterface.h>
+
+namespace android {
+namespace esed {
+
+using ::android::EseInterface;
+using ::android::hardware::oemlock::V1_0::IOemLock;
+using ::android::hardware::oemlock::V1_0::OemLockSecureStatus;
+using ::android::hardware::oemlock::V1_0::OemLockStatus;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+struct OemLock : public IOemLock {
+ OemLock(EseInterface& ese) : mEse(ese) {}
+
+ // Methods from ::android::hardware::oemlock::V1_0::IOemLock follow.
+ Return<void> getName(getName_cb _hidl_cb) override;
+
+ Return<OemLockSecureStatus> setOemUnlockAllowedByCarrier(
+ bool allowed, const hidl_vec<uint8_t>& signature) override;
+
+ Return<void> isOemUnlockAllowedByCarrier(isOemUnlockAllowedByCarrier_cb _hidl_cb) override;
+
+ Return<OemLockStatus> setOemUnlockAllowedByDevice(bool allowed) override;
+
+ Return<void> isOemUnlockAllowedByDevice(isOemUnlockAllowedByDevice_cb _hidl_cb) override;
+
+private:
+ EseInterface& mEse;
+};
+
+} // namespace esed
+} // namespace android
+
+#endif // ANDROID_ESED_OEMLOCK_H
diff --git a/esed/ScopedEseConnection.h b/esed/ScopedEseConnection.h
new file mode 100644
index 0000000..d953f42
--- /dev/null
+++ b/esed/ScopedEseConnection.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 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 ANDROID_ESED_SCOPED_ESE_CONNECTION_H
+#define ANDROID_ESED_SCOPED_ESE_CONNECTION_H
+
+#include <android-base/logging.h>
+#include <esecpp/EseInterface.h>
+
+namespace android {
+namespace esed {
+
+using ::android::EseInterface;
+
+class ScopedEseConnection {
+ public:
+ ScopedEseConnection(EseInterface& ese) : mEse_(ese) {}
+ ~ScopedEseConnection() { mEse_.close(); }
+
+ bool init() {
+ mEse_.init();
+ int res = mEse_.open();
+ if (res != 0) {
+ LOG(ERROR) << "Failed to open eSE connection: " << res;
+ return false;
+ }
+ return true;
+ }
+
+ private:
+ EseInterface& mEse_;
+};
+
+} // namespace esed
+} // namespace android
+
+#endif // ANDROID_ESED_SCOPED_ESE_CONNECTION_H
diff --git a/esed/Weaver.cpp b/esed/Weaver.cpp
new file mode 100644
index 0000000..8ed10d3
--- /dev/null
+++ b/esed/Weaver.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2017 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 "Weaver.h"
+
+#include <algorithm>
+#include <tuple>
+
+#include <android-base/logging.h>
+#include <utils/String8.h>
+
+#include "../apps/weaver/include/ese/app/weaver.h"
+#include "ScopedEseConnection.h"
+
+// libutils
+using android::String8;
+
+namespace {
+
+const String8 WRONG_KEY_SIZE_MSG = String8{"Key must be 16 bytes"};
+const String8 WRONG_VALUE_SIZE_MSG = String8{"Value must be 16 bytes"};
+
+} // namespace
+
+namespace android {
+namespace esed {
+
+// libhidl
+using ::android::hardware::Status;
+using ::android::hardware::Void;
+
+// HAL
+using ::android::hardware::weaver::V1_0::WeaverConfig;
+using ::android::hardware::weaver::V1_0::WeaverReadResponse;
+using ::android::hardware::weaver::V1_0::WeaverReadStatus;
+
+// Methods from ::android::hardware::weaver::V1_0::IWeaver follow.
+Return<void> Weaver::getConfig(getConfig_cb _hidl_cb) {
+ LOG(VERBOSE) << "Running Weaver::getNumSlots";
+ // Open SE session for applet
+ ScopedEseConnection ese{mEse};
+ ese.init();
+ EseWeaverSession ws;
+ ese_weaver_session_init(&ws);
+ EseAppResult res = ese_weaver_session_open(mEse.ese_interface(), &ws);
+ if (EseAppResultValue(res) == ESE_APP_RESULT_ERROR_OS) {
+ switch (EseAppResultAppValue(res)) {
+ case 0x6999: // SW_APPLET_SELECT_FAILED
+ case 0x6A82: // SW_FILE_NOT_FOUND
+ // No applet means no Weaver storage. Report no slots to prompt
+ // fallback to software mode.
+ _hidl_cb(WeaverStatus::OK, WeaverConfig{0, 0, 0});
+ return Void();
+ }
+ } else if (res != ESE_APP_RESULT_OK) {
+ // Transient error
+ _hidl_cb(WeaverStatus::FAILED, WeaverConfig{});
+ return Void();
+ }
+
+ // Call the applet
+ uint32_t numSlots;
+ if (ese_weaver_get_num_slots(&ws, &numSlots) != ESE_APP_RESULT_OK) {
+ _hidl_cb(WeaverStatus::FAILED, WeaverConfig{});
+ return Void();
+ }
+
+ // Try and close the session
+ if (ese_weaver_session_close(&ws) != ESE_APP_RESULT_OK) {
+ LOG(WARNING) << "Failed to close Weaver session";
+ }
+
+ _hidl_cb(WeaverStatus::OK, WeaverConfig{numSlots, kEseWeaverKeySize, kEseWeaverValueSize});
+ return Void();
+}
+
+Return<WeaverStatus> Weaver::write(uint32_t slotId, const hidl_vec<uint8_t>& key,
+ const hidl_vec<uint8_t>& value) {
+ LOG(INFO) << "Running Weaver::write on slot " << slotId;
+ ScopedEseConnection ese{mEse};
+ ese.init();
+ // Validate the key and value sizes
+ if (key.size() != kEseWeaverKeySize) {
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, WRONG_KEY_SIZE_MSG);
+ }
+ if (value.size() != kEseWeaverValueSize) {
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, WRONG_VALUE_SIZE_MSG);
+ }
+
+ // Open SE session for applet
+ EseWeaverSession ws;
+ ese_weaver_session_init(&ws);
+ if (ese_weaver_session_open(mEse.ese_interface(), &ws) != ESE_APP_RESULT_OK) {
+ return WeaverStatus::FAILED;
+ }
+
+ // Call the applet
+ if (ese_weaver_write(&ws, slotId, key.data(), value.data()) != ESE_APP_RESULT_OK) {
+ return WeaverStatus::FAILED;
+ }
+
+ // Try and close the session
+ if (ese_weaver_session_close(&ws) != ESE_APP_RESULT_OK) {
+ LOG(WARNING) << "Failed to close Weaver session";
+ }
+
+ return WeaverStatus::OK;
+}
+
+Return<void> Weaver::read(uint32_t slotId, const hidl_vec<uint8_t>& key, read_cb _hidl_cb) {
+ LOG(VERBOSE) << "Running Weaver::read on slot " << slotId;
+
+ // Validate the key size
+ if (key.size() != kEseWeaverKeySize) {
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, WRONG_KEY_SIZE_MSG);
+ }
+
+ // Open SE session for applet
+ ScopedEseConnection ese{mEse};
+ ese.init();
+ EseWeaverSession ws;
+ ese_weaver_session_init(&ws);
+ if (ese_weaver_session_open(mEse.ese_interface(), &ws) != ESE_APP_RESULT_OK) {
+ _hidl_cb(WeaverReadStatus::FAILED, WeaverReadResponse{});
+ return Void();
+ }
+
+ // Call the applet
+ hidl_vec<uint8_t> value;
+ value.resize(kEseWeaverValueSize);
+ uint32_t timeout;
+ const int res = ese_weaver_read(&ws, slotId, key.data(), value.data(), &timeout);
+ WeaverReadStatus status;
+ switch (res) {
+ case ESE_APP_RESULT_OK:
+ status = WeaverReadStatus::OK;
+ timeout = 0;
+ break;
+ case ESE_WEAVER_READ_WRONG_KEY:
+ status = WeaverReadStatus::INCORRECT_KEY;
+ value.resize(0);
+ break;
+ case ESE_WEAVER_READ_TIMEOUT:
+ status = WeaverReadStatus::THROTTLE;
+ value.resize(0);
+ break;
+ default:
+ status = WeaverReadStatus::FAILED;
+ timeout = 0;
+ value.resize(0);
+ break;
+ }
+
+ // Try and close the session
+ if (ese_weaver_session_close(&ws) != ESE_APP_RESULT_OK) {
+ LOG(WARNING) << "Failed to close Weaver session";
+ }
+
+ _hidl_cb(status, WeaverReadResponse{timeout, value});
+ return Void();
+}
+
+} // namespace esed
+} // namespace android
diff --git a/esed/Weaver.h b/esed/Weaver.h
new file mode 100644
index 0000000..7b35ef5
--- /dev/null
+++ b/esed/Weaver.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 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 ANDROID_ESED_WEAVER_H
+#define ANDROID_ESED_WEAVER_H
+
+#include <android/hardware/weaver/1.0/IWeaver.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+#include <esecpp/EseInterface.h>
+
+namespace android {
+namespace esed {
+
+using ::android::EseInterface;
+using ::android::hardware::weaver::V1_0::IWeaver;
+using ::android::hardware::weaver::V1_0::WeaverStatus;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+struct Weaver : public IWeaver {
+ Weaver(EseInterface& ese) : mEse(ese) {};
+
+ // Methods from ::android::hardware::weaver::V1_0::IWeaver follow.
+ Return<void> getConfig(getConfig_cb _hidl_cb) override;
+ Return<WeaverStatus> write(uint32_t slotId, const hidl_vec<uint8_t>& key,
+ const hidl_vec<uint8_t>& value) override;
+ Return<void> read(uint32_t slotId, const hidl_vec<uint8_t>& key, read_cb _hidl_cb) override;
+
+private:
+ EseInterface& mEse;
+};
+
+} // namespace esed
+} // namespace android
+
+#endif // ANDROID_ESED_WEAVER_H
diff --git a/esed/esed.cpp b/esed/esed.cpp
index 2bfb890..afc994c 100644
--- a/esed/esed.cpp
+++ b/esed/esed.cpp
@@ -26,6 +26,9 @@
#include <esecpp/NxpPn80tNqNci.h>
using EseInterfaceImpl = android::NxpPn80tNqNci;
+#include "OemLock.h"
+#include "Weaver.h"
+
using android::OK;
using android::sp;
using android::status_t;
@@ -34,13 +37,17 @@
using namespace std::chrono_literals;
+// HALs
+using android::esed::OemLock;
+using android::esed::Weaver;
+
int main(int /* argc */, char** /* argv */) {
LOG(INFO) << "Starting esed...";
// Open connection to the eSE
+ EseInterfaceImpl ese;
uint32_t failCount = 0;
while (true) {
- EseInterfaceImpl ese;
ese.init();
if (ese.open() < 0) {
std::string errMsg = "Failed to open connection to eSE";
@@ -59,6 +66,9 @@
LOG(INFO) << "Opened connection to the eSE";
break;
}
+ // Close it until use.
+ ese.close();
+
// This will be a single threaded daemon. This is important as libese is not
// thread safe so we use binder to synchronize requests for us.
@@ -66,6 +76,21 @@
configureRpcThreadpool(1, thisThreadWillJoinPool);
// -- Instantiate other applet HALs here --
+ status_t status;
+
+ // Create OemLock HAL instance.
+ sp<OemLock> oemLock = new OemLock{ese};
+ status = oemLock->registerAsService();
+ if (status != OK) {
+ LOG(ERROR) << "Failed to register OemLock as a service (status: " << status << ")";
+ }
+
+ // Create Weaver HAL instance
+ sp<Weaver> weaver = new Weaver{ese};
+ status = weaver->registerAsService();
+ if (status != OK) {
+ LOG(ERROR) << "Failed to register Weaver as a service (status: " << status << ")";
+ }
joinRpcThreadpool();
return -1; // Should never reach here
diff --git a/esed/tests/Android.bp b/esed/tests/Android.bp
new file mode 100644
index 0000000..c5ec65a
--- /dev/null
+++ b/esed/tests/Android.bp
@@ -0,0 +1,36 @@
+//
+// Copyright (C) 2017 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.
+//
+
+// TODO: move to a VTS test
+cc_test {
+ name: "esed_integration_tests",
+ proprietary: true,
+ srcs: [
+ "weaver_integration_tests.cpp",
+ "oemlock_integration_tests.cpp",
+ ],
+ host_supported: false,
+ shared_libs: [
+ "android.hardware.weaver@1.0",
+ "android.hardware.oemlock@1.0",
+ "libbase",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "liblog",
+ "libutils",
+ ],
+}
diff --git a/esed/tests/oemlock_integration_tests.cpp b/esed/tests/oemlock_integration_tests.cpp
new file mode 100644
index 0000000..9f1b148
--- /dev/null
+++ b/esed/tests/oemlock_integration_tests.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2017 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 <string>
+
+#include <android-base/logging.h>
+#include <android/hardware/oemlock/1.0/IOemLock.h>
+#include <hidl/Status.h>
+
+#include <gtest/gtest.h>
+
+using ::android::OK;
+using ::android::sp;
+using ::android::status_t;
+using ::android::hardware::oemlock::V1_0::IOemLock;
+using ::android::hardware::oemlock::V1_0::OemLockSecureStatus;
+using ::android::hardware::oemlock::V1_0::OemLockStatus;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using ::testing::Test;
+
+class OemLockClientTest : public virtual Test {
+ public:
+ OemLockClientTest() {
+ }
+ virtual ~OemLockClientTest() { }
+ virtual void SetUp() {
+ service_ = IOemLock::getService();
+ ASSERT_NE(service_, nullptr);
+ }
+ virtual void TearDown() { }
+ sp<IOemLock> service_;
+};
+
+TEST_F(OemLockClientTest, GetName) {
+ std::string name;
+ OemLockStatus status;
+ auto get_name_cb = [&status, &name](OemLockStatus cb_status, hidl_string cb_name) {
+ status = cb_status;
+ name = cb_name.c_str();
+ };
+ Return<void> ret = service_->getName(get_name_cb);
+
+ EXPECT_TRUE(ret.isOk());
+ EXPECT_EQ(status, OemLockStatus::OK);
+ EXPECT_STREQ(name.c_str(), "01");
+};
+
+TEST_F(OemLockClientTest, AllowedByDeviceToggle) {
+ // Should always work as it is independent of carrier and boot lock states.
+ bool allowed = true;
+ OemLockStatus status;
+ auto get_allowed_cb = [&status, &allowed](OemLockStatus cb_status, bool cb_allowed) {
+ status = cb_status;
+ allowed = cb_allowed;
+ };
+
+ Return<OemLockStatus> set_ret = service_->setOemUnlockAllowedByDevice(allowed);
+ EXPECT_EQ(set_ret, OemLockStatus::OK);
+ Return<void> get_ret = service_->isOemUnlockAllowedByDevice(get_allowed_cb);
+ EXPECT_EQ(status, OemLockStatus::OK);
+ EXPECT_EQ(true, allowed);
+
+ allowed = false;
+ set_ret = service_->setOemUnlockAllowedByDevice(allowed);
+ EXPECT_EQ(set_ret, OemLockStatus::OK);
+ get_ret = service_->isOemUnlockAllowedByDevice(get_allowed_cb);
+ EXPECT_EQ(status, OemLockStatus::OK);
+ EXPECT_EQ(false, allowed);
+};
+
+TEST_F(OemLockClientTest, GetAllowedByCarrierIsFalse) {
+ bool allowed = true;
+ OemLockStatus status;
+ auto get_allowed_cb = [&status, &allowed](OemLockStatus cb_status, bool cb_allowed) {
+ status = cb_status;
+ allowed = cb_allowed;
+ };
+
+ Return<void> ret = service_->isOemUnlockAllowedByCarrier(get_allowed_cb);
+ EXPECT_EQ(status, OemLockStatus::OK);
+ EXPECT_EQ(false, allowed);
+};
diff --git a/esed/tests/weaver_integration_tests.cpp b/esed/tests/weaver_integration_tests.cpp
new file mode 100644
index 0000000..747955c
--- /dev/null
+++ b/esed/tests/weaver_integration_tests.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2017 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 <string>
+
+#include <android-base/logging.h>
+#include <android/hardware/weaver/1.0/IWeaver.h>
+#include <hidl/Status.h>
+
+#include <gtest/gtest.h>
+
+using ::android::OK;
+using ::android::sp;
+using ::android::status_t;
+using ::android::hardware::weaver::V1_0::IWeaver;
+using ::android::hardware::weaver::V1_0::WeaverConfig;
+using ::android::hardware::weaver::V1_0::WeaverReadResponse;
+using ::android::hardware::weaver::V1_0::WeaverReadStatus;
+using ::android::hardware::weaver::V1_0::WeaverStatus;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using ::testing::Test;
+
+const std::vector<uint8_t> KEY{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+const std::vector<uint8_t> WRONG_KEY{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const std::vector<uint8_t> VALUE{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
+
+struct WeaverClientTest : public Test {
+ sp<IWeaver> service;
+
+ WeaverClientTest() = default;
+ virtual ~WeaverClientTest() = default;
+ void SetUp() override {
+ service = IWeaver::getService();
+ ASSERT_NE(service, nullptr);
+ }
+ void TearDown() override {}
+};
+
+TEST_F(WeaverClientTest, getConfig) {
+ bool cbkCalled = false;
+ WeaverStatus status;
+ WeaverConfig config;
+ auto ret = service->getConfig([&](WeaverStatus s, WeaverConfig c) {
+ cbkCalled = true;
+ status = s;
+ config = c;
+ });
+
+ EXPECT_TRUE(cbkCalled);
+ EXPECT_TRUE(ret.isOk());
+ EXPECT_EQ(status, WeaverStatus::OK);
+ const WeaverConfig expectedConfig{64, 16, 16};
+ EXPECT_EQ(config, expectedConfig);
+}
+
+TEST_F(WeaverClientTest, writeAndReadBack) {
+ const uint32_t slotId = 3;
+ auto ret = service->write(slotId, KEY, VALUE);
+ EXPECT_TRUE(ret.isOk());
+ EXPECT_EQ(ret, WeaverStatus::OK);
+
+ bool cbkCalled = false;
+ WeaverReadStatus status;
+ std::vector<uint8_t> readValue;
+ uint32_t timeout;
+ auto readRet = service->read(slotId, KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
+ cbkCalled = true;
+ status = s;
+ readValue = r.value;
+ timeout = r.timeout;
+ });
+ EXPECT_TRUE(cbkCalled);
+ EXPECT_TRUE(readRet.isOk());
+ EXPECT_EQ(status, WeaverReadStatus::OK);
+ EXPECT_EQ(readValue, VALUE);
+}
+
+TEST_F(WeaverClientTest, writeAndReadWithWrongKey) {
+ const uint32_t slotId = 3;
+ auto ret = service->write(slotId, KEY, VALUE);
+ EXPECT_TRUE(ret.isOk());
+ EXPECT_EQ(ret, WeaverStatus::OK);
+
+ bool cbkCalled = false;
+ WeaverReadStatus status;
+ std::vector<uint8_t> readValue;
+ uint32_t timeout;
+ auto readRet = service->read(slotId, WRONG_KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
+ cbkCalled = true;
+ status = s;
+ readValue = r.value;
+ timeout = r.timeout;
+ });
+ EXPECT_TRUE(cbkCalled);
+ EXPECT_TRUE(readRet.isOk());
+ EXPECT_EQ(status, WeaverReadStatus::INCORRECT_KEY);
+ EXPECT_EQ(timeout, uint32_t{0}); // first timeout is 0
+}
diff --git a/libese-cpp/NxpPn80tNqNci.cpp b/libese-cpp/NxpPn80tNqNci.cpp
index 3cdcda0..8cbd3b1 100644
--- a/libese-cpp/NxpPn80tNqNci.cpp
+++ b/libese-cpp/NxpPn80tNqNci.cpp
@@ -20,7 +20,9 @@
namespace android {
void NxpPn80tNqNci::init() {
- mEse = new ::EseInterface;
+ if (mEse == nullptr) {
+ mEse = new ::EseInterface;
+ }
ese_init(mEse, ESE_HW_NXP_PN80T_NQ_NCI);
}