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.
181 lines
5.0 KiB
181 lines
5.0 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) 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 <cassert>
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// 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_messageId = KMM_MessageType::MODIFY_KEY_CMD;
|
|
|
|
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 KMMModifyKey. */
|
|
|
|
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);
|
|
|
|
m_decryptInfoFmt = data[10U]; // Decryption Instruction Format
|
|
m_algId = data[11U]; // Algorithm ID
|
|
m_kId = __GET_UINT16B(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 + 14U, MI_LENGTH_BYTES);
|
|
offset += 9U;
|
|
}
|
|
|
|
m_keysetItem.keysetId(data[14U + offset]);
|
|
m_keysetItem.algId(data[15U + offset]);
|
|
m_keysetItem.keyLength(data[16U + offset]);
|
|
|
|
uint8_t keyCount = data[17U + offset];
|
|
for (uint8_t i = 0U; i < keyCount; i++) {
|
|
KeyItem key = KeyItem();
|
|
|
|
UInt8Array __keyPayload = std::make_unique<uint8_t[]>(m_keysetItem.keyLength());
|
|
uint8_t* keyPayload = __keyPayload.get();
|
|
|
|
uint8_t keyFormat = data[18U + offset];
|
|
uint8_t keyNameLen = keyFormat & 0x1FU;
|
|
|
|
key.keyFormat(keyFormat & 0xE0U);
|
|
|
|
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 + (23U + 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);
|
|
m_messageLength = length();
|
|
|
|
KMMFrame::encodeHeader(data);
|
|
|
|
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
|
|
__SET_UINT16B(m_kId, data, 12U); // Key ID
|
|
|
|
uint16_t offset = 0U;
|
|
if (m_decryptInfoFmt == KMM_DECRYPT_INSTRUCT_MI) {
|
|
::memcpy(data + 14U, m_mi, MI_LENGTH_BYTES);
|
|
offset += 9U;
|
|
}
|
|
|
|
data[14U + offset] = m_keysetItem.keysetId();
|
|
data[15U + offset] = m_keysetItem.algId();
|
|
data[16U + offset] = m_keysetItem.keyLength();
|
|
|
|
uint8_t keyCount = m_keysetItem.keys().size();
|
|
data[17U + offset] = keyCount;
|
|
for (auto key : m_keysetItem.keys()) {
|
|
uint8_t keyNameLen = key.keyFormat() & 0x1FU;
|
|
data[18U + offset] = key.keyFormat();
|
|
__SET_UINT16B(key.sln(), data, 19U + offset);
|
|
__SET_UINT16B(key.kId(), data, 21U + offset);
|
|
|
|
UInt8Array __keyPayload = std::make_unique<uint8_t[]>(m_keysetItem.keyLength());
|
|
uint8_t* keyPayload = __keyPayload.get();
|
|
key.getKey(keyPayload);
|
|
|
|
::memcpy(data + (23U + 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)
|
|
{
|
|
KMMFrame::copy(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;
|
|
}
|