From 60b3655ea6c5f9ac97c4f448ca765036051793cb Mon Sep 17 00:00:00 2001 From: Nanosonde <2073569+nanosonde@users.noreply.github.com> Date: Sat, 27 Jun 2020 11:46:47 +0200 Subject: [PATCH] save work --- src/knx/application_layer.cpp | 4 +- src/knx/application_layer.h | 42 +++++--- src/knx/secure_application_layer.cpp | 150 +++++++++++++++++---------- src/knx/secure_application_layer.h | 16 +-- 4 files changed, 132 insertions(+), 80 deletions(-) diff --git a/src/knx/application_layer.cpp b/src/knx/application_layer.cpp index 0b8b4e9..34d7ce3 100644 --- a/src/knx/application_layer.cpp +++ b/src/knx/application_layer.cpp @@ -23,7 +23,7 @@ static constexpr SecurityControl noSecurity {.toolAccess=true, .dataSecurity=Dat #pragma region TL Callbacks -void ApplicationLayer::dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl& secCtrl = ApplicationLayer::noSecurity) +void ApplicationLayer::dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl& secCtrl) { uint8_t len = apdu.length(); uint8_t dataArray[len]; @@ -310,7 +310,7 @@ void ApplicationLayer::dataConnectedIndication(Priority priority, uint16_t tsap, individualIndication(NetworkLayerParameter, priority, tsap, apdu, secCtrl); } -void ApplicationLayer::dataConnectedConfirm(uint16_t tsap) +void ApplicationLayer::dataConnectedConfirm(uint16_t tsap, const SecurityControl& secCtrl) { } diff --git a/src/knx/application_layer.h b/src/knx/application_layer.h index 44b7ab8..b79059a 100644 --- a/src/knx/application_layer.h +++ b/src/knx/application_layer.h @@ -29,6 +29,9 @@ class ApplicationLayer void transportLayer(TransportLayer& layer); // from transport layer + // Note: a derived class(e.g. SecureApplicationLayer) just hides the implementation of these entry points from the transport layer + // So hiding is enough here, we do not need virtual member methods here. + // Without data secure feature, the application layer is just used with SecurtyControl.dataSecurity = none #pragma region Transport - Layer - Callbacks /** * Somebody send us an APDU via multicast communiation. See 3.2 of @cite knx:3/3/4. @@ -44,7 +47,6 @@ class ApplicationLayer * * @param hopType Should routing be endless or should the NetworkLayer::hopCount be used? See also ::HopCountType. */ - void dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl &secCtrl); void dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu) {dataGroupIndication(hopType, priority, tsap, apdu, noSecurity);} /** * Report the status of an APDU that we sent via multicast communiation back to us. See 3.2 of @cite knx:3/3/4. @@ -64,31 +66,37 @@ class ApplicationLayer * * @param ack Did we want a DataLinkLayer acknowledgement? See ::AckType. */ - void dataGroupConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, - APDU& apdu, const SecurityControl& secCtrl, bool status); void dataGroupConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status) {dataGroupConfirm(ack, hopType, priority, tsap, apdu, noSecurity, status);} - void dataBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu, const SecurityControl& secCtrl); void dataBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) {dataBroadcastIndication(hopType, priority, source, apdu, noSecurity);} - void dataBroadcastConfirm(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, const SecurityControl& secCtrl, bool status); - void dataBroadcastConfirm(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, bool status) {dataBroadcastConfirm(ack, hopType, priority, apdu, status);} - void dataSystemBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu, const SecurityControl& secCtrl); - void dataSystemBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) {dataSystemBroadcastIndication(hopType, priority, source, apdu);} - void dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, const SecurityControl& secCtrl, bool status); - void dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, bool status) {dataSystemBroadcastConfirm(hopType, priority, apdu, status);} - void dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu, const SecurityControl& secCtrl); - void dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) {dataIndividualIndication(hopType, priority, source, apdu);} - void dataIndividualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl& secCtrl, bool status); - void dataIndividualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status) {dataIndividualConfirm(ack, hopType, priority, tsap, apdu, status);} - void dataConnectedIndication(Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl& secCtrl); - void dataConnectedIndication(Priority priority, uint16_t tsap, APDU& apdu) {dataConnectedIndication(priority, tsap, apdu);} - void dataConnectedConfirm(uint16_t tsap); + void dataBroadcastConfirm(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, bool status) {dataBroadcastConfirm(ack, hopType, priority, apdu, noSecurity, status);} + void dataSystemBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) {dataSystemBroadcastIndication(hopType, priority, source, apdu, noSecurity);} + void dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, bool status) {dataSystemBroadcastConfirm(hopType, priority, apdu, noSecurity, status);} + void dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu) {dataIndividualIndication(hopType, priority, source, apdu, noSecurity);} + void dataIndividualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status) {dataIndividualConfirm(ack, hopType, priority, tsap, apdu, noSecurity, status);} + void dataConnectedIndication(Priority priority, uint16_t tsap, APDU& apdu) {dataConnectedIndication(priority, tsap, apdu, noSecurity);} + void dataConnectedConfirm(uint16_t tsap) {dataConnectedConfirm(tsap, noSecurity);} void connectIndication(uint16_t tsap); void connectConfirm(uint16_t destination, uint16_t tsap, bool status); void disconnectIndication(uint16_t tsap); void disconnectConfirm(Priority priority, uint16_t tsap, bool status); #pragma endregion + // hooks that can be implemented by derived class (e.g. SecureApplicationLayer) +#pragma region hooks + void dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl &secCtrl); + void dataGroupConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, + APDU& apdu, const SecurityControl& secCtrl, bool status); + void dataBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu, const SecurityControl& secCtrl); + void dataBroadcastConfirm(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, const SecurityControl& secCtrl, bool status); + void dataSystemBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu, const SecurityControl& secCtrl); + void dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, const SecurityControl& secCtrl, bool status); + void dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu, const SecurityControl& secCtrl); + void dataIndividualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl& secCtrl, bool status); + void dataConnectedIndication(Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl& secCtrl); + void dataConnectedConfirm(uint16_t tsap, const SecurityControl& secCtrl); +#pragma endregion + #pragma region from bau void groupValueReadRequest(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl); void groupValueReadResponse(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl& secCtrl, uint8_t* data, uint8_t dataLength); diff --git a/src/knx/secure_application_layer.cpp b/src/knx/secure_application_layer.cpp index 7c24c19..97dc85a 100644 --- a/src/knx/secure_application_layer.cpp +++ b/src/knx/secure_application_layer.cpp @@ -41,7 +41,7 @@ void SecureApplicationLayer::dataGroupIndication(HopCountType hopType, Priority if (apdu.type() == SecureService) { - // TODO: + // Will be filled in by decodeSecureApdu() SecurityControl secCtrl; // Decrypt secure APDU @@ -49,7 +49,7 @@ void SecureApplicationLayer::dataGroupIndication(HopCountType hopType, Priority uint16_t plainApduLength = apdu.length() - 1 - 6 - 4; // secureAdsuLength - sizeof(scf) - sizeof(seqNum) - sizeof(mac) CemiFrame plainFrame(plainApduLength); // Decrypt secure APDU - if (decodeSecureApdu(apdu, plainFrame.apdu())) + if (decodeSecureApdu(apdu, plainFrame.apdu(), secCtrl)) { // Process decrypted inner APDU ApplicationLayer::dataGroupIndication(hopType, priority, tsap, plainFrame.apdu(), secCtrl); @@ -66,15 +66,18 @@ void SecureApplicationLayer::dataGroupConfirm(AckType ack, HopCountType hopType, if (apdu.type() == SecureService) { + // Will be filled in by decodeSecureApdu() + SecurityControl secCtrl; + // Decrypt secure APDU // Somehow ugly that we need to know the size in advance here at this point uint16_t plainApduLength = apdu.length() - 1 - 6 - 4; // secureAdsuLength - sizeof(scf) - sizeof(seqNum) - sizeof(mac) CemiFrame plainFrame(plainApduLength); // Decrypt secure APDU - if (decodeSecureApdu(apdu, plainFrame.apdu())) + if (decodeSecureApdu(apdu, plainFrame.apdu(), secCtrl)) { // Process decrypted inner APDU - ApplicationLayer::dataGroupConfirm(ack, hopType, priority, tsap, plainFrame.apdu(), status); + ApplicationLayer::dataGroupConfirm(ack, hopType, priority, tsap, plainFrame.apdu(), secCtrl, status); } return; } @@ -88,15 +91,18 @@ void SecureApplicationLayer::dataBroadcastIndication(HopCountType hopType, Prior if (apdu.type() == SecureService) { + // Will be filled in by decodeSecureApdu() + SecurityControl secCtrl; + // Decrypt secure APDU // Somehow ugly that we need to know the size in advance here at this point uint16_t plainApduLength = apdu.length() - 1 - 6 - 4; // secureAdsuLength - sizeof(scf) - sizeof(seqNum) - sizeof(mac) CemiFrame plainFrame(plainApduLength); // Decrypt secure APDU - if (decodeSecureApdu(apdu, plainFrame.apdu())) + if (decodeSecureApdu(apdu, plainFrame.apdu(), secCtrl)) { // Process decrypted inner APDU - ApplicationLayer::dataBroadcastIndication(hopType, priority, source, plainFrame.apdu()); + ApplicationLayer::dataBroadcastIndication(hopType, priority, source, plainFrame.apdu(), secCtrl); } return; } @@ -110,18 +116,19 @@ void SecureApplicationLayer::dataBroadcastConfirm(AckType ack, HopCountType hopT if (apdu.type() == SecureService) { -/* + // Will be filled in by decodeSecureApdu() + SecurityControl secCtrl; + // Decrypt secure APDU // Somehow ugly that we need to know the size in advance here at this point uint16_t plainApduLength = apdu.length() - 1 - 6 - 4; // secureAdsuLength - sizeof(scf) - sizeof(seqNum) - sizeof(mac) CemiFrame plainFrame(plainApduLength); // Decrypt secure APDU - if (decodeSecureApdu(apdu, plainFrame.apdu())) + if (decodeSecureApdu(apdu, plainFrame.apdu(), secCtrl)) { // Process decrypted inner APDU - ApplicationLayer::dataBroadcastConfirm(ack, hopType, priority, plainFrame.apdu(), status); + ApplicationLayer::dataBroadcastConfirm(ack, hopType, priority, plainFrame.apdu(), secCtrl, status); } -*/ return; } ApplicationLayer::dataBroadcastConfirm(ack, hopType, priority, apdu, status); @@ -133,15 +140,18 @@ void SecureApplicationLayer::dataSystemBroadcastIndication(HopCountType hopType, if (apdu.type() == SecureService) { + // Will be filled in by decodeSecureApdu() + SecurityControl secCtrl; + // Decrypt secure APDU // Somehow ugly that we need to know the size in advance here at this point uint16_t plainApduLength = apdu.length() - 1 - 6 - 4; // secureAdsuLength - sizeof(scf) - sizeof(seqNum) - sizeof(mac) CemiFrame plainFrame(plainApduLength); // Decrypt secure APDU - if (decodeSecureApdu(apdu, plainFrame.apdu())) + if (decodeSecureApdu(apdu, plainFrame.apdu(), secCtrl)) { // Process decrypted inner APDU - ApplicationLayer::dataSystemBroadcastIndication(hopType, priority, source, plainFrame.apdu()); + ApplicationLayer::dataSystemBroadcastIndication(hopType, priority, source, plainFrame.apdu(), secCtrl); } return; } @@ -155,18 +165,19 @@ void SecureApplicationLayer::dataSystemBroadcastConfirm(HopCountType hopType, Pr if (apdu.type() == SecureService) { -/* + // Will be filled in by decodeSecureApdu() + SecurityControl secCtrl; + // Decrypt secure APDU // Somehow ugly that we need to know the size in advance here at this point uint16_t plainApduLength = apdu.length() - 1 - 6 - 4; // secureAdsuLength - sizeof(scf) - sizeof(seqNum) - sizeof(mac) CemiFrame plainFrame(plainApduLength); // Decrypt secure APDU - if (decodeSecureApdu(apdu, plainFrame.apdu())) + if (decodeSecureApdu(apdu, plainFrame.apdu(), secCtrl)) { // Process decrypted inner APDU - ApplicationLayer::dataSystemBroadcastConfirm(hopType, priority, plainFrame.apdu(), status); + ApplicationLayer::dataSystemBroadcastConfirm(hopType, priority, plainFrame.apdu(), secCtrl, status); } -*/ return; } @@ -179,15 +190,18 @@ void SecureApplicationLayer::dataIndividualIndication(HopCountType hopType, Prio if (apdu.type() == SecureService) { + // Will be filled in by decodeSecureApdu() + SecurityControl secCtrl; + // Decrypt secure APDU // Somehow ugly that we need to know the size in advance here at this point uint16_t plainApduLength = apdu.length() - 1 - 6 - 4; // secureAdsuLength - sizeof(scf) - sizeof(seqNum) - sizeof(mac) CemiFrame plainFrame(plainApduLength); // Decrypt secure APDU - if (decodeSecureApdu(apdu, plainFrame.apdu())) + if (decodeSecureApdu(apdu, plainFrame.apdu(), secCtrl)) { // Process decrypted inner APDU - ApplicationLayer::dataIndividualIndication(hopType, priority, source, plainFrame.apdu()); + ApplicationLayer::dataIndividualIndication(hopType, priority, source, plainFrame.apdu(), secCtrl); } return; } @@ -201,12 +215,19 @@ void SecureApplicationLayer::dataIndividualConfirm(AckType ack, HopCountType hop if (apdu.type() == SecureService) { -/* - // Decrypt secure APDU + // Will be filled in by decodeSecureApdu() + SecurityControl secCtrl; - // Process decrypted inner APDU - ApplicationLayer::dataIndividualConfirm(ack, hopType, priority, source, apdu, status); -*/ + // Decrypt secure APDU + // Somehow ugly that we need to know the size in advance here at this point + uint16_t plainApduLength = apdu.length() - 1 - 6 - 4; // secureAdsuLength - sizeof(scf) - sizeof(seqNum) - sizeof(mac) + CemiFrame plainFrame(plainApduLength); + // Decrypt secure APDU + if (decodeSecureApdu(apdu, plainFrame.apdu(), secCtrl)) + { + // Process decrypted inner APDU + ApplicationLayer::dataIndividualConfirm(ack, hopType, priority, source, apdu, secCtrl, status); + } return; } else @@ -221,14 +242,18 @@ void SecureApplicationLayer::dataConnectedIndication(Priority priority, uint16_t if (apdu.type() == SecureService) { + // Will be filled in by decodeSecureApdu() + SecurityControl secCtrl; + + // Decrypt secure APDU // Somehow ugly that we need to know the size in advance here at this point uint16_t plainApduLength = apdu.length() - 1 - 6 - 4; // secureAdsuLength - sizeof(scf) - sizeof(seqNum) - sizeof(mac) CemiFrame plainFrame(plainApduLength); // Decrypt secure APDU - if (decodeSecureApdu(apdu, plainFrame.apdu())) + if (decodeSecureApdu(apdu, plainFrame.apdu(), secCtrl)) { // Process decrypted inner APDU - ApplicationLayer::dataConnectedIndication(priority, tsap, plainFrame.apdu()); + ApplicationLayer::dataConnectedIndication(priority, tsap, plainFrame.apdu(), secCtrl); } return; } @@ -238,6 +263,7 @@ void SecureApplicationLayer::dataConnectedIndication(Priority priority, uint16_t void SecureApplicationLayer::dataConnectedConfirm(uint16_t tsap) { + // Just the confirmation issued by the transport layer in case of T_DATA_CONNECTED ApplicationLayer::dataConnectedConfirm(tsap); } @@ -250,7 +276,7 @@ void SecureApplicationLayer::dataGroupRequest(AckType ack, HopCountType hopType, uint16_t secureApduLength = apdu.length() + 2 + 6 + 4; // 2(TPCI,APCI,SCF) + sizeof(seqNum) + apdu.length() + 4 CemiFrame secureFrame(secureApduLength); // create secure APDU - if (createSecureApdu(apdu, secureFrame.apdu(), true, true)) // TODO: toolAccess, confidentialty + if (createSecureApdu(apdu, secureFrame.apdu(), secCtrl)) { ApplicationLayer::dataGroupRequest(ack, hopType, priority, tsap, secureFrame.apdu(), secCtrl); } @@ -267,7 +293,7 @@ void SecureApplicationLayer::dataBroadcastRequest(AckType ack, HopCountType hopT uint16_t secureApduLength = apdu.length() + 2 + 6 + 4; // 2(TPCI,APCI,SCF) + sizeof(seqNum) + apdu.length() + 4 CemiFrame secureFrame(secureApduLength); // create secure APDU - if (createSecureApdu(apdu, secureFrame.apdu(), true, true)) // TODO: toolAccess, confidentialty + if (createSecureApdu(apdu, secureFrame.apdu(), secCtrl)) { ApplicationLayer::dataBroadcastRequest(ack, hopType, SystemPriority, secureFrame.apdu(), secCtrl); } @@ -284,7 +310,7 @@ void SecureApplicationLayer::dataSystemBroadcastRequest(AckType ack, HopCountTyp uint16_t secureApduLength = apdu.length() + 2 + 6 + 4; // 2(TPCI,APCI,SCF) + sizeof(seqNum) + apdu.length() + 4 CemiFrame secureFrame(secureApduLength); // create secure APDU - if (createSecureApdu(apdu, secureFrame.apdu(), true, true)) // TODO: toolAccess, confidentialty + if (createSecureApdu(apdu, secureFrame.apdu(), secCtrl)) { ApplicationLayer::dataSystemBroadcastRequest(ack, hopType, SystemPriority, secureFrame.apdu(), secCtrl); } @@ -301,7 +327,7 @@ void SecureApplicationLayer::dataIndividualRequest(AckType ack, HopCountType hop uint16_t secureApduLength = apdu.length() + 2 + 6 + 4; // 2(TPCI,APCI,SCF) + sizeof(seqNum) + apdu.length() + 4 CemiFrame secureFrame(secureApduLength); // create secure APDU - if (createSecureApdu(apdu, secureFrame.apdu(), true, true)) // TODO: toolAccess, confidentialty + if (createSecureApdu(apdu, secureFrame.apdu(), secCtrl)) { ApplicationLayer::dataIndividualRequest(ack, hopType, priority, destination, secureFrame.apdu(), secCtrl); } @@ -318,7 +344,7 @@ void SecureApplicationLayer::dataConnectedRequest(uint16_t tsap, Priority priori uint16_t secureApduLength = apdu.length() + 2 + 6 + 4; // 2(TPCI,APCI,SCF) + sizeof(seqNum) + apdu.length() + 4 CemiFrame secureFrame(secureApduLength); // create secure APDU - if (createSecureApdu(apdu, secureFrame.apdu(), true, true)) // TODO: toolAccess, confidentialty + if (createSecureApdu(apdu, secureFrame.apdu(), secCtrl)) { ApplicationLayer::dataConnectedRequest(tsap, priority, secureFrame.apdu(), secCtrl); } @@ -576,8 +602,14 @@ void SecureApplicationLayer::updateLastValidSequence(bool toolAccess, uint16_t r } } -void SecureApplicationLayer::sendSyncRequest(uint16_t dstAddr, bool dstAddrIsGroupAddr, bool toolAccess) +void SecureApplicationLayer::sendSyncRequest(uint16_t dstAddr, bool dstAddrIsGroupAddr, const SecurityControl &secCtrl) { + if (secCtrl.dataSecurity != DataSecurity::authConf) + { + println("sync.req is always sent with auth+conf!"); + return; + } + _syncReqBroadcastOutgoing = (dstAddr == 0x0000) && dstAddrIsGroupAddr; // use random number in SyncResponse @@ -597,7 +629,7 @@ void SecureApplicationLayer::sendSyncRequest(uint16_t dstAddr, bool dstAddrIsGro print("sendSyncRequest: TPCI: "); println(tpci, HEX); - if(secure(request.data() + APDU_LPDU_DIFF, SecureSyncRequest, _deviceObj.induvidualAddress(), dstAddr, dstAddrIsGroupAddr, tpci, asdu, sizeof(asdu), toolAccess, true)) + if(secure(request.data() + APDU_LPDU_DIFF, SecureSyncRequest, _deviceObj.induvidualAddress(), dstAddr, dstAddrIsGroupAddr, tpci, asdu, sizeof(asdu), secCtrl)) { println("SyncRequest: "); request.apdu().printPDU(); @@ -625,9 +657,15 @@ void SecureApplicationLayer::sendSyncRequest(uint16_t dstAddr, bool dstAddrIsGro } } -void SecureApplicationLayer::sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGroupAddr, bool toolAccess, uint64_t remoteNextSeqNum) +void SecureApplicationLayer::sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGroupAddr, const SecurityControl &secCtrl, uint64_t remoteNextSeqNum) { - uint64_t ourNextSeqNum = nextSequenceNumber(toolAccess); + if (secCtrl.dataSecurity != DataSecurity::authConf) + { + println("sync.res is always sent with auth+conf!"); + return; + } + + uint64_t ourNextSeqNum = nextSequenceNumber(secCtrl.toolAccess); uint8_t asdu[12]; sixBytesFromUInt64(ourNextSeqNum, &asdu[0]); @@ -644,7 +682,7 @@ void SecureApplicationLayer::sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGr print("sendSyncResponse: TPCI: "); println(tpci, HEX); - if(secure(response.data() + APDU_LPDU_DIFF, SecureSyncResponse, _deviceObj.induvidualAddress(), dstAddr, dstAddrIsGroupAddr, tpci, asdu, sizeof(asdu), toolAccess, true)) + if(secure(response.data() + APDU_LPDU_DIFF, SecureSyncResponse, _deviceObj.induvidualAddress(), dstAddr, dstAddrIsGroupAddr, tpci, asdu, sizeof(asdu), secCtrl)) { _lastSyncRes = millis(); @@ -671,14 +709,14 @@ void SecureApplicationLayer::sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGr } } -void SecureApplicationLayer::receivedSyncRequest(uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, bool toolAccess, uint8_t* seqNum, uint64_t challenge) +void SecureApplicationLayer::receivedSyncRequest(uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, const SecurityControl &secCtrl, uint8_t* seqNum, uint64_t challenge) { uint64_t nextRemoteSeqNum = sixBytesToUInt64(seqNum); - uint64_t nextSeqNum = 1 + lastValidSequenceNumber(toolAccess, srcAddr); + uint64_t nextSeqNum = 1 + lastValidSequenceNumber(secCtrl.toolAccess, srcAddr); if (nextRemoteSeqNum > nextSeqNum) { - updateLastValidSequence(toolAccess, srcAddr, nextRemoteSeqNum - 1); + updateLastValidSequence(secCtrl.toolAccess, srcAddr, nextRemoteSeqNum - 1); nextSeqNum = nextRemoteSeqNum; } @@ -690,10 +728,10 @@ void SecureApplicationLayer::receivedSyncRequest(uint16_t srcAddr, uint16_t dstA uint16_t toAddr = _syncReqBroadcastIncoming ? dstAddr : srcAddr; bool toIsGroupAddress = _syncReqBroadcastIncoming; - sendSyncResponse(toAddr, toIsGroupAddress, toolAccess, nextSeqNum); + sendSyncResponse(toAddr, toIsGroupAddress, secCtrl, nextSeqNum); } -void SecureApplicationLayer::receivedSyncResponse(uint16_t remote, bool toolAccess, uint8_t* plainApdu) +void SecureApplicationLayer::receivedSyncResponse(uint16_t remote, const SecurityControl &secCtrl, uint8_t* plainApdu) { if (_syncReqBroadcastOutgoing) { @@ -717,24 +755,24 @@ void SecureApplicationLayer::receivedSyncResponse(uint16_t remote, bool toolAcce uint64_t remoteSeq = sixBytesToUInt64(plainApdu + 0); uint64_t localSeq = sixBytesToUInt64(plainApdu + 6); - uint64_t last = lastValidSequenceNumber(toolAccess, remote); + uint64_t last = lastValidSequenceNumber(secCtrl.toolAccess, remote); if (remoteSeq - 1 > last) { //logger.debug("sync.res update {} last valid {} seq -> {}", remote, toolAccess ? "tool access" : "p2p", remoteSeq -1); - updateLastValidSequence(toolAccess, remote, remoteSeq - 1); + updateLastValidSequence(secCtrl.toolAccess, remote, remoteSeq - 1); } - uint64_t next = nextSequenceNumber(toolAccess); + uint64_t next = nextSequenceNumber(secCtrl.toolAccess); if (localSeq > next) { //logger.debug("sync.res update local next {} seq -> {}", toolAccess ? "tool access" : "p2p", localSeq); - updateSequenceNumber(toolAccess, localSeq); + updateSequenceNumber(secCtrl.toolAccess, localSeq); } Addr remoteAddr = _syncReqBroadcastOutgoing ? (Addr)GrpAddr(0) : (Addr)IndAddr(remote); _pendingOutgoingSyncRequests.erase(remoteAddr); } -bool SecureApplicationLayer::decrypt(uint8_t* plainApdu, uint16_t plainApduLength, uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, uint8_t tpci, uint8_t* secureAsdu) +bool SecureApplicationLayer::decrypt(uint8_t* plainApdu, uint16_t plainApduLength, uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, uint8_t tpci, uint8_t* secureAsdu, SecurityControl& secCtrl) { const uint8_t* pBuf; uint8_t scf; @@ -747,6 +785,9 @@ bool SecureApplicationLayer::decrypt(uint8_t* plainApdu, uint16_t plainApduLengt bool authOnly = ( sai == 0); uint8_t service = (scf & 0x07); // only 0x0 (S-A_Data-PDU), 0x2 (S-A_Sync_Req-PDU) or 0x3 (S-A_Sync_Rsp-PDU) are valid values + secCtrl.toolAccess = toolAccess; + secCtrl.dataSecurity = authOnly ? DataSecurity::auth : DataSecurity::authConf; + bool syncReq = service == SecureSyncRequest; bool syncRes = service == SecureSyncResponse; @@ -910,11 +951,11 @@ bool SecureApplicationLayer::decrypt(uint8_t* plainApdu, uint16_t plainApduLengt if (syncReq) { uint64_t challenge = sixBytesToUInt64(&plainApdu[0]); - receivedSyncRequest(srcAddr, dstAddr, dstAddrIsGroupAddr, toolAccess, seqNum, challenge); + receivedSyncRequest(srcAddr, dstAddr, dstAddrIsGroupAddr, secCtrl, seqNum, challenge); } else if (syncRes) { - receivedSyncResponse(srcAddr, toolAccess, plainApdu); + receivedSyncResponse(srcAddr, secCtrl, plainApdu); } else { @@ -937,7 +978,7 @@ bool SecureApplicationLayer::decrypt(uint8_t* plainApdu, uint16_t plainApduLengt return true; } -bool SecureApplicationLayer::decodeSecureApdu(APDU& secureApdu, APDU& plainApdu) +bool SecureApplicationLayer::decodeSecureApdu(APDU& secureApdu, APDU& plainApdu, SecurityControl& secCtrl) { // Decode secure APDU @@ -960,7 +1001,7 @@ bool SecureApplicationLayer::decodeSecureApdu(APDU& secureApdu, APDU& plainApdu) // In T_DATA_* services the bits1-0 of TPCI octet are used as bits9-8 for APCI type which is fixed to 0x03. SecureService APCI is 0x03F1. // FIXME: when cEMI class is refactored, there might be additional info fields in cEMI (fixed APDU_LPDU_DIFF) - if (decrypt(plainApdu.frame().data()+APDU_LPDU_DIFF, plainApdu.length()-1, srcAddress, dstAddress, isDstAddrGroupAddr, tpci, secureApdu.data()+1)) + if (decrypt(plainApdu.frame().data()+APDU_LPDU_DIFF, plainApdu.length()-1, srcAddress, dstAddress, isDstAddrGroupAddr, tpci, secureApdu.data()+1, secCtrl)) { println("decodeSecureApdu: Plain APDU: "); plainApdu.frame().apdu().printPDU(); @@ -972,8 +1013,11 @@ bool SecureApplicationLayer::decodeSecureApdu(APDU& secureApdu, APDU& plainApdu) } bool 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) + uint8_t* apdu, uint16_t apduLength, const SecurityControl& secCtrl) { + bool toolAccess = secCtrl.toolAccess; + bool confidentiality = secCtrl.dataSecurity == DataSecurity::authConf; + if (toolAccess) { if (!confidentiality) @@ -1107,7 +1151,7 @@ bool SecureApplicationLayer::secure(uint8_t* buffer, uint16_t service, uint16_t return true; } -bool SecureApplicationLayer::createSecureApdu(APDU& plainApdu, APDU& secureApdu, bool toolAccess, bool confidentialty) +bool SecureApplicationLayer::createSecureApdu(APDU& plainApdu, APDU& secureApdu, const SecurityControl& secCtrl) { // Create secure APDU @@ -1130,9 +1174,9 @@ bool SecureApplicationLayer::createSecureApdu(APDU& plainApdu, APDU& secureApdu, // In T_DATA_* services the bits1-0 of TPCI octet are used as bits9-8 for APCI type which is fixed to 0x03. SecureService APCI is 0x03F1. // FIXME: when cEMI class is refactored, there might be additional info fields in cEMI (fixed APDU_LPDU_DIFF) - if(secure(secureApdu.frame().data()+APDU_LPDU_DIFF, SecureDataPdu, srcAddress, dstAddress, isDstAddrGroupAddr, tpci, plainApdu.data()+1, plainApdu.length()-1, toolAccess, confidentialty)) + if(secure(secureApdu.frame().data()+APDU_LPDU_DIFF, SecureDataPdu, srcAddress, dstAddress, isDstAddrGroupAddr, tpci, plainApdu.data()+1, plainApdu.length()-1, secCtrl)) { - updateSequenceNumber(toolAccess, nextSequenceNumber(toolAccess) + 1); + updateSequenceNumber(secCtrl.toolAccess, nextSequenceNumber(secCtrl.toolAccess) + 1); println("createSecureApdu: Secure APDU: "); plainApdu.frame().apdu().printPDU(); diff --git a/src/knx/secure_application_layer.h b/src/knx/secure_application_layer.h index 484de7b..b8577ec 100644 --- a/src/knx/secure_application_layer.h +++ b/src/knx/secure_application_layer.h @@ -247,16 +247,16 @@ class SecureApplicationLayer : public ApplicationLayer 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); + void sendSyncRequest(uint16_t dstAddr, bool dstAddrIsGroupAddr, const SecurityControl &secCtrl); + void sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGroupAddr, const SecurityControl &secCtrl, uint64_t remoteNextSeqNum); + void receivedSyncRequest(uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, const SecurityControl &secCtrl, uint8_t* seq, uint64_t challenge); + void receivedSyncResponse(uint16_t remoteAddr, const SecurityControl &secCtrl, uint8_t* plainApdu); - bool decrypt(uint8_t* plainApdu, uint16_t plainapduLength, uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, uint8_t tpci, uint8_t* secureAsdu); - bool 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 decrypt(uint8_t* plainApdu, uint16_t plainapduLength, uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, uint8_t tpci, uint8_t* secureAsdu, SecurityControl &secCtrl); + bool secure(uint8_t* buffer, uint16_t service, uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, uint8_t tpci, uint8_t* apdu, uint16_t apduLength, const SecurityControl &secCtrl); - bool decodeSecureApdu(APDU& secureApdu, APDU& plainApdu); - bool createSecureApdu(APDU& plainApdu, APDU& secureApdu, bool toolAccess, bool confidentialty); + bool decodeSecureApdu(APDU& secureApdu, APDU& plainApdu, SecurityControl &secCtrl); + bool createSecureApdu(APDU& plainApdu, APDU& secureApdu, const SecurityControl &secCtrl); void encryptAesCbc(uint8_t* buffer, uint16_t bufLen, const uint8_t* iv, const uint8_t* key); void xcryptAesCtr(uint8_t* buffer, uint16_t bufLen, const uint8_t* iv, const uint8_t* key);