diff --git a/Conf.cpp b/Conf.cpp index 9038b28..f47a8a6 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -169,6 +169,7 @@ m_nxdnTXHang(5U), m_nxdnModeHang(10U), m_m17Enabled(false), m_m17SelfOnly(false), +m_m17AllowEncryption(false), m_m17TXHang(5U), m_m17ModeHang(10U), m_pocsagEnabled(false), @@ -706,6 +707,8 @@ bool CConf::read() m_m17Enabled = ::atoi(value) == 1; else if (::strcmp(key, "SelfOnly") == 0) m_m17SelfOnly = ::atoi(value) == 1; + else if (::strcmp(key, "AllowEncryption") == 0) + m_m17AllowEncryption = ::atoi(value) == 1; else if (::strcmp(key, "TXHang") == 0) m_m17TXHang = (unsigned int)::atoi(value); else if (::strcmp(key, "ModeHang") == 0) @@ -1516,6 +1519,11 @@ bool CConf::getM17SelfOnly() const return m_m17SelfOnly; } +bool CConf::getM17AllowEncryption() const +{ + return m_m17AllowEncryption; +} + unsigned int CConf::getM17TXHang() const { return m_m17TXHang; diff --git a/Conf.h b/Conf.h index 9470746..435c049 100644 --- a/Conf.h +++ b/Conf.h @@ -164,6 +164,7 @@ public: // The M17 section bool getM17Enabled() const; bool getM17SelfOnly() const; + bool getM17AllowEncryption() const; unsigned int getM17TXHang() const; unsigned int getM17ModeHang() const; @@ -440,6 +441,7 @@ private: bool m_m17Enabled; bool m_m17SelfOnly; + bool m_m17AllowEncryption; unsigned int m_m17TXHang; unsigned int m_m17ModeHang; diff --git a/M17Control.cpp b/M17Control.cpp index bca351f..060f4ef 100644 --- a/M17Control.cpp +++ b/M17Control.cpp @@ -57,9 +57,10 @@ const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04 #define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) #define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) -CM17Control::CM17Control(const std::string& callsign, bool selfOnly, CM17Network* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper) : +CM17Control::CM17Control(const std::string& callsign, bool selfOnly, bool allowEncryption, CM17Network* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper) : m_callsign(callsign), m_selfOnly(selfOnly), +m_allowEncryption(allowEncryption), m_network(network), m_display(display), m_duplex(duplex), @@ -189,6 +190,15 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len) } } + if (!m_allowEncryption) { + bool ret = m_rfLICH.isNONCENull(); + if (!ret) { + LogMessage("M17, invalid access attempt from %s to %s", source.c_str(), dest.c_str()); + m_rfState = RS_RF_REJECTED; + return false; + } + } + unsigned char dataType = m_rfLICH.getDataType(); switch (dataType) { case 1U: @@ -531,9 +541,15 @@ void CM17Control::writeNetwork() m_networkWatchdog.start(); - if (m_netState == RS_NET_IDLE) { - m_netLICH.setNetwork(netData); + m_netLICH.setNetwork(netData); + if (!m_allowEncryption) { + bool ret = m_rfLICH.isNONCENull(); + if (!ret) + return; + } + + if (m_netState == RS_NET_IDLE) { std::string source = m_netLICH.getSource(); std::string dest = m_netLICH.getDest(); diff --git a/M17Control.h b/M17Control.h index 71c402d..bff2d19 100644 --- a/M17Control.h +++ b/M17Control.h @@ -34,7 +34,7 @@ class CM17Control { public: - CM17Control(const std::string& callsign, bool selfOnly, CM17Network* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper); + CM17Control(const std::string& callsign, bool selfOnly, bool allowEncryption, CM17Network* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper); ~CM17Control(); bool writeModem(unsigned char* data, unsigned int len); @@ -50,6 +50,7 @@ public: private: std::string m_callsign; bool m_selfOnly; + bool m_allowEncryption; CM17Network* m_network; CDisplay* m_display; bool m_duplex; diff --git a/M17Defines.h b/M17Defines.h index ed530a4..53b5f63 100644 --- a/M17Defines.h +++ b/M17Defines.h @@ -40,6 +40,10 @@ const unsigned int M17_LICH_FRAGMENT_FEC_LENGTH_BYTES = M17_LICH_FRAGMENT_FEC_LE const unsigned int M17_PAYLOAD_LENGTH_BITS = 128U; const unsigned int M17_PAYLOAD_LENGTH_BYTES = M17_PAYLOAD_LENGTH_BITS / 8U; +const unsigned char M17_NULL_NONCE[] = {0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U}; +const unsigned int M17_NONCE_LENGTH_BITS = 112U; +const unsigned int M17_NONCE_LENGTH_BYTES = M17_NONCE_LENGTH_BITS / 8U; + const unsigned int M17_FN_LENGTH_BITS = 16U; const unsigned int M17_FN_LENGTH_BYTES = M17_FN_LENGTH_BITS / 8U; diff --git a/M17LICH.cpp b/M17LICH.cpp index ed2b870..0c0469a 100644 --- a/M17LICH.cpp +++ b/M17LICH.cpp @@ -89,6 +89,11 @@ void CM17LICH::setDataType(unsigned char type) m_lich[13U] |= (type << 1) & 0x06U; } +bool CM17LICH::isNONCENull() const +{ + return ::memcmp(m_lich + 14U, M17_NULL_NONCE, M17_NONCE_LENGTH_BYTES) == 0; +} + void CM17LICH::reset() { ::memset(m_lich, 0x00U, 30U); diff --git a/M17LICH.h b/M17LICH.h index 14e3a2d..8842e22 100644 --- a/M17LICH.h +++ b/M17LICH.h @@ -38,6 +38,8 @@ public: unsigned char getDataType() const; void setDataType(unsigned char type); + bool isNONCENull() const; + void reset(); bool isValid() const; diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index b665905..2015516 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -610,16 +610,18 @@ int CMMDVMHost::run() } if (m_m17Enabled) { - bool selfOnly = m_conf.getM17SelfOnly(); - unsigned int txHang = m_conf.getM17TXHang(); - m_m17RFModeHang = m_conf.getM17ModeHang(); + bool selfOnly = m_conf.getM17SelfOnly(); + bool allowEncryption = m_conf.getM17AllowEncryption(); + unsigned int txHang = m_conf.getM17TXHang(); + m_m17RFModeHang = m_conf.getM17ModeHang(); LogInfo("M17 RF Parameters"); LogInfo(" Self Only: %s", selfOnly ? "yes" : "no"); + LogInfo(" Allow Encryption: %s", allowEncryption ? "yes" : "no"); LogInfo(" TX Hang: %us", txHang); LogInfo(" Mode Hang: %us", m_m17RFModeHang); - m_m17 = new CM17Control(m_callsign, selfOnly, m_m17Network, m_display, m_timeout, m_duplex, rssi); + m_m17 = new CM17Control(m_callsign, selfOnly, allowEncryption, m_m17Network, m_display, m_timeout, m_duplex, rssi); } CTimer pocsagTimer(1000U, 30U);