diff --git a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp index 87daddbc..20a1ac5c 100644 --- a/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp +++ b/HAL/keymaster/4.1/JavacardKeymaster4Device.cpp @@ -136,7 +136,7 @@ static inline std::unique_ptr& getTransportFacto if (!isEmulator) { std::string fingerprint = android::base::GetProperty(PROP_BUILD_FINGERPRINT, ""); if (!fingerprint.empty()) { - if (fingerprint.find(CUTTLEFISH_FINGERPRINT_SS, 0)) { + if (fingerprint.find(CUTTLEFISH_FINGERPRINT_SS, 0) != std::string::npos) { isEmulator = true; } } diff --git a/HAL/keymaster/4.1/OmapiTransport.cpp b/HAL/keymaster/4.1/OmapiTransport.cpp index 5aaefc91..e7bd9a84 100644 --- a/HAL/keymaster/4.1/OmapiTransport.cpp +++ b/HAL/keymaster/4.1/OmapiTransport.cpp @@ -14,36 +14,214 @@ ** 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 + +#include + #include "Transport.h" -#define PORT 8080 -#define IPADDR "10.9.40.24" #define UNUSED_V(a) a=a namespace se_transport { -bool OmapiTransport::openConnection() { +class SEListener : public ::aidl::android::system::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_getService(omapiServiceName)); + omapiSeService = aidl::android::system::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::system::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::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::shared_ptr reader, + std::vector apdu, std::vector& transmitResponse) { + std::shared_ptr session; + std::shared_ptr channel; + auto mSEListener = std::make_shared(); + std::vector selectResponse = {}; + std::vector 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 uint8_t* inData, const size_t inLen, + std::vector& output) { + 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; + } + } + + if (inData == NULL) { + LOG(ERROR) << "Failed to send data, APDU is null"; + return false; + } + + if (eSEReader != nullptr) { + LOG(DEBUG) << "Sending apdu data to secure element: " << ESE_READER_PREFIX; + return internalTransmitApdu(eSEReader, apdu, 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() { - 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 cb88780c..6e30218e 100644 --- a/HAL/keymaster/Android.bp +++ b/HAL/keymaster/Android.bp @@ -47,6 +47,10 @@ cc_binary { "libjc_transport", "libjc_common", "libcrypto", + "libbinder_ndk", + ], + static_libs: [ + "android.system.omapi-V1-ndk_platform", ], required: [ "android.hardware.strongbox_keystore.xml", @@ -87,7 +91,6 @@ cc_library { cc_library { name: "libjc_transport", - host_supported: true, vendor_available: true, vndk: { enabled: true, @@ -104,6 +107,10 @@ cc_library { "libbinder", "libbase", "liblog", + "libbinder_ndk", + ], + static_libs: [ + "android.system.omapi-V1-ndk_platform", ], } diff --git a/HAL/keymaster/include/Transport.h b/HAL/keymaster/include/Transport.h index c6674dca..1df7bf4f 100644 --- a/HAL/keymaster/include/Transport.h +++ b/HAL/keymaster/include/Transport.h @@ -17,6 +17,17 @@ #ifndef __SE_TRANSPORT__ #define __SE_TRANSPORT__ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + namespace se_transport { /** @@ -75,6 +86,19 @@ class OmapiTransport : public ITransport { */ bool isConnected() override; +private: + std::shared_ptr omapiSeService = nullptr; + std::shared_ptr eSEReader = nullptr; + std::map> + 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 reader, + std::vector apdu, std::vector& transmitResponse); }; class SocketTransport : public ITransport {