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
245 changes: 231 additions & 14 deletions HAL/keymaster/4.1/OmapiTransport.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,36 +14,253 @@
** 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 <stdio.h>
#include <unistd.h>
#include <string.h>
#include <vector>
#include "Transport.h"

#define PORT 8080
#define IPADDR "10.9.40.24"
#define UNUSED_V(a) a=a
#include <android-base/logging.h>

#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<std::string> 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<SEListener>();
int size = sizeof(kSelectableAid) / sizeof(kSelectableAid[0]);
std::vector<uint8_t> 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<uint8_t>& output) {
std::vector<uint8_t> test(inData, inData+inLen);
output = std::move(test);
bool OmapiTransport::internalTransmitApdu(std::vector<uint8_t> apdu,
std::vector<uint8_t>& 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<SEListener>();
int size = sizeof(kSelectableAid) / sizeof(kSelectableAid[0]);
std::vector<uint8_t> 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<uint8_t> 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<uint8_t>& output) {

if (inData == NULL) {
LOG(ERROR) << "Failed to send data, APDU is null";
return false;
}
std::vector<uint8_t> 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;
}

}
6 changes: 6 additions & 0 deletions HAL/keymaster/Android.bp
Original file line numberDiff line numberDiff line change
Expand Up@@ -47,6 +47,8 @@ cc_binary {
"libjc_transport",
"libjc_common",
"libcrypto",
"libbinder_ndk",
"android.se.omapi-V1-ndk",
],
required: [
"android.hardware.strongbox_keystore.xml",
Expand DownExpand Up@@ -82,6 +84,8 @@ cc_library {
"android.hardware.keymaster@4.0",
"libjc_transport",
"libcrypto",
"libbinder_ndk",
"android.se.omapi-V1-ndk",
],
}

Expand All@@ -100,6 +104,8 @@ cc_library {
"libbinder",
"libbase",
"liblog",
"libbinder_ndk",
"android.se.omapi-V1-ndk",
],
}

Expand Down
30 changes: 26 additions & 4 deletions HAL/keymaster/include/Transport.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,6 +17,16 @@
#ifndef __SE_TRANSPORT__
#define __SE_TRANSPORT__

#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>

namespace se_transport {

/**
Expand All@@ -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.
*/
Expand All@@ -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.
*/
Expand All@@ -75,6 +87,16 @@ class OmapiTransport : public ITransport {
*/
bool isConnected() override;

private:
std::shared_ptr<aidl::android::se::omapi::ISecureElementService> omapiSeService;
std::shared_ptr<aidl::android::se::omapi::ISecureElementReader> eSEReader;
std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
std::map<std::string, std::shared_ptr<aidl::android::se::omapi::ISecureElementReader>>
mVSReaders;
// Private functions
bool initialize();
bool internalTransmitApdu(std::vector<uint8_t> apdu, std::vector<uint8_t>& transmitResponse);
};

class SocketTransport : public ITransport {
Expand All@@ -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.
*/
Expand Down
Loading