diff --git a/.gitignore b/.gitignore
index 70eac42..0347e2c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
-libuECC.o
-libcppb64.o
+libuECC.a
+libcppb64.a
U2FDevice
obj/*
U2F_Priv_Keys.txt
diff --git a/Architecture.hpp b/Architecture.hpp
index 8f0536d..759bc26 100644
--- a/Architecture.hpp
+++ b/Architecture.hpp
@@ -20,17 +20,21 @@ along with this program. If not, see .
#define ARCH_RASPBERRY_PI 1
#define ARCH_ANDROID 2
-#define ARCHITECTURE ARCH_RASPBERRY_PI
+#define ARCHITECTURE ARCH_ANDROID
#if ARCHITECTURE == ARCH_RASPBERRY_PI
#define STORAGE_PREFIX "/usr/share/"
#define HID_DEV "/dev/hidg0"
- #define DEBUG_STREAMS
+ #define DEBUG_STREAMS "/tmp/"
+// #define DEBUG_MSGS
+ #define LEDS
#elif ARCHITECTURE == ARCH_ANDROID
- #define STORAGE_PREFIX "/sdcard/U2F"
+ #define STORAGE_PREFIX "/sdcard/U2F/"
#define HID_DEV "/dev/hidg2"
+ #define DEBUG_STREAMS "/data/local/tmp/"
+// #define DEBUG_MSGS
#endif
#undef ARCH_ANDROID
#undef ARCH_RASPBERRY_PI
-#undef ARCHITECTURE
\ No newline at end of file
+#undef ARCHITECTURE
diff --git a/Controller.cpp b/Controller.cpp
index 6554d56..97cf7dd 100644
--- a/Controller.cpp
+++ b/Controller.cpp
@@ -64,6 +64,11 @@ void Controller::handleTransaction()
}
}
+#ifdef DEBUG_MSGS
+ clog << "Message:" << endl;
+ clog << "cid: " << msg->cid << ", cmd: " << static_cast(msg->cmd) << endl;
+#endif
+
channels.at(opChannel).handle(msg);
}
diff --git a/IO.cpp b/IO.cpp
index 081e4a3..6f4f0b8 100644
--- a/IO.cpp
+++ b/IO.cpp
@@ -20,14 +20,17 @@ along with this program. If not, see .
#include "Streams.hpp"
#include
#include
-#include
//#include
#include
#include
#include
#include
+#include
+#include
+#include
#include "u2f.hpp"
#include "Macro.hpp"
+#include "U2FDevice.hpp"
using namespace std;
@@ -38,7 +41,6 @@ vector readNonBlock(const size_t count)
{
if (!bytesAvailable(count))
{
- //clog << "No bytes available" << endl;
return vector{};
}
@@ -46,8 +48,6 @@ vector readNonBlock(const size_t count)
auto buffStart = buffer.begin(), buffEnd = buffer.begin() + count;
vector bytes{ buffStart, buffEnd };
buffer.erase(buffStart, buffEnd);
-
- fwrite(bytes.data(), 1, bytes.size(), getComHostStream().get());
errno = 0;
@@ -74,7 +74,27 @@ void write(const uint8_t* bytes, const size_t count)
bool bytesAvailable(const size_t count)
{
- return getBuffer().size() >= count;
+ auto startTime = std::chrono::high_resolution_clock::now();
+ const timespec iterDelay{ 0, 1000 };
+ chrono::duration delay{ 0 };
+
+ while (delay.count() < U2FHID_TRANS_TIMEOUT && contProc)
+ {
+ delay = chrono::high_resolution_clock::now() - startTime;
+ if (getBuffer().size() >= count) {
+#ifdef DEBUG_MSGS
+ clog << "Requested " << count << " bytes" << endl;
+#endif
+ return true;
+ }
+ nanosleep(&iterDelay, nullptr);
+ }
+
+#ifdef DEBUG_MSGS
+ cerr << "Failed to obtain " << count << " bytes, having " << getBuffer().size() << endl;
+#endif
+
+ return false;
}
vector& bufferVar()
@@ -92,21 +112,38 @@ vector& getBuffer()
while (true)
{
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));
+
+#ifdef DEBUG_STREAMS
+ fwrite(bytes.data(), 1, readByteCount, getComHostStream().get());
+#endif
+
}
else if (errno != EAGAIN && errno != EWOULDBLOCK) //Expect read would block
{
ERR();
+#if DEBUG_MSGS
+ cerr << "Unknown stream error: " << errno << endl;
+#endif
+ break;
}
else
{
+ errno = 0;
break; //Escape loop if blocking would occur
}
}
return buff;
}
-
diff --git a/LED.cpp b/LED.cpp
index 3a82a56..68045e9 100644
--- a/LED.cpp
+++ b/LED.cpp
@@ -35,9 +35,9 @@ bool getLEDState()
return ledState();
}
-void disableACTTrigger(bool nowDisabled)
+void disableACTTrigger([[maybe_unused]] bool nowDisabled)
{
-#if ARCHITECTURE == RASPBERRY_PI
+#ifdef LEDS
ofstream trigFile{ "/sys/class/leds/led0/trigger", ofstream::out | ofstream::trunc };
if (!trigFile)
@@ -48,9 +48,9 @@ void disableACTTrigger(bool nowDisabled)
#endif
}
-void enableACTLED(bool nowOn)
+void enableACTLED([[maybe_unused]] bool nowOn)
{
-#if ARCHITECTURE == RASPBERRY_PI
+#ifdef LEDS
if (nowOn == getLEDState())
return;
diff --git a/Packet.cpp b/Packet.cpp
index b030352..1f0e983 100644
--- a/Packet.cpp
+++ b/Packet.cpp
@@ -80,6 +80,7 @@ shared_ptr InitPacket::getPacket(const uint32_t rCID, const uint8_t
p->bcntl = bcntl;
p->data = dataBytes;
+#ifdef DEBUG_STREAMS
auto hPStream = getHostPacketStream().get();
fprintf(hPStream, "\t\t\n"
"\t\t\t\n"
@@ -107,6 +108,7 @@ shared_ptr InitPacket::getPacket(const uint32_t rCID, const uint8_t
"\t\t\t\n"
"\t\t
"
"\t\t
");
+#endif
bytesRead = 0;
return p;
@@ -136,6 +138,7 @@ shared_ptr ContPacket::getPacket(const uint32_t rCID, const uint8_t
p->seq = rSeq;
p->data = dataBytes;
+#ifdef DEBUG_STREAMS
auto hPStream = getHostPacketStream().get();
fprintf(hPStream, "\t\t\n"
"\t\t\t\n"
@@ -159,6 +162,7 @@ shared_ptr ContPacket::getPacket(const uint32_t rCID, const uint8_t
"\t\t\t\n"
"\t\t
\n"
"\t\t
");
+#endif
readBytes = 0;
return p;
@@ -230,13 +234,18 @@ void Packet::writePacket()
void InitPacket::writePacket()
{
Packet::writePacket();
+
+#ifdef DEBUG_STREAMS
auto devStream = getComDevStream().get();
+#endif
memcpy(this->buf + 4, &cmd, 1);
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));
+
+#ifdef DEBUG_STREAMS
fwrite(this->buf, 1, sizeof(this->buf), devStream);
auto dPStream = getDevPacketStream().get();
@@ -266,16 +275,22 @@ void InitPacket::writePacket()
"\t\t\t\n"
"\t\t"
"\t\t
");
+#endif
}
void ContPacket::writePacket()
{
Packet::writePacket();
+
+#ifdef DEBUG_STREAMS
auto devStream = getComDevStream().get();
+#endif
memcpy(this->buf + 4, &seq, 1);
memcpy(this->buf + 5, data.data(), data.size());
write(this->buf, HID_RPT_SIZE);
+
+#ifdef DEBUG_STREAMS
fwrite(this->buf, HID_RPT_SIZE, 1, devStream);
auto dPStream = getDevPacketStream().get();
@@ -302,4 +317,5 @@ void ContPacket::writePacket()
"\t\t\t\n"
"\t\t\n"
"\t\t
");
+#endif
}
diff --git a/Streams.cpp b/Streams.cpp
index 32c8c7f..4f51ec3 100644
--- a/Streams.cpp
+++ b/Streams.cpp
@@ -46,9 +46,10 @@ shared_ptr getHostDescriptor()
return descriptor;
}
+#ifdef DEBUG_STREAMS
shared_ptr getComHostStream()
{
- static shared_ptr stream{ fopen("/tmp/comhost.txt", "wb"), [](FILE *f){
+ static shared_ptr stream{ fopen(DEBUG_STREAMS "comhost.txt", "wb"), [](FILE *f){
clog << "Closing comhost stream" << endl;
fclose(f);
} };
@@ -61,7 +62,7 @@ shared_ptr getComHostStream()
shared_ptr getHostPacketStream()
{
- static shared_ptr stream{ initHTML(fopen("/tmp/hostpackets.html", "wb"), "Host Packets"), [](FILE *f){
+ static shared_ptr stream{ initHTML(fopen(DEBUG_STREAMS "hostpackets.html", "wb"), "Host Packets"), [](FILE *f){
clog << "Closing hostPackets stream" << endl;
closeHTML(f);
} };
@@ -74,7 +75,7 @@ shared_ptr getHostPacketStream()
shared_ptr getHostAPDUStream()
{
- static shared_ptr stream{ initHTML(fopen("/tmp/hostAPDU.html", "wb"), "Host APDU"), [](FILE *f){
+ static shared_ptr stream{ initHTML(fopen(DEBUG_STREAMS "hostAPDU.html", "wb"), "Host APDU"), [](FILE *f){
clog << "Closing host APDU stream" << endl;
closeHTML(f);
} };
@@ -87,7 +88,7 @@ shared_ptr getHostAPDUStream()
shared_ptr getComDevStream()
{
- static shared_ptr stream{ fopen("/tmp/comdev.txt", "wb"), [](FILE *f){
+ static shared_ptr stream{ fopen(DEBUG_STREAMS "comdev.txt", "wb"), [](FILE *f){
clog << "Closing comdev stream" << endl;
fclose(f);
} };
@@ -100,7 +101,7 @@ shared_ptr getComDevStream()
shared_ptr getDevPacketStream()
{
- static shared_ptr stream{ initHTML(fopen("/tmp/devpackets.html", "wb"), "Dev Packets"), [](FILE *f){
+ static shared_ptr stream{ initHTML(fopen(DEBUG_STREAMS "devpackets.html", "wb"), "Dev Packets"), [](FILE *f){
clog << "Closing devPackets stream" << endl;
closeHTML(f);
} };
@@ -113,7 +114,7 @@ shared_ptr getDevPacketStream()
shared_ptr getDevAPDUStream()
{
- static shared_ptr stream{ initHTML(fopen("/tmp/devAPDU.html", "wb"), "Dev APDU"), [](FILE *f){
+ static shared_ptr stream{ initHTML(fopen(DEBUG_STREAMS "devAPDU.html", "wb"), "Dev APDU"), [](FILE *f){
clog << "Closing dev APDU stream" << endl;
closeHTML(f);
} };
@@ -124,7 +125,6 @@ shared_ptr getDevAPDUStream()
return stream;
}
-#ifdef DEBUG_STREAMS
FILE* initHTML(FILE *fPtr, const string &title)
{
fprintf(fPtr, "\n"
diff --git a/U2FDevice.hpp b/U2FDevice.hpp
index fcdb464..5ab1dba 100644
--- a/U2FDevice.hpp
+++ b/U2FDevice.hpp
@@ -19,6 +19,8 @@ along with this program. If not, see .
#pragma once
#include
+extern volatile bool contProc;
+
bool initialiseLights(const std::string& prog);
bool deinitialiseLights(const std::string& prog);
int handleTransactions(const std::string& prog, const std::string& privKeyDir);
diff --git a/U2FMessage.cpp b/U2FMessage.cpp
index b429d9c..dd5b508 100644
--- a/U2FMessage.cpp
+++ b/U2FMessage.cpp
@@ -23,12 +23,14 @@ along with this program. If not, see .
#include
#include "Streams.hpp"
#include "u2f.hpp"
+#include "IO.hpp"
using namespace std;
shared_ptr U2FMessage::readNonBlock()
{
- static size_t currSeq = -1;
+ const static size_t startSeq = (size_t)-1ull;
+ static size_t currSeq = startSeq;
static uint16_t messageSize;
static uint32_t cid;
static uint8_t cmd;
@@ -36,7 +38,7 @@ shared_ptr U2FMessage::readNonBlock()
shared_ptr p{};
- if (currSeq == -1u)
+ if (currSeq == startSeq)
{
cid = 0;
cmd = 0;
@@ -52,6 +54,11 @@ shared_ptr U2FMessage::readNonBlock()
return {};
initPack = dynamic_pointer_cast(p);
+
+#ifdef DEBUG_MSGS
+ if (!initPack)
+ cerr << "Spurious cont. packet" << endl;
+#endif
} while (!initPack); //Spurious cont. packet - spec states ignore
messageSize = ((static_cast(initPack->bcnth) << 8u) + initPack->bcntl);
@@ -61,7 +68,7 @@ shared_ptr U2FMessage::readNonBlock()
cmd = initPack->cmd;
copy(initPack->data.begin(), initPack->data.begin() + copyByteCount, back_inserter(dataBytes));
- currSeq++;
+ currSeq = 0;
}
while (messageSize > dataBytes.size() && static_cast(p = Packet::getPacket())) //While there is a packet
@@ -70,38 +77,50 @@ shared_ptr U2FMessage::readNonBlock()
if (!contPack) //Spurious init. packet
{
- currSeq = -1; //Reset
+#ifdef DEBUG_MSGS
+ cerr << "Spurious init. packet" << endl;
+#endif
+ currSeq = startSeq; //Reset
return {};
}
if (contPack->cid != cid) //Cont. packet of different CID
{
+#ifdef DEBUG_MSGS
cerr << "Invalid CID: was handling channel 0x" << hex << cid << " and received packet from channel 0x" << contPack->cid << dec << endl;
+#endif
U2FMessage::error(contPack->cid, ERR_CHANNEL_BUSY);
- currSeq = -1;
+ currSeq = startSeq;
return {};
}
if (contPack->seq != currSeq)
{
+#ifdef DEBUG_MSGS
cerr << "Invalid packet seq. value" << endl;
+#endif
U2FMessage::error(cid, ERR_INVALID_SEQ);
- currSeq = -1;
+ currSeq = startSeq;
return {};
}
const uint16_t remainingBytes = messageSize - dataBytes.size();
const uint16_t copyBytes = min(static_cast(contPack->data.size()), remainingBytes);
+
dataBytes.insert(dataBytes.end(), contPack->data.begin(), contPack->data.begin() + copyBytes);
currSeq++;
}
- if (messageSize != dataBytes.size())
+ if (messageSize != dataBytes.size()) {
+#ifdef DEBUG_MSGS
+ cerr << "Invalid message size: " << messageSize << " when received " << dataBytes.size() << endl;
+#endif
return {};
+ }
auto message = make_shared(cid, cmd);
message->data.assign(dataBytes.begin(), dataBytes.end());
- currSeq = -1u;
+ currSeq = startSeq;
return message;
}
@@ -146,6 +165,7 @@ void U2FMessage::write()
if (cmd == U2FHID_MSG)
{
+#ifdef DEBUG_STREAMS
auto dAS = getDevAPDUStream().get();
fprintf(dAS, "\n"
@@ -161,16 +181,19 @@ void U2FMessage::write()
for (size_t i = 0; i < data.size() - 2; i++)
fprintf(dAS, "%3u ", data[i]);
+#endif
uint16_t err = data[data.size() - 2] << 8;
err |= data.back();
+#ifdef DEBUG_STREAMS
fprintf(dAS, "\n"
"\t\t\t\t\t| 0x%04X | \n"
"\t\t\t\t\n"
"\t\t\t\n"
"\t\t
\n"
"\t\t
", err);
+#endif
}
}
diff --git a/U2F_Msg_CMD.cpp b/U2F_Msg_CMD.cpp
index 3c3907d..b78d0b2 100644
--- a/U2F_Msg_CMD.cpp
+++ b/U2F_Msg_CMD.cpp
@@ -138,6 +138,7 @@ shared_ptr U2F_Msg_CMD::generate(const shared_ptr uMsg)
const auto dBytes = vector(startPtr, endPtr);
+#ifdef DEBUG_STREAMS
auto hAS = getHostAPDUStream().get();
fprintf(hAS, "\n"
@@ -170,6 +171,7 @@ shared_ptr U2F_Msg_CMD::generate(const shared_ptr uMsg)
"\t\t\t\n"
"\t\t
\n"
"\t\t
", cmd.le);
+#endif
try
{
diff --git a/main.cpp b/main.cpp
index a3745af..4a8ec35 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,9 +1,41 @@
#include "U2FDevice.hpp"
#include "Architecture.hpp"
+#include
+#include
+
+#ifdef DEBUG_MSGS
+//Courtesy StackOverflow answer https://stackoverflow.com/a/3356421
+void terminateHandler()
+{
+ void *trace_elems[20];
+ int trace_elem_count(backtrace(trace_elems, 20));
+ char **stack_syms(backtrace_symbols(trace_elems, trace_elem_count));
+ for (int i = 0; i < trace_elem_count; ++i)
+ {
+ std::cout << stack_syms[i] << "\n";
+ }
+ free(stack_syms);
+
+ exit(1);
+}
+#endif
int main(int argc, char **argv) {
- initialiseLights(argv[0]);
+#ifdef DEBUG_MSGS
+ std::set_terminate(terminate_handler);
+#endif
int retCode = handleTransactions(argv[0], argc == 2 ? argv[1] : STORAGE_PREFIX);
- deinitialiseLights(argv[0]);
+
+ try
+ {
+ initialiseLights(argv[0]);
+ deinitialiseLights(argv[0]);
+ }
+ catch (std::exception &e)
+ {
+ std::cerr << "Exception in code: " << e.what() << std::endl;
+ throw;
+ }
+
return retCode;
}