From ded260216a4e4034f0f733953c3067b658f547f6 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Mon, 10 Mar 2025 14:41:13 -0400 Subject: [PATCH] implement the beginnings of KMM frame handling (for future use); --- src/common/CMakeLists.txt | 2 + src/common/dmr/DMRDefines.h | 2 + src/common/nxdn/NXDNDefines.h | 2 + src/common/p25/P25Defines.h | 54 +++++++ src/common/p25/kmm/KMMFrame.cpp | 107 +++++++++++++ src/common/p25/kmm/KMMFrame.h | 140 +++++++++++++++++ src/common/p25/kmm/KMMModifyKey.cpp | 171 +++++++++++++++++++++ src/common/p25/kmm/KMMModifyKey.h | 119 +++++++++++++++ src/common/p25/kmm/KeysetItem.h | 228 ++++++++++++++++++++++++++++ src/host/Host.cpp | 6 +- 10 files changed, 828 insertions(+), 3 deletions(-) create mode 100644 src/common/p25/kmm/KMMFrame.cpp create mode 100644 src/common/p25/kmm/KMMFrame.h create mode 100644 src/common/p25/kmm/KMMModifyKey.cpp create mode 100644 src/common/p25/kmm/KMMModifyKey.h create mode 100644 src/common/p25/kmm/KeysetItem.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 04cd4e5d..6f58ac17 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -28,6 +28,7 @@ file(GLOB common_SRC "src/common/p25/lc/tsbk/*.cpp" "src/common/p25/lc/tsbk/mbt/*.cpp" "src/common/p25/sndcp/*.cpp" + "src/common/p25/kmm/*.cpp" "src/common/p25/lookups/*.cpp" # NXDN module @@ -73,6 +74,7 @@ file(GLOB common_INCLUDE "src/common/p25/lc/tsbk/*.h" "src/common/p25/lc/tsbk/mbt/*.h" "src/common/p25/sndcp/*.h" + "src/common/p25/kmm/*.h" "src/common/p25/lookups/*.h" # NXDN module diff --git a/src/common/dmr/DMRDefines.h b/src/common/dmr/DMRDefines.h index 73a50dcd..86bd049c 100644 --- a/src/common/dmr/DMRDefines.h +++ b/src/common/dmr/DMRDefines.h @@ -22,7 +22,9 @@ #include "common/Defines.h" // Shorthand macro to dmr::defines -- keeps source code that doesn't use "using" concise +#if !defined(DMRDEF) #define DMRDEF dmr::defines +#endif // DMRDEF namespace dmr { namespace defines diff --git a/src/common/nxdn/NXDNDefines.h b/src/common/nxdn/NXDNDefines.h index a40c6af8..077c28e5 100644 --- a/src/common/nxdn/NXDNDefines.h +++ b/src/common/nxdn/NXDNDefines.h @@ -22,7 +22,9 @@ #include "common/Defines.h" // Shorthand macro to nxdn::defines -- keeps source code that doesn't use "using" concise +#if !defined(NXDDEF) #define NXDDEF nxdn::defines +#endif // NXDDEF namespace nxdn { namespace defines diff --git a/src/common/p25/P25Defines.h b/src/common/p25/P25Defines.h index 31bd2ccc..6e7b2505 100644 --- a/src/common/p25/P25Defines.h +++ b/src/common/p25/P25Defines.h @@ -22,7 +22,9 @@ #include "common/Defines.h" // Shorthand macro to p25::defines -- keeps source code that doesn't use "using" concise +#if !defined(P25DEF) #define P25DEF p25::defines +#endif // P25DEF namespace p25 { namespace defines @@ -411,6 +413,58 @@ namespace p25 }; } + /** @brief KMM Message Type */ + namespace KMM_MessageType { + enum : uint8_t { + NULL_CMD = 0x00U, //! Null + + CHANGE_RSI_CMD = 0x03U, //! Change RSI Command + CHANGE_RSI_RSP = 0x04U, //! Change RSI Response + CHANGEOVER_CMD = 0x05U, //! Changeover Command + CHANGEOVER_RSP = 0x06U, //! Changeover Response + + HELLO = 0x0CU, //! Hello + + INVENTORY_CMD = 0x0DU, //! Inventory Command + INVENTORY_RSP = 0x0EU, //! Inventory Response + + MODIFY_KEY_CMD = 0x13U, //! Modify Key Command + + NAK = 0x16U, //! Negative Ack + + ZEROIZE_CMD = 0x21U, //! Zeroize Command + ZEROIZE_RSP = 0x22U, //! Zeroize Response + }; + } + + /** @brief KMM Response Kind */ + namespace KMM_ResponseKind { + enum : uint8_t { + NONE = 0x00U, //! Response Kind 1 (None) + DELAYED = 0x01U, //! Response Kind 2 (Delayed) + IMMEDIATE = 0x02U, //! Response Kind 3 (Immediate) + }; + } + + /** @brief KMM Message Authentication */ + namespace KMM_MAC { + enum : uint8_t { + NO_MAC = 0x00U, //! No Message Authentication + ENH_MAC = 0x02U, //! Enhanced Message Authentication + DES_MAC = 0x03U, //! DES Message Authentication + }; + } + + /** @brief KMM Decryption Instruction - None */ + const uint8_t KMM_DECRYPT_INSTRUCT_NONE = 0x00U; + /** @brief KMM Decryption Instruction - Message Indicator */ + const uint8_t KMM_DECRYPT_INSTRUCT_MI = 0x40U; + + /** @brief KMM Key Format TEK */ + const uint8_t KEY_FORMAT_TEK = 0x80U; + /** @brief KMM Key Format Delete Key */ + const uint8_t KEY_FORMAT_DELETE = 0x20U; + /** @brief SNDCP version 1 */ const uint8_t SNDCP_VERSION_1 = 0x01U; /** @brief 296 byte MTU */ diff --git a/src/common/p25/kmm/KMMFrame.cpp b/src/common/p25/kmm/KMMFrame.cpp new file mode 100644 index 00000000..10cd7f29 --- /dev/null +++ b/src/common/p25/kmm/KMMFrame.cpp @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Digital Voice Modem - Common Library + * GPLv2 Open Source. Use is subject to license terms. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright (C) 2025 Bryan Biedenkapp, N2PLL + * + */ +#include "Defines.h" +#include "p25/P25Defines.h" +#include "p25/kmm/KMMFrame.h" +#include "Log.h" + +using namespace p25; +using namespace p25::defines; +using namespace p25::kmm; + +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/* Initializes a copy instance of the KMMFrame class. */ + +KMMFrame::KMMFrame(const KMMFrame& data) : KMMFrame() +{ + copy(data); +} + +/* Initializes a new instance of the KMMFrame class. */ + +KMMFrame::KMMFrame() : + m_messageId(KMM_MessageType::NULL_CMD), + m_messageLength(7U), + m_respKind(KMM_ResponseKind::NONE), + m_complete(true), + m_mfMessageNumber(0U), + m_mfMac(KMM_MAC::NO_MAC) +{ + /* stub */ +} + +/* Finalizes a instance of the KMMFrame class. */ + +KMMFrame::~KMMFrame() = default; + +// --------------------------------------------------------------------------- +// Protected Class Members +// --------------------------------------------------------------------------- + +/* Internal helper to decode a SNDCP header. */ + +bool KMMFrame::decodeHeader(const uint8_t* data, bool outbound) +{ + assert(data != nullptr); + + m_messageId = data[0U]; // Message ID + m_messageLength = __GET_UINT16B(data, 1U); // Message Length + + m_respKind = (data[2U] >> 6U) & 0x03U; // Response Kind + m_mfMessageNumber = (data[2U] >> 4U) & 0x03U; // Message Number + m_mfMac = (data[2U] >> 2U) & 0x03U; // MAC + + bool done = (data[2U] & 0x01U) == 0x01U; // Done Flag + if (!done) + m_complete = true; + else + m_complete = false; + + m_dstLlId = __GET_UINT16(data, 4U); // Destination RSI + m_srcLlId = __GET_UINT16(data, 7U); // Source RSI + + return true; +} + +/* Internal helper to encode a SNDCP header. */ + +void KMMFrame::encodeHeader(uint8_t* data, bool outbound) +{ + assert(data != nullptr); + + data[0U] = m_messageId; // Message ID + __SET_UINT16B(m_messageLength, data, 2U); // Message Length + + data[2U] = ((m_respKind & 0x03U) << 6U) + // Response Kind + ((m_mfMessageNumber & 0x03U) << 4U) + // Message Number + ((m_mfMac & 0x03U) << 2U) + // MAC + ((!m_complete) ? 0x01U : 0x00U); // Done Flag + + __SET_UINT16(m_dstLlId, data, 4U); // Destination RSI + __SET_UINT16(m_srcLlId, data, 7U); // Source RSI +} + +/* Internal helper to copy the the class. */ + +void KMMFrame::copy(const KMMFrame& data) +{ + m_messageId = data.m_messageId; + m_messageLength = data.m_messageLength; + m_respKind = data.m_respKind; + m_complete = data.m_complete; + + m_mfMessageNumber = data.m_mfMessageNumber; + m_mfMac = data.m_mfMac; +} diff --git a/src/common/p25/kmm/KMMFrame.h b/src/common/p25/kmm/KMMFrame.h new file mode 100644 index 00000000..ef9ab0aa --- /dev/null +++ b/src/common/p25/kmm/KMMFrame.h @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Digital Voice Modem - Common Library + * GPLv2 Open Source. Use is subject to license terms. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright (C) 2025 Bryan Biedenkapp, N2PLL + * + */ +/** + * @defgroup p25_kmm Key Management Message + * @brief Implementation for the data handling of the TIA-102.AACA Project 25 standard. + * @ingroup p25 + * + * @file KMMFrame.h + * @ingroup p25_kmm + * @file KMMFrame.cpp + * @ingroup p25_kmm + */ +#if !defined(__P25_KMM__KMM_FRAME_H__) +#define __P25_KMM__KMM_FRAME_H__ + +#include "common/Defines.h" +#include "common/Utils.h" + +#include + +namespace p25 +{ + namespace kmm + { + // --------------------------------------------------------------------------- + // Constants + // --------------------------------------------------------------------------- + + /** + * @addtogroup p25_kmm + * @{ + */ + + const uint32_t KMM_FRAME_LENGTH = 9U; + + /** @} */ + + // --------------------------------------------------------------------------- + // Class Declaration + // --------------------------------------------------------------------------- + + /** + * @brief Represents a KMM frame packet header. + * @ingroup p25_kmm + */ + class HOST_SW_API KMMFrame { + public: + /** + * @brief Initializes a copy instance of the KMMFrame class. + * @param data Instance of KMMFrame to copy/ + */ + KMMFrame(const KMMFrame& data); + /** + * @brief Initializes a new instance of the KMMFrame class. + */ + KMMFrame(); + /** + * @brief Finalizes a instance of the KMMFrame class. + */ + ~KMMFrame(); + + /** + * @brief Gets the byte length of this KMMFrame. + * @return uint32_t Length of KMMFrame. + */ + virtual uint32_t length() const { return KMM_FRAME_LENGTH; } + + /** + * @brief Decode a KMM frame. + * @param[in] data Buffer containing KMM frame data to decode. + * @returns bool True, if decoded, otherwise false. + */ + virtual bool decode(const uint8_t* data) = 0; + /** + * @brief Encode a KMM frame. + * @param[out] data Buffer to encode KMM frame data to. + */ + virtual void encode(uint8_t* data) = 0; + + public: + // Common Data + /** + * @brief + */ + __PROTECTED_PROPERTY(uint8_t, messageId, MessageId); + /** + * @brief + */ + __PROTECTED_PROPERTY(uint16_t, messageLength, MessageLength); + + /** + * @brief + */ + __PROTECTED_PROPERTY(uint8_t, respKind, ResponseKind); + + /** + * @brief Destination Logical link ID. + */ + __PROTECTED_PROPERTY(uint32_t, dstLlId, DstLLId); + /** + * @brief Source Logical link ID. + */ + __PROTECTED_PROPERTY(uint32_t, srcLlId, SrcLLId); + + /** + * @brief + */ + __PROTECTED_PROPERTY(bool, complete, Complete); + + protected: + uint8_t m_mfMessageNumber; + uint8_t m_mfMac; + + /** + * @brief Internal helper to decode a KMM header. + * @param data Buffer containing KMM packet data to decode. + * @param outbound Flag indicating whether the packet is inbound or outbound. + * @returns bool True, if decoded, otherwise false. + */ + bool decodeHeader(const uint8_t* data, bool outbound = false); + /** + * @brief Internal helper to encode a KMM header. + * @param data Buffer to encode KMM packet data to. + * @param outbound Flag indicating whether the packet is inbound or outbound. + */ + void encodeHeader(uint8_t* data, bool outbound = false); + + __PROTECTED_COPY(KMMFrame); + }; + } // namespace kmm +} // namespace p25 + +#endif // __P25_KMM__KMM_FRAME_H__ diff --git a/src/common/p25/kmm/KMMModifyKey.cpp b/src/common/p25/kmm/KMMModifyKey.cpp new file mode 100644 index 00000000..4c86e389 --- /dev/null +++ b/src/common/p25/kmm/KMMModifyKey.cpp @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Digital Voice Modem - Common Library + * GPLv2 Open Source. Use is subject to license terms. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright (C) 2025 Bryan Biedenkapp, N2PLL + * + */ +#include "Defines.h" +#include "p25/P25Defines.h" +#include "p25/kmm/KMMModifyKey.h" +#include "Log.h" + +using namespace p25; +using namespace p25::defines; +using namespace p25::kmm; + +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/* Initializes a new instance of the KMMModifyKey class. */ + +KMMModifyKey::KMMModifyKey() : KMMFrame(), + m_decryptInfoFmt(KMM_DECRYPT_INSTRUCT_NONE), + m_algId(ALGO_UNENCRYPT), + m_kId(0U), + m_keysetItem(), + m_miSet(false), + m_mi(nullptr) +{ + m_mi = new uint8_t[MI_LENGTH_BYTES]; + ::memset(m_mi, 0x00U, MI_LENGTH_BYTES); +} + +/* Finalizes a instance of the KMMModifyKey class. */ + +KMMModifyKey::~KMMModifyKey() +{ + if (m_mi != nullptr) { + delete[] m_mi; + m_mi = nullptr; + } +} + +/* Gets the byte length of this KMMFrame. */ + +uint32_t KMMModifyKey::length() const +{ + uint32_t len = KMM_MODIFY_KEY_LENGTH; + if (m_miSet) + len += MI_LENGTH_BYTES; + len += m_keysetItem.length(); + + return len; +} + +/* Decode a KMM modify key. */ + +bool KMMModifyKey::decode(const uint8_t* data) +{ + assert(data != nullptr); + + KMMFrame::decodeHeader(data, false); + + m_decryptInfoFmt = data[10U]; // Decryption Instruction Format + m_algId = data[11U]; // Algorithm ID + m_kId = data[12U]; // Key ID + + uint16_t offset = 0U; + if (m_decryptInfoFmt == KMM_DECRYPT_INSTRUCT_MI) { + ::memset(m_mi, 0x00U, MI_LENGTH_BYTES); + ::memcpy(m_mi, data + 13U, MI_LENGTH_BYTES); + offset += 9U; + } + + m_keysetItem.keysetId(data[13U + offset]); + m_keysetItem.algId(data[14U + offset]); + m_keysetItem.keyLength(data[15U + offset]); + + uint8_t keyCount = data[16U + offset]; + for (uint8_t i = 0U; i < keyCount; i++) { + KeyItem* key = new KeyItem(); + + UInt8Array __keyPayload = std::make_unique(m_keysetItem.keyLength()); + uint8_t* keyPayload = __keyPayload.get(); + + uint8_t keyFormat = data[17U + offset]; + uint8_t keyNameLen = keyFormat & 0x1FU; + + key->keyFormat(keyFormat & 0xE0U); + key->sln(data[18U + offset]); + key->kId(data[19U + offset]); + + ::memcpy(keyPayload, data + (20U + offset), m_keysetItem.keyLength()); + key->setKey(keyPayload, m_keysetItem.keyLength()); + + m_keysetItem.push_back(key); + + offset += 5U + keyNameLen + m_keysetItem.keyLength(); + } + + return true; +} + +/* Encode a KMM modify key. */ + +void KMMModifyKey::encode(uint8_t* data) +{ + assert(data != nullptr); + + KMMFrame::encodeHeader(data, true); + + if (!m_miSet && m_decryptInfoFmt == KMM_DECRYPT_INSTRUCT_MI) { + m_decryptInfoFmt = KMM_DECRYPT_INSTRUCT_NONE; + } + + data[10U] = m_decryptInfoFmt; // Decryption Instruction Format + data[11U] = m_algId; // Algorithm ID + data[12U] = m_kId; // Key ID + + uint16_t offset = 0U; + if (m_decryptInfoFmt == KMM_DECRYPT_INSTRUCT_MI) { + ::memcpy(data + 13U, m_mi, MI_LENGTH_BYTES); + offset += 9U; + } + + data[13U + offset] = m_keysetItem.keysetId(); + data[14U + offset] = m_keysetItem.algId(); + data[15U + offset] = m_keysetItem.keyLength(); + + uint8_t keyCount = m_keysetItem.keys().size(); + data[16U + offset] = keyCount; + for (auto key : m_keysetItem.keys()) { + uint8_t keyNameLen = key->keyFormat() & 0x1FU; + data[17U + offset] = key->keyFormat(); + data[18U + offset] = key->sln(); + data[19U + offset] = key->kId(); + + UInt8Array __keyPayload = std::make_unique(m_keysetItem.keyLength()); + uint8_t* keyPayload = __keyPayload.get(); + key->getKey(keyPayload); + + ::memcpy(data + (20U + offset), keyPayload, m_keysetItem.keyLength()); + + offset += 5U + keyNameLen + m_keysetItem.keyLength(); + } +} + +// --------------------------------------------------------------------------- +// Protected Class Members +// --------------------------------------------------------------------------- + +/* Internal helper to copy the the class. */ + +void KMMModifyKey::copy(const KMMModifyKey& data) +{ + m_decryptInfoFmt = data.m_decryptInfoFmt; + m_algId = data.m_algId; + m_kId = data.m_kId; + + if (data.m_mi != nullptr) { + ::memset(m_mi, 0x00U, MI_LENGTH_BYTES); + ::memcpy(m_mi, data.m_mi, MI_LENGTH_BYTES); + } + + m_keysetItem = data.m_keysetItem; +} diff --git a/src/common/p25/kmm/KMMModifyKey.h b/src/common/p25/kmm/KMMModifyKey.h new file mode 100644 index 00000000..6e8ae200 --- /dev/null +++ b/src/common/p25/kmm/KMMModifyKey.h @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Digital Voice Modem - Common Library + * GPLv2 Open Source. Use is subject to license terms. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright (C) 2025 Bryan Biedenkapp, N2PLL + * + */ +/** + * @file KMMModifyKey.h + * @ingroup p25_kmm + * @file KMMModifyKey.cpp + * @ingroup p25_kmm + */ +#if !defined(__P25_KMM__KMM_MODIFY_KEY_H__) +#define __P25_KMM__KMM_MODIFY_KEY_H__ + +#include "common/Defines.h" +#include "common/p25/kmm/KMMFrame.h" +#include "common/p25/kmm/KeysetItem.h" +#include "common/Utils.h" + +#include +#include + +namespace p25 +{ + namespace kmm + { + // --------------------------------------------------------------------------- + // Constants + // --------------------------------------------------------------------------- + + /** + * @addtogroup p25_kmm + * @{ + */ + + const uint32_t KMM_MODIFY_KEY_LENGTH = KMM_FRAME_LENGTH + 4U; + + /** @} */ + + // --------------------------------------------------------------------------- + // Class Declaration + // --------------------------------------------------------------------------- + + class HOST_SW_API KMMModifyKey : public KMMFrame { + public: + /** + * @brief Initializes a new instance of the KMMModifyKey class. + */ + KMMModifyKey(); + /** + * @brief Finalizes a instance of the KMMModifyKey class. + */ + ~KMMModifyKey(); + + /** + * @brief Gets the byte length of this KMMFrame. + * @return uint32_t Length of KMMFrame. + */ + uint32_t length() const override; + + /** + * @brief Decode a KMM modify key packet. + * @param[in] data Buffer containing KMM packet data to decode. + * @returns bool True, if decoded, otherwise false. + */ + bool decode(const uint8_t* data); + /** + * @brief Encode a KMM modify key packet. + * @param[out] data Buffer to encode KMM packet data to. + */ + void encode(uint8_t* data); + + /** @name Encryption data */ + /** + * @brief Sets the encryption message indicator. + * @param[in] mi Buffer containing the 9-byte Message Indicator. + */ + void setMI(const uint8_t* mi); + /** + * @brief Gets the encryption message indicator. + * @param[out] mi Buffer containing the 9-byte Message Indicator. + */ + void getMI(uint8_t* mi) const; + /** @} */ + + public: + /** + * @brief + */ + __PROPERTY(uint8_t, decryptInfoFmt, DecryptInfoFmt); + /** + * @brief Encryption algorithm ID. + */ + __PROPERTY(uint8_t, algId, AlgId); + /** + * @brief Encryption key ID. + */ + __PROPERTY(uint32_t, kId, KId); + + /** + * @brief + */ + __PROPERTY(KeysetItem, keysetItem, KeysetItem); + + __COPY(KMMModifyKey); + + private: + // Encryption data + bool m_miSet; + uint8_t* m_mi; + }; + } // namespace kmm +} // namespace p25 + +#endif // __P25_KMM__KMM_MODIFY_KEY_H__ diff --git a/src/common/p25/kmm/KeysetItem.h b/src/common/p25/kmm/KeysetItem.h new file mode 100644 index 00000000..395ed00d --- /dev/null +++ b/src/common/p25/kmm/KeysetItem.h @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Digital Voice Modem - Common Library + * GPLv2 Open Source. Use is subject to license terms. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright (C) 2025 Bryan Biedenkapp, N2PLL + * + */ +/** + * @file KeysetItem.h + * @ingroup p25_kmm + */ +#if !defined(__P25_KMM__KEYSET_ITEM_H__) +#define __P25_KMM__KEYSET_ITEM_H__ + +#include "common/Defines.h" +#include "common/Utils.h" + +#include +#include + +namespace p25 +{ + namespace kmm + { + // --------------------------------------------------------------------------- + // Class Declaration + // --------------------------------------------------------------------------- + + /** + * @brief Represents a key set item within a KMM frame packet. + * @ingroup p25_kmm + */ + class HOST_SW_API KeyItem { + public: + /** + * @brief Initializes a new instance of the KeyItem class. + */ + KeyItem() : + m_keyFormat(0x80U/*P25DEF::KEY_FORMAT_TEK*/), + m_sln(0U), + m_kId(0U), + m_keyLength(0U), + m_keyMaterial(nullptr) + { + /* stub */ + } + /** + * @brief Finalizes a instance of the KeyItem class. + */ + ~KeyItem() + { + if (m_keyMaterial != nullptr) { + delete[] m_keyMaterial; + m_keyMaterial = nullptr; + } + } + + /** + * @brief Equals operator. Copies this KeyItem to another KeyItem. + * @param data Instance of KeyItem to copy. + */ + virtual KeyItem& operator= (const KeyItem& data) + { + if (this != &data) { + m_keyFormat = data.m_keyFormat; + m_sln = data.m_sln; + m_kId = data.m_kId; + + if (data.m_keyLength > 0U) { + if (m_keyMaterial != nullptr) { + delete[] m_keyMaterial; + } + + m_keyMaterial = new uint8_t[data.m_keyLength]; + m_keyLength = data.m_keyLength; + ::memcpy(m_keyMaterial, data.m_keyMaterial, data.m_keyLength); + } + } + + return *this; + } + + /** + * @brief Set the key material. + * @param key + * @param keyLength + */ + void setKey(const uint8_t* key, uint32_t keyLength) + { + assert(key != nullptr); + m_keyLength = keyLength; + ::memcpy(m_keyMaterial, key, keyLength); + } + + /** + * @brief Get the key material. + * @param key + */ + void getKey(uint8_t* key) const + { + assert(key != nullptr); + ::memcpy(key, m_keyMaterial, m_keyLength); + } + + public: + /** + * @brief + */ + __PROPERTY_PLAIN(uint8_t, keyFormat); + /** + * @brief + */ + __PROPERTY_PLAIN(uint16_t, sln); + /** + * @brief + */ + __PROPERTY_PLAIN(uint16_t, kId); + + private: + uint32_t m_keyLength; + uint8_t* m_keyMaterial; + }; + + // --------------------------------------------------------------------------- + // Class Declaration + // --------------------------------------------------------------------------- + + /** + * @brief Represents a key set item within a KMM frame packet. + * @ingroup p25_kmm + */ + class HOST_SW_API KeysetItem { + public: + /** + * @brief Initializes a new instance of the KeysetItem class. + */ + KeysetItem() : + m_keysetId(0U), + m_algId(0U), + m_keyLength(0U), + m_keys() + { + /* stub */ + } + /** + * @brief Finalizes a instance of the KeysetItem class. + */ + ~KeysetItem() + { + for (auto key : m_keys) { + delete key; + } + } + + /** + * @brief Equals operator. Copies this KeysetItem to another KeysetItem. + * @param data Instance of KeysetItem to copy. + */ + virtual KeysetItem& operator= (const KeysetItem& data) + { + if (this != &data) { + m_keysetId = data.m_keysetId; + m_algId = data.m_algId; + m_keyLength = data.m_keyLength; + + for (auto key : m_keys) { + delete key; + } + m_keys.clear(); + + for (auto key : data.m_keys) { + KeyItem* copy = key; + m_keys.push_back(copy); + } + } + + return *this; + } + + /** + * @brief Gets the byte length of this keyset item. + * @return uint32_t Length of keyset item. + */ + uint32_t length() const + { + uint32_t len = 4U; + + uint32_t keyItemLength = m_keys.size() * 5U; + uint32_t combinedKeyLength = m_keys.size() * m_keyLength; + len += keyItemLength + combinedKeyLength; + + return len; + } + + /** + * @brief Add a key to the key list. + * @param key + */ + void push_back(KeyItem* key) + { + m_keys.push_back(key); + } + + public: + /** + * @brief + */ + __PROPERTY_PLAIN(uint8_t, keysetId); + /** + * @brief Encryption algorithm ID. + */ + __PROPERTY_PLAIN(uint8_t, algId); + /** + * @brief + */ + __PROPERTY_PLAIN(uint8_t, keyLength); + + /** + * @brief List of keys. + */ + __PROPERTY_PLAIN(std::vector, keys); + }; + } // namespace kmm +} // namespace p25 + +#endif // __P25_KMM__KEYSET_ITEM_H__ diff --git a/src/host/Host.cpp b/src/host/Host.cpp index 09d418f4..8c4a0d6b 100644 --- a/src/host/Host.cpp +++ b/src/host/Host.cpp @@ -1519,9 +1519,9 @@ bool Host::rmtPortModemHandler(Modem* modem, uint32_t ms, modem::RESP_TYPE_DVM r if (modem->getTrace()) Utils::dump(1U, "TX Remote Data", buffer, len); - // never send less then 3 bytes - if (len < 3U) - return false; + // never send less then 3 bytes + if (len < 3U) + return false; // send entire modem packet over the remote port m_modemRemotePort->write(buffer, len);