From 7dc90b577f671e916b9c6a642725181090418835 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Tue, 11 Mar 2025 12:05:45 -0400 Subject: [PATCH] fix KMM copy issue; implement list key IDs and keysets inventory reponses; --- src/common/p25/kmm/KMMHello.cpp | 2 + src/common/p25/kmm/KMMInventoryCommand.cpp | 6 +- .../p25/kmm/KMMInventoryResponseHeader.cpp | 77 ++++++++++++ .../p25/kmm/KMMInventoryResponseHeader.h | 86 +++++++++++++ .../kmm/KMMInventoryResponseListKeyIDs.cpp | 115 ++++++++++++++++++ .../p25/kmm/KMMInventoryResponseListKeyIDs.h | 89 ++++++++++++++ .../kmm/KMMInventoryResponseListKeysets.cpp | 93 ++++++++++++++ .../p25/kmm/KMMInventoryResponseListKeysets.h | 76 ++++++++++++ src/common/p25/kmm/KMMModifyKey.cpp | 2 + 9 files changed, 544 insertions(+), 2 deletions(-) create mode 100644 src/common/p25/kmm/KMMInventoryResponseHeader.cpp create mode 100644 src/common/p25/kmm/KMMInventoryResponseHeader.h create mode 100644 src/common/p25/kmm/KMMInventoryResponseListKeyIDs.cpp create mode 100644 src/common/p25/kmm/KMMInventoryResponseListKeyIDs.h create mode 100644 src/common/p25/kmm/KMMInventoryResponseListKeysets.cpp create mode 100644 src/common/p25/kmm/KMMInventoryResponseListKeysets.h diff --git a/src/common/p25/kmm/KMMHello.cpp b/src/common/p25/kmm/KMMHello.cpp index ff179fbe..e18a0139 100644 --- a/src/common/p25/kmm/KMMHello.cpp +++ b/src/common/p25/kmm/KMMHello.cpp @@ -68,5 +68,7 @@ void KMMHello::encode(uint8_t* data) void KMMHello::copy(const KMMHello& data) { + KMMFrame::copy(data); + m_flag = data.m_flag; } diff --git a/src/common/p25/kmm/KMMInventoryCommand.cpp b/src/common/p25/kmm/KMMInventoryCommand.cpp index 24b7f32b..c36aeb02 100644 --- a/src/common/p25/kmm/KMMInventoryCommand.cpp +++ b/src/common/p25/kmm/KMMInventoryCommand.cpp @@ -35,7 +35,7 @@ KMMInventoryCommand::KMMInventoryCommand() : KMMFrame(), KMMInventoryCommand::~KMMInventoryCommand() = default; -/* Decode a KMM modify key. */ +/* Decode a KMM inventory command. */ bool KMMInventoryCommand::decode(const uint8_t* data) { @@ -48,7 +48,7 @@ bool KMMInventoryCommand::decode(const uint8_t* data) return true; } -/* Encode a KMM modify key. */ +/* Encode a KMM inventory command. */ void KMMInventoryCommand::encode(uint8_t* data) { @@ -68,5 +68,7 @@ void KMMInventoryCommand::encode(uint8_t* data) void KMMInventoryCommand::copy(const KMMInventoryCommand& data) { + KMMFrame::copy(data); + m_inventoryType = data.m_inventoryType; } diff --git a/src/common/p25/kmm/KMMInventoryResponseHeader.cpp b/src/common/p25/kmm/KMMInventoryResponseHeader.cpp new file mode 100644 index 00000000..254df4d2 --- /dev/null +++ b/src/common/p25/kmm/KMMInventoryResponseHeader.cpp @@ -0,0 +1,77 @@ +// 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/KMMInventoryResponseHeader.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 KMMInventoryResponseHeader class. */ + +KMMInventoryResponseHeader::KMMInventoryResponseHeader() : KMMFrame(), + m_inventoryType(KMM_InventoryType::NULL_INVENTORY) +{ + m_messageId = KMM_MessageType::INVENTORY_RSP; + m_respKind = KMM_ResponseKind::IMMEDIATE; +} + +/* Finalizes a instance of the KMMInventoryResponseHeader class. */ + +KMMInventoryResponseHeader::~KMMInventoryResponseHeader() = default; + +/* Decode a KMM inventory response header. */ + +bool KMMInventoryResponseHeader::decode(const uint8_t* data) +{ + assert(data != nullptr); + + KMMFrame::decodeHeader(data); + + m_inventoryType = data[10U]; // Inventory Type + m_numberOfItems = __GET_UINT16B(data, 11U); // Number of Items + + return true; +} + +/* Encode a KMM inventory response header. */ + +void KMMInventoryResponseHeader::encode(uint8_t* data) +{ + assert(data != nullptr); + m_messageLength = KMM_INVENTORY_RSP_HDR_LENGTH; + + KMMFrame::encodeHeader(data); + + data[10U] = m_inventoryType; // Inventory Type + __SET_UINT16B(m_numberOfItems, data, 11U); // Number of Items +} + +// --------------------------------------------------------------------------- +// Protected Class Members +// --------------------------------------------------------------------------- + +/* Internal helper to copy the the class. */ + +void KMMInventoryResponseHeader::copy(const KMMInventoryResponseHeader& data) +{ + KMMFrame::copy(data); + + m_inventoryType = data.m_inventoryType; + m_numberOfItems = data.m_numberOfItems; +} diff --git a/src/common/p25/kmm/KMMInventoryResponseHeader.h b/src/common/p25/kmm/KMMInventoryResponseHeader.h new file mode 100644 index 00000000..10a5baf9 --- /dev/null +++ b/src/common/p25/kmm/KMMInventoryResponseHeader.h @@ -0,0 +1,86 @@ +// 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 KMMInventoryResponseHeader.h + * @ingroup p25_kmm + * @file KMMInventoryResponseHeader.cpp + * @ingroup p25_kmm + */ +#if !defined(__P25_KMM__KMM_INVENTORY_RESPONSE_HDR_H__) +#define __P25_KMM__KMM_INVENTORY_RESPONSE_HDR_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_INVENTORY_RSP_HDR_LENGTH = KMM_FRAME_LENGTH + 3U; + + /** @} */ + + // --------------------------------------------------------------------------- + // Class Declaration + // --------------------------------------------------------------------------- + + class HOST_SW_API KMMInventoryResponseHeader : public KMMFrame { + public: + /** + * @brief Initializes a new instance of the KMMInventoryResponseHeader class. + */ + KMMInventoryResponseHeader(); + /** + * @brief Finalizes a instance of the KMMInventoryResponseHeader class. + */ + ~KMMInventoryResponseHeader(); + + /** + * @brief Decode a KMM inventory response header. + * @param[in] data Buffer containing KMM frame data to decode. + * @returns bool True, if decoded, otherwise false. + */ + bool decode(const uint8_t* data) override; + /** + * @brief Encode a KMM inventory reponse header. + * @param[out] data Buffer to encode KMM frame data to. + */ + void encode(uint8_t* data) override; + + public: + /** + * @brief + */ + __PROTECTED_PROPERTY(uint8_t, inventoryType, InventoryType); + /** + * @brief + */ + __PROTECTED_PROPERTY(uint16_t, numberOfItems, NumberOfItems); + + __PROTECTED_COPY(KMMInventoryResponseHeader); + }; + } // namespace kmm +} // namespace p25 + +#endif // __P25_KMM__KMM_INVENTORY_RESPONSE_HDR_H__ diff --git a/src/common/p25/kmm/KMMInventoryResponseListKeyIDs.cpp b/src/common/p25/kmm/KMMInventoryResponseListKeyIDs.cpp new file mode 100644 index 00000000..fee94b2b --- /dev/null +++ b/src/common/p25/kmm/KMMInventoryResponseListKeyIDs.cpp @@ -0,0 +1,115 @@ +// 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/KMMInventoryResponseListKeyIDs.h" +#include "Log.h" + +using namespace p25; +using namespace p25::defines; +using namespace p25::kmm; + +#include + +/* +** bryanb: this implementation is naive; it will only process the first returned key ID list +** and not the subsequent ones +*/ + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/* Initializes a new instance of the KMMInventoryResponseListKeyIDs class. */ + +KMMInventoryResponseListKeyIDs::KMMInventoryResponseListKeyIDs() : KMMInventoryResponseHeader(), + m_keysetId(0U), + m_algId(P25DEF::ALGO_UNENCRYPT), + m_numberOfKeyIDs(0U), + m_keyIds() +{ + m_messageId = KMM_MessageType::INVENTORY_RSP; + m_inventoryType = KMM_InventoryType::LIST_ACTIVE_KEY_IDS; + m_respKind = KMM_ResponseKind::IMMEDIATE; +} + +/* Finalizes a instance of the KMMInventoryResponseListKeyIDs class. */ + +KMMInventoryResponseListKeyIDs::~KMMInventoryResponseListKeyIDs() = default; + +/* Gets the byte length of this KMMInventoryResponseListKeyIDs. */ + +uint32_t KMMInventoryResponseListKeyIDs::length() const +{ + uint32_t len = KMM_INVENTORY_RSP_HDR_LENGTH + 3U; + len += m_keyIds.size() * 2U; + + return len; +} + +/* Decode a KMM inventory response header. */ + +bool KMMInventoryResponseListKeyIDs::decode(const uint8_t* data) +{ + assert(data != nullptr); + + KMMInventoryResponseHeader::decodeHeader(data); + + m_keysetId = data[13U]; + m_algId = data[14U]; + m_numberOfKeyIDs = data[15U]; + + uint16_t offset = 0U; + for (uint16_t i = 0U; i < m_numberOfKeyIDs; i++) { + uint16_t keyId = __GET_UINT16B(data, 16U + offset); + m_keyIds.push_back(keyId); + offset += 2U; + } + + return true; +} + +/* Encode a KMM inventory response header. */ + +void KMMInventoryResponseListKeyIDs::encode(uint8_t* data) +{ + assert(data != nullptr); + m_messageLength = KMM_INVENTORY_RSP_HDR_LENGTH; + m_numberOfItems = 1U; // this is a naive approach... + + KMMInventoryResponseHeader::encodeHeader(data); + + data[13U] = m_keysetId; + data[14U] = m_algId; + data[15U] = m_numberOfKeyIDs; + + uint16_t offset = 0U; + for (auto entry : m_keyIds) { + __SET_UINT16B(entry, data, 16U + offset); + offset += 2U; + } +} + +// --------------------------------------------------------------------------- +// Protected Class Members +// --------------------------------------------------------------------------- + +/* Internal helper to copy the the class. */ + +void KMMInventoryResponseListKeyIDs::copy(const KMMInventoryResponseListKeyIDs& data) +{ + KMMInventoryResponseHeader::copy(data); + + m_keysetId = data.m_keysetId; + m_algId = data.m_algId; + m_numberOfKeyIDs = data.m_numberOfKeyIDs; + + m_keyIds = data.m_keyIds; +} diff --git a/src/common/p25/kmm/KMMInventoryResponseListKeyIDs.h b/src/common/p25/kmm/KMMInventoryResponseListKeyIDs.h new file mode 100644 index 00000000..4f5cc6a4 --- /dev/null +++ b/src/common/p25/kmm/KMMInventoryResponseListKeyIDs.h @@ -0,0 +1,89 @@ +// 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 KMMInventoryResponseListKeyIDs.h + * @ingroup p25_kmm + * @file KMMInventoryResponseListKeyIDs.cpp + * @ingroup p25_kmm + */ +#if !defined(__P25_KMM__KMM_INVENTORY_RESPONSE_LIST_KEY_IDS_H__) +#define __P25_KMM__KMM_INVENTORY_RESPONSE_LIST_KEY_IDS_H__ + +#include "common/Defines.h" +#include "common/p25/kmm/KMMFrame.h" +#include "common/p25/kmm/KMMInventoryResponseHeader.h" +#include "common/p25/kmm/KeysetItem.h" +#include "common/Utils.h" + +#include +#include + +namespace p25 +{ + namespace kmm + { + // --------------------------------------------------------------------------- + // Class Declaration + // --------------------------------------------------------------------------- + + class HOST_SW_API KMMInventoryResponseListKeyIDs : public KMMInventoryResponseHeader { + public: + /** + * @brief Initializes a new instance of the KMMInventoryResponseListKeyIDs class. + */ + KMMInventoryResponseListKeyIDs(); + /** + * @brief Finalizes a instance of the KMMInventoryResponseListKeyIDs class. + */ + ~KMMInventoryResponseListKeyIDs(); + + /** + * @brief Gets the byte length of this KMMFrame. + * @return uint32_t Length of KMMFrame. + */ + uint32_t length() const override; + + /** + * @brief Decode a KMM inventory response. + * @param[in] data Buffer containing KMM frame data to decode. + * @returns bool True, if decoded, otherwise false. + */ + bool decode(const uint8_t* data) override; + /** + * @brief Encode a KMM inventory reponse. + * @param[out] data Buffer to encode KMM frame data to. + */ + void encode(uint8_t* data) override; + + public: + /** + * @brief + */ + __PROPERTY(uint8_t, keysetId, KeysetId); + /** + * @brief Encryption algorithm ID. + */ + __PROPERTY(uint8_t, algId, AlgId); + /** + * @brief Encryption algorithm ID. + */ + __PROPERTY(uint8_t, numberOfKeyIDs, NumberOfKeyIDs); + + /** + * @brief + */ + __PROPERTY(std::vector, keyIds, KeyIds); + + __COPY(KMMInventoryResponseListKeyIDs); + }; + } // namespace kmm +} // namespace p25 + +#endif // __P25_KMM__KMM_INVENTORY_RESPONSE_LIST_KEY_IDS_H__ diff --git a/src/common/p25/kmm/KMMInventoryResponseListKeysets.cpp b/src/common/p25/kmm/KMMInventoryResponseListKeysets.cpp new file mode 100644 index 00000000..9844937d --- /dev/null +++ b/src/common/p25/kmm/KMMInventoryResponseListKeysets.cpp @@ -0,0 +1,93 @@ +// 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/KMMInventoryResponseListKeysets.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 KMMInventoryResponseListKeysets class. */ + +KMMInventoryResponseListKeysets::KMMInventoryResponseListKeysets() : KMMInventoryResponseHeader(), + m_keysetIds() +{ + m_messageId = KMM_MessageType::INVENTORY_RSP; + m_inventoryType = KMM_InventoryType::LIST_ACTIVE_KEYSET_IDS; + m_respKind = KMM_ResponseKind::IMMEDIATE; +} + +/* Finalizes a instance of the KMMInventoryResponseListKeysets class. */ + +KMMInventoryResponseListKeysets::~KMMInventoryResponseListKeysets() = default; + +/* Gets the byte length of this KMMInventoryResponseListKeysets. */ + +uint32_t KMMInventoryResponseListKeysets::length() const +{ + uint32_t len = KMM_INVENTORY_RSP_HDR_LENGTH; + len += m_keysetIds.size(); + + return len; +} + +/* Decode a KMM inventory response header. */ + +bool KMMInventoryResponseListKeysets::decode(const uint8_t* data) +{ + assert(data != nullptr); + + KMMInventoryResponseHeader::decodeHeader(data); + + for (uint16_t i = 0U; i < m_numberOfItems; i++) { + uint8_t keysetId = data[13U + i]; + m_keysetIds.push_back(keysetId); + } + + return true; +} + +/* Encode a KMM inventory response header. */ + +void KMMInventoryResponseListKeysets::encode(uint8_t* data) +{ + assert(data != nullptr); + m_messageLength = KMM_INVENTORY_RSP_HDR_LENGTH; + m_numberOfItems = (uint16_t)m_keysetIds.size(); + + KMMInventoryResponseHeader::encodeHeader(data); + + uint16_t offset = 0U; + for (auto entry : m_keysetIds) { + data[13U + offset] = entry; + offset += 1U; + } +} + +// --------------------------------------------------------------------------- +// Protected Class Members +// --------------------------------------------------------------------------- + +/* Internal helper to copy the the class. */ + +void KMMInventoryResponseListKeysets::copy(const KMMInventoryResponseListKeysets& data) +{ + KMMInventoryResponseHeader::copy(data); + + m_keysetIds = data.m_keysetIds; +} diff --git a/src/common/p25/kmm/KMMInventoryResponseListKeysets.h b/src/common/p25/kmm/KMMInventoryResponseListKeysets.h new file mode 100644 index 00000000..8f142093 --- /dev/null +++ b/src/common/p25/kmm/KMMInventoryResponseListKeysets.h @@ -0,0 +1,76 @@ +// 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 KMMInventoryResponseListKeysets.h + * @ingroup p25_kmm + * @file KMMInventoryResponseListKeysets.cpp + * @ingroup p25_kmm + */ +#if !defined(__P25_KMM__KMM_INVENTORY_RESPONSE_LIST_KEYSETS_H__) +#define __P25_KMM__KMM_INVENTORY_RESPONSE_LIST_KEYSETS_H__ + +#include "common/Defines.h" +#include "common/p25/kmm/KMMFrame.h" +#include "common/p25/kmm/KMMInventoryResponseHeader.h" +#include "common/p25/kmm/KeysetItem.h" +#include "common/Utils.h" + +#include +#include + +namespace p25 +{ + namespace kmm + { + // --------------------------------------------------------------------------- + // Class Declaration + // --------------------------------------------------------------------------- + + class HOST_SW_API KMMInventoryResponseListKeysets : public KMMInventoryResponseHeader { + public: + /** + * @brief Initializes a new instance of the KMMInventoryResponseListKeysets class. + */ + KMMInventoryResponseListKeysets(); + /** + * @brief Finalizes a instance of the KMMInventoryResponseListKeysets class. + */ + ~KMMInventoryResponseListKeysets(); + + /** + * @brief Gets the byte length of this KMMFrame. + * @return uint32_t Length of KMMFrame. + */ + uint32_t length() const override; + + /** + * @brief Decode a KMM inventory response. + * @param[in] data Buffer containing KMM frame data to decode. + * @returns bool True, if decoded, otherwise false. + */ + bool decode(const uint8_t* data) override; + /** + * @brief Encode a KMM inventory reponse. + * @param[out] data Buffer to encode KMM frame data to. + */ + void encode(uint8_t* data) override; + + public: + /** + * @brief + */ + __PROPERTY(std::vector, keysetIds, KeysetIds); + + __COPY(KMMInventoryResponseListKeysets); + }; + } // namespace kmm +} // namespace p25 + +#endif // __P25_KMM__KMM_INVENTORY_RESPONSE_LIST_KEYSETS_H__ diff --git a/src/common/p25/kmm/KMMModifyKey.cpp b/src/common/p25/kmm/KMMModifyKey.cpp index 33d96394..1415976e 100644 --- a/src/common/p25/kmm/KMMModifyKey.cpp +++ b/src/common/p25/kmm/KMMModifyKey.cpp @@ -165,6 +165,8 @@ void KMMModifyKey::encode(uint8_t* data) void KMMModifyKey::copy(const KMMModifyKey& data) { + KMMFrame::copy(data); + m_decryptInfoFmt = data.m_decryptInfoFmt; m_algId = data.m_algId; m_kId = data.m_kId;