Save work

This commit is contained in:
Nanosonde 2020-06-12 15:03:34 +02:00
parent 79d9586940
commit 0d2daaaaef
2 changed files with 49 additions and 24 deletions

View File

@ -428,16 +428,23 @@ void SecureApplicationLayer::updateLastValidSequence(bool toolAccess, uint16_t r
//lastValidSequence.put(remoteAddr, seqNo);
}
void SecureApplicationLayer::sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGroupAddr, bool toolAccess, uint16_t remoteNextSeqNum)
void SecureApplicationLayer::sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGroupAddr, bool toolAccess, uint64_t remoteNextSeqNum)
{
uint64_t ourNextSeqNum = nextSequenceNumber(toolAccess);
// asdu = ByteBuffer.allocate(12).put(sixBytes(ourNextSeq)).put(sixBytes(remoteNextSeq));
// response = secure(SecureSyncResponse, address(), dst, asdu.array(), toolAccess, true).get();
_lastSyncRes = millis();
uint8_t asdu[12];
sixBytes(ourNextSeqNum, &asdu[0]);
sixBytes(remoteNextSeqNum, &asdu[6]);
// Send encrypted SyncResponse message using T_DATA_INDIVIDUAL
//dataIndividualRequest(AckType::AckDontCare, NetworkLayerParameter, SystemPriority, dstAddr, apdu);
CemiFrame response(3 + 6 + sizeof(asdu) + 4); // 3 bytes (TPCI, APCI, SCF) + 6 bytes (SeqNum) + 12 bytes + 4 bytes (MAC)
if(secure(response.data() + APDU_LPDU_DIFF, SecureSyncResponse, _deviceObj.induvidualAddress(), dstAddr, dstAddrIsGroupAddr, asdu, sizeof(asdu), toolAccess, true))
{
_lastSyncRes = millis();
// Send encrypted SyncResponse message using T_DATA_INDIVIDUAL
_transportLayer->dataIndividualRequest(AckType::AckDontCare, NetworkLayerParameter, SystemPriority, dstAddr, response.apdu());
}
}
void SecureApplicationLayer::receivedSyncRequest(uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, bool toolAccess, uint8_t* seqNum, long challenge)
@ -451,6 +458,11 @@ void SecureApplicationLayer::receivedSyncRequest(uint16_t srcAddr, uint16_t dstA
nextSeqNum = nextRemoteSeqNum;
}
// Remember challenge for securing the sync.res later
//stashSyncRequest(srcAddr, challenge); // TODO: save challenge in a map to handle multiple requests
sixBytes(challenge, _challenge);
_challengeSrcAddr = srcAddr;
_syncReqBroadcast = (dstAddr == 0x0000) && dstAddrIsGroupAddr;
uint16_t toAddr = _syncReqBroadcast ? dstAddr : srcAddr;
@ -547,17 +559,22 @@ bool SecureApplicationLayer::decrypt(uint8_t* plainApdu, uint16_t srcAddr, uint1
}
else if (syncRes)
{
// TODO
// 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)
{
println("Did not find matching challenge for source address!");
return false;
}
// 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 seq to use it for block0 and ctr0
//final var challengeXorRandom = BitSet.valueOf(seq);
//final var challenge = BitSet.valueOf(sixBytes((long) request[0]));
//challengeXorRandom.xor(challenge);
//seq = challengeXorRandom.toByteArray();
// 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];
}
}
uint16_t apduLength = secureAdsuLength - 1 - 6 - 4; // secureAdsuLength - sizeof(scf) - sizeof(seqNum) - sizeof(mac)
@ -671,27 +688,27 @@ bool SecureApplicationLayer::decrypt(uint8_t* plainApdu, uint16_t srcAddr, uint1
return true;
}
void SecureApplicationLayer::secure(uint8_t* buffer, uint16_t service, uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr,
uint8_t tpci, uint8_t* apdu, uint16_t apduLength, bool toolAccess, bool confidentiality)
bool SecureApplicationLayer::secure(uint8_t* buffer, uint16_t service, uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr,
uint8_t* apdu, uint16_t apduLength, bool toolAccess, bool confidentiality)
{
if (toolAccess)
{
if (!confidentiality)
{
println("Error: tool access requires auth+conf security");
return;
return false;
}
if (dstAddrIsGroupAddr && dstAddr != 0)
{
println("Error: tool access requires individual address");
return;
return false;
}
}
const uint8_t* key = toolAccess ? toolKey(_syncReqBroadcast ? _deviceObj.induvidualAddress() : dstAddr) : securityKey(dstAddr, dstAddrIsGroupAddr);
if (key == nullptr)
{
return;
return false;
}
bool syncReq = service == SecureSyncRequest;
@ -700,11 +717,11 @@ void SecureApplicationLayer::secure(uint8_t* buffer, uint16_t service, uint16_t
uint8_t snoLength = syncReq ? 6 : 0;
//ByteBuffer secureApdu = ByteBuffer.allocate(3 + SeqSize + snoLength + apdu.length + MacSize);
uint8_t tmpTpci = _transportLayer->getTPCI(dstAddr) | (SecureService >> 8);
uint8_t tpci = _transportLayer->getTPCI(dstAddr) | (SecureService >> 8);
uint8_t apci = SecureService & 0x00FF;
uint8_t* pBuf = buffer;
pBuf = pushByte(tmpTpci, pBuf); // TPCI
pBuf = pushByte(SecureService & 0x00FF, pBuf); // APCI
pBuf = pushByte(tpci, pBuf); // TPCI
pBuf = pushByte(apci, pBuf); // APCI
bool systemBcast = false; // Not implemented yet
@ -756,6 +773,11 @@ void SecureApplicationLayer::secure(uint8_t* buffer, uint16_t service, uint16_t
//final var request = pendingSyncRequests.remove(dst);
//if (request == null)
// throw new KnxSecureException("sending sync.res without corresponding .req");
if (_challengeSrcAddr != dstAddr)
{
println("Did not find matching challenge for destination address!");
return false;
}
// Now XOR the new random SeqNum with the challenge from the SyncRequest
uint8_t rndXorChallenge[6];
@ -772,7 +794,7 @@ void SecureApplicationLayer::secure(uint8_t* buffer, uint16_t service, uint16_t
// Clear IV buffer
uint8_t iv[16] = {0x00};
// Create first block B0 for AES CBC MAC calculation, used as IV later
block0(iv, seq, srcAddr, dstAddr, dstAddrIsGroupAddr, extendedFrameFormat, tpci | (SecureService >> 8), SecureService & 0x00FF, apduLength);
block0(iv, seq, srcAddr, dstAddr, dstAddrIsGroupAddr, extendedFrameFormat, tpci, apci, apduLength);
// Clear block counter0 buffer
uint8_t ctr0[16] = {0x00};
@ -804,6 +826,8 @@ void SecureApplicationLayer::secure(uint8_t* buffer, uint16_t service, uint16_t
pBuf = pushByteArray(apdu, apduLength, pBuf); // Plain APDU
pBuf = pushInt(tmpMac, pBuf); // MAC
}
return true;
}
/*

View File

@ -78,16 +78,17 @@ class SecureApplicationLayer : public ApplicationLayer
uint64_t lastValidSequenceNumber(bool toolAcces, uint16_t srcAddr);
void updateLastValidSequence(bool toolAccess, uint16_t remoteAddr, uint64_t seqNo);
void sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGroupAddr, bool toolAccess, uint16_t remoteNextSeqNum);
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, long challenge);
void receivedSyncResponse(uint16_t remoteAddr, bool toolAccess, uint8_t* plainApdu);
bool decrypt(uint8_t* plainApdu, uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, uint8_t tpci, uint8_t* secureAsdu, uint16_t secureAdsuLength);
void secure(uint8_t* buffer, uint16_t service, uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, uint8_t tpci, uint8_t* apdu, uint16_t apduLength, bool toolAccess, bool confidentiality);
bool secure(uint8_t* buffer, uint16_t service, uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, uint8_t* apdu, uint16_t apduLength, bool toolAccess, bool confidentiality);
bool _syncReqBroadcast;
uint32_t _lastSyncRes;
uint8_t _challenge[6];
uint16_t _challengeSrcAddr;
SecurityInterfaceObject& _secIfObj;
DeviceObject& _deviceObj;