Skip to content

Commit

Permalink
Added limits to check encryption keys. Addresses #451.
Browse files Browse the repository at this point in the history
  • Loading branch information
hmatuschek committed Jul 16, 2024
1 parent 8d4bbc0 commit 4bceb26
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 4 deletions.
19 changes: 19 additions & 0 deletions lib/dm1701_limits.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "dm1701_limits.hh"
#include "dm1701_codeplug.hh"
#include "channel.hh"
#include "radioid.hh"
#include "contact.hh"
Expand Down Expand Up @@ -154,6 +155,24 @@ DM1701Limits::DM1701Limits(QObject *parent)
{ "revert", new RadioLimitObjRef(DMRChannel::staticMetaObject, true) }
} ) );

/* Check encryption keys. */
add("commercial", new RadioLimitItem {
{"encryptionKeys", new RadioLimitList {
{BasicEncryptionKey::staticMetaObject,
0, TyTCodeplug::EncryptionElement::Limit::basicKeys(),
new RadioLimitObject {
{"name", new RadioLimitIgnored()},
{"key", new RadioLimitStringRegEx("[0-9a-fA-F]{4}")}
}},
{AESEncryptionKey::staticMetaObject,
0, TyTCodeplug::EncryptionElement::Limit::advancedKeys(),
new RadioLimitObject {
{"name", new RadioLimitIgnored()},
{"key", new RadioLimitStringRegEx("[0-9a-fA-F]{32}")}
}} }
}
});

/* Ignore roaming zones. */
add("roaming", new RadioLimitList(
ConfigObject::staticMetaObject, -1, -1, new RadioLimitIgnored(RadioLimitIssue::Hint)
Expand Down
14 changes: 13 additions & 1 deletion lib/gd73_limits.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ GD73Limits::GD73Limits(QObject *parent)
})
) );

/* Ignore scan lists. */
/* Check scan lists. */
add("scanlists", new RadioLimitList(
ScanList::staticMetaObject, 1, GD73Codeplug::ScanListBankElement::Limit::memberCount(), new RadioLimitObject{
{ "name", new RadioLimitString(1, GD73Codeplug::ScanListElement::Limit::nameLength(), RadioLimitString::Unicode) },
Expand All @@ -140,6 +140,17 @@ GD73Limits::GD73Limits(QObject *parent)
{ "channels", new RadioLimitRefList(0, GD73Codeplug::ScanListElement::Limit::memberCount(), Channel::staticMetaObject) }
}));

/* Check encryption keys. */
add("commercial", new RadioLimitItem {
{"encryptionKeys", new RadioLimitList(
BasicEncryptionKey::staticMetaObject,
0, GD73Codeplug::EncryptionKeyBankElement::Limit::keys(),
new RadioLimitObject {
{"name", new RadioLimitIgnored()},
{"key", new RadioLimitStringRegEx("[0-9a-fA-F]{2,8}")}
})}
});

/* Ignore positioning systems. */
add("positioning", new RadioLimitList(
ConfigObject::staticMetaObject, -1, -1, new RadioLimitIgnored()) );
Expand All @@ -148,4 +159,5 @@ GD73Limits::GD73Limits(QObject *parent)
add("roaming",
new RadioLimitList(
ConfigObject::staticMetaObject, -1, -1, new RadioLimitIgnored()) );

}
12 changes: 12 additions & 0 deletions lib/gd77_limits.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "gd77_limits.hh"
#include "gd77_codeplug.hh"
#include "channel.hh"
#include "radioid.hh"
#include "contact.hh"
Expand Down Expand Up @@ -148,6 +149,17 @@ GD77Limits::GD77Limits(QObject *parent)
{ "channels", new RadioLimitRefList(0, 32, Channel::staticMetaObject) }
}));

/* Check encryption keys. */
add("commercial", new RadioLimitItem {
{"encryptionKeys", new RadioLimitList(
BasicEncryptionKey::staticMetaObject,
0, RadioddityCodeplug::EncryptionElement::Limit::basicEncryptionKeys(),
new RadioLimitObject {
{"name", new RadioLimitIgnored()},
{"key", new RadioLimitStringRegEx("[0-9a-fA-F]{8}")}
})}
});

/* Ignore positioning systems. */
add("positioning", new RadioLimitList(
ConfigObject::staticMetaObject, -1, -1, new RadioLimitIgnored()) );
Expand Down
19 changes: 19 additions & 0 deletions lib/md2017_limits.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "md2017_limits.hh"
#include "md2017_codeplug.hh"
#include "channel.hh"
#include "radioid.hh"
#include "contact.hh"
Expand Down Expand Up @@ -154,6 +155,24 @@ MD2017Limits::MD2017Limits(QObject *parent)
{ "revert", new RadioLimitObjRef(DMRChannel::staticMetaObject, true) }
} ) );

/* Check encryption keys. */
add("commercial", new RadioLimitItem {
{"encryptionKeys", new RadioLimitList {
{BasicEncryptionKey::staticMetaObject,
0, TyTCodeplug::EncryptionElement::Limit::basicKeys(),
new RadioLimitObject {
{"name", new RadioLimitIgnored()},
{"key", new RadioLimitStringRegEx("[0-9a-fA-F]{4}")}
}},
{AESEncryptionKey::staticMetaObject,
0, TyTCodeplug::EncryptionElement::Limit::advancedKeys(),
new RadioLimitObject {
{"name", new RadioLimitIgnored()},
{"key", new RadioLimitStringRegEx("[0-9a-fA-F]{32}")}
}} }
}
});

/* Ignore roaming zones. */
add("roaming", new RadioLimitList(
ConfigObject::staticMetaObject, -1, -1, new RadioLimitIgnored(RadioLimitIssue::Hint)
Expand Down
19 changes: 19 additions & 0 deletions lib/md390_limits.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "md390_limits.hh"

#include "md390_codeplug.hh"
#include "channel.hh"
#include "radioid.hh"
#include "contact.hh"
Expand Down Expand Up @@ -151,6 +152,24 @@ MD390Limits::MD390Limits(const std::initializer_list<std::pair<Frequency,Frequen
{ "revert", new RadioLimitObjRef(DMRChannel::staticMetaObject, true) }
} ) );

/* Check encryption keys. */
add("commercial", new RadioLimitItem {
{"encryptionKeys", new RadioLimitList {
{BasicEncryptionKey::staticMetaObject,
0, TyTCodeplug::EncryptionElement::Limit::basicKeys(),
new RadioLimitObject {
{"name", new RadioLimitIgnored()},
{"key", new RadioLimitStringRegEx("[0-9a-fA-F]{4}")}
}},
{AESEncryptionKey::staticMetaObject,
0, TyTCodeplug::EncryptionElement::Limit::advancedKeys(),
new RadioLimitObject {
{"name", new RadioLimitIgnored()},
{"key", new RadioLimitStringRegEx("[0-9a-fA-F]{32}")}
}} }
}
});

/* Ignore roaming zones. */
add("roaming", new RadioLimitList(
ConfigObject::staticMetaObject, -1, -1, new RadioLimitIgnored(RadioLimitIssue::Hint)
Expand Down
7 changes: 4 additions & 3 deletions lib/radioddity_codeplug.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2648,8 +2648,9 @@ bool
RadioddityCodeplug::EncryptionElement::fromCommercialExt(CommercialExtension *ext, Context &ctx) {
clear();

if (ext->encryptionKeys()->count() > 16) {
logError() << "Cannot encode encryption extension. Can only encode 16 keys.";
if (ext->encryptionKeys()->count() > (int)Limit::basicEncryptionKeys()) {
logError() << "Cannot encode encryption extension. Can only encode "
<< Limit::basicEncryptionKeys() << " keys.";
return false;
}

Expand All @@ -2675,7 +2676,7 @@ bool RadioddityCodeplug::EncryptionElement::updateCommercialExt(Context &ctx) {
return false;

CommercialExtension *ext = ctx.config()->commercialExtension();
for (int i=0; i<16; i++) {
for (unsigned int i=0; i<Limit::basicEncryptionKeys(); i++) {
if (! isBasicKeySet(i))
continue;
// Assemble key
Expand Down
8 changes: 8 additions & 0 deletions lib/radioddity_codeplug.hh
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,14 @@ public:
virtual bool updateCommercialExt(Context &ctx);
/** Links the given encryption extension. */
virtual bool linkCommercialExt(CommercialExtension *ext, Context &ctx);

public:
/** Some limits for the encryption element. */
struct Limit {
/** The maximum number of (basic) encryption keys. */
static constexpr unsigned int basicEncryptionKeys() { return 16; }
};

};

protected:
Expand Down
12 changes: 12 additions & 0 deletions lib/rd5r_limits.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "rd5r_limits.hh"
#include "rd5r_codeplug.hh"
#include "radioid.hh"
#include "channel.hh"
#include "scanlist.hh"
Expand Down Expand Up @@ -149,6 +150,17 @@ RD5RLimits::RD5RLimits(QObject *parent)
{ "channels", new RadioLimitRefList(0, 31, Channel::staticMetaObject) }
}));

/* Check encryption keys. */
add("commercial", new RadioLimitItem {
{"encryptionKeys", new RadioLimitList(
BasicEncryptionKey::staticMetaObject,
0, RadioddityCodeplug::EncryptionElement::Limit::basicEncryptionKeys(),
new RadioLimitObject {
{"name", new RadioLimitIgnored()},
{"key", new RadioLimitStringRegEx("[0-9a-fA-F]{8}")}
})}
});

/* Ignore positioning systems. */
add("positioning",
new RadioLimitList(
Expand Down
19 changes: 19 additions & 0 deletions lib/uv390_limits.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "uv390_limits.hh"
#include "uv390_codeplug.hh"
#include "channel.hh"
#include "radioid.hh"
#include "contact.hh"
Expand Down Expand Up @@ -156,6 +157,24 @@ UV390Limits::UV390Limits(QObject *parent)
{ "revert", new RadioLimitObjRef(DMRChannel::staticMetaObject, true) }
} ) );

/* Check encryption keys. */
add("commercial", new RadioLimitItem {
{"encryptionKeys", new RadioLimitList {
{BasicEncryptionKey::staticMetaObject,
0, TyTCodeplug::EncryptionElement::Limit::basicKeys(),
new RadioLimitObject {
{"name", new RadioLimitIgnored()},
{"key", new RadioLimitStringRegEx("[0-9a-fA-F]{4}")}
}},
{AESEncryptionKey::staticMetaObject,
0, TyTCodeplug::EncryptionElement::Limit::advancedKeys(),
new RadioLimitObject {
{"name", new RadioLimitIgnored()},
{"key", new RadioLimitStringRegEx("[0-9a-fA-F]{32}")}
}} }
}
});

/* Ignore roaming zones. */
add("roaming", new RadioLimitList(
ConfigObject::staticMetaObject, -1, -1, new RadioLimitIgnored(RadioLimitIssue::Hint)
Expand Down
78 changes: 78 additions & 0 deletions test/gd73_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "config.hh"
#include "gd73.hh"
#include "gd73_codeplug.hh"
#include "gd73_limits.hh"
#include "errorstack.hh"
#include <iostream>
#include <QTest>
Expand Down Expand Up @@ -222,5 +223,82 @@ GD73Test::testEncryption() {
config.channelList()->channel(0)->as<DMRChannel>()->commercialExtension()->encryptionKey()->key());
}


void
GD73Test::testEncryptionLimits() {
Config config;
config.radioIDs()->add(new DMRRadioID("ID", 1234567));

DMRContact *cnt = new DMRContact(DMRContact::GroupCall, "GroupCall", 1234, false);
config.contacts()->add(cnt);

RXGroupList *grpLst = new RXGroupList("GrpLst");
grpLst->addContact(cnt);
config.rxGroupLists()->add(grpLst);

BasicEncryptionKey *key = new BasicEncryptionKey();
key->setName("Key 1");
key->fromHex("1234");
config.commercialExtension()->encryptionKeys()->add(key);
QCOMPARE(key->toHex(), "1234");

auto *ext = new CommercialChannelExtension();
ext->setEncryptionKey(key);

DMRChannel *ch = new DMRChannel();
ch->setName("Ch");
ch->setTXContactObj(cnt);
ch->setGroupListObj(grpLst);
ch->setTXFrequency(Frequency::fromMHz(440));
ch->setRXFrequency(Frequency::fromMHz(440));
ch->setCommercialExtension(ext);
config.channelList()->add(ch);

Zone *zone = new Zone("Zone");
zone->A()->add(ch);
config.zones()->add(zone);

{
RadioLimitContext issues;
GD73Limits().verifyConfig(&config, issues);
QStringList status;
for (int i=0; i<issues.count(); i++)
status.append(issues.message(i).format());
QVERIFY2(1 == issues.count(), status.join("\n").toLocal8Bit().constData());
}

// Add wrong key type
AESEncryptionKey *key2 = new AESEncryptionKey();
key2->setName("Key 2");
key2->fromHex("1234567890abcdef1234567890abcdef");
config.commercialExtension()->encryptionKeys()->add(key2);

{
RadioLimitContext issues;
GD73Limits().verifyConfig(&config, issues);
QStringList status;
for (int i=0; i<issues.count(); i++)
status.append(issues.message(i).format());
QVERIFY2(2 == issues.count(), status.join("\n").toLocal8Bit().constData());
}

// add a larger key
config.commercialExtension()->encryptionKeys()->del(key2);
BasicEncryptionKey *key3 = new BasicEncryptionKey();
key3->setName("Key 2");
key3->fromHex("1234567890");
config.commercialExtension()->encryptionKeys()->add(key3);
QCOMPARE(key3->toHex(), "1234567890");

{
RadioLimitContext issues;
GD73Limits().verifyConfig(&config, issues);
QStringList status;
for (int i=0; i<issues.count(); i++)
status.append(issues.message(i).format());
QVERIFY2(2 == issues.count(), status.join("\n").toLocal8Bit().constData());
}
}

QTEST_GUILESS_MAIN(GD73Test)

1 change: 1 addition & 0 deletions test/gd73_test.hh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ private slots:
void testSMSTemplates();
void testFMSignaling();
void testEncryption();
void testEncryptionLimits();
};

#endif // GD73TEST_HH

0 comments on commit 4bceb26

Please sign in to comment.