From 854f8b875f79a81acc98501c0af36e32009f1a59 Mon Sep 17 00:00:00 2001 From: Subrahmanyaman Date: Thu, 26 May 2022 00:45:51 +0000 Subject: [PATCH] For OMAPI Transport, establish the connection only once at initialization. --- HAL/keymaster/4.1/OmapiTransport.cpp | 245 +++++++++++- HAL/keymaster/Android.bp | 6 + HAL/keymaster/include/Transport.h | 30 +- .../JavacardKeymaster_remove_omapi.patch | 376 ++++++++++++++++++ 4 files changed, 639 insertions(+), 18 deletions(-) create mode 100644 aosp_integration_patches_aosp_12_r15/JavacardKeymaster_remove_omapi.patch diff --git a/HAL/keymaster/4.1/OmapiTransport.cpp b/HAL/keymaster/4.1/OmapiTransport.cpp index 5aaefc91..cb363254 100644 --- a/HAL/keymaster/4.1/OmapiTransport.cpp +++ b/HAL/keymaster/4.1/OmapiTransport.cpp @@ -14,36 +14,253 @@ ** See the License for the specific language governing permissions and ** limitations under the License. */ -#include -#include -#include -#include -#include +#include +#include +#include #include -#include "Transport.h" -#define PORT 8080 -#define IPADDR "10.9.40.24" -#define UNUSED_V(a) a=a +#include + +#include "Transport.h" namespace se_transport { -bool OmapiTransport::openConnection() { +constexpr const char kEseReaderPrefix[] = "eSE"; +constexpr const char kOmapiServiceName[] = + "android.system.omapi.ISecureElementService/default"; +constexpr const uint8_t kSelectableAid[] = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64, + 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x31}; + +class SEListener : public ::aidl::android::se::omapi::BnSecureElementListener {}; + +bool OmapiTransport::initialize() { + std::vector readers = {}; + + LOG(DEBUG) << "Initialize the secure element connection"; + + // Get OMAPI vendor stable service handler + ::ndk::SpAIBinder ks2Binder(AServiceManager_checkService(kOmapiServiceName)); + 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(kEseReaderPrefix, 0) != std::string::npos) { + LOG(DEBUG) << "eSE reader found: " << name; + eSEReader = reader; + break; + } + } + } + + if (eSEReader == nullptr) { + LOG(ERROR) << "secure element reader " << kEseReaderPrefix << " not found"; + return false; + } + bool isSecureElementPresent = false; + auto res = eSEReader->isSecureElementPresent(&isSecureElementPresent); + if (!res.isOk()) { + eSEReader = nullptr; + LOG(ERROR) << "isSecureElementPresent error: " << res.getMessage(); + return false; + } + if (!isSecureElementPresent) { + eSEReader = nullptr; + LOG(ERROR) << "secure element not found"; + return false; + } + + status = eSEReader->openSession(&session); + if (!status.isOk()) { + LOG(ERROR) << "Could not open session error: " << status.getMessage(); + return false; + } + if (session == nullptr) { + LOG(ERROR) << "Could not open session null"; + return false; + } + + auto mSEListener = ndk::SharedRefBase::make(); + int size = sizeof(kSelectableAid) / sizeof(kSelectableAid[0]); + std::vector aid(kSelectableAid, kSelectableAid + size); + status = session->openLogicalChannel(aid, 0x00, mSEListener, &channel); + if (!status.isOk()) { + LOG(ERROR) << "Could not open channel error: " << status.getMessage(); + return false; + } + if (channel == nullptr) { + LOG(ERROR) << "Could not open channel null"; + return false; + } return true; } -bool OmapiTransport::sendData(const uint8_t* inData, const size_t inLen, std::vector& output) { - std::vector test(inData, inData+inLen); - output = std::move(test); +bool OmapiTransport::internalTransmitApdu(std::vector apdu, + std::vector& transmitResponse) { + bool isClosed = true; + ndk::ScopedAStatus res; + LOG(DEBUG) << "internalTransmitApdu: trasmitting data to secure element"; + if (session != nullptr) { + res = session->isClosed(&isClosed); + if (!res.isOk()) { + LOG(ERROR) << "isClosed error: " << res.getMessage(); + return false; + } + } + if(isClosed) { + res = eSEReader->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; + } + } + isClosed = true; + if (channel != nullptr) { + res = channel->isClosed(&isClosed); + if (!res.isOk()) { + LOG(ERROR) << "isClosed error: " << res.getMessage(); + return false; + } + } + if(isClosed) { + auto mSEListener = ndk::SharedRefBase::make(); + int size = sizeof(kSelectableAid) / sizeof(kSelectableAid[0]); + std::vector aid(kSelectableAid, kSelectableAid + size); + res = session->openLogicalChannel(aid, 0x00, mSEListener, &channel); + if (!res.isOk()) { + LOG(ERROR) << "Could not open channel error: " << res.getMessage(); + return false; + } + if (channel == nullptr) { + LOG(ERROR) << "Could not open channel null"; + return false; + } + } + + std::vector selectResponse = {}; + res = channel->getSelectResponse(&selectResponse); + if (!res.isOk()) { + LOG(ERROR) << "getSelectResponse error: " << res.getMessage(); + return false; + } + if ((selectResponse.size() < 2) || + ((selectResponse[selectResponse.size() - 1] & 0xFF) == 0x00) || + ((selectResponse[selectResponse.size() - 2] & 0xFF) == 0x90)) { + LOG(ERROR) << "Failed to select the Applet."; + return false; + } + + res = channel->transmit(apdu, &transmitResponse); + + LOG(INFO) << "STATUS OF TRANSMIT: " << 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 uint8_t* inData, const size_t inLen, + std::vector& output) { + + if (inData == NULL) { + LOG(ERROR) << "Failed to send data, APDU is null"; + return false; + } + std::vector apdu(inData, inData+inLen); + + 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; + } + } + + LOG(DEBUG) << "Sending apdu data to secure element: " << kEseReaderPrefix; + return internalTransmitApdu(apdu, output); +} + 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(); + } + } + if (channel != nullptr) { + channel->close(); + channel = nullptr; + } + if (session != nullptr) { + session->close(); + session = nullptr; + } return true; } bool OmapiTransport::isConnected() { - return true; + // 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/keymaster/Android.bp b/HAL/keymaster/Android.bp index 9bfe7faa..33f255f6 100644 --- a/HAL/keymaster/Android.bp +++ b/HAL/keymaster/Android.bp @@ -47,6 +47,8 @@ cc_binary { "libjc_transport", "libjc_common", "libcrypto", + "libbinder_ndk", + "android.se.omapi-V1-ndk", ], required: [ "android.hardware.strongbox_keystore.xml", @@ -82,6 +84,8 @@ cc_library { "android.hardware.keymaster@4.0", "libjc_transport", "libcrypto", + "libbinder_ndk", + "android.se.omapi-V1-ndk", ], } @@ -100,6 +104,8 @@ cc_library { "libbinder", "libbase", "liblog", + "libbinder_ndk", + "android.se.omapi-V1-ndk", ], } diff --git a/HAL/keymaster/include/Transport.h b/HAL/keymaster/include/Transport.h index c6674dca..f525479c 100644 --- a/HAL/keymaster/include/Transport.h +++ b/HAL/keymaster/include/Transport.h @@ -17,6 +17,16 @@ #ifndef __SE_TRANSPORT__ #define __SE_TRANSPORT__ +#include +#include +#include +#include +#include +#include +#include + +#include + namespace se_transport { /** @@ -30,7 +40,7 @@ class ITransport { /** * Opens connection. */ - virtual bool openConnection() = 0; + virtual bool openConnection() = 0; /** * Send data over communication channel and receives data back from the remote end. */ @@ -54,12 +64,14 @@ class ITransport { class OmapiTransport : public ITransport { public: - + OmapiTransport() : omapiSeService(nullptr), eSEReader(nullptr), session(nullptr), + channel(nullptr) { + } /** * Gets the binder instance of ISEService, gets the reader corresponding to secure element, establishes a session * and opens a basic channel. */ - bool openConnection() override; + bool openConnection() override; /** * Transmists the data over the opened basic channel and receives the data back. */ @@ -75,6 +87,16 @@ class OmapiTransport : public ITransport { */ bool isConnected() override; +private: + std::shared_ptr omapiSeService; + std::shared_ptr eSEReader; + std::shared_ptr session; + std::shared_ptr channel; + std::map> + mVSReaders; + // Private functions + bool initialize(); + bool internalTransmitApdu(std::vector apdu, std::vector& transmitResponse); }; class SocketTransport : public ITransport { @@ -85,7 +107,7 @@ class SocketTransport : public ITransport { /** * Creates a socket instance and connects to the provided server IP and port. */ - bool openConnection() override; + bool openConnection() override; /** * Sends data over socket and receives data back. */ diff --git a/aosp_integration_patches_aosp_12_r15/JavacardKeymaster_remove_omapi.patch b/aosp_integration_patches_aosp_12_r15/JavacardKeymaster_remove_omapi.patch new file mode 100644 index 00000000..d12eccf4 --- /dev/null +++ b/aosp_integration_patches_aosp_12_r15/JavacardKeymaster_remove_omapi.patch @@ -0,0 +1,376 @@ +diff --git a/HAL/keymaster/4.1/OmapiTransport.cpp b/HAL/keymaster/4.1/OmapiTransport.cpp +index cb36325..5aaefc9 100644 +--- a/HAL/keymaster/4.1/OmapiTransport.cpp ++++ b/HAL/keymaster/4.1/OmapiTransport.cpp +@@ -14,253 +14,36 @@ + ** See the License for the specific language governing permissions and + ** limitations under the License. + */ +-#include +-#include +-#include ++#include ++#include ++#include ++#include ++#include + #include +- +-#include +- + #include "Transport.h" + +-namespace se_transport { +- +-constexpr const char kEseReaderPrefix[] = "eSE"; +-constexpr const char kOmapiServiceName[] = +- "android.system.omapi.ISecureElementService/default"; +-constexpr const uint8_t kSelectableAid[] = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64, +- 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x31}; +- +-class SEListener : public ::aidl::android::se::omapi::BnSecureElementListener {}; +- +-bool OmapiTransport::initialize() { +- std::vector readers = {}; +- +- LOG(DEBUG) << "Initialize the secure element connection"; +- +- // Get OMAPI vendor stable service handler +- ::ndk::SpAIBinder ks2Binder(AServiceManager_checkService(kOmapiServiceName)); +- omapiSeService = aidl::android::se::omapi::ISecureElementService::fromBinder(ks2Binder); ++#define PORT 8080 ++#define IPADDR "10.9.40.24" ++#define UNUSED_V(a) a=a + +- 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(kEseReaderPrefix, 0) != std::string::npos) { +- LOG(DEBUG) << "eSE reader found: " << name; +- eSEReader = reader; +- break; +- } +- } +- } +- +- if (eSEReader == nullptr) { +- LOG(ERROR) << "secure element reader " << kEseReaderPrefix << " not found"; +- return false; +- } +- bool isSecureElementPresent = false; +- auto res = eSEReader->isSecureElementPresent(&isSecureElementPresent); +- if (!res.isOk()) { +- eSEReader = nullptr; +- LOG(ERROR) << "isSecureElementPresent error: " << res.getMessage(); +- return false; +- } +- if (!isSecureElementPresent) { +- eSEReader = nullptr; +- LOG(ERROR) << "secure element not found"; +- return false; +- } +- +- status = eSEReader->openSession(&session); +- if (!status.isOk()) { +- LOG(ERROR) << "Could not open session error: " << status.getMessage(); +- return false; +- } +- if (session == nullptr) { +- LOG(ERROR) << "Could not open session null"; +- return false; +- } ++namespace se_transport { + +- auto mSEListener = ndk::SharedRefBase::make(); +- int size = sizeof(kSelectableAid) / sizeof(kSelectableAid[0]); +- std::vector aid(kSelectableAid, kSelectableAid + size); +- status = session->openLogicalChannel(aid, 0x00, mSEListener, &channel); +- if (!status.isOk()) { +- LOG(ERROR) << "Could not open channel error: " << status.getMessage(); +- return false; +- } +- if (channel == nullptr) { +- LOG(ERROR) << "Could not open channel null"; +- return false; +- } ++bool OmapiTransport::openConnection() { + return true; + } + +-bool OmapiTransport::internalTransmitApdu(std::vector apdu, +- std::vector& transmitResponse) { +- bool isClosed = true; +- ndk::ScopedAStatus res; +- LOG(DEBUG) << "internalTransmitApdu: trasmitting data to secure element"; +- if (session != nullptr) { +- res = session->isClosed(&isClosed); +- if (!res.isOk()) { +- LOG(ERROR) << "isClosed error: " << res.getMessage(); +- return false; +- } +- } +- if(isClosed) { +- res = eSEReader->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; +- } +- } +- isClosed = true; +- if (channel != nullptr) { +- res = channel->isClosed(&isClosed); +- if (!res.isOk()) { +- LOG(ERROR) << "isClosed error: " << res.getMessage(); +- return false; +- } +- } +- if(isClosed) { +- auto mSEListener = ndk::SharedRefBase::make(); +- int size = sizeof(kSelectableAid) / sizeof(kSelectableAid[0]); +- std::vector aid(kSelectableAid, kSelectableAid + size); +- res = session->openLogicalChannel(aid, 0x00, mSEListener, &channel); +- if (!res.isOk()) { +- LOG(ERROR) << "Could not open channel error: " << res.getMessage(); +- return false; +- } +- if (channel == nullptr) { +- LOG(ERROR) << "Could not open channel null"; +- return false; +- } +- } +- +- std::vector selectResponse = {}; +- res = channel->getSelectResponse(&selectResponse); +- if (!res.isOk()) { +- LOG(ERROR) << "getSelectResponse error: " << res.getMessage(); +- return false; +- } +- if ((selectResponse.size() < 2) || +- ((selectResponse[selectResponse.size() - 1] & 0xFF) == 0x00) || +- ((selectResponse[selectResponse.size() - 2] & 0xFF) == 0x90)) { +- LOG(ERROR) << "Failed to select the Applet."; +- return false; +- } +- +- res = channel->transmit(apdu, &transmitResponse); +- +- LOG(INFO) << "STATUS OF TRANSMIT: " << res.getExceptionCode() << " Message: " +- << res.getMessage(); +- if (!res.isOk()) { +- LOG(ERROR) << "transmit error: " << res.getMessage(); +- return false; +- } +- ++bool OmapiTransport::sendData(const uint8_t* inData, const size_t inLen, std::vector& output) { ++ std::vector test(inData, inData+inLen); ++ output = std::move(test); + 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 uint8_t* inData, const size_t inLen, +- std::vector& output) { +- +- if (inData == NULL) { +- LOG(ERROR) << "Failed to send data, APDU is null"; +- return false; +- } +- std::vector apdu(inData, inData+inLen); +- +- 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; +- } +- } +- +- LOG(DEBUG) << "Sending apdu data to secure element: " << kEseReaderPrefix; +- return internalTransmitApdu(apdu, output); +-} +- + 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(); +- } +- } +- if (channel != nullptr) { +- channel->close(); +- channel = nullptr; +- } +- if (session != nullptr) { +- session->close(); +- session = nullptr; +- } + 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; ++ return true; + } + + } +diff --git a/HAL/keymaster/Android.bp b/HAL/keymaster/Android.bp +index 33f255f..9bfe7fa 100644 +--- a/HAL/keymaster/Android.bp ++++ b/HAL/keymaster/Android.bp +@@ -47,8 +47,6 @@ cc_binary { + "libjc_transport", + "libjc_common", + "libcrypto", +- "libbinder_ndk", +- "android.se.omapi-V1-ndk", + ], + required: [ + "android.hardware.strongbox_keystore.xml", +@@ -84,8 +82,6 @@ cc_library { + "android.hardware.keymaster@4.0", + "libjc_transport", + "libcrypto", +- "libbinder_ndk", +- "android.se.omapi-V1-ndk", + ], + } + +@@ -104,8 +100,6 @@ cc_library { + "libbinder", + "libbase", + "liblog", +- "libbinder_ndk", +- "android.se.omapi-V1-ndk", + ], + } + +diff --git a/HAL/keymaster/include/Transport.h b/HAL/keymaster/include/Transport.h +index f525479..c6674dc 100644 +--- a/HAL/keymaster/include/Transport.h ++++ b/HAL/keymaster/include/Transport.h +@@ -17,16 +17,6 @@ + #ifndef __SE_TRANSPORT__ + #define __SE_TRANSPORT__ + +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- + namespace se_transport { + + /** +@@ -40,7 +30,7 @@ class ITransport { + /** + * Opens connection. + */ +- virtual bool openConnection() = 0; ++ virtual bool openConnection() = 0; + /** + * Send data over communication channel and receives data back from the remote end. + */ +@@ -64,14 +54,12 @@ class ITransport { + class OmapiTransport : public ITransport { + + public: +- OmapiTransport() : omapiSeService(nullptr), eSEReader(nullptr), session(nullptr), +- channel(nullptr) { +- } ++ + /** + * Gets the binder instance of ISEService, gets the reader corresponding to secure element, establishes a session + * and opens a basic channel. + */ +- bool openConnection() override; ++ bool openConnection() override; + /** + * Transmists the data over the opened basic channel and receives the data back. + */ +@@ -87,16 +75,6 @@ public: + */ + bool isConnected() override; + +-private: +- std::shared_ptr omapiSeService; +- std::shared_ptr eSEReader; +- std::shared_ptr session; +- std::shared_ptr channel; +- std::map> +- mVSReaders; +- // Private functions +- bool initialize(); +- bool internalTransmitApdu(std::vector apdu, std::vector& transmitResponse); + }; + + class SocketTransport : public ITransport { +@@ -107,7 +85,7 @@ public: + /** + * Creates a socket instance and connects to the provided server IP and port. + */ +- bool openConnection() override; ++ bool openConnection() override; + /** + * Sends data over socket and receives data back. + */