You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
4.7 KiB
111 lines
4.7 KiB
// 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) 2017-2026 Bryan Biedenkapp, N2PLL
|
|
*
|
|
*/
|
|
#include "Defines.h"
|
|
#include "common/p25/kmm/KMMFactory.h"
|
|
#include "common/Log.h"
|
|
#include "network/Network.h"
|
|
|
|
using namespace network;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Public Class Members
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/* Handles NET_FUNC::KEY_LLA_RSP packets. */
|
|
|
|
bool Network::PacketHandler::llaKeyResponse(Network* network, uint32_t peerId, uint32_t streamId, uint64_t now,
|
|
const frame::RTPFNEHeader& fneHeader, const frame::RTPHeader& rtpHeader, const uint8_t* buffer, int length)
|
|
{
|
|
(void)peerId;
|
|
(void)streamId;
|
|
(void)now;
|
|
(void)fneHeader;
|
|
(void)rtpHeader;
|
|
(void)length;
|
|
|
|
if (network->m_enabled) {
|
|
using namespace p25::kmm;
|
|
|
|
std::unique_ptr<KMMFrame> frame = KMMFactory::create(buffer + 11U);
|
|
if (frame == nullptr) {
|
|
LogWarning(LOG_NET, "PEER %u, undecodable KMM frame from master", network->m_peerId);
|
|
return false;
|
|
}
|
|
|
|
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];
|
|
LogInfoEx(LOG_NET, "PEER %u, master reported LLA enc. key, algId = $%02X, kID = $%04X", network->m_peerId,
|
|
ks.algId(), ki.kId());
|
|
|
|
if (!network->m_passKeysWithNoPresharedKey && (modifyKey->getDecryptInfoFmt() == KMM_DECRYPT_PEER_ENC)) {
|
|
// if the to decrypt the key with a preshared key, do that now
|
|
if (network->m_kmfPresharedKey != nullptr) {
|
|
uint8_t encryptedKey[P25DEF::MAX_ENC_KEY_LENGTH_BYTES];
|
|
::memset(encryptedKey, 0x00U, P25DEF::MAX_ENC_KEY_LENGTH_BYTES);
|
|
ki.getKey(encryptedKey);
|
|
|
|
uint8_t* key = nullptr;
|
|
crypto::AES aes = crypto::AES(crypto::AESKeyLength::AES_256);
|
|
key = aes.decryptECB(encryptedKey, P25DEF::MAX_ENC_KEY_LENGTH_BYTES, network->m_kmfPresharedKey);
|
|
|
|
uint32_t keyLength = P25DEF::MAX_ENC_KEY_LENGTH_BYTES;
|
|
switch (ks.algId()) {
|
|
case P25DEF::ALGO_AES_128:
|
|
keyLength = P25DEF::AES_128_ENC_KEY_LENGTH_BYTES;
|
|
break;
|
|
|
|
case P25DEF::ALGO_AES_256:
|
|
default:
|
|
LogWarning(LOG_NET, "PEER %u, unknown algorithm ID $%02X, unable to determine key length", network->m_peerId, ks.algId());
|
|
break;
|
|
}
|
|
|
|
if (network->m_debug)
|
|
Utils::dump(1U, "Network::clock(), Key", key, keyLength);
|
|
|
|
if (key != nullptr) {
|
|
ki.setKey(key, keyLength);
|
|
ks.keyLength(keyLength);
|
|
delete[] key;
|
|
}
|
|
}
|
|
else {
|
|
if (modifyKey->getDecryptInfoFmt() == KMM_DECRYPT_PEER_ENC) {
|
|
LogInfoEx(LOG_NET, "PEER %u, received encrypted LLA enc. key, but no preshared key available, algId = $%02X, kID = $%04X", network->m_peerId,
|
|
ks.algId(), ki.kId());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// fire off key response callback if we have one
|
|
if (network->m_llaKeyRespCallback != nullptr) {
|
|
network->m_llaKeyRespCallback(modifyKey->getDstLLId(), ki, ks.keyLength());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|