From 0606772cc3beb1dedefed96df49dc903e017b0e7 Mon Sep 17 00:00:00 2001 From: Michael Kuc Date: Fri, 23 Aug 2019 13:00:22 +0100 Subject: [PATCH] Basic U2FDevice implementation. --- IO.cpp | 109 +++++++++++++++++++++++++------------------------- IO.hpp | 5 ++- Packet.cpp | 4 +- Streams.cpp | 13 +++--- U2FDevice.cpp | 11 +---- 5 files changed, 68 insertions(+), 74 deletions(-) diff --git a/IO.cpp b/IO.cpp index 854dc0c..b6d3b52 100644 --- a/IO.cpp +++ b/IO.cpp @@ -23,25 +23,35 @@ along with this program. If not, see . #include #include #include -#include +#include #include #include +#include +#include +#include +#include +#include +#include #include "u2f.hpp" #include "Macro.hpp" #include "U2FDevice.hpp" -#include using namespace std; -bool bytesAvailable(const size_t count); +bool bytesAvailable(size_t count); vector& getBuffer(); +string binaryDirectory{}; +string cacheDirectory{ DEBUG_STREAMS }; + +// Thanks to https://stackoverflow.com/a/478960 +vector execOutput(const string &cmd); +void execInput(const string &cmd, const vector &stdinData); + vector readNonBlock(const size_t count) { if (!bytesAvailable(count)) - { return vector{}; - } auto &buffer = getBuffer(); auto buffStart = buffer.begin(), buffEnd = buffer.begin() + count; @@ -53,33 +63,20 @@ vector readNonBlock(const size_t count) return bytes; } -void write(const uint8_t* bytes, const size_t count) +void write(const vector &bytes) { - size_t totalBytes = 0; - auto hostDescriptor = *getHostDescriptor(); - - while (totalBytes < count) - { - auto writtenBytes = write(hostDescriptor, bytes + totalBytes, count - totalBytes); - - if (writtenBytes > 0) - totalBytes += writtenBytes; - else if (errno != 0 && errno != EAGAIN && errno != EWOULDBLOCK) //Expect file blocking behaviour - ERR(); - } - - errno = 0; + __android_log_print(ANDROID_LOG_DEBUG, "U2FAndroid", "Writing %zu bytes", bytes.size()); + execInput("su -c \"" + binaryDirectory + "/U2FAndroid_Write\"", bytes); } bool bytesAvailable(const size_t count) { auto startTime = std::chrono::high_resolution_clock::now(); - const timespec iterDelay{ 0, 1000 }; + const timespec iterDelay{ 0, 10000000 }; chrono::duration delay{ 0 }; - while (delay.count() < U2FHID_TRANS_TIMEOUT && contProc) + while (delay.count() < U2FHID_TRANS_TIMEOUT) { - delay = chrono::high_resolution_clock::now() - startTime; if (getBuffer().size() >= count) { #ifdef DEBUG_MSGS clog << "Requested " << count << " bytes" << endl; @@ -87,6 +84,7 @@ bool bytesAvailable(const size_t count) return true; } nanosleep(&iterDelay, nullptr); + delay = chrono::high_resolution_clock::now() - startTime; } #ifdef DEBUG_MSGS @@ -105,44 +103,45 @@ vector& bufferVar() vector& getBuffer() { auto &buff = bufferVar(); - array bytes{}; - auto hostDescriptor = *getHostDescriptor(); + vector bytes = execOutput("su -c \"" + binaryDirectory + "/U2FAndroid_Read\""); - while (true) + if (!bytes.empty()) { - auto readByteCount = read(hostDescriptor, bytes.data(), HID_RPT_SIZE); - - if (readByteCount > 0 && readByteCount != HID_RPT_SIZE) - { - //Failed to copy an entire packet in, so log this packet -#ifdef DEBUG_MSGS - cerr << "Only retrieved " << readByteCount << " bytes from expected full packet." << endl; -#endif - } - - if (readByteCount > 0) - { - copy(bytes.begin(), bytes.begin() + readByteCount, back_inserter(buff)); + __android_log_print(ANDROID_LOG_DEBUG, "U2FAndroid", "Reading bytes: got %zu", bytes.size()); + buff.insert(buff.end(), bytes.begin(), bytes.end()); #ifdef DEBUG_STREAMS - fwrite(bytes.data(), 1, readByteCount, getComHostStream().get()); + fwrite(bytes.data(), 1, bytes.size(), getComHostStream().get()); #endif - - } - else if (errno != EAGAIN && errno != EWOULDBLOCK) //Expect read would block - { - ERR(); -#ifdef DEBUG_MSGS - cerr << "Unknown stream error: " << errno << endl; -#endif - break; - } - else - { - errno = 0; - break; //Escape loop if blocking would occur - } } return buff; } + +vector execOutput(const string &cmd) +{ + // NOLINT(hicpp-member-init) + array buffer; + vector result{}; + unique_ptr pipe{ popen(cmd.c_str(), "rb"), pclose }; + + if (!pipe) + throw std::runtime_error("popen() failed!"); + while (size_t readBytes = fread(buffer.data(), 1, buffer.size(), pipe.get())) + copy(buffer.begin(), buffer.begin() + readBytes, back_inserter(result)); + + return result; +} + +void execInput(const string &cmd, const vector &stdinData) +{ + assert(stdinData.size() % HID_RPT_SIZE == 0); + + size_t writtenBytes = 0; + unique_ptr pipe{ popen(cmd.c_str(), "wb"), pclose }; + + if (!pipe) + throw std::runtime_error("popen() failed!"); + while (writtenBytes < stdinData.size()) + writtenBytes += fwrite(stdinData.data(), 1, HID_RPT_SIZE, pipe.get()); +} diff --git a/IO.hpp b/IO.hpp index 57fadcc..2e25d7c 100644 --- a/IO.hpp +++ b/IO.hpp @@ -21,9 +21,12 @@ along with this program. If not, see . #include #include +extern std::string binaryDirectory; +extern std::string cacheDirectory; + //Returns either the number of bytes specified, //or returns empty vector without discarding bytes from HID stream std::vector readNonBlock(const size_t count); //Blocking write to HID stream - shouldn't block for too long -void write(const uint8_t* bytes, const size_t count); +void write(const std::vector& data); diff --git a/Packet.cpp b/Packet.cpp index 1f0e983..ef412ca 100644 --- a/Packet.cpp +++ b/Packet.cpp @@ -243,7 +243,7 @@ void InitPacket::writePacket() memcpy(this->buf + 5, &bcnth, 1); memcpy(this->buf + 6, &bcntl, 1); memcpy(this->buf + 7, data.data(), data.size()); - write(this->buf, sizeof(this->buf)); + write(vector{ this->buf, this->buf + sizeof(this->buf) }); #ifdef DEBUG_STREAMS fwrite(this->buf, 1, sizeof(this->buf), devStream); @@ -288,7 +288,7 @@ void ContPacket::writePacket() memcpy(this->buf + 4, &seq, 1); memcpy(this->buf + 5, data.data(), data.size()); - write(this->buf, HID_RPT_SIZE); + write(vector{this->buf, this->buf + HID_RPT_SIZE }); #ifdef DEBUG_STREAMS fwrite(this->buf, HID_RPT_SIZE, 1, devStream); diff --git a/Streams.cpp b/Streams.cpp index 4f51ec3..35afadd 100644 --- a/Streams.cpp +++ b/Streams.cpp @@ -17,6 +17,7 @@ along with this program. If not, see . */ #include "Streams.hpp" +#include "IO.hpp" #include #include #include @@ -49,7 +50,7 @@ shared_ptr getHostDescriptor() #ifdef DEBUG_STREAMS shared_ptr getComHostStream() { - static shared_ptr stream{ fopen(DEBUG_STREAMS "comhost.txt", "wb"), [](FILE *f){ + static shared_ptr stream{ fopen((cacheDirectory + "comhost.txt").c_str(), "wb"), [](FILE *f){ clog << "Closing comhost stream" << endl; fclose(f); } }; @@ -62,7 +63,7 @@ shared_ptr getComHostStream() shared_ptr getHostPacketStream() { - static shared_ptr stream{ initHTML(fopen(DEBUG_STREAMS "hostpackets.html", "wb"), "Host Packets"), [](FILE *f){ + static shared_ptr stream{ initHTML(fopen((cacheDirectory + "hostpackets.html").c_str(), "wb"), "Host Packets"), [](FILE *f){ clog << "Closing hostPackets stream" << endl; closeHTML(f); } }; @@ -75,7 +76,7 @@ shared_ptr getHostPacketStream() shared_ptr getHostAPDUStream() { - static shared_ptr stream{ initHTML(fopen(DEBUG_STREAMS "hostAPDU.html", "wb"), "Host APDU"), [](FILE *f){ + static shared_ptr stream{ initHTML(fopen((cacheDirectory + "hostAPDU.html").c_str(), "wb"), "Host APDU"), [](FILE *f){ clog << "Closing host APDU stream" << endl; closeHTML(f); } }; @@ -88,7 +89,7 @@ shared_ptr getHostAPDUStream() shared_ptr getComDevStream() { - static shared_ptr stream{ fopen(DEBUG_STREAMS "comdev.txt", "wb"), [](FILE *f){ + static shared_ptr stream{ fopen((cacheDirectory + "comdev.txt").c_str(), "wb"), [](FILE *f){ clog << "Closing comdev stream" << endl; fclose(f); } }; @@ -101,7 +102,7 @@ shared_ptr getComDevStream() shared_ptr getDevPacketStream() { - static shared_ptr stream{ initHTML(fopen(DEBUG_STREAMS "devpackets.html", "wb"), "Dev Packets"), [](FILE *f){ + static shared_ptr stream{ initHTML(fopen((cacheDirectory + "devpackets.html").c_str(), "wb"), "Dev Packets"), [](FILE *f){ clog << "Closing devPackets stream" << endl; closeHTML(f); } }; @@ -114,7 +115,7 @@ shared_ptr getDevPacketStream() shared_ptr getDevAPDUStream() { - static shared_ptr stream{ initHTML(fopen(DEBUG_STREAMS "devAPDU.html", "wb"), "Dev APDU"), [](FILE *f){ + static shared_ptr stream{ initHTML(fopen((cacheDirectory + "devAPDU.html").c_str(), "wb"), "Dev APDU"), [](FILE *f){ clog << "Closing dev APDU stream" << endl; closeHTML(f); } }; diff --git a/U2FDevice.cpp b/U2FDevice.cpp index fb34cd2..a8ecf8d 100644 --- a/U2FDevice.cpp +++ b/U2FDevice.cpp @@ -21,7 +21,7 @@ along with this program. If not, see . #include "Storage.hpp" #include "Controller.hpp" #include "LED.hpp" -#include +#include #include using namespace std; @@ -40,9 +40,6 @@ bool initialiseLights(const string& prog) { { cerr << e.what() << endl; - if (getuid() != 0) - cerr << "Try running as root, using \'sudo " << prog << "\'" << endl; - return false; } @@ -65,9 +62,6 @@ int handleTransactions(const string& prog, const string& privKeyDir) { cerr << e.what() << endl; - if (getuid() != 0) - cerr << "Try running as root, using \'sudo " << prog << "\'" << endl; - raise(SIGINT); return EXIT_FAILURE; } @@ -88,9 +82,6 @@ bool deinitialiseLights(const string& prog) { { cerr << e.what() << endl; - if (getuid() != 0) - cerr << "Try running as root, using \'sudo " << prog << "\'" << endl; - return false; }