mirror of
https://github.com/thelsing/knx.git
synced 2025-01-25 00:06:20 +01:00
save work
This commit is contained in:
parent
9cee6c8bc5
commit
eb11180858
@ -149,6 +149,8 @@ class ApplicationLayer
|
||||
virtual void dataIndividualRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t destination, APDU& apdu);
|
||||
virtual void dataConnectedRequest(uint16_t tsap, Priority priority, APDU& apdu); // apdu must be valid until it was confirmed
|
||||
|
||||
uint16_t getConnectedTsasp() {return _connectedTsap;}
|
||||
|
||||
// Protected: we need to access it in derived class SecureApplicationLayer
|
||||
TransportLayer* _transportLayer = 0;
|
||||
|
||||
|
@ -39,6 +39,9 @@ void BauSystemB::loop()
|
||||
_transLayer.loop();
|
||||
sendNextGroupTelegram();
|
||||
nextRestartState();
|
||||
#ifdef USE_DATASECURE
|
||||
_appLayer.loop();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool BauSystemB::enabled()
|
||||
|
@ -25,7 +25,6 @@ uint64_t sequenceNumber = 0;
|
||||
uint64_t lastValidSequenceNumberTool = 0;
|
||||
uint64_t lastValidSequenceNumber = 0;
|
||||
|
||||
|
||||
SecureApplicationLayer::SecureApplicationLayer(DeviceObject &deviceObj, SecurityInterfaceObject &secIfObj, AssociationTableObject& assocTable, BusAccessUnit& bau):
|
||||
ApplicationLayer(assocTable, bau),
|
||||
_secIfObj(secIfObj),
|
||||
@ -244,7 +243,7 @@ void SecureApplicationLayer::dataConnectedConfirm(uint16_t tsap)
|
||||
void SecureApplicationLayer::dataGroupRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu)
|
||||
{
|
||||
// TODO:
|
||||
// get flags for this TSAP from PID_GO_SECURITY_FLAGS from SecIntObj
|
||||
// get flags auth and confidentiality for this TSAP from PID_GO_SECURITY_FLAGS from SecIntObj
|
||||
bool needsEncryption = false;
|
||||
|
||||
if (needsEncryption)
|
||||
@ -265,7 +264,6 @@ void SecureApplicationLayer::dataGroupRequest(AckType ack, HopCountType hopType,
|
||||
void SecureApplicationLayer::dataBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu)
|
||||
{
|
||||
// TODO:
|
||||
// get flags for this TSAP from PID_GO_SECURITY_FLAGS from SecIntObj
|
||||
bool needsEncryption = true;
|
||||
|
||||
if (needsEncryption)
|
||||
@ -286,7 +284,6 @@ void SecureApplicationLayer::dataBroadcastRequest(AckType ack, HopCountType hopT
|
||||
void SecureApplicationLayer::dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu)
|
||||
{
|
||||
// TODO:
|
||||
// get flags for this TSAP from PID_GO_SECURITY_FLAGS from SecIntObj
|
||||
bool needsEncryption = true;
|
||||
|
||||
if (needsEncryption)
|
||||
@ -307,7 +304,6 @@ void SecureApplicationLayer::dataSystemBroadcastRequest(AckType ack, HopCountTyp
|
||||
void SecureApplicationLayer::dataIndividualRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t destination, APDU& apdu)
|
||||
{
|
||||
// TODO:
|
||||
// get flags for this TSAP from PID_GO_SECURITY_FLAGS from SecIntObj
|
||||
bool needsEncryption = true;
|
||||
|
||||
if (needsEncryption)
|
||||
@ -328,7 +324,6 @@ void SecureApplicationLayer::dataIndividualRequest(AckType ack, HopCountType hop
|
||||
void SecureApplicationLayer::dataConnectedRequest(uint16_t tsap, Priority priority, APDU& apdu)
|
||||
{
|
||||
// TODO:
|
||||
// get flags for this TSAP from PID_GO_SECURITY_FLAGS from SecIntObj
|
||||
bool needsEncryption = true;
|
||||
|
||||
if (needsEncryption)
|
||||
@ -594,6 +589,55 @@ void SecureApplicationLayer::updateLastValidSequence(bool toolAccess, uint16_t r
|
||||
}
|
||||
}
|
||||
|
||||
void SecureApplicationLayer::sendSyncRequest(uint16_t dstAddr, bool dstAddrIsGroupAddr, bool toolAccess)
|
||||
{
|
||||
_syncReqBroadcastOutgoing = (dstAddr == 0x0000) && dstAddrIsGroupAddr;
|
||||
|
||||
// use random number in SyncResponse
|
||||
uint64_t challenge = getRandomNumber();
|
||||
|
||||
uint8_t asdu[6];
|
||||
sixBytesFromUInt64(challenge, &asdu[0]);
|
||||
|
||||
CemiFrame request(2 + 6 + sizeof(asdu) + 4); // 2 bytes (APCI, SCF) + 6 bytes (SeqNum) + 6 bytes (challenge) + 4 bytes (MAC)
|
||||
// Note: additional TPCI byte is already handled internally!
|
||||
|
||||
uint8_t tpci = 0;
|
||||
if (!_syncReqBroadcastOutgoing)
|
||||
{
|
||||
tpci = _transportLayer->getTPCI(dstAddr); // get next TPCI sequence number for MAC calculation from TL
|
||||
}
|
||||
print("sendSyncRequest: TPCI: ");
|
||||
println(tpci, HEX);
|
||||
|
||||
if(secure(request.data() + APDU_LPDU_DIFF, SecureSyncRequest, _deviceObj.induvidualAddress(), dstAddr, dstAddrIsGroupAddr, tpci, asdu, sizeof(asdu), toolAccess, true))
|
||||
{
|
||||
println("SyncRequest: ");
|
||||
request.apdu().printPDU();
|
||||
|
||||
if (_syncReqBroadcastOutgoing)
|
||||
{
|
||||
_transportLayer->dataBroadcastRequest(AckType::AckDontCare, HopCountType::NetworkLayerParameter, Priority::SystemPriority, request.apdu());
|
||||
}
|
||||
else
|
||||
{
|
||||
// either send on T_DATA_INDIVIDUAL or T_DATA_CONNECTED
|
||||
if (isConnected())
|
||||
{
|
||||
_transportLayer->dataConnectedRequest(getConnectedTsasp(), SystemPriority, request.apdu());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send encrypted SyncResponse message using T_DATA_INDIVIDUAL
|
||||
_transportLayer->dataIndividualRequest(AckType::AckDontCare, NetworkLayerParameter, SystemPriority, dstAddr, request.apdu());
|
||||
}
|
||||
}
|
||||
|
||||
Addr toAddr = _syncReqBroadcastOutgoing ? (Addr)GrpAddr(0) : (Addr)IndAddr(dstAddr);
|
||||
_pendingOutgoingSyncRequests.insertOrAssign(toAddr, challenge);
|
||||
}
|
||||
}
|
||||
|
||||
void SecureApplicationLayer::sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGroupAddr, bool toolAccess, uint64_t remoteNextSeqNum)
|
||||
{
|
||||
uint64_t ourNextSeqNum = nextSequenceNumber(toolAccess);
|
||||
@ -606,7 +650,7 @@ void SecureApplicationLayer::sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGr
|
||||
// Note: additional TPCI byte is already handled internally!
|
||||
|
||||
uint8_t tpci = 0;
|
||||
if (!_syncReqBroadcast)
|
||||
if (!_syncReqBroadcastIncoming)
|
||||
{
|
||||
tpci = _transportLayer->getTPCI(dstAddr); // get next TPCI sequence number for MAC calculation from TL
|
||||
}
|
||||
@ -620,16 +664,22 @@ void SecureApplicationLayer::sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGr
|
||||
println("SyncResponse: ");
|
||||
response.apdu().printPDU();
|
||||
|
||||
if (_syncReqBroadcast)
|
||||
if (_syncReqBroadcastIncoming)
|
||||
{
|
||||
_transportLayer->dataBroadcastRequest(AckType::AckDontCare, HopCountType::NetworkLayerParameter, Priority::SystemPriority, response.apdu());
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: either send on T_DATA_INDIVIDUAL or T_DATA_CONNECTED depending on reception
|
||||
|
||||
// Send encrypted SyncResponse message using T_DATA_INDIVIDUAL
|
||||
_transportLayer->dataIndividualRequest(AckType::AckDontCare, NetworkLayerParameter, SystemPriority, dstAddr, response.apdu());
|
||||
// either send on T_DATA_INDIVIDUAL or T_DATA_CONNECTED
|
||||
if (isConnected())
|
||||
{
|
||||
_transportLayer->dataConnectedRequest(getConnectedTsasp(), SystemPriority, response.apdu());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send encrypted SyncResponse message using T_DATA_INDIVIDUAL
|
||||
_transportLayer->dataIndividualRequest(AckType::AckDontCare, NetworkLayerParameter, SystemPriority, dstAddr, response.apdu());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -646,29 +696,34 @@ void SecureApplicationLayer::receivedSyncRequest(uint16_t srcAddr, uint16_t dstA
|
||||
}
|
||||
|
||||
// Remember challenge for securing the sync.res later
|
||||
//stashSyncRequest(srcAddr, challenge); // TODO: save challenge in a map to handle multiple requests
|
||||
sixBytesFromUInt64(challenge, _challenge);
|
||||
_pendingIncomingSyncRequests.insertOrAssign(IndAddr(srcAddr), challenge);
|
||||
|
||||
_syncReqBroadcast = (dstAddr == 0x0000) && dstAddrIsGroupAddr;
|
||||
_syncReqBroadcastIncoming = (dstAddr == 0x0000) && dstAddrIsGroupAddr;
|
||||
|
||||
uint16_t toAddr = _syncReqBroadcast ? dstAddr : srcAddr;
|
||||
bool toIsGroupAddress = _syncReqBroadcast;
|
||||
|
||||
_challengeSrcAddr = toAddr;
|
||||
_isChallengeValid = true;
|
||||
uint16_t toAddr = _syncReqBroadcastIncoming ? dstAddr : srcAddr;
|
||||
bool toIsGroupAddress = _syncReqBroadcastIncoming;
|
||||
|
||||
sendSyncResponse(toAddr, toIsGroupAddress, toolAccess, nextSeqNum);
|
||||
}
|
||||
|
||||
void SecureApplicationLayer::receivedSyncResponse(uint16_t remoteAddr, bool toolAccess, uint8_t* plainApdu)
|
||||
{
|
||||
// final var request = pendingSyncRequests.get(remote);
|
||||
// if (request == null)
|
||||
// return;
|
||||
if (_challengeSrcAddr != remoteAddr)
|
||||
// TODO: check if _syncReqBroadcastOutgoing is true
|
||||
if (_syncReqBroadcastOutgoing)
|
||||
{
|
||||
println("receivedSyncResponse(): Did not find matching challenge for remoteAddr!");
|
||||
return;
|
||||
if (_pendingOutgoingSyncRequests.get(GrpAddr(0)) == nullptr)
|
||||
{
|
||||
println("Cannot handle sync.res without pending sync.req! (broadcast)");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_pendingOutgoingSyncRequests.get(IndAddr(remoteAddr)) == nullptr)
|
||||
{
|
||||
println("Cannot handle sync.res without pending sync.req!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Bytes 0-5 in the "APDU" buffer contain the remote sequence number
|
||||
@ -689,7 +744,7 @@ void SecureApplicationLayer::receivedSyncResponse(uint16_t remoteAddr, bool tool
|
||||
updateSequenceNumber(toolAccess, localSeq);
|
||||
}
|
||||
|
||||
//syncRequestCompleted(request);
|
||||
_pendingOutgoingSyncRequests.erase(IndAddr(remoteAddr));
|
||||
}
|
||||
|
||||
bool SecureApplicationLayer::decrypt(uint8_t* plainApdu, uint16_t plainApduLength, uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, uint8_t tpci, uint8_t* secureAsdu)
|
||||
@ -762,21 +817,21 @@ bool SecureApplicationLayer::decrypt(uint8_t* plainApdu, uint16_t plainApduLengt
|
||||
}
|
||||
else if (syncRes)
|
||||
{
|
||||
// TODO: fetch challenge depending on srcAddr to handle multiple requests (would use std::unordered_map normally)
|
||||
//final var request = pendingSyncRequests.get(src);
|
||||
//if (request == null)
|
||||
// return null;
|
||||
if (_challengeSrcAddr != srcAddr)
|
||||
// fetch challenge depending on srcAddr to handle multiple requests
|
||||
uint64_t *challenge = _pendingOutgoingSyncRequests.get(IndAddr(srcAddr));
|
||||
if (challenge == nullptr)
|
||||
{
|
||||
println("Did not find matching challenge for source address!");
|
||||
println("Cannot find matching challenge for source address!");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t _challengeSixBytes[6];
|
||||
sixBytesFromUInt64(*challenge, _challengeSixBytes);
|
||||
// in a sync.res, seq actually contains our challenge from sync.req xored with a random value
|
||||
// extract the random value and store it in seqNum to use it for block0 and ctr0
|
||||
for (uint8_t i = 0; i < sizeof(seqNum); i++)
|
||||
{
|
||||
seqNum[i] ^= _challenge[i];
|
||||
seqNum[i] ^= _challengeSixBytes[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -946,7 +1001,7 @@ bool SecureApplicationLayer::secure(uint8_t* buffer, uint16_t service, uint16_t
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t* key = toolAccess ? toolKey(_syncReqBroadcast ? _deviceObj.induvidualAddress() : dstAddr) : securityKey(dstAddr, dstAddrIsGroupAddr);
|
||||
const uint8_t* key = toolAccess ? toolKey(_syncReqBroadcastIncoming ? _deviceObj.induvidualAddress() : dstAddr) : securityKey(dstAddr, dstAddrIsGroupAddr);
|
||||
if (key == nullptr)
|
||||
{
|
||||
print("Error: No key found. toolAccess: ");
|
||||
@ -997,32 +1052,30 @@ bool SecureApplicationLayer::secure(uint8_t* buffer, uint16_t service, uint16_t
|
||||
else if (syncRes)
|
||||
{
|
||||
// use random number in SyncResponse
|
||||
uint64_t randomNumber = 0x000102030405; // TODO: generate random number
|
||||
uint64_t randomNumber = getRandomNumber();
|
||||
sixBytesFromUInt64(randomNumber, seq);
|
||||
|
||||
// TODO: maybe implement something like std::map for pending SyncRequests?
|
||||
//final var request = pendingSyncRequests.remove(dst);
|
||||
//if (request == null)
|
||||
// throw new KnxSecureException("sending sync.res without corresponding .req");
|
||||
if (_isChallengeValid && (_challengeSrcAddr == dstAddr))
|
||||
// Get challenge from sync.req
|
||||
uint64_t *challenge = _pendingIncomingSyncRequests.get(IndAddr(dstAddr));
|
||||
if (challenge == nullptr)
|
||||
{
|
||||
// Invalidate _challengeSrcAddr
|
||||
_challengeSrcAddr = 0;
|
||||
_isChallengeValid = false;
|
||||
println("Cannot send sync.res without corresponding sync.req");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
println("sending sync.res without corresponding .req");
|
||||
_pendingIncomingSyncRequests.erase(IndAddr(dstAddr));
|
||||
}
|
||||
|
||||
//printHex("Decrypted challenge: ", _challenge, 6);
|
||||
uint8_t challengeSixBytes[6];
|
||||
sixBytesFromUInt64(*challenge, challengeSixBytes);
|
||||
//printHex("Decrypted challenge: ", challengeSixBytes, 6);
|
||||
|
||||
// Now XOR the new random SeqNum with the challenge from the SyncRequest
|
||||
uint8_t rndXorChallenge[6];
|
||||
pushByteArray(seq, 6, rndXorChallenge);
|
||||
for (uint8_t i = 0; i < sizeof(rndXorChallenge); i++)
|
||||
{
|
||||
rndXorChallenge[i] ^= _challenge[i];
|
||||
rndXorChallenge[i] ^= challengeSixBytes[i];
|
||||
}
|
||||
pBuf = pushByteArray(rndXorChallenge, 6, pBuf);
|
||||
}
|
||||
@ -1130,3 +1183,14 @@ uint8_t SecureApplicationLayer::getFromFailureLogByIndex(uint8_t index, uint8_t*
|
||||
println(index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t SecureApplicationLayer::getRandomNumber()
|
||||
{
|
||||
return 0x000102030405; // TODO: generate random number
|
||||
}
|
||||
|
||||
void SecureApplicationLayer::loop()
|
||||
{
|
||||
// TODO: handle timeout of outgoing sync requests
|
||||
//_pendingOutgoingSyncRequests
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <stdint.h>
|
||||
#include "knx_types.h"
|
||||
#include "apdu.h"
|
||||
#include "bits.h"
|
||||
|
||||
class DeviceObject;
|
||||
class SecurityInterfaceObject;
|
||||
@ -18,6 +19,46 @@ class BusAccessUnit;
|
||||
*/
|
||||
class SecureApplicationLayer : public ApplicationLayer
|
||||
{
|
||||
|
||||
public:
|
||||
/**
|
||||
* The constructor.
|
||||
* @param assocTable The AssociationTable is used to translate between asap (i.e. group objects) and group addresses.
|
||||
* @param bau methods are called here depending of the content of the APDU
|
||||
*/
|
||||
SecureApplicationLayer(DeviceObject& deviceObj, SecurityInterfaceObject& secIfObj, AssociationTableObject& assocTable, BusAccessUnit& bau);
|
||||
|
||||
void setSecurityMode(bool enabled);
|
||||
bool isSecurityModeEnabled();
|
||||
void clearFailureLog();
|
||||
void getFailureCounters(uint8_t* data);
|
||||
uint8_t getFromFailureLogByIndex(uint8_t index, uint8_t* data, uint8_t maxDataLen);
|
||||
|
||||
// from transport layer
|
||||
virtual void dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu) override;
|
||||
virtual void dataGroupConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap,
|
||||
APDU& apdu, bool status) override;
|
||||
virtual void dataBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) override;
|
||||
virtual void dataBroadcastConfirm(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, bool status) override;
|
||||
virtual void dataSystemBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) override;
|
||||
virtual void dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, bool status) override;
|
||||
virtual void dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) override;
|
||||
virtual void dataIndividualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status) override;
|
||||
virtual void dataConnectedIndication(Priority priority, uint16_t tsap, APDU& apdu) override;
|
||||
virtual void dataConnectedConfirm(uint16_t tsap) override;
|
||||
|
||||
void loop();
|
||||
|
||||
protected:
|
||||
// to transport layer
|
||||
virtual void dataGroupRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu) override;
|
||||
virtual void dataBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu) override;
|
||||
virtual void dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu) override;
|
||||
virtual void dataIndividualRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t destination, APDU& apdu) override;
|
||||
virtual void dataConnectedRequest(uint16_t tsap, Priority priority, APDU& apdu) override; // apdu must be valid until it was confirmed
|
||||
|
||||
private:
|
||||
|
||||
template <typename K, typename V, int SIZE>
|
||||
class Map
|
||||
{
|
||||
@ -27,11 +68,6 @@ class SecureApplicationLayer : public ApplicationLayer
|
||||
static_assert (SIZE <= 64, "Map is too big! Max. 64 elements.");
|
||||
}
|
||||
|
||||
void setInvalidValue(V value)
|
||||
{
|
||||
_invalidValue = value;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
_validEntries = 0;
|
||||
@ -107,7 +143,7 @@ class SecureApplicationLayer : public ApplicationLayer
|
||||
return false;
|
||||
}
|
||||
|
||||
V operator[](K key) const
|
||||
V* get(K key)
|
||||
{
|
||||
// Try to find the key
|
||||
for (uint8_t i = 0; i < SIZE; i++)
|
||||
@ -118,38 +154,11 @@ class SecureApplicationLayer : public ApplicationLayer
|
||||
// Key found?
|
||||
if (keys[i] == key)
|
||||
{
|
||||
return values[i];
|
||||
return &values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return _invalidValue;
|
||||
}
|
||||
|
||||
V &operator[](K key)
|
||||
{
|
||||
// Try to find the key
|
||||
for (uint8_t i = 0; i < SIZE; i++)
|
||||
{
|
||||
// Check if this array slot is occupied
|
||||
if ((_validEntries >> i) & 0x01)
|
||||
{
|
||||
// Key found?
|
||||
if (keys[i] == key)
|
||||
{
|
||||
return values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Key was not found, so add key and value
|
||||
uint8_t index = getNextFreeIndex();
|
||||
if (index != noFreeEntryFoundIndex)
|
||||
{
|
||||
_validEntries |= 1 << index;
|
||||
keys[index] = key;
|
||||
return values[index];
|
||||
}
|
||||
return _invalidValue;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -170,45 +179,15 @@ class SecureApplicationLayer : public ApplicationLayer
|
||||
K keys[SIZE];
|
||||
V values[SIZE];
|
||||
static constexpr uint8_t noFreeEntryFoundIndex = 255;
|
||||
V _invalidValue;
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* The constructor.
|
||||
* @param assocTable The AssociationTable is used to translate between asap (i.e. group objects) and group addresses.
|
||||
* @param bau methods are called here depending of the content of the APDU
|
||||
*/
|
||||
SecureApplicationLayer(DeviceObject& deviceObj, SecurityInterfaceObject& secIfObj, AssociationTableObject& assocTable, BusAccessUnit& bau);
|
||||
enum class AddrType : uint8_t
|
||||
{
|
||||
group,
|
||||
individual,
|
||||
unknown
|
||||
};
|
||||
|
||||
void setSecurityMode(bool enabled);
|
||||
bool isSecurityModeEnabled();
|
||||
void clearFailureLog();
|
||||
void getFailureCounters(uint8_t* data);
|
||||
uint8_t getFromFailureLogByIndex(uint8_t index, uint8_t* data, uint8_t maxDataLen);
|
||||
|
||||
// from transport layer
|
||||
virtual void dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu) override;
|
||||
virtual void dataGroupConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap,
|
||||
APDU& apdu, bool status) override;
|
||||
virtual void dataBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) override;
|
||||
virtual void dataBroadcastConfirm(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, bool status) override;
|
||||
virtual void dataSystemBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) override;
|
||||
virtual void dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, bool status) override;
|
||||
virtual void dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) override;
|
||||
virtual void dataIndividualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status) override;
|
||||
virtual void dataConnectedIndication(Priority priority, uint16_t tsap, APDU& apdu) override;
|
||||
virtual void dataConnectedConfirm(uint16_t tsap) override;
|
||||
|
||||
protected:
|
||||
// to transport layer
|
||||
virtual void dataGroupRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu) override;
|
||||
virtual void dataBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu) override;
|
||||
virtual void dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu) override;
|
||||
virtual void dataIndividualRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t destination, APDU& apdu) override;
|
||||
virtual void dataConnectedRequest(uint16_t tsap, Priority priority, APDU& apdu) override; // apdu must be valid until it was confirmed
|
||||
|
||||
private:
|
||||
enum class DataSecurity
|
||||
{
|
||||
none,
|
||||
@ -216,6 +195,37 @@ class SecureApplicationLayer : public ApplicationLayer
|
||||
authConf
|
||||
};
|
||||
|
||||
struct Addr
|
||||
{
|
||||
Addr() = default;
|
||||
Addr(uint8_t addr) : addr{addr} {}
|
||||
|
||||
uint16_t addr;
|
||||
AddrType addrType{AddrType::unknown};
|
||||
|
||||
bool operator ==(const Addr &cmpAddr) const
|
||||
{
|
||||
if ((cmpAddr.addrType == AddrType::unknown) || (addrType == AddrType::unknown))
|
||||
{
|
||||
println("Unknown address type detected!");
|
||||
return false;
|
||||
}
|
||||
return (cmpAddr.addr == addr) && (cmpAddr.addrType == addrType);
|
||||
}
|
||||
};
|
||||
|
||||
struct GrpAddr : Addr
|
||||
{
|
||||
GrpAddr() {addrType = AddrType::group;}
|
||||
GrpAddr(uint8_t addr) : Addr{addr} {addrType = AddrType::group;}
|
||||
};
|
||||
|
||||
struct IndAddr : Addr
|
||||
{
|
||||
IndAddr() { addrType = AddrType::individual; }
|
||||
IndAddr(uint8_t addr) : Addr{addr} { addrType = AddrType::individual; }
|
||||
};
|
||||
|
||||
struct SecurityControl
|
||||
{
|
||||
bool toolAccess;
|
||||
@ -248,6 +258,9 @@ class SecureApplicationLayer : public ApplicationLayer
|
||||
uint64_t lastValidSequenceNumber(bool toolAcces, uint16_t srcAddr);
|
||||
void updateLastValidSequence(bool toolAccess, uint16_t remoteAddr, uint64_t seqNo);
|
||||
|
||||
uint64_t getRandomNumber();
|
||||
|
||||
void sendSyncRequest(uint16_t dstAddr, bool dstAddrIsGroupAddr, bool toolAccess);
|
||||
void sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGroupAddr, bool toolAccess, uint64_t remoteNextSeqNum);
|
||||
void receivedSyncRequest(uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, bool toolAccess, uint8_t* seq, uint64_t challenge);
|
||||
void receivedSyncResponse(uint16_t remoteAddr, bool toolAccess, uint8_t* plainApdu);
|
||||
@ -263,13 +276,13 @@ class SecureApplicationLayer : public ApplicationLayer
|
||||
|
||||
bool _securityModeEnabled {false};
|
||||
|
||||
bool _syncReqBroadcast;
|
||||
bool _syncReqBroadcastIncoming{false};
|
||||
bool _syncReqBroadcastOutgoing{false};
|
||||
uint32_t _lastSyncRes;
|
||||
uint8_t _challenge[6];
|
||||
uint16_t _challengeSrcAddr;
|
||||
bool _isChallengeValid {false};
|
||||
|
||||
Map<uint16_t, SecurityControl, 8> _pendingRequests;
|
||||
Map<Addr, SecurityControl, 1> _pendingDataRequests;
|
||||
Map<Addr, uint64_t, 1> _pendingOutgoingSyncRequests;
|
||||
Map<Addr, uint64_t, 1> _pendingIncomingSyncRequests;
|
||||
|
||||
SecurityInterfaceObject& _secIfObj;
|
||||
DeviceObject& _deviceObj;
|
||||
|
Loading…
Reference in New Issue
Block a user