add more KMM frames; implement support in the network core for key request and response (this allows peers to request a encryption key from a EKC file loaded on the FNE to use for encryption/decryption, i.e. peer keyloading);

pull/86/head
Bryan Biedenkapp 11 months ago
parent 0fd6758161
commit df648a2c50

@ -15,6 +15,7 @@
#include "common/nxdn/NXDNDefines.h" #include "common/nxdn/NXDNDefines.h"
#include "common/p25/dfsi/DFSIDefines.h" #include "common/p25/dfsi/DFSIDefines.h"
#include "common/p25/dfsi/LC.h" #include "common/p25/dfsi/LC.h"
#include "common/p25/kmm/KMMModifyKey.h"
#include "network/BaseNetwork.h" #include "network/BaseNetwork.h"
#include "Utils.h" #include "Utils.h"
@ -112,6 +113,37 @@ bool BaseNetwork::writeGrantReq(const uint8_t mode, const uint32_t srcId, const
return writeMaster({ NET_FUNC::GRANT_REQ, NET_SUBFUNC::NOP }, buffer, MSG_HDR_SIZE, RTP_END_OF_CALL_SEQ, 0U); return writeMaster({ NET_FUNC::GRANT_REQ, NET_SUBFUNC::NOP }, buffer, MSG_HDR_SIZE, RTP_END_OF_CALL_SEQ, 0U);
} }
/* Writes enc. key request to the network. */
bool BaseNetwork::writeKeyReq(const uint16_t kId, const uint8_t algId)
{
using namespace p25::defines;
using namespace p25::kmm;
if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING)
return false;
uint8_t buffer[DATA_PACKET_LENGTH];
::memset(buffer, 0x00U, DATA_PACKET_LENGTH);
KMMModifyKey modifyKeyCmd = KMMModifyKey();
modifyKeyCmd.setDecryptInfoFmt(KMM_DECRYPT_INSTRUCT_NONE);
modifyKeyCmd.setAlgId(algId);
modifyKeyCmd.setKId(kId);
KeysetItem ks = KeysetItem();
ks.keysetId(0U);
ks.algId(algId);
ks.keyLength(P25DEF::MAX_ENC_KEY_LENGTH_BYTES);
modifyKeyCmd.setKeysetItem(ks);
modifyKeyCmd.encode(buffer + 11U);
Utils::dump("writeKeyReq", buffer, modifyKeyCmd.length() + 11U);
return writeMaster({ NET_FUNC::KEY_REQ, NET_SUBFUNC::NOP }, buffer, modifyKeyCmd.length() + 11U, RTP_END_OF_CALL_SEQ, 0U);
}
/* Writes the local activity log to the network. */ /* Writes the local activity log to the network. */
bool BaseNetwork::writeActLog(const char* message) bool BaseNetwork::writeActLog(const char* message)

@ -59,6 +59,7 @@
#define TAG_REPEATER_PING "RPTP" #define TAG_REPEATER_PING "RPTP"
#define TAG_REPEATER_GRANT "RPTG" #define TAG_REPEATER_GRANT "RPTG"
#define TAG_REPEATER_KEY "RKEY"
#define TAG_TRANSFER "TRNS" #define TAG_TRANSFER "TRNS"
#define TAG_TRANSFER_ACT_LOG "TRNSLOG" #define TAG_TRANSFER_ACT_LOG "TRNSLOG"
@ -172,6 +173,14 @@ namespace network
*/ */
bool writeGrantReq(const uint8_t mode, const uint32_t srcId, const uint32_t dstId, const uint8_t slot, const bool unitToUnit); bool writeGrantReq(const uint8_t mode, const uint32_t srcId, const uint32_t dstId, const uint8_t slot, const bool unitToUnit);
/**
* @brief Writes a enc. key request to the network.
* @param kId Key ID.
* @param algId Algorithm ID.
* @returns bool True, if request was sent, otherwise false.
*/
bool writeKeyReq(const uint16_t kId, const uint8_t algId);
/** /**
* @brief Writes the local activity log to the network. * @brief Writes the local activity log to the network.
* @param message Textual string to send as activity log information. * @param message Textual string to send as activity log information.

@ -117,6 +117,8 @@ namespace p25
const uint8_t AUTH_RAND_SEED_LENGTH_BYTES = 10U; const uint8_t AUTH_RAND_SEED_LENGTH_BYTES = 10U;
const uint8_t AUTH_RAND_CHLNG_LENGTH_BYTES = 5U; const uint8_t AUTH_RAND_CHLNG_LENGTH_BYTES = 5U;
const uint8_t AUTH_KEY_LENGTH_BYTES = 16U; const uint8_t AUTH_KEY_LENGTH_BYTES = 16U;
const uint8_t MAX_ENC_KEY_LENGTH_BYTES = 32U;
/* @} */ /* @} */
/** @name Thresholds */ /** @name Thresholds */
@ -143,6 +145,12 @@ namespace p25
/** @name Encryption Algorithms */ /** @name Encryption Algorithms */
/** @brief Unencrypted */ /** @brief Unencrypted */
const uint8_t ALGO_UNENCRYPT = 0x80U; const uint8_t ALGO_UNENCRYPT = 0x80U;
/** @brief DES-OFB */
const uint8_t ALGO_DES = 0x81U;
/** @brief AES-256 */
const uint8_t ALGO_AES_256 = 0x84U;
/** @brief ARC4 */
const uint8_t ALGO_ARC4 = 0xAAU;
/** @} */ /** @} */
/** @name IDEN Table Bandwidth Sizes */ /** @name IDEN Table Bandwidth Sizes */
@ -455,6 +463,28 @@ namespace p25
}; };
} }
/** @brief KMM Inventory Type */
namespace KMM_InventoryType {
enum : uint8_t {
NULL_INVENTORY = 0x00U, //! Null
LIST_ACTIVE_KEYSET_IDS = 0x01U, //! List Active Keyset IDs
LIST_INACTIVE_KEYSET_IDS = 0x02U, //! List Inactive Keyset IDs
LIST_ACTIVE_KEY_IDS = 0x03U, //! List Active Key IDs
LIST_INACTIVE_KEY_IDS = 0x04U, //! List Inactive Key IDs
};
}
/** @brief KMM Hello Flag */
namespace KMM_HelloFlag {
enum : uint8_t {
IDENT_ONLY = 0x00U, //! KMF or SU Identification Only
REKEY_REQUEST_UKEK = 0x01U, //! Rekey Request (UKEK Exists)
REKEY_REQUEST_NO_UKEK = 0x02U, //! Rekey Request (UKEK does not exist)
};
}
/** @brief KMM Decryption Instruction - None */ /** @brief KMM Decryption Instruction - None */
const uint8_t KMM_DECRYPT_INSTRUCT_NONE = 0x00U; const uint8_t KMM_DECRYPT_INSTRUCT_NONE = 0x00U;
/** @brief KMM Decryption Instruction - Message Indicator */ /** @brief KMM Decryption Instruction - Message Indicator */

@ -0,0 +1,73 @@
// 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/KMMFactory.h"
#include "Log.h"
#include "Utils.h"
using namespace p25;
using namespace p25::defines;
using namespace p25::kmm;
#include <cassert>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/* Initializes a new instance of the KMMFactory class. */
KMMFactory::KMMFactory() = default;
/* Finalizes a instance of KMMFactory class. */
KMMFactory::~KMMFactory() = default;
/* Create an instance of a KMMFrame. */
std::unique_ptr<KMMFrame> KMMFactory::create(const uint8_t* data)
{
assert(data != nullptr);
uint8_t messageId = data[0U]; // Message ID
switch (messageId) {
case KMM_MessageType::HELLO:
return decode(new KMMHello(), data);
case KMM_MessageType::INVENTORY_CMD:
return decode(new KMMInventoryCommand(), data);
case KMM_MessageType::MODIFY_KEY_CMD:
return decode(new KMMModifyKey(), data);
default:
LogError(LOG_P25, "KMMFactory::create(), unknown KMM message ID value, messageId = $%02X", messageId);
break;
}
return nullptr;
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/* Decode a SNDCP packet. */
std::unique_ptr<KMMFrame> KMMFactory::decode(KMMFrame* packet, const uint8_t* data)
{
assert(packet != nullptr);
assert(data != nullptr);
if (!packet->decode(data)) {
return nullptr;
}
return std::unique_ptr<KMMFrame>(packet);
}

@ -0,0 +1,70 @@
// 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 KMMFactory.h
* @ingroup p25_kmm
* @file KMMFactory.cpp
* @ingroup p25_kmm
*/
#if !defined(__P25_KMM__KMM_FACTORY_H__)
#define __P25_KMM__KMM_FACTORY_H__
#include "common/Defines.h"
#include "common/p25/kmm/KeysetItem.h"
#include "common/p25/kmm/KMMFrame.h"
#include "common/p25/kmm/KMMHello.h"
#include "common/p25/kmm/KMMInventoryCommand.h"
#include "common/p25/kmm/KMMModifyKey.h"
namespace p25
{
namespace kmm
{
// ---------------------------------------------------------------------------
// Class Declaration
// ---------------------------------------------------------------------------
/**
* @brief Helper class to instantiate an instance of a KMM frame packet.
* @ingroup p25_kmm
*/
class HOST_SW_API KMMFactory {
public:
/**
* @brief Initializes a new instance of the KMMFactory class.
*/
KMMFactory();
/**
* @brief Finalizes a instance of the KMMFactory class.
*/
~KMMFactory();
/**
* @brief Create an instance of a KMMFrame.
* @param[in] data Buffer containing KMM frame packet data to decode.
* @returns KMMFrame* Instance of a KMMFrame representing the decoded data.
*/
static std::unique_ptr<KMMFrame> create(const uint8_t* data);
private:
/**
* @brief Decode a KMM frame.
* @param packet Instance of KMMFrame.
* @param[in] data Buffer containing KMM frame packet data to decode.
* @returns KMMFrame* Instance of a KMMFrame representing the decoded data.
*/
static std::unique_ptr<KMMFrame> decode(KMMFrame* packet, const uint8_t* data);
};
} // namespace kmm
} // namespace p25
#endif // __P25_KMM__KMM_FACTORY_H__

@ -33,7 +33,7 @@ KMMFrame::KMMFrame(const KMMFrame& data) : KMMFrame()
KMMFrame::KMMFrame() : KMMFrame::KMMFrame() :
m_messageId(KMM_MessageType::NULL_CMD), m_messageId(KMM_MessageType::NULL_CMD),
m_messageLength(7U), m_messageLength(KMM_FRAME_LENGTH),
m_respKind(KMM_ResponseKind::NONE), m_respKind(KMM_ResponseKind::NONE),
m_complete(true), m_complete(true),
m_mfMessageNumber(0U), m_mfMessageNumber(0U),
@ -50,20 +50,20 @@ KMMFrame::~KMMFrame() = default;
// Protected Class Members // Protected Class Members
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/* Internal helper to decode a SNDCP header. */ /* Internal helper to decode a KMM header. */
bool KMMFrame::decodeHeader(const uint8_t* data, bool outbound) bool KMMFrame::decodeHeader(const uint8_t* data)
{ {
assert(data != nullptr); assert(data != nullptr);
m_messageId = data[0U]; // Message ID m_messageId = data[0U]; // Message ID
m_messageLength = __GET_UINT16B(data, 1U); // Message Length m_messageLength = __GET_UINT16B(data, 1U); // Message Length
m_respKind = (data[2U] >> 6U) & 0x03U; // Response Kind m_respKind = (data[3U] >> 6U) & 0x03U; // Response Kind
m_mfMessageNumber = (data[2U] >> 4U) & 0x03U; // Message Number m_mfMessageNumber = (data[3U] >> 4U) & 0x03U; // Message Number
m_mfMac = (data[2U] >> 2U) & 0x03U; // MAC m_mfMac = (data[3U] >> 2U) & 0x03U; // MAC
bool done = (data[2U] & 0x01U) == 0x01U; // Done Flag bool done = (data[3U] & 0x01U) == 0x01U; // Done Flag
if (!done) if (!done)
m_complete = true; m_complete = true;
else else
@ -75,16 +75,16 @@ bool KMMFrame::decodeHeader(const uint8_t* data, bool outbound)
return true; return true;
} }
/* Internal helper to encode a SNDCP header. */ /* Internal helper to encode a KMM header. */
void KMMFrame::encodeHeader(uint8_t* data, bool outbound) void KMMFrame::encodeHeader(uint8_t* data)
{ {
assert(data != nullptr); assert(data != nullptr);
data[0U] = m_messageId; // Message ID data[0U] = m_messageId; // Message ID
__SET_UINT16B(m_messageLength, data, 2U); // Message Length __SET_UINT16B(m_messageLength, data, 1U); // Message Length
data[2U] = ((m_respKind & 0x03U) << 6U) + // Response Kind data[3U] = ((m_respKind & 0x03U) << 6U) + // Response Kind
((m_mfMessageNumber & 0x03U) << 4U) + // Message Number ((m_mfMessageNumber & 0x03U) << 4U) + // Message Number
((m_mfMac & 0x03U) << 2U) + // MAC ((m_mfMac & 0x03U) << 2U) + // MAC
((!m_complete) ? 0x01U : 0x00U); // Done Flag ((!m_complete) ? 0x01U : 0x00U); // Done Flag

@ -121,16 +121,14 @@ namespace p25
/** /**
* @brief Internal helper to decode a KMM header. * @brief Internal helper to decode a KMM header.
* @param data Buffer containing KMM packet data to decode. * @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. * @returns bool True, if decoded, otherwise false.
*/ */
bool decodeHeader(const uint8_t* data, bool outbound = false); bool decodeHeader(const uint8_t* data);
/** /**
* @brief Internal helper to encode a KMM header. * @brief Internal helper to encode a KMM header.
* @param data Buffer to encode KMM packet data to. * @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); void encodeHeader(uint8_t* data);
__PROTECTED_COPY(KMMFrame); __PROTECTED_COPY(KMMFrame);
}; };

@ -0,0 +1,72 @@
// 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/KMMHello.h"
#include "Log.h"
using namespace p25;
using namespace p25::defines;
using namespace p25::kmm;
#include <cassert>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/* Initializes a new instance of the KMMHello class. */
KMMHello::KMMHello() : KMMFrame(),
m_flag(KMM_HelloFlag::IDENT_ONLY)
{
m_messageId = KMM_MessageType::HELLO;
m_respKind = KMM_ResponseKind::DELAYED;
}
/* Finalizes a instance of the KMMHello class. */
KMMHello::~KMMHello() = default;
/* Decode a KMM modify key. */
bool KMMHello::decode(const uint8_t* data)
{
assert(data != nullptr);
KMMFrame::decodeHeader(data);
m_flag = data[10U]; // Hello Flag
return true;
}
/* Encode a KMM modify key. */
void KMMHello::encode(uint8_t* data)
{
assert(data != nullptr);
m_messageLength = KMM_HELLO_LENGTH;
KMMFrame::encodeHeader(data);
data[10U] = m_flag; // Hello Flag
}
// ---------------------------------------------------------------------------
// Protected Class Members
// ---------------------------------------------------------------------------
/* Internal helper to copy the the class. */
void KMMHello::copy(const KMMHello& data)
{
m_flag = data.m_flag;
}

@ -0,0 +1,82 @@
// 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 KMMHello.h
* @ingroup p25_kmm
* @file KMMHello.cpp
* @ingroup p25_kmm
*/
#if !defined(__P25_KMM__KMM_HELLO_H__)
#define __P25_KMM__KMM_HELLO_H__
#include "common/Defines.h"
#include "common/p25/kmm/KMMFrame.h"
#include "common/p25/kmm/KeysetItem.h"
#include "common/Utils.h"
#include <string>
#include <vector>
namespace p25
{
namespace kmm
{
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
/**
* @addtogroup p25_kmm
* @{
*/
const uint32_t KMM_HELLO_LENGTH = KMM_FRAME_LENGTH + 1U;
/** @} */
// ---------------------------------------------------------------------------
// Class Declaration
// ---------------------------------------------------------------------------
class HOST_SW_API KMMHello : public KMMFrame {
public:
/**
* @brief Initializes a new instance of the KMMHello class.
*/
KMMHello();
/**
* @brief Finalizes a instance of the KMMHello class.
*/
~KMMHello();
/**
* @brief Decode a KMM hello.
* @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 hello.
* @param[out] data Buffer to encode KMM frame data to.
*/
void encode(uint8_t* data) override;
public:
/**
* @brief
*/
__PROPERTY(uint8_t, flag, Flag);
__COPY(KMMHello);
};
} // namespace kmm
} // namespace p25
#endif // __P25_KMM__KMM_HELLO_H__

@ -0,0 +1,72 @@
// 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/KMMInventoryCommand.h"
#include "Log.h"
using namespace p25;
using namespace p25::defines;
using namespace p25::kmm;
#include <cassert>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/* Initializes a new instance of the KMMInventoryCommand class. */
KMMInventoryCommand::KMMInventoryCommand() : KMMFrame(),
m_inventoryType(KMM_InventoryType::NULL_INVENTORY)
{
m_messageId = KMM_MessageType::INVENTORY_CMD;
m_respKind = KMM_ResponseKind::IMMEDIATE;
}
/* Finalizes a instance of the KMMInventoryCommand class. */
KMMInventoryCommand::~KMMInventoryCommand() = default;
/* Decode a KMM modify key. */
bool KMMInventoryCommand::decode(const uint8_t* data)
{
assert(data != nullptr);
KMMFrame::decodeHeader(data);
m_inventoryType = data[10U]; // Inventory Type
return true;
}
/* Encode a KMM modify key. */
void KMMInventoryCommand::encode(uint8_t* data)
{
assert(data != nullptr);
m_messageLength = KMM_INVENTORY_CMD_LENGTH;
KMMFrame::encodeHeader(data);
data[10U] = m_inventoryType; // Inventory Type
}
// ---------------------------------------------------------------------------
// Protected Class Members
// ---------------------------------------------------------------------------
/* Internal helper to copy the the class. */
void KMMInventoryCommand::copy(const KMMInventoryCommand& data)
{
m_inventoryType = data.m_inventoryType;
}

@ -0,0 +1,82 @@
// 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 KMMInventoryCommand.h
* @ingroup p25_kmm
* @file KMMInventoryCommand.cpp
* @ingroup p25_kmm
*/
#if !defined(__P25_KMM__KMM_INVENTORY_COMMAND_H__)
#define __P25_KMM__KMM_INVENTORY_COMMAND_H__
#include "common/Defines.h"
#include "common/p25/kmm/KMMFrame.h"
#include "common/p25/kmm/KeysetItem.h"
#include "common/Utils.h"
#include <string>
#include <vector>
namespace p25
{
namespace kmm
{
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
/**
* @addtogroup p25_kmm
* @{
*/
const uint32_t KMM_INVENTORY_CMD_LENGTH = KMM_FRAME_LENGTH + 1U;
/** @} */
// ---------------------------------------------------------------------------
// Class Declaration
// ---------------------------------------------------------------------------
class HOST_SW_API KMMInventoryCommand : public KMMFrame {
public:
/**
* @brief Initializes a new instance of the KMMInventoryCommand class.
*/
KMMInventoryCommand();
/**
* @brief Finalizes a instance of the KMMInventoryCommand class.
*/
~KMMInventoryCommand();
/**
* @brief Decode a KMM inventory command.
* @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 command.
* @param[out] data Buffer to encode KMM frame data to.
*/
void encode(uint8_t* data) override;
public:
/**
* @brief
*/
__PROPERTY(uint8_t, inventoryType, InventoryType);
__COPY(KMMInventoryCommand);
};
} // namespace kmm
} // namespace p25
#endif // __P25_KMM__KMM_INVENTORY_COMMAND_H__

@ -32,6 +32,8 @@ KMMModifyKey::KMMModifyKey() : KMMFrame(),
m_miSet(false), m_miSet(false),
m_mi(nullptr) m_mi(nullptr)
{ {
m_messageId = KMM_MessageType::MODIFY_KEY_CMD;
m_mi = new uint8_t[MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
::memset(m_mi, 0x00U, MI_LENGTH_BYTES); ::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
} }
@ -46,7 +48,7 @@ KMMModifyKey::~KMMModifyKey()
} }
} }
/* Gets the byte length of this KMMFrame. */ /* Gets the byte length of this KMMModifyKey. */
uint32_t KMMModifyKey::length() const uint32_t KMMModifyKey::length() const
{ {
@ -64,39 +66,43 @@ bool KMMModifyKey::decode(const uint8_t* data)
{ {
assert(data != nullptr); assert(data != nullptr);
KMMFrame::decodeHeader(data, false); KMMFrame::decodeHeader(data);
m_decryptInfoFmt = data[10U]; // Decryption Instruction Format m_decryptInfoFmt = data[10U]; // Decryption Instruction Format
m_algId = data[11U]; // Algorithm ID m_algId = data[11U]; // Algorithm ID
m_kId = data[12U]; // Key ID m_kId = __GET_UINT16B(data, 12U); // Key ID
uint16_t offset = 0U; uint16_t offset = 0U;
if (m_decryptInfoFmt == KMM_DECRYPT_INSTRUCT_MI) { if (m_decryptInfoFmt == KMM_DECRYPT_INSTRUCT_MI) {
::memset(m_mi, 0x00U, MI_LENGTH_BYTES); ::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
::memcpy(m_mi, data + 13U, MI_LENGTH_BYTES); ::memcpy(m_mi, data + 14U, MI_LENGTH_BYTES);
offset += 9U; offset += 9U;
} }
m_keysetItem.keysetId(data[13U + offset]); m_keysetItem.keysetId(data[14U + offset]);
m_keysetItem.algId(data[14U + offset]); m_keysetItem.algId(data[15U + offset]);
m_keysetItem.keyLength(data[15U + offset]); m_keysetItem.keyLength(data[16U + offset]);
uint8_t keyCount = data[16U + offset]; uint8_t keyCount = data[17U + offset];
for (uint8_t i = 0U; i < keyCount; i++) { for (uint8_t i = 0U; i < keyCount; i++) {
KeyItem* key = new KeyItem(); KeyItem key = KeyItem();
UInt8Array __keyPayload = std::make_unique<uint8_t[]>(m_keysetItem.keyLength()); UInt8Array __keyPayload = std::make_unique<uint8_t[]>(m_keysetItem.keyLength());
uint8_t* keyPayload = __keyPayload.get(); uint8_t* keyPayload = __keyPayload.get();
uint8_t keyFormat = data[17U + offset]; uint8_t keyFormat = data[18U + offset];
uint8_t keyNameLen = keyFormat & 0x1FU; uint8_t keyNameLen = keyFormat & 0x1FU;
key->keyFormat(keyFormat & 0xE0U); key.keyFormat(keyFormat & 0xE0U);
key->sln(data[18U + offset]);
key->kId(data[19U + offset]); uint16_t sln = __GET_UINT16B(data, 19U + offset);
key.sln(sln);
uint16_t kId = __GET_UINT16B(data, 21U + offset);
key.kId(kId);
::memcpy(keyPayload, data + (20U + offset), m_keysetItem.keyLength()); ::memcpy(keyPayload, data + (23U + offset), m_keysetItem.keyLength());
key->setKey(keyPayload, m_keysetItem.keyLength()); key.setKey(keyPayload, m_keysetItem.keyLength());
m_keysetItem.push_back(key); m_keysetItem.push_back(key);
@ -111,8 +117,9 @@ bool KMMModifyKey::decode(const uint8_t* data)
void KMMModifyKey::encode(uint8_t* data) void KMMModifyKey::encode(uint8_t* data)
{ {
assert(data != nullptr); assert(data != nullptr);
m_messageLength = length();
KMMFrame::encodeHeader(data, true); KMMFrame::encodeHeader(data);
if (!m_miSet && m_decryptInfoFmt == KMM_DECRYPT_INSTRUCT_MI) { if (!m_miSet && m_decryptInfoFmt == KMM_DECRYPT_INSTRUCT_MI) {
m_decryptInfoFmt = KMM_DECRYPT_INSTRUCT_NONE; m_decryptInfoFmt = KMM_DECRYPT_INSTRUCT_NONE;
@ -120,31 +127,31 @@ void KMMModifyKey::encode(uint8_t* data)
data[10U] = m_decryptInfoFmt; // Decryption Instruction Format data[10U] = m_decryptInfoFmt; // Decryption Instruction Format
data[11U] = m_algId; // Algorithm ID data[11U] = m_algId; // Algorithm ID
data[12U] = m_kId; // Key ID __SET_UINT16B(m_kId, data, 12U); // Key ID
uint16_t offset = 0U; uint16_t offset = 0U;
if (m_decryptInfoFmt == KMM_DECRYPT_INSTRUCT_MI) { if (m_decryptInfoFmt == KMM_DECRYPT_INSTRUCT_MI) {
::memcpy(data + 13U, m_mi, MI_LENGTH_BYTES); ::memcpy(data + 14U, m_mi, MI_LENGTH_BYTES);
offset += 9U; offset += 9U;
} }
data[13U + offset] = m_keysetItem.keysetId(); data[14U + offset] = m_keysetItem.keysetId();
data[14U + offset] = m_keysetItem.algId(); data[15U + offset] = m_keysetItem.algId();
data[15U + offset] = m_keysetItem.keyLength(); data[16U + offset] = m_keysetItem.keyLength();
uint8_t keyCount = m_keysetItem.keys().size(); uint8_t keyCount = m_keysetItem.keys().size();
data[16U + offset] = keyCount; data[17U + offset] = keyCount;
for (auto key : m_keysetItem.keys()) { for (auto key : m_keysetItem.keys()) {
uint8_t keyNameLen = key->keyFormat() & 0x1FU; uint8_t keyNameLen = key.keyFormat() & 0x1FU;
data[17U + offset] = key->keyFormat(); data[18U + offset] = key.keyFormat();
data[18U + offset] = key->sln(); __SET_UINT16B(key.sln(), data, 19U + offset);
data[19U + offset] = key->kId(); __SET_UINT16B(key.kId(), data, 21U + offset);
UInt8Array __keyPayload = std::make_unique<uint8_t[]>(m_keysetItem.keyLength()); UInt8Array __keyPayload = std::make_unique<uint8_t[]>(m_keysetItem.keyLength());
uint8_t* keyPayload = __keyPayload.get(); uint8_t* keyPayload = __keyPayload.get();
key->getKey(keyPayload); key.getKey(keyPayload);
::memcpy(data + (20U + offset), keyPayload, m_keysetItem.keyLength()); ::memcpy(data + (23U + offset), keyPayload, m_keysetItem.keyLength());
offset += 5U + keyNameLen + m_keysetItem.keyLength(); offset += 5U + keyNameLen + m_keysetItem.keyLength();
} }

@ -37,7 +37,7 @@ namespace p25
* @{ * @{
*/ */
const uint32_t KMM_MODIFY_KEY_LENGTH = KMM_FRAME_LENGTH + 4U; const uint32_t KMM_MODIFY_KEY_LENGTH = KMM_FRAME_LENGTH + 8U;
/** @} */ /** @} */
@ -63,16 +63,16 @@ namespace p25
uint32_t length() const override; uint32_t length() const override;
/** /**
* @brief Decode a KMM modify key packet. * @brief Decode a KMM modify key.
* @param[in] data Buffer containing KMM packet data to decode. * @param[in] data Buffer containing KMM frame data to decode.
* @returns bool True, if decoded, otherwise false. * @returns bool True, if decoded, otherwise false.
*/ */
bool decode(const uint8_t* data); bool decode(const uint8_t* data) override;
/** /**
* @brief Encode a KMM modify key packet. * @brief Encode a KMM modify key.
* @param[out] data Buffer to encode KMM packet data to. * @param[out] data Buffer to encode KMM frame data to.
*/ */
void encode(uint8_t* data); void encode(uint8_t* data) override;
/** @name Encryption data */ /** @name Encryption data */
/** /**

@ -24,6 +24,19 @@ namespace p25
{ {
namespace kmm namespace kmm
{ {
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
/**
* @addtogroup p25_kmm
* @{
*/
const uint8_t MAX_ENC_KEY_LENGTH_BYTES = 32U;
/** @} */
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Class Declaration // Class Declaration
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -42,19 +55,9 @@ namespace p25
m_sln(0U), m_sln(0U),
m_kId(0U), m_kId(0U),
m_keyLength(0U), m_keyLength(0U),
m_keyMaterial(nullptr) m_keyMaterial()
{ {
/* stub */ ::memset(m_keyMaterial, 0x00U, MAX_ENC_KEY_LENGTH_BYTES);
}
/**
* @brief Finalizes a instance of the KeyItem class.
*/
~KeyItem()
{
if (m_keyMaterial != nullptr) {
delete[] m_keyMaterial;
m_keyMaterial = nullptr;
}
} }
/** /**
@ -69,11 +72,8 @@ namespace p25
m_kId = data.m_kId; m_kId = data.m_kId;
if (data.m_keyLength > 0U) { if (data.m_keyLength > 0U) {
if (m_keyMaterial != nullptr) { ::memset(m_keyMaterial, 0x00U, MAX_ENC_KEY_LENGTH_BYTES);
delete[] m_keyMaterial;
}
m_keyMaterial = new uint8_t[data.m_keyLength];
m_keyLength = data.m_keyLength; m_keyLength = data.m_keyLength;
::memcpy(m_keyMaterial, data.m_keyMaterial, data.m_keyLength); ::memcpy(m_keyMaterial, data.m_keyMaterial, data.m_keyLength);
} }
@ -91,6 +91,10 @@ namespace p25
{ {
assert(key != nullptr); assert(key != nullptr);
m_keyLength = keyLength; m_keyLength = keyLength;
if (m_keyMaterial == nullptr) {
::memset(m_keyMaterial, 0x00U, MAX_ENC_KEY_LENGTH_BYTES);
::memset(m_keyMaterial, 0x00U, m_keyLength);
}
::memcpy(m_keyMaterial, key, keyLength); ::memcpy(m_keyMaterial, key, keyLength);
} }
@ -120,7 +124,7 @@ namespace p25
private: private:
uint32_t m_keyLength; uint32_t m_keyLength;
uint8_t* m_keyMaterial; uint8_t m_keyMaterial[MAX_ENC_KEY_LENGTH_BYTES];
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -144,15 +148,6 @@ namespace p25
{ {
/* stub */ /* 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. * @brief Equals operator. Copies this KeysetItem to another KeysetItem.
@ -165,13 +160,9 @@ namespace p25
m_algId = data.m_algId; m_algId = data.m_algId;
m_keyLength = data.m_keyLength; m_keyLength = data.m_keyLength;
for (auto key : m_keys) {
delete key;
}
m_keys.clear(); m_keys.clear();
for (auto key : data.m_keys) { for (auto key : data.m_keys) {
KeyItem* copy = key; KeyItem copy = key;
m_keys.push_back(copy); m_keys.push_back(copy);
} }
} }
@ -198,7 +189,7 @@ namespace p25
* @brief Add a key to the key list. * @brief Add a key to the key list.
* @param key * @param key
*/ */
void push_back(KeyItem* key) void push_back(KeyItem key)
{ {
m_keys.push_back(key); m_keys.push_back(key);
} }
@ -220,7 +211,7 @@ namespace p25
/** /**
* @brief List of keys. * @brief List of keys.
*/ */
__PROPERTY_PLAIN(std::vector<KeyItem*>, keys); __PROPERTY_PLAIN(std::vector<KeyItem>, keys);
}; };
} // namespace kmm } // namespace kmm
} // namespace p25 } // namespace p25

@ -46,12 +46,12 @@ namespace p25
* @param[in] data Buffer containing SNDCP packet data to decode. * @param[in] data Buffer containing SNDCP packet data to decode.
* @returns bool True, if decoded, otherwise false. * @returns bool True, if decoded, otherwise false.
*/ */
bool decode(const uint8_t* data); bool decode(const uint8_t* data) override;
/** /**
* @brief Encode a SNDCP context activation response. * @brief Encode a SNDCP context activation response.
* @param[out] data Buffer to encode SNDCP packet data to. * @param[out] data Buffer to encode SNDCP packet data to.
*/ */
void encode(uint8_t* data); void encode(uint8_t* data) override;
public: public:
/** /**

@ -46,12 +46,12 @@ namespace p25
* @param[in] data Buffer containing SNDCP packet data to decode. * @param[in] data Buffer containing SNDCP packet data to decode.
* @returns bool True, if decoded, otherwise false. * @returns bool True, if decoded, otherwise false.
*/ */
bool decode(const uint8_t* data); bool decode(const uint8_t* data) override;
/** /**
* @brief Encode a SNDCP context activation reject packet. * @brief Encode a SNDCP context activation reject packet.
* @param[out] data Buffer to encode SNDCP packet data to. * @param[out] data Buffer to encode SNDCP packet data to.
*/ */
void encode(uint8_t* data); void encode(uint8_t* data) override;
public: public:
/** /**

@ -46,12 +46,12 @@ namespace p25
* @param[in] data Buffer containing SNDCP packet data to decode. * @param[in] data Buffer containing SNDCP packet data to decode.
* @returns bool True, if decoded, otherwise false. * @returns bool True, if decoded, otherwise false.
*/ */
bool decode(const uint8_t* data); bool decode(const uint8_t* data) override;
/** /**
* @brief Encode a SNDCP context activation request. * @brief Encode a SNDCP context activation request.
* @param[out] data Buffer to encode SNDCP packet data to. * @param[out] data Buffer to encode SNDCP packet data to.
*/ */
void encode(uint8_t* data); void encode(uint8_t* data) override;
public: public:
/** /**

@ -46,12 +46,12 @@ namespace p25
* @param[in] data Buffer containing SNDCP packet data to decode. * @param[in] data Buffer containing SNDCP packet data to decode.
* @returns bool True, if decoded, otherwise false. * @returns bool True, if decoded, otherwise false.
*/ */
bool decode(const uint8_t* data); bool decode(const uint8_t* data) override;
/** /**
* @brief Encode a SNDCP context deactivation packet. * @brief Encode a SNDCP context deactivation packet.
* @param[out] data Buffer to encode SNDCP packet data to. * @param[out] data Buffer to encode SNDCP packet data to.
*/ */
void encode(uint8_t* data); void encode(uint8_t* data) override;
public: public:
/** /**

@ -573,7 +573,7 @@ bool HostFNE::createMasterNetwork()
parrotDelay, parrotGrantDemand, m_allowActivityTransfer, m_allowDiagnosticTransfer, m_pingTime, m_updateLookupTime); parrotDelay, parrotGrantDemand, m_allowActivityTransfer, m_allowDiagnosticTransfer, m_pingTime, m_updateLookupTime);
m_network->setOptions(masterConf, true); m_network->setOptions(masterConf, true);
m_network->setLookups(m_ridLookup, m_tidLookup, m_peerListLookup); m_network->setLookups(m_ridLookup, m_tidLookup, m_peerListLookup, m_cryptoLookup);
if (m_RESTAPI != nullptr) { if (m_RESTAPI != nullptr) {
m_RESTAPI->setNetwork(m_network); m_RESTAPI->setNetwork(m_network);

@ -10,6 +10,7 @@
#include "fne/Defines.h" #include "fne/Defines.h"
#include "common/edac/SHA256.h" #include "common/edac/SHA256.h"
#include "common/network/json/json.h" #include "common/network/json/json.h"
#include "common/p25/kmm/KMMFactory.h"
#include "common/zlib/zlib.h" #include "common/zlib/zlib.h"
#include "common/Log.h" #include "common/Log.h"
#include "common/Utils.h" #include "common/Utils.h"
@ -209,13 +210,15 @@ void FNENetwork::setOptions(yaml::Node& conf, bool printOptions)
} }
} }
/* Sets the instances of the Radio ID, Talkgroup Rules, and Peer List lookup tables. */ /* Sets the instances of the Radio ID, Talkgroup ID Peer List, and Crypto lookup tables. */
void FNENetwork::setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup, lookups::PeerListLookup* peerListLookup) void FNENetwork::setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup, lookups::PeerListLookup* peerListLookup,
CryptoContainer* cryptoLookup)
{ {
m_ridLookup = ridLookup; m_ridLookup = ridLookup;
m_tidLookup = tidLookup; m_tidLookup = tidLookup;
m_peerListLookup = peerListLookup; m_peerListLookup = peerListLookup;
m_cryptoLookup = cryptoLookup;
} }
/* Sets endpoint preshared encryption key. */ /* Sets endpoint preshared encryption key. */
@ -1061,13 +1064,88 @@ void* FNENetwork::threadedNetworkRx(void* arg)
} }
} }
break; break;
case NET_FUNC::INCALL_CTRL:
case NET_FUNC::INCALL_CTRL: // In-Call Control
{ {
// FNEs are god-like entities, and we don't recognize the authority of foreign FNEs telling us what // FNEs are god-like entities, and we don't recognize the authority of foreign FNEs telling us what
// to do... // to do...
} }
break; break;
case NET_FUNC::KEY_REQ: // Enc. Key Request
{
using namespace p25::defines;
using namespace p25::kmm;
if (peerId > 0 && (network->m_peers.find(peerId) != network->m_peers.end())) {
FNEPeerConnection* connection = network->m_peers[peerId];
if (connection != nullptr) {
std::string ip = udp::Socket::address(req->address);
// validate peer (simple validation really)
if (connection->connected() && connection->address() == ip) {
std::unique_ptr<KMMFrame> frame = KMMFactory::create(req->buffer + 11U);
if (frame == nullptr) {
LogWarning(LOG_NET, "PEER %u (%s), undecodable KMM frame from peer", peerId, connection->identity().c_str());
break;
}
switch (frame->getMessageId()) {
case P25DEF::KMM_MessageType::MODIFY_KEY_CMD:
{
KMMModifyKey* modifyKey = static_cast<KMMModifyKey*>(frame.get());
if (modifyKey->getAlgId() > 0U && modifyKey->getKId() > 0U) {
LogMessage(LOG_NET, "PEER %u (%s) requested enc. key, algId = $%02X, kID = $%04X", peerId, connection->identity().c_str(),
modifyKey->getAlgId(), modifyKey->getKId());
::KeyItem keyItem = network->m_cryptoLookup->find(modifyKey->getKId());
if (!keyItem.isInvalid()) {
uint8_t buffer[DATA_PACKET_LENGTH];
::memset(buffer, 0x00U, DATA_PACKET_LENGTH);
KMMModifyKey modifyKeyRsp = KMMModifyKey();
modifyKeyRsp.setDecryptInfoFmt(KMM_DECRYPT_INSTRUCT_NONE);
modifyKeyRsp.setAlgId(modifyKey->getAlgId());
modifyKeyRsp.setKId(0U);
KeysetItem ks = KeysetItem();
ks.keysetId(1U);
ks.algId(modifyKey->getAlgId());
ks.keyLength(P25DEF::MAX_ENC_KEY_LENGTH_BYTES); // bryanb: this --- will be problematic and should be properly calculated
p25::kmm::KeyItem ki = p25::kmm::KeyItem();
ki.keyFormat(KEY_FORMAT_TEK);
ki.kId((uint16_t)keyItem.kId());
ki.sln((uint16_t)keyItem.sln());
uint8_t key[P25DEF::MAX_ENC_KEY_LENGTH_BYTES];
::memset(key, 0x00U, P25DEF::MAX_ENC_KEY_LENGTH_BYTES);
keyItem.getKey(key);
ki.setKey(key, P25DEF::MAX_ENC_KEY_LENGTH_BYTES); // bryanb: this --- will be problematic and should be properly calculated
ks.push_back(ki);
modifyKeyRsp.setKeysetItem(ks);
modifyKeyRsp.encode(buffer + 11U);
network->writePeer(peerId, { NET_FUNC::KEY_RSP, NET_SUBFUNC::NOP }, buffer, modifyKeyRsp.length() + 11U,
RTP_END_OF_CALL_SEQ, network->createStreamId(), false, false, true);
}
}
}
break;
default:
break;
}
}
else {
network->writePeerNAK(peerId, streamId, TAG_REPEATER_KEY, NET_CONN_NAK_FNE_UNAUTHORIZED);
}
}
}
}
break;
case NET_FUNC::TRANSFER: case NET_FUNC::TRANSFER:
{ {
// are activity/diagnostic transfers occurring from the alternate port? // are activity/diagnostic transfers occurring from the alternate port?

@ -32,6 +32,7 @@
#include "common/lookups/TalkgroupRulesLookup.h" #include "common/lookups/TalkgroupRulesLookup.h"
#include "common/lookups/PeerListLookup.h" #include "common/lookups/PeerListLookup.h"
#include "fne/network/influxdb/InfluxDB.h" #include "fne/network/influxdb/InfluxDB.h"
#include "fne/CryptoContainer.h"
#include "host/network/Network.h" #include "host/network/Network.h"
#include <string> #include <string>
@ -456,12 +457,14 @@ namespace network
callhandler::TagNXDNData* nxdnTrafficHandler() const { return m_tagNXDN; } callhandler::TagNXDNData* nxdnTrafficHandler() const { return m_tagNXDN; }
/** /**
* @brief Sets the instances of the Radio ID, Talkgroup ID and Peer List lookup tables. * @brief Sets the instances of the Radio ID, Talkgroup ID Peer List, and Crypto lookup tables.
* @param ridLookup Radio ID Lookup Table Instance * @param ridLookup Radio ID Lookup Table Instance
* @param tidLookup Talkgroup Rules Lookup Table Instance * @param tidLookup Talkgroup Rules Lookup Table Instance
* @param peerListLookup Peer List Lookup Table Instance * @param peerListLookup Peer List Lookup Table Instance
* @param cryptoLookup Crypto Container Lookup Table Instance
*/ */
void setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup, lookups::PeerListLookup* peerListLookup); void setLookups(lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup, lookups::PeerListLookup* peerListLookup,
CryptoContainer* cryptoLookup);
/** /**
* @brief Sets endpoint preshared encryption key. * @brief Sets endpoint preshared encryption key.
* @param presharedKey Encryption preshared key for networking. * @param presharedKey Encryption preshared key for networking.
@ -537,6 +540,8 @@ namespace network
lookups::TalkgroupRulesLookup* m_tidLookup; lookups::TalkgroupRulesLookup* m_tidLookup;
lookups::PeerListLookup* m_peerListLookup; lookups::PeerListLookup* m_peerListLookup;
CryptoContainer* m_cryptoLookup;
NET_CONN_STATUS m_status; NET_CONN_STATUS m_status;
static std::mutex m_peerMutex; static std::mutex m_peerMutex;

@ -13,6 +13,7 @@
#include "common/network/RTPHeader.h" #include "common/network/RTPHeader.h"
#include "common/network/RTPFNEHeader.h" #include "common/network/RTPFNEHeader.h"
#include "common/network/json/json.h" #include "common/network/json/json.h"
#include "common/p25/kmm/KMMFactory.h"
#include "common/Log.h" #include "common/Log.h"
#include "common/Utils.h" #include "common/Utils.h"
#include "network/Network.h" #include "network/Network.h"
@ -74,7 +75,8 @@ Network::Network(const std::string& address, uint16_t port, uint16_t localPort,
m_promiscuousPeer(false), m_promiscuousPeer(false),
m_dmrInCallCallback(nullptr), m_dmrInCallCallback(nullptr),
m_p25InCallCallback(nullptr), m_p25InCallCallback(nullptr),
m_nxdnInCallCallback(nullptr) m_nxdnInCallCallback(nullptr),
m_keyRespCallback(nullptr)
{ {
assert(!address.empty()); assert(!address.empty());
assert(port > 0U); assert(port > 0U);
@ -592,6 +594,44 @@ void Network::clock(uint32_t ms)
} }
break; break;
case NET_FUNC::KEY_RSP: // Enc. Key Response
{
if (m_enabled) {
using namespace p25::kmm;
std::unique_ptr<KMMFrame> frame = KMMFactory::create(buffer.get() + 11U);
if (frame == nullptr) {
LogWarning(LOG_NET, "PEER %u, undecodable KMM frame from master", m_peerId);
break;
}
switch (frame->getMessageId()) {
case P25DEF::KMM_MessageType::MODIFY_KEY_CMD:
{
KMMModifyKey* modifyKey = static_cast<KMMModifyKey*>(frame.get());
if (modifyKey->getAlgId() > 0U) {
KeysetItem ks = modifyKey->getKeysetItem();
if (ks.keys().size() > 0U) {
// fetch first key (a master response should never really send back more then one key)
KeyItem ki = ks.keys()[0];
LogMessage(LOG_NET, "PEER %u, master reported enc. key, algId = $%02X, kID = $%04X", m_peerId,
ks.algId(), ki.kId());
if (m_keyRespCallback != nullptr) {
m_keyRespCallback(ki, ks.algId(), ks.keyLength());
}
}
}
}
break;
default:
break;
}
}
}
break;
case NET_FUNC::NAK: // Master Negative Ack case NET_FUNC::NAK: // Master Negative Ack
{ {
// DVM 3.6 adds support to respond with a NAK reason, as such we just check if the NAK response is greater // DVM 3.6 adds support to respond with a NAK reason, as such we just check if the NAK response is greater

@ -25,6 +25,7 @@
#include "common/network/BaseNetwork.h" #include "common/network/BaseNetwork.h"
#include "common/lookups/RadioIdLookup.h" #include "common/lookups/RadioIdLookup.h"
#include "common/lookups/TalkgroupRulesLookup.h" #include "common/lookups/TalkgroupRulesLookup.h"
#include "common/p25/kmm/KeysetItem.h"
#include <string> #include <string>
#include <cstdint> #include <cstdint>
@ -165,6 +166,12 @@ namespace network
*/ */
void setNXDNICCCallback(std::function<void(NET_ICC::ENUM, uint32_t)>&& callback) { m_nxdnInCallCallback = callback; } void setNXDNICCCallback(std::function<void(NET_ICC::ENUM, uint32_t)>&& callback) { m_nxdnInCallCallback = callback; }
/**
* @brief Helper to set the enc. key response callback.
* @param callback
*/
void setKeyResponseCallback(std::function<void(p25::kmm::KeyItem, uint8_t, uint8_t)>&& callback) { m_keyRespCallback = callback; }
public: public:
/** /**
* @brief Last received RTP sequence number. * @brief Last received RTP sequence number.
@ -230,6 +237,8 @@ namespace network
std::function<void(NET_ICC::ENUM command, uint32_t dstId)> m_p25InCallCallback; std::function<void(NET_ICC::ENUM command, uint32_t dstId)> m_p25InCallCallback;
std::function<void(NET_ICC::ENUM command, uint32_t dstId)> m_nxdnInCallCallback; std::function<void(NET_ICC::ENUM command, uint32_t dstId)> m_nxdnInCallCallback;
std::function<void(p25::kmm::KeyItem ki, uint8_t algId, uint8_t keyLength)> m_keyRespCallback;
/** /**
* @brief User overrideable handler that allows user code to process network packets not handled by this class. * @brief User overrideable handler that allows user code to process network packets not handled by this class.
* @param peerId Peer ID. * @param peerId Peer ID.

Loading…
Cancel
Save

Powered by TurnKey Linux.