Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion HAL/Android.bp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ cc_library {

cc_library {
name: "libjc_keymint_transport",
host_supported: true,
vendor_available: true,
srcs: [
"SocketTransport.cpp",
Expand Down
385 changes: 385 additions & 0 deletions aosp_integration_patches/omapi_patches/JavacardKeymaster.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,385 @@
diff --git a/HAL/Android.bp b/HAL/Android.bp
index c705a01..10dd93e 100644
--- a/HAL/Android.bp
+++ b/HAL/Android.bp
@@ -55,13 +55,17 @@ cc_library {
vendor_available: true,
srcs: [
"SocketTransport.cpp",
+ "OmapiTransport.cpp"
],
export_include_dirs: [
"."
],
shared_libs: [
+ "libbinder",
"libbase",
"liblog",
+ "libbinder_ndk",
+ "android.se.omapi-V1-ndk",
],
}

@@ -90,6 +94,7 @@ cc_binary {
"libjc_keymint_transport",
"liblog",
"libutils",
+ "android.se.omapi-V1-ndk",
],
srcs: [
"service.cpp",
diff --git a/HAL/OmapiTransport.cpp b/HAL/OmapiTransport.cpp
new file mode 100644
index 0000000..dd81d3d
--- /dev/null
+++ b/HAL/OmapiTransport.cpp
@@ -0,0 +1,218 @@
+/*
+ **
+ ** Copyright 2020, 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 <stdio.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <string.h>
+#include <vector>
+
+#include <android-base/logging.h>
+
+#include "OmapiTransport.h"
+
+namespace keymint::javacard {
+
+class SEListener : public ::aidl::android::se::omapi::BnSecureElementListener {};
+
+bool OmapiTransport::initialize() {
+ std::vector<std::string> readers = {};
+
+ LOG(DEBUG) << "Initialize the secure element connection";
+
+ // Get OMAPI vendor stable service handler
+ ::ndk::SpAIBinder ks2Binder(AServiceManager_getService(omapiServiceName));
+ omapiSeService = aidl::android::se::omapi::ISecureElementService::fromBinder(ks2Binder);
+
+ if (omapiSeService == nullptr) {
+ LOG(ERROR) << "Failed to start omapiSeService null";
+ return false;
+ }
+
+ // reset readers, clear readers if already existing
+ if (mVSReaders.size() > 0) {
+ closeConnection();
+ }
+
+ // Get available readers
+ auto status = omapiSeService->getReaders(&readers);
+ if (!status.isOk()) {
+ LOG(ERROR) << "getReaders failed to get available readers: " << status.getMessage();
+ return false;
+ }
+
+ // Get SE readers handlers
+ for (auto readerName : readers) {
+ std::shared_ptr<::aidl::android::se::omapi::ISecureElementReader> reader;
+ status = omapiSeService->getReader(readerName, &reader);
+ if (!status.isOk()) {
+ LOG(ERROR) << "getReader for " << readerName.c_str() << " Failed: "
+ << status.getMessage();
+ return false;
+ }
+
+ mVSReaders[readerName] = reader;
+ }
+
+ // Find eSE reader, as of now assumption is only eSE available on device
+ LOG(DEBUG) << "Finding eSE reader";
+ eSEReader = nullptr;
+ if (mVSReaders.size() > 0) {
+ for (const auto& [name, reader] : mVSReaders) {
+ if (name.find(ESE_READER_PREFIX, 0) != std::string::npos) {
+ LOG(DEBUG) << "eSE reader found: " << name;
+ eSEReader = reader;
+ }
+ }
+ }
+
+ if (eSEReader == nullptr) {
+ LOG(ERROR) << "secure element reader " << ESE_READER_PREFIX << " not found";
+ return false;
+ }
+
+ return true;
+}
+
+bool OmapiTransport::internalTransmitApdu(
+ std::shared_ptr<aidl::android::se::omapi::ISecureElementReader> reader,
+ std::vector<uint8_t> apdu, std::vector<uint8_t>& transmitResponse) {
+ std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+ std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+ auto mSEListener = std::make_shared<SEListener>();
+ std::vector<uint8_t> selectResponse = {};
+ std::vector<uint8_t> SELECTABLE_AID = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+ 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x31};
+
+ LOG(DEBUG) << "internalTransmitApdu: trasmitting data to secure element";
+
+ if (reader == nullptr) {
+ LOG(ERROR) << "eSE reader is null";
+ return false;
+ }
+
+ bool status = false;
+ auto res = reader->isSecureElementPresent(&status);
+ if (!res.isOk()) {
+ LOG(ERROR) << "isSecureElementPresent error: " << res.getMessage();
+ return false;
+ }
+ if (!status) {
+ LOG(ERROR) << "secure element not found";
+ return false;
+ }
+
+ res = reader->openSession(&session);
+ if (!res.isOk()) {
+ LOG(ERROR) << "openSession error: " << res.getMessage();
+ return false;
+ }
+ if (session == nullptr) {
+ LOG(ERROR) << "Could not open session null";
+ return false;
+ }
+
+ res = session->openLogicalChannel(SELECTABLE_AID, 0x00, mSEListener, &channel);
+ if (!res.isOk()) {
+ LOG(ERROR) << "openLogicalChannel error: " << res.getMessage();
+ return false;
+ }
+ if (channel == nullptr) {
+ LOG(ERROR) << "Could not open channel null";
+ return false;
+ }
+
+ res = channel->getSelectResponse(&selectResponse);
+ if (!res.isOk()) {
+ LOG(ERROR) << "getSelectResponse error: " << res.getMessage();
+ return false;
+ }
+ if (selectResponse.size() < 2) {
+ LOG(ERROR) << "getSelectResponse size error";
+ return false;
+ }
+
+ res = channel->transmit(apdu, &transmitResponse);
+ if (channel != nullptr) channel->close();
+ if (session != nullptr) session->close();
+
+ LOG(INFO) << "STATUS OF TRNSMIT: " << res.getExceptionCode() << " Message: "
+ << res.getMessage();
+ if (!res.isOk()) {
+ LOG(ERROR) << "transmit error: " << res.getMessage();
+ return false;
+ }
+
+ return true;
+}
+
+bool OmapiTransport::openConnection() {
+
+ // if already conection setup done, no need to initialise it again.
+ if (isConnected()) {
+ return true;
+ }
+
+ return initialize();
+}
+
+bool OmapiTransport::sendData(const vector<uint8_t>& inData, vector<uint8_t>& output) {
+
+ if (!isConnected()) {
+ // Try to initialize connection to eSE
+ LOG(INFO) << "Failed to send data, try to initialize connection SE connection";
+ if (!initialize()) {
+ LOG(ERROR) << "Failed to send data, initialization not completed";
+ closeConnection();
+ return false;
+ }
+ }
+
+ if (eSEReader != nullptr) {
+ LOG(DEBUG) << "Sending apdu data to secure element: " << ESE_READER_PREFIX;
+ return internalTransmitApdu(eSEReader, inData, output);
+ } else {
+ LOG(ERROR) << "secure element reader " << ESE_READER_PREFIX << " not found";
+ return false;
+ }
+}
+
+bool OmapiTransport::closeConnection() {
+ LOG(DEBUG) << "Closing all connections";
+ if (omapiSeService != nullptr) {
+ if (mVSReaders.size() > 0) {
+ for (const auto& [name, reader] : mVSReaders) {
+ reader->closeSessions();
+ }
+ mVSReaders.clear();
+ }
+ }
+ return true;
+}
+
+bool OmapiTransport::isConnected() {
+ // Check already initialization completed or not
+ if (omapiSeService != nullptr && eSEReader != nullptr) {
+ LOG(DEBUG) << "Connection initialization already completed";
+ return true;
+ }
+
+ LOG(DEBUG) << "Connection initialization not completed";
+ return false;
+}
+
+}
diff --git a/HAL/OmapiTransport.h b/HAL/OmapiTransport.h
new file mode 100644
index 0000000..f7711e7
--- /dev/null
+++ b/HAL/OmapiTransport.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include "ITransport.h"
+#include <aidl/android/se/omapi/BnSecureElementListener.h>
+#include <aidl/android/se/omapi/ISecureElementChannel.h>
+#include <aidl/android/se/omapi/ISecureElementListener.h>
+#include <aidl/android/se/omapi/ISecureElementReader.h>
+#include <aidl/android/se/omapi/ISecureElementService.h>
+#include <aidl/android/se/omapi/ISecureElementSession.h>
+#include <android/binder_manager.h>
+#include <map>
+#include <memory>
+#include <vector>
+
+namespace keymint::javacard {
+using std::vector;
+
+/**
+ * OmapiTransport is derived from ITransport. This class gets the OMAPI service binder instance and uses IPC to
+ * communicate with OMAPI service. OMAPI inturn communicates with hardware via ISecureElement.
+ */
+class OmapiTransport : public ITransport {
+
+public:
+
+ /**
+ * Gets the binder instance of ISEService, gets the reader corresponding to secure element, establishes a session
+ * and opens a basic channel.
+ */
+ bool openConnection() override;
+ /**
+ * Transmists the data over the opened basic channel and receives the data back.
+ */
+ bool sendData(const vector<uint8_t>& inData, vector<uint8_t>& output) override;
+
+ /**
+ * Closes the connection.
+ */
+ bool closeConnection() override;
+ /**
+ * Returns the state of the connection status. Returns true if the connection is active, false if connection is
+ * broken.
+ */
+ bool isConnected() override;
+
+private:
+ std::shared_ptr<aidl::android::se::omapi::ISecureElementService> omapiSeService = nullptr;
+ std::shared_ptr<aidl::android::se::omapi::ISecureElementReader> eSEReader = nullptr;
+ std::map<std::string, std::shared_ptr<aidl::android::se::omapi::ISecureElementReader>>
+ mVSReaders = {};
+ std::string const ESE_READER_PREFIX = "eSE";
+ constexpr static const char omapiServiceName[] =
+ "android.system.omapi.ISecureElementService/default";
+
+ bool initialize();
+ bool internalTransmitApdu(
+ std::shared_ptr<aidl::android::se::omapi::ISecureElementReader> reader,
+ std::vector<uint8_t> apdu, std::vector<uint8_t>& transmitResponse);
+};
+
+}
\ No newline at end of file
diff --git a/HAL/service.cpp b/HAL/service.cpp
index 3d51877..14580f8 100644
--- a/HAL/service.cpp
+++ b/HAL/service.cpp
@@ -22,18 +22,24 @@

#include "JavacardKeyMintDevice.h"
#include <aidl/android/hardware/security/keymint/SecurityLevel.h>
-
+#include <android-base/properties.h>
#include "JavacardSecureElement.h"
#include "JavacardSharedSecret.h"
#include "keymint_utils.h"
#include "JavacardRemotelyProvisionedComponentDevice.h"
#include <SocketTransport.h>
+#include <OmapiTransport.h>

using aidl::android::hardware::security::keymint::JavacardKeyMintDevice;
using aidl::android::hardware::security::keymint::JavacardSharedSecret;
using aidl::android::hardware::security::keymint::SecurityLevel;
using namespace keymint::javacard;

+#define PROP_BUILD_QEMU "ro.kernel.qemu"
+#define PROP_BUILD_FINGERPRINT "ro.build.fingerprint"
+// Cuttlefish build fingerprint substring.
+#define CUTTLEFISH_FINGERPRINT_SS "aosp_cf_"
+
template <typename T, class... Args> std::shared_ptr<T> addService(Args&&... args) {
std::shared_ptr<T> ser = ndk::SharedRefBase::make<T>(std::forward<Args>(args)...);
auto instanceName = std::string(T::descriptor) + "/strongbox";
@@ -44,11 +50,31 @@ template <typename T, class... Args> std::shared_ptr<T> addService(Args&&... arg
return ser;
}

+std::shared_ptr<ITransport> getTransportInstance() {
+ bool isEmulator = false;
+ // Check if the current build is for emulator or device.
+ isEmulator = android::base::GetBoolProperty(PROP_BUILD_QEMU, false);
+ if (!isEmulator) {
+ std::string fingerprint = android::base::GetProperty(PROP_BUILD_FINGERPRINT, "");
+ if (!fingerprint.empty()) {
+ if (fingerprint.find(CUTTLEFISH_FINGERPRINT_SS, 0) != std::string::npos) {
+ isEmulator = true;
+ }
+ }
+ }
+
+ if (!isEmulator) {
+ return std::make_shared<OmapiTransport>();
+ } else {
+ return std::make_shared<SocketTransport>();
+ }
+}
+
int main() {
ABinderProcess_setThreadPoolMaxThreadCount(0);
// Javacard Secure Element
std::shared_ptr<JavacardSecureElement> card =
- std::make_shared<JavacardSecureElement>(std::make_shared<SocketTransport>(), getOsVersion(),
+ std::make_shared<JavacardSecureElement>(getTransportInstance(), getOsVersion(),
getOsPatchlevel(), getVendorPatchlevel());
// Add Keymint Service
addService<JavacardKeyMintDevice>(card);
Loading