diff --git a/main/MessageHelper.cpp b/main/MessageHelper.cpp index 03c6916..9232608 100644 --- a/main/MessageHelper.cpp +++ b/main/MessageHelper.cpp @@ -1,7 +1,7 @@ #include "MessageHelper.h" #include "terminal_utils.h" +#include "aes128.h" -#include #include #include @@ -33,7 +33,19 @@ #define DBG_HEADER "(" << __func__ << ":" << __LINE__ << ")" -static bool DEBUG_MESSAGE_HELPER=true; +#define DBG_EMERGENCY (0) // System is unusable +#define DBG_ALERT (1) // Action must be taken immediately +#define DBG_CRITICAL (2) // Critical conditions +#define DBG_ERROR (3) // Error conditions +#define DBG_WARNING (4) // Warning conditions +#define DBG_NOTICE (5) // Normal but significant conditions + // Conditions that are not error conditions, but that may require special handling +#define DBG_INFORMATION (6) // Informational messages + // Confirmation that the program is working as expected +#define DBG_DEBUG (7) // Debug-level messages + // Messages that contain information normally of use only when debugging a program + +static int DBG_LEVEL = DBG_INFORMATION; struct MessageHeader { uint8_t packetType; @@ -44,13 +56,18 @@ struct MessageHeader { MessageHelper::MessageHelper(QString const &posID, QString const &apak) : m_posID(posID.toUtf8().constData()) - , m_apak(apak) , m_posIDLength(m_posID.size()) , m_messageHeaderPrefix(1 + PACKET_ID_SIZE + 1, 0x00) , m_rawPacket(IUC_ASYNCHPOS_MAX_TX_PACKET_SIZE, 0x00) { m_messageHeaderPrefix[9] = (uint8_t)m_posID.size(); - if (DEBUG_MESSAGE_HELPER) { + for (int p = 0; p < apak.size(); p+=2) { + uint8_t n = strtoul(apak.mid(p, 2).toStdString().c_str(), nullptr, 16); + m_apak.push_back(n); + } + + if (DBG_LEVEL >= DBG_DEBUG) { + qCritical() << DBG_HEADER << apak << m_apak.toHex(':'); qCritical() << DBG_HEADER << m_posID.toHex(':'); qCritical() << DBG_HEADER << m_messageHeaderPrefix.toHex(':'); } @@ -58,13 +75,18 @@ MessageHelper::MessageHelper(QString const &posID, QString const &apak) MessageHelper::MessageHelper(QByteArray const &posID, QString const &apak) : m_posID(posID) - , m_apak(apak) , m_posIDLength(m_posID.size()) , m_messageHeaderPrefix(1 + PACKET_ID_SIZE + 1, 0x00) , m_rawPacket(IUC_ASYNCHPOS_MAX_TX_PACKET_SIZE, 0x00) { m_messageHeaderPrefix[9] = (uint8_t)m_posID.size(); - if (DEBUG_MESSAGE_HELPER) { + for (int p = 0; p < apak.size(); p+=2) { + uint8_t n = strtoul(apak.mid(p, 2).toStdString().c_str(), nullptr, 16); + m_apak.push_back(n); + } + + if (DBG_LEVEL >= DBG_DEBUG) { + qCritical() << DBG_HEADER << apak << m_apak.toHex(':'); qCritical() << DBG_HEADER << m_posID.toHex(':'); qCritical() << DBG_HEADER << m_messageHeaderPrefix.toHex(':'); } @@ -111,7 +133,7 @@ bool MessageHelper::createMessageHeaderPrefix(PacketType packetType, QByteArray for (int i = 1; i <= 8; ++i) { m_messageHeaderPrefix[i] = (uint8_t)encryptedPacketID[i-1]; } - if (DEBUG_MESSAGE_HELPER) { + if (DBG_LEVEL >= DBG_DEBUG) { qCritical() << DBG_HEADER << m_messageHeaderPrefix.toHex(':'); } return true; @@ -134,6 +156,7 @@ void MessageHelper::createLoginMessage() { QDateTime current = QDateTime::currentDateTime(); // TODO: wieder entfernen current.setTime(QTime(12, 0, 0)); + current.setDate(QDate(2024, 6, 12)); QByteArray time(current.toString(Qt::ISODate).toStdString().c_str()); time[10] = ' '; @@ -147,43 +170,11 @@ void MessageHelper::createLoginMessage() { m_loginMessage.push_back((char)0x00); - if (DEBUG_MESSAGE_HELPER) { - qCritical() << DBG_HEADER << m_loginMessage.toHex(':'); + if (DBG_LEVEL >= DBG_INFORMATION) { + qCritical() << DBG_HEADER << "loginMessage" << m_loginMessage.toHex(':'); } } -uint32_t iuc_asynchpos_sub_updateCRC_2(uint32_t crc, char* pData, size_t len) { - // berechne CRC32 nach Polynom x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 - - QByteArray a(pData, len); - qCritical() << "updateCRC" << a.toHex(' '); - qCritical() << "updateCRC" << len << hex << crc; - - int i = 0; - int j = 0; - unsigned char ucCarry = 0x00; - - crc = ~crc; - while (len > 0) { - crc ^= (uint32_t) pData[i]; - ++i; - - for (j = 0; j < 8; ++j) { - ucCarry = crc & 1; - crc >>= 1; - - if (ucCarry) { - crc ^= IUC_ASYNCHPOS_POLYNOME; - } - } - --len; - } - - return ~crc; - -} - - QByteArrayList const &MessageHelper::createLoginMessageChunksToSend(char etx) { QByteArray encryptedPacketID(QByteArray("\x01\x02\x03\x04\x05\x06\x07\x08")); @@ -191,85 +182,83 @@ QByteArrayList const &MessageHelper::createLoginMessageChunksToSend(char etx) { createLoginMessage(); createRawPacket(PacketType::POS_ECR, encryptedPacketID, m_loginMessage); - if (DEBUG_MESSAGE_HELPER) { + if (DBG_LEVEL >= DBG_DEBUG) { qCritical() << DBG_HEADER << m_rawPacket.toHex(':'); } QByteArray const &ba = m_rawPacket.mid(11); - if (DEBUG_MESSAGE_HELPER) { + + if (DBG_LEVEL >= DBG_DEBUG) { qCritical() << DBG_HEADER << ba.toHex(':'); } - //uint32_t crc = TU::crc32(m_rawPacket.mid(11)); - uint32_t crc = 0; + // calculate crc32 on message starting from (including) POSID length + uint32_t crc = TU::crc32(ba); - unsigned char posID = 16; - unsigned char uctemp = posID; - - fprintf(stderr, "POSID=%0X\n", uctemp); - - uint32_t chksum = IUC_ASYNCHPOS_POLYNOME_INITIAL; - chksum = iuc_asynchpos_sub_updateCRC_2(chksum,(char *)&uctemp,1); - fprintf(stderr, "%d CRC32=%04X\n", __LINE__, chksum); - chksum = iuc_asynchpos_sub_updateCRC_2(chksum, (char *)m_posID.data() ,posID); - fprintf(stderr, "%d CRC32=%04X\n", __LINE__, chksum); - //for (uitmp = 0; uitmp < length_; ++uitmp) { - chksum = iuc_asynchpos_sub_updateCRC_2(chksum, (char *)m_loginMessage.data(), m_loginMessage.size()); - fprintf(stderr, "%d CRC32=%04X\n", __LINE__, chksum); - //} - - crc = iuc_asynchpos_sub_updateCRC_2(crc, (char *)ba.toStdString().c_str(), ba.size()); - - if (DEBUG_MESSAGE_HELPER) { - qCritical() << DBG_HEADER << "crc" << hex << crc; + if (DBG_LEVEL >= DBG_DEBUG) { + qCritical() << DBG_HEADER << "crc32" << hex << crc; } - crc = 0; - crc = TU::crc32(ba); + unsigned char cipherText[256]; + memset(cipherText, 0, sizeof(cipherText)); - if (DEBUG_MESSAGE_HELPER) { - qCritical() << DBG_HEADER << "crc" << hex << crc; + // XOR crc32-value (4 bytes) with APAK starting from left + // (rest of APAK untouched) + QByteArray clearText(m_apak); + clearText[0] = clearText[0] ^ ((uint8_t)(crc >> 24)); + clearText[1] = clearText[1] ^ ((uint8_t)(crc >> 16)); + clearText[2] = clearText[2] ^ ((uint8_t)(crc >> 8)); + clearText[3] = clearText[3] ^ ((uint8_t)(crc >> 0)); + + if (DBG_LEVEL >= DBG_DEBUG) { + qCritical() << DBG_HEADER << "clearText" << clearText.toHex(); } - // aes aufrufen - //unsigned char key[] = "8AC304380E0E476BA2558B75DB9E2516"; - //unsigned char output[256]; - //memset(output, 0, sizeof(output)); + // encrypt XOR result with APAK using AES129, ECB mode + aes_encrypt((uint8_t *)clearText.data(), + (uint8_t *)cipherText, + (uint8_t *)m_apak.toStdString().c_str()); - //aes_encrypt((unsigned char*)ba.data(), output, key); + // 8 left bytes of encryption result is signature (Packet ID) + encryptedPacketID = QByteArray((const char *)cipherText, 8); + if (DBG_LEVEL >= DBG_INFORMATION) { + qCritical() << DBG_HEADER << "cipherText (new PacketID)" << encryptedPacketID.toHex(':'); + } + + // insert PacketID in packet if (insertEncryptedPacketID(encryptedPacketID)) { - if (DEBUG_MESSAGE_HELPER) { - qCritical() << DBG_HEADER << m_rawPacket.toHex(':'); - } + // build chunks to be sent over serial line + int const chunks = m_rawPacket.size() / IUC_ASYNCHPOS_MIN_PACKET_SIZE; - if (DEBUG_MESSAGE_HELPER) { + if (DBG_LEVEL >= DBG_DEBUG) { qCritical() << DBG_HEADER << "nr of chunks" << chunks; } - for (int i = 0; i < chunks; ++i) { + int i = 0; + for (; i < chunks; ++i) { QByteArray messageChunk = m_rawPacket.mid(IUC_ASYNCHPOS_MIN_PACKET_SIZE*i, IUC_ASYNCHPOS_MIN_PACKET_SIZE); - if (DEBUG_MESSAGE_HELPER) { - qCritical() << DBG_HEADER << i << messageChunk.toHex(':'); + if (DBG_LEVEL >= DBG_DEBUG) { + qCritical() << DBG_HEADER << i << "unmasked" << messageChunk.toHex(':'); } messageChunk = MessageHelper::mask(messageChunk); - if (DEBUG_MESSAGE_HELPER) { - qCritical() << DBG_HEADER << i << messageChunk.toHex(':'); + if (DBG_LEVEL >= DBG_DEBUG) { + qCritical() << DBG_HEADER << i << " masked" << messageChunk.toHex(':'); } - char const lrc = TU::lrc(messageChunk); - - messageChunk.push_front(STX); messageChunk.push_back(etx == ACK1 ? ETX2 : ETX1); // etx must be ACK1 or ACK2 - messageChunk.push_back(lrc); - if (DEBUG_MESSAGE_HELPER) { - qCritical() << DBG_HEADER << i << messageChunk.toHex(':'); + char const lrc = TU::lrc(messageChunk); + messageChunk.push_back(lrc); + messageChunk.push_front(STX); + + if (DBG_LEVEL >= DBG_INFORMATION) { + qCritical() << DBG_HEADER << "chunk to send" << messageChunk.toHex(':'); } m_messageChunkList += messageChunk; @@ -278,15 +267,28 @@ QByteArrayList const &MessageHelper::createLoginMessageChunksToSend(char etx) { int const rest = m_rawPacket.size() % IUC_ASYNCHPOS_MIN_PACKET_SIZE; if (rest) { QByteArray messageChunk = m_rawPacket.mid(IUC_ASYNCHPOS_MIN_PACKET_SIZE*chunks, rest); - char const lrc = TU::lrc(messageChunk); - messageChunk.push_front(STX); - - messageChunk.push_back(etx == ACK1 ? ETX2 : ETX1); // etx must be ACK1 or ACK2 - messageChunk.push_back(lrc); + if (DBG_LEVEL >= DBG_DEBUG) { + qCritical() << DBG_HEADER << i << "unmasked" << messageChunk.toHex(':'); + } messageChunk = mask(messageChunk); + if (DBG_LEVEL >= DBG_DEBUG) { + qCritical() << DBG_HEADER << i << " masked" << messageChunk.toHex(':'); + } + + messageChunk.push_back(etx == ACK1 ? ETX2 : ETX1); // etx must be ACK1 or ACK2 + + char const lrc = TU::lrc(messageChunk); + messageChunk.push_back(lrc); + messageChunk.push_front(STX); + + + if (DBG_LEVEL >= DBG_INFORMATION) { + qCritical() << DBG_HEADER << "chunk to send" << messageChunk.toHex(':'); + } + m_messageChunkList += messageChunk; } } @@ -296,12 +298,17 @@ QByteArrayList const &MessageHelper::createLoginMessageChunksToSend(char etx) { bool MessageHelper::insertEncryptedPacketID(QByteArray const &encryptedPacketID) { if (encryptedPacketID.size() == PACKET_ID_SIZE) { + // m_rawPacket has already full length for (int i = 0; i < PACKET_ID_SIZE; ++i) { m_messageHeaderPrefix[i+1] = encryptedPacketID[i]; + m_rawPacket[i+3] = encryptedPacketID[i]; } - if (DEBUG_MESSAGE_HELPER) { + + if (DBG_LEVEL >= DBG_DEBUG) { qCritical() << DBG_HEADER << m_messageHeaderPrefix.toHex(':'); + qCritical() << DBG_HEADER << m_rawPacket.toHex(':'); } + return true; } return false; @@ -329,10 +336,6 @@ QByteArray const &MessageHelper::mask(QByteArray &messageChunk) { } } - if (DEBUG_MESSAGE_HELPER) { - qCritical() << DBG_HEADER << ba.toHex(':'); - } - messageChunk = ba; return messageChunk; } diff --git a/main/MessageHelper.h b/main/MessageHelper.h index c620caa..dab6fef 100644 --- a/main/MessageHelper.h +++ b/main/MessageHelper.h @@ -6,7 +6,6 @@ #include #include - class MessageHelper { public: enum PacketType : std::uint8_t { @@ -36,7 +35,7 @@ public: // private: QByteArray m_posID; - QString m_apak; + QByteArray m_apak; uint8_t m_posIDLength; QByteArray m_messageHeaderPrefix; QByteArray m_rawPacket; // without leading STX and trailing [ETX(1/2), LRC] diff --git a/main/main.cpp b/main/main.cpp index 60e7119..2051b02 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -264,7 +264,10 @@ void biox_CopyBlock(unsigned char *src, UINT srcPos, UCHAR *dest, UINT destPos, void iuc_asynchpos_sub_synchTime() { QDateTime current = QDateTime::currentDateTime(); + current.setTime(QTime(12, 0, 0)); + current.setDate(QDate(2024, 6, 12)); + QString const &s = current.toString(Qt::ISODate); QByteArray time(s.toStdString().c_str()); @@ -290,7 +293,7 @@ uint32_t iuc_asynchpos_sub_updateCRC(uint32_t crc, unsigned char* pData, size_t crc = ~crc; while (len > 0) { - crc ^= (uint32_t) pData[i]; + crc ^= (uint32_t)pData[i]; ++i; for (j = 0; j < 8; ++j) { @@ -704,7 +707,7 @@ int main() { qCritical() << "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" << endl; - //return 0; + // return 0; // unsigned static char terminalID[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; // unsigned static char terminalAPAK[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; diff --git a/main/terminal_utils.cpp b/main/terminal_utils.cpp index d2df754..8b1d71f 100644 --- a/main/terminal_utils.cpp +++ b/main/terminal_utils.cpp @@ -43,28 +43,9 @@ namespace TU { return htobe16(((j / 10) + 0x30) << 8) | ((j % 10) + 0x30); } - //https://lxp32.github.io/docs/a-simple-example-crc32-calculation/ - uint32_t crc32(const char *s, size_t n) { - uint32_t crc=0xFFFFFFFF; + uint32_t crc32(uint32_t crc, unsigned char* pData, size_t len) { - for(size_t i=0;i>=1; - if(b) crc=crc^0xEDB88320; - ch>>=1; - } - } - - return ~crc; - } - - - uint32_t CRC32(uint32_t crc, unsigned char* pData, size_t len) { - - QByteArray a((char *)pData, len); - qCritical() << "updateCRC" << a.toHex(' '); + qCritical() << "updateCRC" << QByteArray((char *)pData, len).toHex(); int i = 0; int j = 0; @@ -72,7 +53,8 @@ namespace TU { crc = ~crc; while (len > 0) { - crc ^= (uint32_t) pData[i]; + uint32_t const c = pData[i]; + crc ^= c; ++i; for (j = 0; j < 8; ++j) { @@ -91,18 +73,8 @@ namespace TU { } uint32_t crc32(QByteArray const &ba) { - uint32_t crc = 0x00000000; - - unsigned char posIDLength = ba[0]; - crc = CRC32(crc, &posIDLength, 1); - - unsigned char *posID = (unsigned char *)ba.mid(1, 16).data(); - crc = CRC32(crc, posID, 16); - - unsigned char *rest = (unsigned char *)ba.mid(16).data(); - crc = CRC32(crc, rest, ba.size()-16); - - return crc; + uint32_t crc = 0; + return crc32(crc, (uint8_t *)ba.data(), ba.size()); } char lrc(QByteArray const &ba) { diff --git a/main/terminal_utils.h b/main/terminal_utils.h index 48d85eb..7cd1db6 100644 --- a/main/terminal_utils.h +++ b/main/terminal_utils.h @@ -20,9 +20,10 @@ namespace TU { QByteArray int2Hex(int i); uint16_t getNextTransactionId(); - uint32_t crc32(const char *s, size_t n); + //uint32_t crc32(const char *s, size_t n); + //uint32_t crc32(QByteArray const &ba); uint32_t crc32(QByteArray const &ba); - uint32_t crc32(uint32_t crc, QByteArray const &ba); + uint32_t crc32(uint32_t crc, unsigned char* pData, size_t len); char lrc(QByteArray const &ba); bool isBigEndian();