Add support for KNX data secure (#66)

* initial comic

* save work

* Handle SystemBroadcast and Broadcast for TP and IP

* Rework

* Fix comment

* save work

* save work

* save work

* save work

* save work

* Restore old broadcast structure

* Readd systembroadcast methods

* Make sure that services from SystemBroadcast are also available from Broadcast on closed media

* save work

* Save work

* save work

* Save work

* save work

* save work

* save work

* save work

* save work

* Change maximum number of elements for the key tables, etc.

* save work

* First working seqno sync with ETS

* save work

* save work

* save work

* save work

* save work

* save work

* Remove magic value and add comment

* save work

* Extend restart and masterreset for factory reset

* save work

* First working secure broadcast mode with IA programming

* Add FunctionPropertyExt* AL services

* Fix FunctionPropertyExt*. Working T_DATA_CONNECTED with FunctionPropertyExt*.

* Add PropertyValueExt* AL services. Handle master reset in AL service RESTART.

* Fix FunctionPropertyExtStateRead, fix restart. MILESTONE: Working physical programming of IA and toolkey with confirmed restart. Reading deviceinfos working.

* Handle PDT_CONTROL in FunctionPropertyExt*

* Fix FunctionPropertyExt* and FunctionProperty for PDT_CONTROL

* Change comment.

* save work

* save work

* Add group object security handling

* Move map to own file

* use simple_map

* Include simple_map.h in CmakeFile

* Move code from header to source file

* Remove obsolete code

* MILESTONE: working programming of secure device with IA and tables

* cleanup

* bugfix

* flashSize must be big enough. Security IF object contains a lot more data.

* Merge master into feat_datasecure

* Revert "Merge master into feat_datasecure"

This reverts commit 0c8358692a.

* Revert "Revert "Merge master into feat_datasecure""

This reverts commit aa59253785.

* Bugfixes

* cleanup

* cleanup

* Add printing of uint64_t

* Don't compile secapplayer if data secure not enabled

* pin platform for ESP8266 to specific version

* SecIfObject: save/restore required for persisting STATE. Bugfix: use correct PID for group key table

* Cleanup comment and debug output

* Further cleanup.

* Refactor master reset

* Remove unused IP data link layer test code

* Only reset TOOL kkey to FDSK on factory reset

* Modify .gitignore and remove vscode config file

* Correct comment

* Handle SBC flag (systembroadcast) in SCF field. Couplers between open and closed media need this.

* Remove code that slipped in.
This commit is contained in:
nanosonde 2020-07-06 19:16:54 +02:00 committed by GitHub
parent 8cfd67662f
commit 96884f768e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 4636 additions and 479 deletions

View File

@ -1,5 +1,2 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
.vscode

View File

@ -1,7 +0,0 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
]
}

View File

@ -26,7 +26,7 @@ build_flags =
;--- ESP8266 -----------------------------------------------
[env:nodemcuv2]
platform = espressif8266
platform = espressif8266@2.2.3
board = nodemcuv2
framework = arduino
lib_deps =

View File

@ -35,7 +35,7 @@ build_flags =
;--- ESP8266 -----------------------------------------------
[env:nodemcuv2]
platform = espressif8266
platform = espressif8266@2.2.3
board = nodemcuv2
framework = arduino
; We consider that the this projects is opened within its project directory
@ -43,7 +43,7 @@ framework = arduino
lib_extra_dirs = ../../../
lib_deps =
WifiManager
WifiManager@0.15.0
knx
build_flags =

View File

@ -4,7 +4,10 @@ set(LIBRARIES_FROM_REFERENCES "")
add_executable(knx-linux
../../src/knx/address_table_object.cpp
../../src/knx/address_table_object.h
../../src/knx/apdu.cpp
../../src/knx/aes.c
../../src/knx/aes.h
../../src/knx/aes.hpp
../../src/knx/apdu.cpp
../../src/knx/apdu.h
../../src/knx/application_layer.cpp
../../src/knx/application_layer.h
@ -42,7 +45,8 @@ add_executable(knx-linux
../../src/knx/dpt.h
../../src/knx/dptconvert.cpp
../../src/knx/dptconvert.h
../../src/knx/group_object.cpp
../../src/knx/function_property.h
../../src/knx/group_object.cpp
../../src/knx/group_object.h
../../src/knx/group_object_table_object.cpp
../../src/knx/group_object_table_object.h
@ -87,6 +91,12 @@ add_executable(knx-linux
../../src/knx/rf_medium_object.h
../../src/knx/rf_physical_layer.cpp
../../src/knx/rf_physical_layer.h
../../src/knx/secure_application_layer.cpp
../../src/knx/secure_application_layer.h
../../src/knx/security_interface_object.cpp
../../src/knx/security_interface_object.h
../../src/knx/simple_map.h
../../src/knx/table_object.cpp
../../src/knx/save_restore.h
../../src/knx/table_object.cpp
../../src/knx/table_object.h
@ -102,6 +112,8 @@ add_executable(knx-linux
../../src/knx_facade.h
../../src/linux_platform.cpp
../../src/linux_platform.h
fdsk.cpp
fdsk.h
main.cpp)
target_link_libraries(knx-linux "${LIBRARIES_FROM_REFERENCES}")
include_directories(../../src)

196
examples/knx-linux/fdsk.cpp Normal file
View File

@ -0,0 +1,196 @@
#include "fdsk.h"
#include <string.h>
// CRC-4 generator polynom: 10011 (x^4+x+1)
const uint8_t FdskCalculator::crc4_tab[16] =
{
0x0, 0x3, 0x6, 0x5, 0xc, 0xf, 0xa, 0x9,
0xb, 0x8, 0xd, 0xe, 0x7, 0x4, 0x1, 0x2
};
int FdskCalculator::snprintFdsk(char* str, int strSize, uint8_t* serialNumber, uint8_t* key)
{
char* tmpStr = generateFdskString(serialNumber, key);
int written = 0;
for (int i = 0; i < 36; i++)
{
if (((i % 6) == 0) && (i!=0))
{
*(str+written++) = '-';
if (written >= strSize-1)
break;
}
*(str+written++) = tmpStr[i];
if (written >= strSize-1)
break;
}
*(str+written++) = '\0';
delete[] tmpStr;
return written;
}
char* FdskCalculator::generateFdskString(uint8_t* serialNumber, uint8_t* key)
{
uint8_t buffer[6 + 16 + 1]; // 6 bytes serialnumber + 16 bytes key + 1 byte placeholder for crc-4
memcpy(&buffer[0], serialNumber, 6);
memcpy(&buffer[6], key, 16);
buffer[22] = (crc4Array(buffer, sizeof(buffer)-1)<<4) &0xFF;
uint8_t* outEncoded = nullptr;
toBase32(buffer, sizeof(buffer), outEncoded, false);
return (char*)outEncoded;
}
int FdskCalculator::ceil(float num)
{
int inum = (int)num;
if (num == (float)inum) {
return inum;
}
return inum + 1;
}
int FdskCalculator::toBase32(uint8_t* in, long length, uint8_t*& out, bool usePadding)
{
char base32StandardAlphabet[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"};
char standardPaddingChar = '=';
int result = 0;
int count = 0;
int bufSize = 8;
int index = 0;
int size = 0; // size of temporary array
uint8_t* temp = nullptr;
if (length < 0 || length > 268435456LL)
{
return 0;
}
size = 8 * ceil(length / 4.0); // Calculating size of temporary array. Not very precise.
temp = new uint8_t[size];
if (length > 0)
{
int buffer = in[0];
int next = 1;
int bitsLeft = 8;
while (count < bufSize && (bitsLeft > 0 || next < length))
{
if (bitsLeft < 5)
{
if (next < length)
{
buffer <<= 8;
buffer |= in[next] & 0xFF;
next++;
bitsLeft += 8;
}
else
{
int pad = 5 - bitsLeft;
buffer <<= pad;
bitsLeft += pad;
}
}
index = 0x1F & (buffer >> (bitsLeft -5));
bitsLeft -= 5;
temp[result] = (uint8_t)base32StandardAlphabet[index];
result++;
}
}
if (usePadding)
{
int pads = (result % 8);
if (pads > 0)
{
pads = (8 - pads);
for (int i = 0; i < pads; i++)
{
temp[result] = standardPaddingChar;
result++;
}
}
}
out = new uint8_t[result];
memcpy(out, temp, result);
delete [] temp;
return result;
}
int FdskCalculator::fromBase32(uint8_t* in, long length, uint8_t*& out)
{
int result = 0; // Length of the array of decoded values.
int buffer = 0;
int bitsLeft = 0;
uint8_t* temp = NULL;
temp = new uint8_t[length]; // Allocating temporary array.
for (int i = 0; i < length; i++)
{
uint8_t ch = in[i];
// ignoring some characters: ' ', '\t', '\r', '\n', '='
if (ch == 0xA0 || ch == 0x09 || ch == 0x0A || ch == 0x0D || ch == 0x3D)
continue;
// recovering mistyped: '0' -> 'O', '1' -> 'L', '8' -> 'B'
if (ch == 0x30)
{
ch = 0x4F;
}
else if (ch == 0x31)
{
ch = 0x4C;
}
else if (ch == 0x38)
{
ch = 0x42;
}
// look up one base32 symbols: from 'A' to 'Z' or from 'a' to 'z' or from '2' to '7'
if ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))
{
ch = ((ch & 0x1F) - 1);
}
else if (ch >= 0x32 && ch <= 0x37)
{
ch -= (0x32 - 26);
}
else {
delete [] temp;
return 0;
}
buffer <<= 5;
buffer |= ch;
bitsLeft += 5;
if (bitsLeft >= 8)
{
temp[result] = (unsigned char)((unsigned int)(buffer >> (bitsLeft - 8)) & 0xFF);
result++;
bitsLeft -= 8;
}
}
out = new uint8_t[result];
memcpy(out, temp, result);
delete [] temp;
return result;
}

37
examples/knx-linux/fdsk.h Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#include <stdint.h>
class FdskCalculator
{
public:
int snprintFdsk(char* str, int strSize, uint8_t* serialNumber, uint8_t* key);
private:
char* generateFdskString(uint8_t* serialNumber, uint8_t* key);
int toBase32(uint8_t* in, long length, uint8_t*& out, bool usePadding);
int fromBase32(uint8_t* in, long length, uint8_t*& out);
uint8_t crc4Array(uint8_t* data, uint8_t len) {
uint8_t start = 0;
for (uint8_t i = 0; i <len; i++)
{
start = crc4(start, data[i]);
}
return start;
}
uint8_t crc4(uint8_t c, uint8_t x) {
uint8_t low4Bits = x & 0x0F;
uint8_t high4Bits = x >> 4;
c = crc4_tab[c ^ high4Bits];
c = crc4_tab[c ^ low4Bits];
return c;
}
int ceil(float num);
static const uint8_t crc4_tab[16];
};

View File

@ -14,6 +14,8 @@
#include <sched.h>
#include <sys/mman.h>
#include "fdsk.h"
volatile sig_atomic_t loopActive = 1;
void signalHandler(int sig)
{
@ -119,6 +121,14 @@ int main(int argc, char **argv)
{
printf("main() start.\n");
uint8_t serialNumber[] = { 0x00, 0xFA, 0x01, 0x02, 0x03, 0x04};
uint8_t key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
FdskCalculator calc;
char fdskString[42]; // 6 * 6 chars + 5 dashes + nullbyte = 42
calc.snprintFdsk(fdskString, sizeof(fdskString), serialNumber, key);
printf("FDSK: %s\n", fdskString);
// Prevent swapping of this process
struct sched_param sp;
memset(&sp, 0, sizeof(sp));

View File

@ -111,6 +111,23 @@ int ArduinoPlatform::readWriteSpi(uint8_t *data, size_t len)
return 0;
}
void printUint64(uint64_t value, int base = DEC)
{
char buf[8 * sizeof(uint64_t) + 1];
char* str = &buf[sizeof(buf) - 1];
*str = '\0';
uint64_t n = value;
do {
char c = n % base;
n /= base;
*--str = c < 10 ? c + '0' : c + 'A' - 10;
} while (n > 0);
print(str);
}
void print(const char* s)
{
ArduinoPlatform::SerialDebug->print(s);
@ -170,6 +187,16 @@ void print(unsigned long num, int base)
ArduinoPlatform::SerialDebug->print(num, base);
}
void print(unsigned long long num)
{
printUint64(num);
}
void print(unsigned long long num, int base)
{
printUint64(num, base);
}
void print(double num)
{
ArduinoPlatform::SerialDebug->print(num);
@ -235,6 +262,18 @@ void println(unsigned long num, int base)
ArduinoPlatform::SerialDebug->println(num, base);
}
void println(unsigned long long num)
{
printUint64(num);
println("");
}
void println(unsigned long long num, int base)
{
printUint64(num, base);
println("");
}
void println(double num)
{
ArduinoPlatform::SerialDebug->println(num);

569
src/knx/aes.c Normal file
View File

@ -0,0 +1,569 @@
/*
This is an implementation of the AES algorithm, specifically ECB, CTR and CBC mode.
Block size can be chosen in aes.h - available choices are AES128, AES192, AES256.
The implementation is verified against the test vectors in:
National Institute of Standards and Technology Special Publication 800-38A 2001 ED
ECB-AES128
----------
plain-text:
6bc1bee22e409f96e93d7e117393172a
ae2d8a571e03ac9c9eb76fac45af8e51
30c81c46a35ce411e5fbc1191a0a52ef
f69f2445df4f9b17ad2b417be66c3710
key:
2b7e151628aed2a6abf7158809cf4f3c
resulting cipher
3ad77bb40d7a3660a89ecaf32466ef97
f5d3d58503b9699de785895a96fdbaaf
43b1cd7f598ece23881b00e3ed030688
7b0c785e27e8ad3f8223207104725dd4
NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0)
You should pad the end of the string with zeros if this is not the case.
For AES192/256 the key size is proportionally larger.
*/
/*****************************************************************************/
/* Includes: */
/*****************************************************************************/
#include <string.h> // CBC mode, for memset
#include "aes.h"
/*****************************************************************************/
/* Defines: */
/*****************************************************************************/
// The number of columns comprising a state in AES. This is a constant in AES. Value=4
#define Nb 4
#if defined(AES256) && (AES256 == 1)
#define Nk 8
#define Nr 14
#elif defined(AES192) && (AES192 == 1)
#define Nk 6
#define Nr 12
#else
#define Nk 4 // The number of 32 bit words in a key.
#define Nr 10 // The number of rounds in AES Cipher.
#endif
// jcallan@github points out that declaring Multiply as a function
// reduces code size considerably with the Keil ARM compiler.
// See this link for more information: https://github.com/kokke/tiny-AES-C/pull/3
#ifndef MULTIPLY_AS_A_FUNCTION
#define MULTIPLY_AS_A_FUNCTION 0
#endif
/*****************************************************************************/
/* Private variables: */
/*****************************************************************************/
// state - array holding the intermediate results during decryption.
typedef uint8_t state_t[4][4];
// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
// The numbers below can be computed dynamically trading ROM for RAM -
// This can be useful in (embedded) bootloader applications, where ROM is often limited.
static const uint8_t sbox[256] = {
//0 1 2 3 4 5 6 7 8 9 A B C D E F
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
static const uint8_t rsbox[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
// The round constant word array, Rcon[i], contains the values given by
// x to the power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
static const uint8_t Rcon[11] = {
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
/*
* Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES-C/pull/12),
* that you can remove most of the elements in the Rcon array, because they are unused.
*
* From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon
*
* "Only the first some of these constants are actually used up to rcon[10] for AES-128 (as 11 round keys are needed),
* up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm."
*/
/*****************************************************************************/
/* Private functions: */
/*****************************************************************************/
/*
static uint8_t getSBoxValue(uint8_t num)
{
return sbox[num];
}
*/
#define getSBoxValue(num) (sbox[(num)])
/*
static uint8_t getSBoxInvert(uint8_t num)
{
return rsbox[num];
}
*/
#define getSBoxInvert(num) (rsbox[(num)])
// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states.
static void KeyExpansion(uint8_t* RoundKey, const uint8_t* Key)
{
unsigned i, j, k;
uint8_t tempa[4]; // Used for the column/row operations
// The first round key is the key itself.
for (i = 0; i < Nk; ++i)
{
RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
}
// All other round keys are found from the previous round keys.
for (i = Nk; i < Nb * (Nr + 1); ++i)
{
{
k = (i - 1) * 4;
tempa[0]=RoundKey[k + 0];
tempa[1]=RoundKey[k + 1];
tempa[2]=RoundKey[k + 2];
tempa[3]=RoundKey[k + 3];
}
if (i % Nk == 0)
{
// This function shifts the 4 bytes in a word to the left once.
// [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
// Function RotWord()
{
const uint8_t u8tmp = tempa[0];
tempa[0] = tempa[1];
tempa[1] = tempa[2];
tempa[2] = tempa[3];
tempa[3] = u8tmp;
}
// SubWord() is a function that takes a four-byte input word and
// applies the S-box to each of the four bytes to produce an output word.
// Function Subword()
{
tempa[0] = getSBoxValue(tempa[0]);
tempa[1] = getSBoxValue(tempa[1]);
tempa[2] = getSBoxValue(tempa[2]);
tempa[3] = getSBoxValue(tempa[3]);
}
tempa[0] = tempa[0] ^ Rcon[i/Nk];
}
#if defined(AES256) && (AES256 == 1)
if (i % Nk == 4)
{
// Function Subword()
{
tempa[0] = getSBoxValue(tempa[0]);
tempa[1] = getSBoxValue(tempa[1]);
tempa[2] = getSBoxValue(tempa[2]);
tempa[3] = getSBoxValue(tempa[3]);
}
}
#endif
j = i * 4; k=(i - Nk) * 4;
RoundKey[j + 0] = RoundKey[k + 0] ^ tempa[0];
RoundKey[j + 1] = RoundKey[k + 1] ^ tempa[1];
RoundKey[j + 2] = RoundKey[k + 2] ^ tempa[2];
RoundKey[j + 3] = RoundKey[k + 3] ^ tempa[3];
}
}
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key)
{
KeyExpansion(ctx->RoundKey, key);
}
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv)
{
KeyExpansion(ctx->RoundKey, key);
memcpy (ctx->Iv, iv, AES_BLOCKLEN);
}
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv)
{
memcpy (ctx->Iv, iv, AES_BLOCKLEN);
}
#endif
// This function adds the round key to state.
// The round key is added to the state by an XOR function.
static void AddRoundKey(uint8_t round, state_t* state, const uint8_t* RoundKey)
{
uint8_t i,j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[i][j] ^= RoundKey[(round * Nb * 4) + (i * Nb) + j];
}
}
}
// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
static void SubBytes(state_t* state)
{
uint8_t i, j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[j][i] = getSBoxValue((*state)[j][i]);
}
}
}
// The ShiftRows() function shifts the rows in the state to the left.
// Each row is shifted with different offset.
// Offset = Row number. So the first row is not shifted.
static void ShiftRows(state_t* state)
{
uint8_t temp;
// Rotate first row 1 columns to left
temp = (*state)[0][1];
(*state)[0][1] = (*state)[1][1];
(*state)[1][1] = (*state)[2][1];
(*state)[2][1] = (*state)[3][1];
(*state)[3][1] = temp;
// Rotate second row 2 columns to left
temp = (*state)[0][2];
(*state)[0][2] = (*state)[2][2];
(*state)[2][2] = temp;
temp = (*state)[1][2];
(*state)[1][2] = (*state)[3][2];
(*state)[3][2] = temp;
// Rotate third row 3 columns to left
temp = (*state)[0][3];
(*state)[0][3] = (*state)[3][3];
(*state)[3][3] = (*state)[2][3];
(*state)[2][3] = (*state)[1][3];
(*state)[1][3] = temp;
}
static uint8_t xtime(uint8_t x)
{
return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
}
// MixColumns function mixes the columns of the state matrix
static void MixColumns(state_t* state)
{
uint8_t i;
uint8_t Tmp, Tm, t;
for (i = 0; i < 4; ++i)
{
t = (*state)[i][0];
Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;
Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ;
Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ;
Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ;
Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ;
}
}
// Multiply is used to multiply numbers in the field GF(2^8)
// Note: The last call to xtime() is unneeded, but often ends up generating a smaller binary
// The compiler seems to be able to vectorize the operation better this way.
// See https://github.com/kokke/tiny-AES-c/pull/34
#if MULTIPLY_AS_A_FUNCTION
static uint8_t Multiply(uint8_t x, uint8_t y)
{
return (((y & 1) * x) ^
((y>>1 & 1) * xtime(x)) ^
((y>>2 & 1) * xtime(xtime(x))) ^
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))); /* this last call to xtime() can be omitted */
}
#else
#define Multiply(x, y) \
( ((y & 1) * x) ^ \
((y>>1 & 1) * xtime(x)) ^ \
((y>>2 & 1) * xtime(xtime(x))) ^ \
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \
#endif
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
// MixColumns function mixes the columns of the state matrix.
// The method used to multiply may be difficult to understand for the inexperienced.
// Please use the references to gain more information.
static void InvMixColumns(state_t* state)
{
int i;
uint8_t a, b, c, d;
for (i = 0; i < 4; ++i)
{
a = (*state)[i][0];
b = (*state)[i][1];
c = (*state)[i][2];
d = (*state)[i][3];
(*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
(*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
(*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
(*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
}
}
// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
static void InvSubBytes(state_t* state)
{
uint8_t i, j;
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
(*state)[j][i] = getSBoxInvert((*state)[j][i]);
}
}
}
static void InvShiftRows(state_t* state)
{
uint8_t temp;
// Rotate first row 1 columns to right
temp = (*state)[3][1];
(*state)[3][1] = (*state)[2][1];
(*state)[2][1] = (*state)[1][1];
(*state)[1][1] = (*state)[0][1];
(*state)[0][1] = temp;
// Rotate second row 2 columns to right
temp = (*state)[0][2];
(*state)[0][2] = (*state)[2][2];
(*state)[2][2] = temp;
temp = (*state)[1][2];
(*state)[1][2] = (*state)[3][2];
(*state)[3][2] = temp;
// Rotate third row 3 columns to right
temp = (*state)[0][3];
(*state)[0][3] = (*state)[1][3];
(*state)[1][3] = (*state)[2][3];
(*state)[2][3] = (*state)[3][3];
(*state)[3][3] = temp;
}
#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
// Cipher is the main function that encrypts the PlainText.
static void Cipher(state_t* state, const uint8_t* RoundKey)
{
uint8_t round = 0;
// Add the First round key to the state before starting the rounds.
AddRoundKey(0, state, RoundKey);
// There will be Nr rounds.
// The first Nr-1 rounds are identical.
// These Nr rounds are executed in the loop below.
// Last one without MixColumns()
for (round = 1; ; ++round)
{
SubBytes(state);
ShiftRows(state);
if (round == Nr) {
break;
}
MixColumns(state);
AddRoundKey(round, state, RoundKey);
}
// Add round key to last round
AddRoundKey(Nr, state, RoundKey);
}
#if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
static void InvCipher(state_t* state, const uint8_t* RoundKey)
{
uint8_t round = 0;
// Add the First round key to the state before starting the rounds.
AddRoundKey(Nr, state, RoundKey);
// There will be Nr rounds.
// The first Nr-1 rounds are identical.
// These Nr rounds are executed in the loop below.
// Last one without InvMixColumn()
for (round = (Nr - 1); ; --round)
{
InvShiftRows(state);
InvSubBytes(state);
AddRoundKey(round, state, RoundKey);
if (round == 0) {
break;
}
InvMixColumns(state);
}
}
#endif // #if (defined(CBC) && CBC == 1) || (defined(ECB) && ECB == 1)
/*****************************************************************************/
/* Public functions: */
/*****************************************************************************/
#if defined(ECB) && (ECB == 1)
void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf)
{
// The next function call encrypts the PlainText with the Key using AES algorithm.
Cipher((state_t*)buf, ctx->RoundKey);
}
void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf)
{
// The next function call decrypts the PlainText with the Key using AES algorithm.
InvCipher((state_t*)buf, ctx->RoundKey);
}
#endif // #if defined(ECB) && (ECB == 1)
#if defined(CBC) && (CBC == 1)
static void XorWithIv(uint8_t* buf, const uint8_t* Iv)
{
uint8_t i;
for (i = 0; i < AES_BLOCKLEN; ++i) // The block in AES is always 128bit no matter the key size
{
buf[i] ^= Iv[i];
}
}
void AES_CBC_encrypt_buffer(struct AES_ctx *ctx, uint8_t* buf, uint32_t length)
{
uintptr_t i;
uint8_t *Iv = ctx->Iv;
for (i = 0; i < length; i += AES_BLOCKLEN)
{
XorWithIv(buf, Iv);
Cipher((state_t*)buf, ctx->RoundKey);
Iv = buf;
buf += AES_BLOCKLEN;
}
/* store Iv in ctx for next call */
memcpy(ctx->Iv, Iv, AES_BLOCKLEN);
}
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length)
{
uintptr_t i;
uint8_t storeNextIv[AES_BLOCKLEN];
for (i = 0; i < length; i += AES_BLOCKLEN)
{
memcpy(storeNextIv, buf, AES_BLOCKLEN);
InvCipher((state_t*)buf, ctx->RoundKey);
XorWithIv(buf, ctx->Iv);
memcpy(ctx->Iv, storeNextIv, AES_BLOCKLEN);
buf += AES_BLOCKLEN;
}
}
#endif // #if defined(CBC) && (CBC == 1)
#if defined(CTR) && (CTR == 1)
/* Symmetrical operation: same function for encrypting as for decrypting. Note any IV/nonce should never be reused with the same key */
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length)
{
uint8_t buffer[AES_BLOCKLEN];
unsigned i;
int bi;
for (i = 0, bi = AES_BLOCKLEN; i < length; ++i, ++bi)
{
if (bi == AES_BLOCKLEN) /* we need to regen xor compliment in buffer */
{
memcpy(buffer, ctx->Iv, AES_BLOCKLEN);
Cipher((state_t*)buffer,ctx->RoundKey);
/* Increment Iv and handle overflow */
for (bi = (AES_BLOCKLEN - 1); bi >= 0; --bi)
{
/* inc will overflow */
if (ctx->Iv[bi] == 255)
{
ctx->Iv[bi] = 0;
continue;
}
ctx->Iv[bi] += 1;
break;
}
bi = 0;
}
buf[i] = (buf[i] ^ buffer[bi]);
}
}
#endif // #if defined(CTR) && (CTR == 1)

90
src/knx/aes.h Normal file
View File

@ -0,0 +1,90 @@
#ifndef _AES_H_
#define _AES_H_
#include <stdint.h>
// #define the macros below to 1/0 to enable/disable the mode of operation.
//
// CBC enables AES encryption in CBC-mode of operation.
// CTR enables encryption in counter-mode.
// ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously.
// The #ifndef-guard allows it to be configured before #include'ing or at compile time.
#ifndef CBC
#define CBC 1
#endif
#ifndef ECB
#define ECB 1
#endif
#ifndef CTR
#define CTR 1
#endif
#define AES128 1
//#define AES192 1
//#define AES256 1
#define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only
#if defined(AES256) && (AES256 == 1)
#define AES_KEYLEN 32
#define AES_keyExpSize 240
#elif defined(AES192) && (AES192 == 1)
#define AES_KEYLEN 24
#define AES_keyExpSize 208
#else
#define AES_KEYLEN 16 // Key length in bytes
#define AES_keyExpSize 176
#endif
struct AES_ctx
{
uint8_t RoundKey[AES_keyExpSize];
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
uint8_t Iv[AES_BLOCKLEN];
#endif
};
void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key);
#if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv);
void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv);
#endif
#if defined(ECB) && (ECB == 1)
// buffer size is exactly AES_BLOCKLEN bytes;
// you need only AES_init_ctx as IV is not used in ECB
// NB: ECB is considered insecure for most uses
void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf);
void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf);
#endif // #if defined(ECB) && (ECB == !)
#if defined(CBC) && (CBC == 1)
// buffer size MUST be mutile of AES_BLOCKLEN;
// Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv()
// no IV should ever be reused with the same key
void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length);
void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length);
#endif // #if defined(CBC) && (CBC == 1)
#if defined(CTR) && (CTR == 1)
// Same function for encrypting as for decrypting.
// IV is incremented for every block, and used after encryption as XOR-compliment for output
// Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
// NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv()
// no IV should ever be reused with the same key
void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length);
#endif // #if defined(CTR) && (CTR == 1)
#endif // _AES_H_

12
src/knx/aes.hpp Normal file
View File

@ -0,0 +1,12 @@
#ifndef _AES_HPP_
#define _AES_HPP_
#ifndef __cplusplus
#error Do not include the hpp header in a c project!
#endif //__cplusplus
extern "C" {
#include "aes.h"
}
#endif //_AES_HPP_

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,9 @@ class ApplicationLayer
void transportLayer(TransportLayer& layer);
// from transport layer
// Note: without data secure feature, the application layer is just used with SecurtyControl.dataSecurity = none
// hooks that can be implemented by derived class (e.g. SecureApplicationLayer)
#pragma region Transport - Layer - Callbacks
/**
* Somebody send us an APDU via multicast communiation. See 3.2 of @cite knx:3/3/4.
@ -39,12 +42,12 @@ class ApplicationLayer
* See 3.1.1 of @cite knx:3/3/7
*
* @param apdu The submitted APDU.
*
*
* @param priority The ::Priority of the received request.
*
* @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);
virtual void dataGroupIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu);
/**
* Report the status of an APDU that we sent via multicast communiation back to us. See 3.2 of @cite knx:3/3/4.
* See also ApplicationLayer::dataGroupConfirm and TransportLayer::dataGroupRequest. This method is called by
@ -63,102 +66,146 @@ 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, bool status);
void dataBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu);
void dataBroadcastConfirm(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, bool status);
void dataSystemBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu);
void dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, bool status);
void dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu);
void dataIndividualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status);
virtual void dataGroupConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status);
virtual void dataBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu);
virtual void dataBroadcastConfirm(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, bool status);
virtual void dataSystemBroadcastIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu);
virtual void dataSystemBroadcastConfirm(HopCountType hopType, Priority priority, APDU& apdu, bool status);
virtual void dataIndividualIndication(HopCountType hopType, Priority priority, uint16_t source, APDU& apdu);
virtual void dataIndividualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status);
virtual void dataConnectedIndication(Priority priority, uint16_t tsap, APDU& apdu);
virtual void dataConnectedConfirm(uint16_t tsap);
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);
void dataConnectedIndication(Priority priority, uint16_t tsap, APDU& apdu);
void dataConnectedConfirm(uint16_t tsap);
#pragma endregion
#pragma region from bau
void groupValueReadRequest(AckType ack, uint16_t asap, Priority priority, HopCountType hopType);
void groupValueReadResponse(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, uint8_t* data, uint8_t dataLength);
void groupValueWriteRequest(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, uint8_t* data, uint8_t dataLength);
void individualAddressWriteRequest(AckType ack, HopCountType hopType, uint16_t newaddress);
void individualAddressReadRequest(AckType ack, HopCountType hopType);
void individualAddressReadResponse(AckType ack, HopCountType hopType);
void individualAddressSerialNumberReadRequest(AckType ack, HopCountType hopType, uint8_t* serialNumber);
void individualAddressSerialNumberReadResponse(AckType ack, HopCountType hopType, uint8_t* serialNumber,
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);
void groupValueWriteRequest(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* data, uint8_t dataLength);
void individualAddressWriteRequest(AckType ack, HopCountType hopType, const SecurityControl &secCtrl, uint16_t newaddress);
void individualAddressReadRequest(AckType ack, HopCountType hopType, const SecurityControl& secCtrl);
void individualAddressReadResponse(AckType ack, HopCountType hopType, const SecurityControl& secCtrl);
void individualAddressSerialNumberReadRequest(AckType ack, HopCountType hopType, const SecurityControl& secCtrl, uint8_t* serialNumber);
void individualAddressSerialNumberReadResponse(AckType ack, HopCountType hopType, const SecurityControl& secCtrl, uint8_t* serialNumber,
uint16_t domainAddress);
void individualAddressSerialNumberWriteRequest(AckType ack, HopCountType hopType, uint8_t* serialNumber,
void individualAddressSerialNumberWriteRequest(AckType ack, HopCountType hopType, const SecurityControl& secCtrl, uint8_t* serialNumber,
uint16_t newaddress);
void deviceDescriptorReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
void deviceDescriptorReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl,
uint8_t descriptorType);
void deviceDescriptorReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
void deviceDescriptorReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t descriptorType, uint8_t* deviceDescriptor);
void connectRequest(uint16_t destination, Priority priority);
void disconnectRequest(Priority priority);
bool isConnected();
void restartRequest(AckType ack, Priority priority, HopCountType hopType);
void propertyValueReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
void restartRequest(AckType ack, Priority priority, HopCountType hopType, const SecurityControl& secCtrl);
void restartResponse(AckType ack, Priority priority, HopCountType hopType, const SecurityControl& secCtrl, uint8_t errorCode, uint16_t processTime);
void propertyValueReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl,
uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex);
void propertyValueReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
void propertyValueReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length);
void propertyValueWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
void propertyValueExtReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint16_t objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length);
void propertyValueExtWriteConResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint16_t objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t returnCode);
void propertyValueWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length);
void functionPropertyStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
void functionPropertyStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t objectIndex, uint8_t propertyId, uint8_t *resultData, uint8_t resultLength);
void propertyDescriptionReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
void functionPropertyExtStateResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl,
uint16_t objectType, uint8_t objectInstance, uint16_t propertyId, uint8_t* resultData, uint8_t resultLength);
void propertyDescriptionReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl,
uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex);
void propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
void propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl,
uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type,
uint16_t maxNumberOfElements, uint8_t access);
void memoryReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
void memoryReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number,
uint16_t memoryAddress);
void memoryReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
void memoryReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number,
uint16_t memoryAddress, uint8_t* data);
void memoryWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
void memoryExtReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, ReturnCodes code, uint8_t number,
uint32_t memoryAddress, uint8_t* data);
void memoryExtWriteResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, ReturnCodes code, uint8_t number,
uint32_t memoryAddress, uint8_t *memoryData);
void memoryWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number,
uint16_t memoryAddress, uint8_t* data);
void userMemoryReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
void userMemoryReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress);
void userMemoryReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
void userMemoryReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* memoryData);
void userMemoryWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
void userMemoryWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* memoryData);
void userManufacturerInfoReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap);
void userManufacturerInfoReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
void userManufacturerInfoReadRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl);
void userManufacturerInfoReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl,
uint8_t* info);
void authorizeRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint32_t key);
void authorizeResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t level);
void keyWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t level, uint32_t key);
void keyWriteResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t level);
void authorizeRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint32_t key);
void authorizeResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t level);
void keyWriteRequest(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t level, uint32_t key);
void keyWriteResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t level);
void systemNetworkParameterReadResponse(Priority priority, HopCountType hopType, uint16_t objectType,
void systemNetworkParameterReadResponse(Priority priority, HopCountType hopType, const SecurityControl& secCtrl, uint16_t objectType,
uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength,
uint8_t* testResult, uint16_t testResultLength);
void domainAddressSerialNumberReadResponse(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
void domainAddressSerialNumberReadResponse(Priority priority, HopCountType hopType, const SecurityControl& secCtrl, const uint8_t* rfDoA,
const uint8_t* knxSerialNumber);
void IndividualAddressSerialNumberReadResponse(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
void IndividualAddressSerialNumberReadResponse(Priority priority, HopCountType hopType, const SecurityControl& secCtrl, const uint8_t* rfDoA,
const uint8_t* knxSerialNumber);
#pragma endregion
protected:
#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
// to transport layer
virtual void dataGroupRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl &secCtrl);
virtual void dataBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, const SecurityControl& secCtrl);
virtual void dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, const SecurityControl& secCtrl);
virtual void dataIndividualRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t destination, APDU& apdu, const SecurityControl& secCtrl);
virtual void dataConnectedRequest(uint16_t tsap, Priority priority, APDU& apdu, const SecurityControl& secCtrl); // 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;
static const SecurityControl noSecurity;
private:
void propertyDataSend(ApduType type, AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
void propertyDataSend(ApduType type, AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data,
uint8_t length);
void memorySend(ApduType type, AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
void propertyExtDataSend(ApduType type, AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl,
uint16_t objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length);
void memorySend(ApduType type, AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl, uint8_t number,
uint16_t memoryAddress, uint8_t* memoryData);
void userMemorySend(ApduType type, AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
void userMemorySend(ApduType type, AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl& secCtrl,
uint8_t number, uint32_t memoryAddress, uint8_t* memoryData);
void groupValueSend(ApduType type, AckType ack, uint16_t asap, Priority priority, HopCountType hopType, uint8_t* data, uint8_t& dataLength);
void individualIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu);
void individualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, bool status);
void individualSend(AckType ack, HopCountType hopType, Priority priority, uint16_t asap, APDU& apdu);
void groupValueSend(ApduType type, AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl& secCtrl, uint8_t* data, uint8_t& dataLength);
void individualIndication(HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl &secCtrl);
void individualConfirm(AckType ack, HopCountType hopType, Priority priority, uint16_t tsap, APDU& apdu, const SecurityControl& secCtrl, bool status);
void individualSend(AckType ack, HopCountType hopType, Priority priority, uint16_t asap, APDU& apdu, const SecurityControl& secCtrl);
uint16_t crc16Ccitt(uint8_t* input, uint16_t length);
uint16_t _savedAsapReadRequest;
uint16_t _savedAsapWriteRequest;
uint16_t _savedAsapResponse;
AssociationTableObject& _assocTable;
BusAccessUnit& _bau;
TransportLayer* _transportLayer = 0;
int32_t _connectedTsap = -1;
};

View File

@ -1,248 +1,297 @@
#include "bau.h"
void BusAccessUnit::groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, bool status)
void BusAccessUnit::groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl& secCtrl, bool status)
{
}
void BusAccessUnit::groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType)
void BusAccessUnit::groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl)
{
}
void BusAccessUnit::groupValueReadResponseConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopTtype, uint8_t* data, uint8_t dataLength, bool status)
void BusAccessUnit::groupValueReadResponseConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopTtype, const SecurityControl &secCtrl, uint8_t* data, uint8_t dataLength, bool status)
{
}
void BusAccessUnit::groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType, uint8_t* data, uint8_t dataLength)
void BusAccessUnit::groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* data, uint8_t dataLength)
{
}
void BusAccessUnit::groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, uint8_t* data, uint8_t dataLength, bool status)
void BusAccessUnit::groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* data, uint8_t dataLength, bool status)
{
}
void BusAccessUnit::groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType, uint8_t* data, uint8_t dataLength)
void BusAccessUnit::groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* data, uint8_t dataLength)
{
}
void BusAccessUnit::individualAddressWriteLocalConfirm(AckType ack, HopCountType hopType, uint16_t newaddress, bool status)
void BusAccessUnit::individualAddressWriteLocalConfirm(AckType ack, HopCountType hopType, const SecurityControl &secCtrl, uint16_t newaddress, bool status)
{
}
void BusAccessUnit::individualAddressWriteIndication(HopCountType hopType, uint16_t newaddress)
void BusAccessUnit::individualAddressWriteIndication(HopCountType hopType, const SecurityControl &secCtrl, uint16_t newaddress)
{
}
void BusAccessUnit::individualAddressReadLocalConfirm(AckType ack, HopCountType hopType, bool status)
void BusAccessUnit::individualAddressReadLocalConfirm(AckType ack, HopCountType hopType, const SecurityControl &secCtrl, bool status)
{
}
void BusAccessUnit::individualAddressReadIndication(HopCountType hopType)
void BusAccessUnit::individualAddressReadIndication(HopCountType hopType, const SecurityControl &secCtrl)
{
}
void BusAccessUnit::individualAddressReadResponseConfirm(AckType ack, HopCountType hopType, bool status)
void BusAccessUnit::individualAddressReadResponseConfirm(AckType ack, HopCountType hopType, const SecurityControl &secCtrl, bool status)
{
}
void BusAccessUnit::individualAddressReadAppLayerConfirm(HopCountType hopType, uint16_t individualAddress)
void BusAccessUnit::individualAddressReadAppLayerConfirm(HopCountType hopType, const SecurityControl &secCtrl, uint16_t individualAddress)
{
}
void BusAccessUnit::individualAddressSerialNumberReadLocalConfirm(AckType ack, HopCountType hopType, uint8_t* serialNumber, bool status)
void BusAccessUnit::individualAddressSerialNumberReadLocalConfirm(AckType ack, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* serialNumber, bool status)
{
}
void BusAccessUnit::individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, uint8_t* knxSerialNumber)
void BusAccessUnit::individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* knxSerialNumber)
{
}
void BusAccessUnit::individualAddressSerialNumberReadResponseConfirm(AckType ack, HopCountType hopType, uint8_t* serialNumber, uint16_t domainAddress, bool status)
void BusAccessUnit::individualAddressSerialNumberReadResponseConfirm(AckType ack, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* serialNumber, uint16_t domainAddress, bool status)
{
}
void BusAccessUnit::individualAddressSerialNumberReadAppLayerConfirm(HopCountType hopType, uint8_t* serialNumber, uint16_t individualAddress, uint16_t domainAddress)
void BusAccessUnit::individualAddressSerialNumberReadAppLayerConfirm(HopCountType hopType, const SecurityControl &secCtrl, uint8_t* serialNumber, uint16_t individualAddress, uint16_t domainAddress)
{
}
void BusAccessUnit::individualAddressSerialNumberWriteLocalConfirm(AckType ack, HopCountType hopType, uint8_t* serialNumber, uint16_t newaddress, bool status)
void BusAccessUnit::individualAddressSerialNumberWriteLocalConfirm(AckType ack, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* serialNumber, uint16_t newaddress, bool status)
{
}
void BusAccessUnit::individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, uint16_t newIndividualAddress,
void BusAccessUnit::individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t newIndividualAddress,
uint8_t* knxSerialNumber)
{
}
void BusAccessUnit::deviceDescriptorReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t descriptorType, bool status)
void BusAccessUnit::deviceDescriptorReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t descriptorType, bool status)
{
}
void BusAccessUnit::deviceDescriptorReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t descriptorType)
void BusAccessUnit::deviceDescriptorReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t descriptorType)
{
}
void BusAccessUnit::deviceDescriptorReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t descriptor_type,
void BusAccessUnit::deviceDescriptorReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t descriptor_type,
uint8_t* device_descriptor, bool status)
{
}
void BusAccessUnit::deviceDescriptorReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t descriptortype, uint8_t* deviceDescriptor)
void BusAccessUnit::deviceDescriptorReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t descriptortype, uint8_t* deviceDescriptor)
{
}
void BusAccessUnit::restartRequestLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, bool status)
void BusAccessUnit::restartRequestLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, bool status)
{
}
void BusAccessUnit::restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap)
void BusAccessUnit::restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, RestartType restartType, EraseCode eraseCode, uint8_t channel)
{
}
void BusAccessUnit::propertyValueReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, bool status)
void BusAccessUnit::propertyValueReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, bool status)
{
}
void BusAccessUnit::propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex)
void BusAccessUnit::propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex)
{
}
void BusAccessUnit::functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t* data, uint8_t length)
void BusAccessUnit::propertyValueExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex)
{
}
void BusAccessUnit::functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t* data, uint8_t length)
void BusAccessUnit::functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t* data, uint8_t length)
{
}
void BusAccessUnit::propertyValueReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool status)
void BusAccessUnit::functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t* data, uint8_t length)
{
}
void BusAccessUnit::propertyValueReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length)
void BusAccessUnit::functionPropertyExtCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t* data, uint8_t length)
{
}
void BusAccessUnit::propertyValueWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool status)
void BusAccessUnit::functionPropertyExtStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t* data, uint8_t length)
{
}
void BusAccessUnit::propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length)
void BusAccessUnit::propertyValueReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool status)
{
}
void BusAccessUnit::propertyDescriptionReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool status)
void BusAccessUnit::propertyValueReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length)
{
}
void BusAccessUnit::propertyDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex)
void BusAccessUnit::propertyValueWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool status)
{
}
void BusAccessUnit::propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type, uint16_t maxNumberOfElements, uint8_t access)
void BusAccessUnit::propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length)
{
}
void BusAccessUnit::propertyDescriptionReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type, uint16_t maxNumberOfElements, uint8_t access, bool status)
void BusAccessUnit::propertyValueExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool confirmed)
{
}
void BusAccessUnit::propertyDescriptionReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type, uint16_t maxNumberOfElements, uint8_t access)
void BusAccessUnit::propertyDescriptionReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool status)
{
}
void BusAccessUnit::memoryReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint16_t memoryAddress, bool status)
void BusAccessUnit::propertyDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex)
{
}
void BusAccessUnit::memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint16_t memoryAddress)
void BusAccessUnit::propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type, uint16_t maxNumberOfElements, uint8_t access)
{
}
void BusAccessUnit::memoryReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint16_t memoryAddress, uint8_t* data, bool status)
void BusAccessUnit::propertyDescriptionReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type, uint16_t maxNumberOfElements, uint8_t access, bool status)
{
}
void BusAccessUnit::memoryReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint16_t memoryAddress, uint8_t* data)
void BusAccessUnit::propertyDescriptionReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type, uint16_t maxNumberOfElements, uint8_t access)
{
}
void BusAccessUnit::memoryWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint16_t memoryAddress, uint8_t* data, bool status)
void BusAccessUnit::memoryReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, bool status)
{
}
void BusAccessUnit::memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint16_t memoryAddress, uint8_t* data)
void BusAccessUnit::memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress)
{
}
void BusAccessUnit::userMemoryReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress, bool status)
void BusAccessUnit::memoryReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t* data, bool status)
{
}
void BusAccessUnit::userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress)
void BusAccessUnit::memoryReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t* data)
{
}
void BusAccessUnit::userMemoryReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress, uint8_t* memoryData, bool status)
void BusAccessUnit::memoryWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t* data, bool status)
{
}
void BusAccessUnit::userMemoryReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress, uint8_t* memoryData)
void BusAccessUnit::memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress, uint8_t* data)
{
}
void BusAccessUnit::userMemoryWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress, uint8_t* memoryData, bool status)
void BusAccessUnit::memoryExtReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, bool status)
{
}
void BusAccessUnit::userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress, uint8_t* memoryData)
void BusAccessUnit::memoryExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress)
{
}
void BusAccessUnit::userManufacturerInfoLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, bool status)
void BusAccessUnit::memoryExtReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data, bool status)
{
}
void BusAccessUnit::userManufacturerInfoIndication(Priority priority, HopCountType hopType, uint16_t asap)
void BusAccessUnit::memoryExtReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data)
{
}
void BusAccessUnit::userManufacturerInfoResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t* info, bool status)
void BusAccessUnit::memoryExtWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data, bool status)
{
}
void BusAccessUnit::userManufacturerInfoAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t* info)
void BusAccessUnit::memoryExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data)
{
}
void BusAccessUnit::authorizeLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint32_t key, bool status)
void BusAccessUnit::memoryExtWriteResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data, bool status)
{
}
void BusAccessUnit::authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, uint32_t key)
void BusAccessUnit::memoryExtWriteAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data)
{
}
void BusAccessUnit::authorizeResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t level, bool status)
void BusAccessUnit::userMemoryReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, bool status)
{
}
void BusAccessUnit::authorizeAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t level)
void BusAccessUnit::userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress)
{
}
void BusAccessUnit::keyWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t level, uint32_t key, bool status)
void BusAccessUnit::userMemoryReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* memoryData, bool status)
{
}
void BusAccessUnit::keyWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t level, uint32_t key)
void BusAccessUnit::userMemoryReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* memoryData)
{
}
void BusAccessUnit::keyWriteResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t level, bool status)
void BusAccessUnit::userMemoryWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* memoryData, bool status)
{
}
void BusAccessUnit::keyWriteAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t level)
void BusAccessUnit::userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* memoryData)
{
}
void BusAccessUnit::userManufacturerInfoLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, bool status)
{
}
void BusAccessUnit::userManufacturerInfoIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl)
{
}
void BusAccessUnit::userManufacturerInfoResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t* info, bool status)
{
}
void BusAccessUnit::userManufacturerInfoAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t* info)
{
}
void BusAccessUnit::authorizeLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint32_t key, bool status)
{
}
void BusAccessUnit::authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint32_t key)
{
}
void BusAccessUnit::authorizeResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t level, bool status)
{
}
void BusAccessUnit::authorizeAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t level)
{
}
void BusAccessUnit::keyWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t level, uint32_t key, bool status)
{
}
void BusAccessUnit::keyWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t level, uint32_t key)
{
}
void BusAccessUnit::keyWriteResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t level, bool status)
{
}
void BusAccessUnit::keyWriteAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t level)
{
}
@ -250,31 +299,31 @@ void BusAccessUnit::connectConfirm(uint16_t destination)
{
}
void BusAccessUnit::systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, uint16_t objectType,
void BusAccessUnit::systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t objectType,
uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength)
{
}
void BusAccessUnit::domainAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
void BusAccessUnit::domainAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* rfDoA,
const uint8_t* knxSerialNumber)
{
}
void BusAccessUnit::domainAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const uint8_t* knxSerialNumber)
void BusAccessUnit::domainAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* knxSerialNumber)
{
}
void BusAccessUnit::systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, uint16_t objectType,
void BusAccessUnit::systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t objectType,
uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength, bool status)
{
}
void BusAccessUnit::domainAddressSerialNumberWriteLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
void BusAccessUnit::domainAddressSerialNumberWriteLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* rfDoA,
const uint8_t* knxSerialNumber, bool status)
{
}
void BusAccessUnit::domainAddressSerialNumberReadLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* knxSerialNumber, bool status)
void BusAccessUnit::domainAddressSerialNumberReadLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* knxSerialNumber, bool status)
{
}

View File

@ -7,129 +7,152 @@ class BusAccessUnit
{
public:
virtual ~BusAccessUnit() {}
virtual void groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, bool status);
virtual void groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType);
virtual void groupValueReadResponseConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopTtype,
virtual void groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, bool status);
virtual void groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl);
virtual void groupValueReadResponseConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopTtype, const SecurityControl &secCtrl,
uint8_t* data, uint8_t dataLength, bool status);
virtual void groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType,
virtual void groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* data, uint8_t dataLength);
virtual void groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType,
virtual void groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* data, uint8_t dataLength, bool status);
virtual void groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType,
virtual void groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* data, uint8_t dataLength);
virtual void individualAddressWriteLocalConfirm(AckType ack, HopCountType hopType,
virtual void individualAddressWriteLocalConfirm(AckType ack, HopCountType hopType, const SecurityControl &secCtrl,
uint16_t newaddress, bool status);
virtual void individualAddressWriteIndication(HopCountType hopType, uint16_t newaddress);
virtual void individualAddressReadLocalConfirm(AckType ack, HopCountType hopType, bool status);
virtual void individualAddressReadIndication(HopCountType hopType);
virtual void individualAddressReadResponseConfirm(AckType ack, HopCountType hopType, bool status);
virtual void individualAddressReadAppLayerConfirm(HopCountType hopType, uint16_t individualAddress);
virtual void individualAddressSerialNumberReadLocalConfirm(AckType ack, HopCountType hopType,
virtual void individualAddressWriteIndication(HopCountType hopType, const SecurityControl &secCtrl, uint16_t newaddress);
virtual void individualAddressReadLocalConfirm(AckType ack, HopCountType hopType, const SecurityControl &secCtrl, bool status);
virtual void individualAddressReadIndication(HopCountType hopType, const SecurityControl &secCtrl);
virtual void individualAddressReadResponseConfirm(AckType ack, HopCountType hopType, const SecurityControl &secCtrl, bool status);
virtual void individualAddressReadAppLayerConfirm(HopCountType hopType, const SecurityControl &secCtrl, uint16_t individualAddress);
virtual void individualAddressSerialNumberReadLocalConfirm(AckType ack, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* serialNumber, bool status);
virtual void individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, uint8_t* knxSerialNumber);
virtual void individualAddressSerialNumberReadResponseConfirm(AckType ack, HopCountType hopType,
virtual void individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* knxSerialNumber);
virtual void individualAddressSerialNumberReadResponseConfirm(AckType ack, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* serialNumber, uint16_t domainAddress, bool status);
virtual void individualAddressSerialNumberReadAppLayerConfirm(HopCountType hopType, uint8_t* serialNumber,
virtual void individualAddressSerialNumberReadAppLayerConfirm(HopCountType hopType, const SecurityControl &secCtrl, uint8_t* serialNumber,
uint16_t individualAddress, uint16_t domainAddress);
virtual void individualAddressSerialNumberWriteLocalConfirm(AckType ack, HopCountType hopType, uint8_t* serialNumber,
virtual void individualAddressSerialNumberWriteLocalConfirm(AckType ack, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* serialNumber,
uint16_t newaddress, bool status);
virtual void individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, uint16_t newIndividualAddress,
virtual void individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t newIndividualAddress,
uint8_t* knxSerialNumber);
virtual void deviceDescriptorReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
virtual void deviceDescriptorReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t descriptorType, bool status);
virtual void deviceDescriptorReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t descriptorType);
virtual void deviceDescriptorReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
virtual void deviceDescriptorReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t descriptorType);
virtual void deviceDescriptorReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t descriptor_type, uint8_t* device_descriptor, bool status);
virtual void deviceDescriptorReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap,
virtual void deviceDescriptorReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t descriptortype, uint8_t* deviceDescriptor);
virtual void restartRequestLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, bool status);
virtual void restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap);
virtual void propertyValueReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
virtual void restartRequestLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, bool status);
virtual void restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, RestartType restartType, EraseCode eraseCode, uint8_t channel);
virtual void propertyValueReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t objectIndex, uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, bool status);
virtual void propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
virtual void propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex);
virtual void functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
virtual void propertyValueExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex);
virtual void functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t* data, uint8_t length);
virtual void functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
virtual void functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t* data, uint8_t length);
virtual void propertyValueReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
virtual void functionPropertyExtCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
uint8_t propertyId, uint8_t* data, uint8_t length);
virtual void functionPropertyExtStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
uint8_t propertyId, uint8_t* data, uint8_t length);
virtual void propertyValueReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool status);
virtual void propertyValueReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
virtual void propertyValueReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length);
virtual void propertyValueWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
virtual void propertyValueWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool status);
virtual void propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
virtual void propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length);
virtual void propertyDescriptionReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
virtual void propertyValueExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool confirmed);
virtual void propertyDescriptionReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool status);
virtual void propertyDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap,
virtual void propertyDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex);
virtual void propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
virtual void propertyDescriptionReadResponse(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type,
uint16_t maxNumberOfElements, uint8_t access);
virtual void propertyDescriptionReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
virtual void propertyDescriptionReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type,
uint16_t maxNumberOfElements, uint8_t access, bool status);
virtual void propertyDescriptionReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap,
virtual void propertyDescriptionReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t objectIndex, uint8_t propertyId, uint8_t propertyIndex, bool writeEnable, uint8_t type,
uint16_t maxNumberOfElements, uint8_t access);
virtual void memoryReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
virtual void memoryReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint16_t memoryAddress, bool status);
virtual void memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint16_t memoryAddress);
virtual void memoryReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
virtual void memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint16_t memoryAddress);
virtual void memoryReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint16_t memoryAddress, uint8_t* data, bool status);
virtual void memoryReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
virtual void memoryReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint16_t memoryAddress, uint8_t* data);
virtual void memoryWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
virtual void memoryWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint16_t memoryAddress, uint8_t* data, bool status);
virtual void memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
virtual void memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint16_t memoryAddress, uint8_t* data);
virtual void userMemoryReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
virtual void memoryExtReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, bool status);
virtual void memoryExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress);
virtual void memoryExtReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* data, bool status);
virtual void memoryExtReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* data);
virtual void memoryExtWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* data, bool status);
virtual void memoryExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* data);
virtual void memoryExtWriteResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* data, bool status);
virtual void memoryExtWriteAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* data);
virtual void userMemoryReadLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, bool status);
virtual void userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
virtual void userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress);
virtual void userMemoryReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
virtual void userMemoryReadResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* memoryData, bool status);
virtual void userMemoryReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
virtual void userMemoryReadAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* memoryData);
virtual void userMemoryWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
virtual void userMemoryWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* memoryData, bool status);
virtual void userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
virtual void userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* memoryData);
virtual void userManufacturerInfoLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, bool status);
virtual void userManufacturerInfoIndication(Priority priority, HopCountType hopType, uint16_t asap);
virtual void userManufacturerInfoResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap,
virtual void userManufacturerInfoLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, bool status);
virtual void userManufacturerInfoIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl);
virtual void userManufacturerInfoResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t* info, bool status);
virtual void userManufacturerInfoAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap,
virtual void userManufacturerInfoAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl,
uint8_t* info);
virtual void authorizeLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint32_t key, bool status);
virtual void authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, uint32_t key);
virtual void authorizeResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t level,
virtual void authorizeLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint32_t key, bool status);
virtual void authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint32_t key);
virtual void authorizeResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t level,
bool status);
virtual void authorizeAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t level);
virtual void keyWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t level,
virtual void authorizeAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t level);
virtual void keyWriteLocalConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t level,
uint32_t key, bool status);
virtual void keyWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t level,
virtual void keyWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t level,
uint32_t key);
virtual void keyWriteResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, uint8_t level,
virtual void keyWriteResponseConfirm(AckType ack, Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t level,
bool status);
virtual void keyWriteAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, uint8_t level);
virtual void keyWriteAppLayerConfirm(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t level);
virtual void connectConfirm(uint16_t destination);
virtual void systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, uint16_t objectType,
virtual void systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t objectType,
uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength);
virtual void domainAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
virtual void domainAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* rfDoA,
const uint8_t* knxSerialNumber);
virtual void domainAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const uint8_t* knxSerialNumber);
virtual void domainAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* knxSerialNumber);
virtual void systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, uint16_t objectType,
virtual void systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t objectType,
uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength, bool status);
virtual void domainAddressSerialNumberWriteLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
virtual void domainAddressSerialNumberWriteLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* rfDoA,
const uint8_t* knxSerialNumber, bool status);
virtual void domainAddressSerialNumberReadLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* knxSerialNumber, bool status);
virtual void domainAddressSerialNumberReadLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* knxSerialNumber, bool status);
virtual void propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId,
uint8_t& numberOfElements, uint16_t startIndex,

View File

@ -20,7 +20,6 @@ Bau07B0::Bau07B0(Platform& platform)
_dlLayer.cemiServer(_cemiServer);
_memory.addSaveRestore(&_cemiServerObject);
#endif
// Set Mask Version in Device Object depending on the BAU
_deviceObj.maskVersion(0x07B0);
@ -33,7 +32,12 @@ Bau07B0::Bau07B0(Platform& platform)
prop->write(3, (uint16_t) OT_ASSOC_TABLE);
prop->write(4, (uint16_t) OT_GRP_OBJ_TABLE);
prop->write(5, (uint16_t) OT_APPLICATION_PROG);
#ifdef USE_CEMI_SERVER
#if defined(USE_DATASECURE) && defined(USE_CEMI_SERVER)
prop->write(6, (uint16_t) OT_SECURITY);
prop->write(7, (uint16_t) OT_CEMI_SERVER);
#elif defined(USE_DATASECURE)
prop->write(6, (uint16_t) OT_SECURITY);
#elif defined(USE_CEMI_SERVER)
prop->write(6, (uint16_t) OT_CEMI_SERVER);
#endif
}
@ -54,10 +58,18 @@ InterfaceObject* Bau07B0::getInterfaceObject(uint8_t idx)
return &_appProgram;
case 5: // would be app_program 2
return nullptr;
#ifdef USE_CEMI_SERVER
#if defined(USE_DATASECURE) && defined(USE_CEMI_SERVER)
case 6:
return &_secIfObj;
case 7:
return &_cemiServerObject;
#elif defined(USE_CEMI_SERVER)
case 6:
return &_cemiServerObject;
#endif
#elif defined(USE_DATASECURE)
case 6:
return &_secIfObj;
#endif
default:
return nullptr;
}
@ -81,6 +93,10 @@ InterfaceObject* Bau07B0::getInterfaceObject(ObjectType objectType, uint8_t obje
return &_groupObjTable;
case OT_APPLICATION_PROG:
return &_appProgram;
#ifdef USE_DATASECURE
case OT_SECURITY:
return &_secIfObj;
#endif
#ifdef USE_CEMI_SERVER
case OT_CEMI_SERVER:
return &_cemiServerObject;

View File

@ -41,8 +41,13 @@ Bau27B0::Bau27B0(Platform& platform)
prop->write(4, (uint16_t) OT_GRP_OBJ_TABLE);
prop->write(5, (uint16_t) OT_APPLICATION_PROG);
prop->write(6, (uint16_t) OT_RF_MEDIUM);
#ifdef USE_CEMI_SERVER
prop->write(7, (uint16_t) OT_CEMI_SERVER);
#if defined(USE_DATASECURE) && defined(USE_CEMI_SERVER)
prop->write(7, (uint16_t) OT_SECURITY);
prop->write(8, (uint16_t) OT_CEMI_SERVER);
#elif defined(USE_DATASECURE)
prop->write(7, (uint16_t) OT_SECURITY);
#elif defined(USE_CEMI_SERVER)
prop->write(7, (uint16_t)OT_CEMI_SERVER);
#endif
}
@ -65,10 +70,18 @@ InterfaceObject* Bau27B0::getInterfaceObject(uint8_t idx)
return nullptr;
case 6:
return &_rfMediumObj;
#ifdef USE_CEMI_SERVER
#if defined(USE_DATASECURE) && defined(USE_CEMI_SERVER)
case 7:
return &_secIfObj;
case 8:
return &_cemiServerObject;
#elif defined(USE_CEMI_SERVER)
case 7:
return &_cemiServerObject;
#endif
#elif defined(USE_DATASECURE)
case 7:
return &_secIfObj;
#endif
default:
return nullptr;
}
@ -94,6 +107,10 @@ InterfaceObject* Bau27B0::getInterfaceObject(ObjectType objectType, uint8_t obje
return &_appProgram;
case OT_RF_MEDIUM:
return &_rfMediumObj;
#ifdef USE_DATASECURE
case OT_SECURITY:
return &_secIfObj;
#endif
#ifdef USE_CEMI_SERVER
case OT_CEMI_SERVER:
return &_cemiServerObject;
@ -103,6 +120,14 @@ InterfaceObject* Bau27B0::getInterfaceObject(ObjectType objectType, uint8_t obje
}
}
void Bau27B0::doMasterReset(EraseCode eraseCode, uint8_t channel)
{
// Common SystemB objects
BauSystemB::doMasterReset(eraseCode, channel);
_rfMediumObj.masterReset(eraseCode, channel);
}
DataLinkLayer& Bau27B0::dataLinkLayer()
{
return _dlLayer;
@ -116,7 +141,7 @@ void Bau27B0::loop()
#endif
}
void Bau27B0::domainAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
void Bau27B0::domainAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* rfDoA,
const uint8_t* knxSerialNumber)
{
// If the received serial number matches our serial number
@ -125,37 +150,28 @@ void Bau27B0::domainAddressSerialNumberWriteIndication(Priority priority, HopCou
_rfMediumObj.rfDomainAddress(rfDoA);
}
void Bau27B0::domainAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const uint8_t* knxSerialNumber)
void Bau27B0::domainAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* knxSerialNumber)
{
// If the received serial number matches our serial number
// then send a response with the current RF domain address stored in the RF medium object
if (!memcmp(knxSerialNumber, _deviceObj.propertyData(PID_SERIAL_NUMBER), 6))
_appLayer.domainAddressSerialNumberReadResponse(priority, hopType, _rfMediumObj.rfDomainAddress(), knxSerialNumber);
_appLayer.domainAddressSerialNumberReadResponse(priority, hopType, secCtrl, _rfMediumObj.rfDomainAddress(), knxSerialNumber);
}
void Bau27B0::individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, uint16_t newIndividualAddress,
uint8_t* knxSerialNumber)
{
// If the received serial number matches our serial number
// then store the received new individual address in the device object
if (!memcmp(knxSerialNumber, _deviceObj.propertyData(PID_SERIAL_NUMBER), 6))
_deviceObj.induvidualAddress(newIndividualAddress);
}
void Bau27B0::individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, uint8_t* knxSerialNumber)
void Bau27B0::individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* knxSerialNumber)
{
// If the received serial number matches our serial number
// then send a response with the current RF domain address stored in the RF medium object and the serial number
if (!memcmp(knxSerialNumber, _deviceObj.propertyData(PID_SERIAL_NUMBER), 6))
_appLayer.IndividualAddressSerialNumberReadResponse(priority, hopType, _rfMediumObj.rfDomainAddress(), knxSerialNumber);
_appLayer.IndividualAddressSerialNumberReadResponse(priority, hopType, secCtrl, _rfMediumObj.rfDomainAddress(), knxSerialNumber);
}
void Bau27B0::domainAddressSerialNumberWriteLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
void Bau27B0::domainAddressSerialNumberWriteLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* rfDoA,
const uint8_t* knxSerialNumber, bool status)
{
}
void Bau27B0::domainAddressSerialNumberReadLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* knxSerialNumber, bool status)
void Bau27B0::domainAddressSerialNumberReadLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* knxSerialNumber, bool status)
{
}

View File

@ -20,6 +20,7 @@ class Bau27B0 : public BauSystemB
InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
DataLinkLayer& dataLinkLayer();
virtual void doMasterReset(EraseCode eraseCode, uint8_t channel) override;
private:
RfDataLinkLayer _dlLayer;
RfMediumObject _rfMediumObj;
@ -28,14 +29,12 @@ class Bau27B0 : public BauSystemB
CemiServerObject _cemiServerObject;
#endif
void domainAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
void domainAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* rfDoA,
const uint8_t* knxSerialNumber) override;
void domainAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const uint8_t* knxSerialNumber) override;
void individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, uint16_t newIndividualAddress,
uint8_t* knxSerialNumber) override;
void individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, uint8_t* knxSerialNumber) override;
void domainAddressSerialNumberWriteLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
void domainAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* knxSerialNumber) override;
void individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* knxSerialNumber) override;
void domainAddressSerialNumberWriteLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* rfDoA,
const uint8_t* knxSerialNumber, bool status) override;
void domainAddressSerialNumberReadLocalConfirm(Priority priority, HopCountType hopType, const uint8_t* knxSerialNumber, bool status) override;
void domainAddressSerialNumberReadLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, const uint8_t* knxSerialNumber, bool status) override;
};
#endif

View File

@ -38,7 +38,12 @@ Bau57B0::Bau57B0(Platform& platform)
prop->write(4, (uint16_t) OT_GRP_OBJ_TABLE);
prop->write(5, (uint16_t) OT_APPLICATION_PROG);
prop->write(6, (uint16_t) OT_IP_PARAMETER);
#ifdef USE_CEMI_SERVER
#if defined(USE_DATASECURE) && defined(USE_CEMI_SERVER)
prop->write(7, (uint16_t) OT_SECURITY);
prop->write(8, (uint16_t) OT_CEMI_SERVER);
#elif defined(USE_DATASECURE)
prop->write(7, (uint16_t) OT_SECURITY);
#elif defined(USE_CEMI_SERVER)
prop->write(7, (uint16_t) OT_CEMI_SERVER);
#endif
}
@ -61,6 +66,18 @@ InterfaceObject* Bau57B0::getInterfaceObject(uint8_t idx)
return nullptr;
case 6:
return &_ipParameters;
#if defined(USE_DATASECURE) && defined(USE_CEMI_SERVER)
case 7:
return &_secIfObj;
case 8:
return &_cemiServerObject;
#elif defined(USE_CEMI_SERVER)
case 7:
return &_cemiServerObject;
#elif defined(USE_DATASECURE)
case 7:
return &_secIfObj;
#endif
default:
return nullptr;
}
@ -86,11 +103,27 @@ InterfaceObject* Bau57B0::getInterfaceObject(ObjectType objectType, uint8_t obje
return &_appProgram;
case OT_IP_PARAMETER:
return &_ipParameters;
#ifdef USE_DATASECURE
case OT_SECURITY:
return &_secIfObj;
#endif
#ifdef USE_CEMI_SERVER
case OT_CEMI_SERVER:
return &_cemiServerObject;
#endif
default:
return nullptr;
}
}
void Bau57B0::doMasterReset(EraseCode eraseCode, uint8_t channel)
{
// Common SystemB objects
BauSystemB::doMasterReset(eraseCode, channel);
_ipParameters.masterReset(eraseCode, channel);
}
DataLinkLayer& Bau57B0::dataLinkLayer()
{
return _dlLayer;

View File

@ -17,6 +17,7 @@ class Bau57B0 : public BauSystemB
InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
DataLinkLayer& dataLinkLayer();
virtual void doMasterReset(EraseCode eraseCode, uint8_t channel) override;
private:
IpParameterObject _ipParameters;
IpDataLinkLayer _dlLayer;
@ -25,4 +26,4 @@ class Bau57B0 : public BauSystemB
CemiServerObject _cemiServerObject;
#endif
};
#endif
#endif

View File

@ -11,11 +11,22 @@ enum NmReadSerialNumberType
NM_Read_SerialNumber_By_ManufacturerSpecific = 0xFE,
};
static constexpr auto kFunctionPropertyResultBufferMaxSize = 64;
static constexpr auto kRestartProcessTime = 3;
BauSystemB::BauSystemB(Platform& platform): _memory(platform, _deviceObj), _addrTable(_memory),
_assocTable(_memory), _groupObjTable(_memory), _appProgram(_memory),
_platform(platform), _appLayer(_assocTable, *this),
_platform(platform),
#ifdef USE_DATASECURE
_appLayer(_deviceObj, _secIfObj, _assocTable, _addrTable, *this),
#else
_appLayer(_assocTable, *this),
#endif
_transLayer(_appLayer, _addrTable), _netLayer(_transLayer)
{
#ifdef USE_DATASECURE
_secIfObj.secureApplicationLayer(_appLayer);
#endif
_appLayer.transportLayer(_transLayer);
_transLayer.networkLayer(_netLayer);
_memory.addSaveRestore(&_deviceObj);
@ -23,6 +34,10 @@ BauSystemB::BauSystemB(Platform& platform): _memory(platform, _deviceObj), _addr
_memory.addSaveRestore(&_addrTable);
_memory.addSaveRestore(&_assocTable);
_memory.addSaveRestore(&_groupObjTable);
#ifdef USE_DATASECURE
_memory.addSaveRestore(&_secIfObj);
#endif
}
void BauSystemB::loop()
@ -31,6 +46,9 @@ void BauSystemB::loop()
_transLayer.loop();
sendNextGroupTelegram();
nextRestartState();
#ifdef USE_DATASECURE
_appLayer.loop();
#endif
}
bool BauSystemB::enabled()
@ -64,15 +82,25 @@ void BauSystemB::sendNextGroupTelegram()
if (!go.communicationEnable())
continue;
SecurityControl goSecurity;
goSecurity.toolAccess = false; // Secured group communication never uses the toolkey. ETS knows all keys, also the group keys.
#ifdef USE_DATASECURE
// Get security flags from Security Interface Object for this group object
goSecurity.dataSecurity = _secIfObj.getGroupObjectSecurity(asap);
#else
goSecurity.dataSecurity = DataSecurity::none;
#endif
if (flag == WriteRequest && go.transmitEnable())
{
uint8_t* data = go.valueRef();
_appLayer.groupValueWriteRequest(AckRequested, asap, go.priority(), NetworkLayerParameter, data,
_appLayer.groupValueWriteRequest(AckRequested, asap, go.priority(), NetworkLayerParameter, goSecurity, data,
go.sizeInTelegram());
}
else if (flag == ReadRequest)
{
_appLayer.groupValueReadRequest(AckRequested, asap, go.priority(), NetworkLayerParameter);
_appLayer.groupValueReadRequest(AckRequested, asap, go.priority(), NetworkLayerParameter, goSecurity);
}
go.commFlag(Transmitting);
@ -141,59 +169,162 @@ bool BauSystemB::configured()
return _configured;
}
void BauSystemB::deviceDescriptorReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t descriptorType)
uint8_t BauSystemB::checkmasterResetValidity(EraseCode eraseCode, uint8_t channel)
{
static constexpr uint8_t successCode = 0x00; // Where does this come from? It is the code for "success".
static constexpr uint8_t invalidEraseCode = 0x02; // Where does this come from? It is the error code for "unspported erase code".
switch (eraseCode)
{
case EraseCode::ConfirmedRestart:
{
println("Confirmed restart requested.");
return successCode;
}
case EraseCode::ResetAP:
{
// TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER)
println("ResetAP requested. Not implemented yet.");
return successCode;
}
case EraseCode::ResetIA:
{
// TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER)
println("ResetAP requested. Not implemented yet.");
return successCode;
}
case EraseCode::ResetLinks:
{
// TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER)
println("ResetLinks requested. Not implemented yet.");
return successCode;
}
case EraseCode::ResetParam:
{
// TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER)
println("ResetParam requested. Not implemented yet.");
return successCode;
}
case EraseCode::FactoryReset:
{
// TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER)
println("Factory reset requested. type: with IA");
return successCode;
}
case EraseCode::FactoryResetWithoutIA:
{
// TODO: increase download counter except for confirmed restart (PID_DOWNLOAD_COUNTER)
println("Factory reset requested. type: without IA");
return successCode;
}
default:
{
print("Unhandled erase code: ");
println(eraseCode, HEX);
return invalidEraseCode;
}
}
}
void BauSystemB::deviceDescriptorReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t descriptorType)
{
if (descriptorType != 0)
descriptorType = 0x3f;
uint8_t data[2];
pushWord(_deviceObj.maskVersion(), data);
_appLayer.deviceDescriptorReadResponse(AckRequested, priority, hopType, asap, descriptorType, data);
_appLayer.deviceDescriptorReadResponse(AckRequested, priority, hopType, asap, secCtrl, descriptorType, data);
}
void BauSystemB::memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
void BauSystemB::memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint16_t memoryAddress, uint8_t * data)
{
_memory.writeMemory(memoryAddress, number, data);
if (_deviceObj.verifyMode())
memoryReadIndication(priority, hopType, asap, number, memoryAddress);
memoryReadIndication(priority, hopType, asap, secCtrl, number, memoryAddress);
}
void BauSystemB::memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
void BauSystemB::memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint16_t memoryAddress)
{
_appLayer.memoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,
_appLayer.memoryReadResponse(AckRequested, priority, hopType, asap, secCtrl, number, memoryAddress,
_memory.toAbsolute(memoryAddress));
}
void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap)
void BauSystemB::memoryExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t * data)
{
_memory.writeMemory(memoryAddress, number, data);
_appLayer.memoryExtWriteResponse(AckRequested, priority, hopType, asap, secCtrl, ReturnCodes::Success, number, memoryAddress, _memory.toAbsolute(memoryAddress));
}
void BauSystemB::memoryExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress)
{
_appLayer.memoryExtReadResponse(AckRequested, priority, hopType, asap, secCtrl, ReturnCodes::Success, number, memoryAddress, _memory.toAbsolute(memoryAddress));
}
void BauSystemB::doMasterReset(EraseCode eraseCode, uint8_t channel)
{
_addrTable.masterReset(eraseCode, channel);
_assocTable.masterReset(eraseCode, channel);
_groupObjTable.masterReset(eraseCode, channel);
_appProgram.masterReset(eraseCode, channel);
#ifdef USE_DATASECURE
// If erase code is FactoryReset or FactoryResetWithoutIA, set FDSK as toolkey again
// and disable security mode.
// FIXME: the A_RestartResponse PDU has still to be sent with the current toolkey.
// Idea: use local confirmation of sent A_RestartResponse PDU to trigger writing the FDSK afterwards
_secIfObj.masterReset(eraseCode, channel);
#endif
}
void BauSystemB::restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, RestartType restartType, EraseCode eraseCode, uint8_t channel)
{
if (restartType == RestartType::BasicRestart)
{
println("Basic restart requested");
}
else if (restartType == RestartType::MasterReset)
{
uint8_t errorCode = checkmasterResetValidity(eraseCode, channel);
// We send the restart response now before actually applying the reset values
// Processing time is kRestartProcessTime (example 3 seconds) that we require for the applying the master reset with restart
_appLayer.restartResponse(AckRequested, priority, hopType, secCtrl, errorCode, (errorCode == 0) ? kRestartProcessTime : 0);
doMasterReset(eraseCode, channel);
}
else
{
// Cannot happen as restartType is just one bit
println("Unhandled restart type.");
_platform.fatalError();
}
// Flush the EEPROM before resetting
_memory.writeMemory();
_platform.restart();
}
void BauSystemB::authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, uint32_t key)
void BauSystemB::authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint32_t key)
{
_appLayer.authorizeResponse(AckRequested, priority, hopType, asap, 0);
_appLayer.authorizeResponse(AckRequested, priority, hopType, asap, secCtrl, 0);
}
void BauSystemB::userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress)
void BauSystemB::userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress)
{
_appLayer.userMemoryReadResponse(AckRequested, priority, hopType, asap, number, memoryAddress,
_appLayer.userMemoryReadResponse(AckRequested, priority, hopType, asap, secCtrl, number, memoryAddress,
_memory.toAbsolute(memoryAddress));
}
void BauSystemB::userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress, uint8_t* data)
void BauSystemB::userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress, uint8_t* data)
{
_memory.writeMemory(memoryAddress, number, data);
if (_deviceObj.verifyMode())
userMemoryReadIndication(priority, hopType, asap, number, memoryAddress);
userMemoryReadIndication(priority, hopType, asap, secCtrl, number, memoryAddress);
}
void BauSystemB::propertyDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
void BauSystemB::propertyDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t propertyIndex)
{
uint8_t pid = propertyId;
@ -205,20 +336,37 @@ void BauSystemB::propertyDescriptionReadIndication(Priority priority, HopCountTy
if (obj)
obj->readPropertyDescription(pid, propertyIndex, writeEnable, type, numberOfElements, access);
_appLayer.propertyDescriptionReadResponse(AckRequested, priority, hopType, asap, objectIndex, pid, propertyIndex,
_appLayer.propertyDescriptionReadResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, pid, propertyIndex,
writeEnable, type, numberOfElements, access);
}
void BauSystemB::propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
void BauSystemB::propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length)
{
InterfaceObject* obj = getInterfaceObject(objectIndex);
if(obj)
obj->writeProperty((PropertyID)propertyId, startIndex, data, numberOfElements);
propertyValueReadIndication(priority, hopType, asap, objectIndex, propertyId, numberOfElements, startIndex);
propertyValueReadIndication(priority, hopType, asap, secCtrl, objectIndex, propertyId, numberOfElements, startIndex);
}
void BauSystemB::propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
void BauSystemB::propertyValueExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool confirmed)
{
uint8_t returnCode = ReturnCodes::Success;
InterfaceObject* obj = getInterfaceObject(objectType, objectInstance);
if(obj)
obj->writeProperty((PropertyID)propertyId, startIndex, data, numberOfElements);
else
returnCode = ReturnCodes::AddressVoid;
if (confirmed)
{
_appLayer.propertyValueExtWriteConResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, numberOfElements, startIndex, returnCode);
}
}
void BauSystemB::propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex)
{
uint8_t size = 0;
@ -242,49 +390,219 @@ void BauSystemB::propertyValueReadIndication(Priority priority, HopCountType hop
if (elementCount == 0)
size = 0;
_appLayer.propertyValueReadResponse(AckRequested, priority, hopType, asap, objectIndex, propertyId, elementCount,
startIndex, data, size);
_appLayer.propertyValueReadResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, propertyId, elementCount,
startIndex, data, size);
}
void BauSystemB::functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
void BauSystemB::propertyValueExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex)
{
uint8_t size = 0;
uint8_t elementCount = numberOfElements;
InterfaceObject* obj = getInterfaceObject(objectType, objectInstance);
if (obj)
{
uint8_t elementSize = obj->propertySize((PropertyID)propertyId);
if (startIndex > 0)
size = elementSize * numberOfElements;
else
size = sizeof(uint16_t); // size of propert array entry 0 which is the size
}
else
elementCount = 0;
uint8_t data[size];
if(obj)
obj->readProperty((PropertyID)propertyId, startIndex, elementCount, data);
if (elementCount == 0)
size = 0;
_appLayer.propertyValueExtReadResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, elementCount,
startIndex, data, size);
}
void BauSystemB::functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t* data, uint8_t length)
{
uint8_t resultLength = 0;
uint8_t resultData[32];
uint8_t resultData[kFunctionPropertyResultBufferMaxSize];
uint8_t resultLength = sizeof(resultData); // tell the callee the maximum size of the buffer
InterfaceObject* obj = getInterfaceObject(objectIndex);
if(obj)
obj->command((PropertyID)propertyId, data, length, resultData, resultLength);
{
if (obj->property((PropertyID)propertyId)->Type() == PDT_FUNCTION)
{
obj->command((PropertyID)propertyId, data, length, resultData, resultLength);
}
else
{
resultLength = 0; // We must not send a return code or any data fields
}
}
_appLayer.functionPropertyStateResponse(AckRequested, priority, hopType, asap, objectIndex, propertyId, resultData, resultLength);
_appLayer.functionPropertyStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, propertyId, resultData, resultLength);
}
void BauSystemB::functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
void BauSystemB::functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t* data, uint8_t length)
{
uint8_t resultLength = 0;
uint8_t resultData[32];
uint8_t resultData[kFunctionPropertyResultBufferMaxSize];
uint8_t resultLength = sizeof(resultData); // tell the callee the maximum size of the buffer
InterfaceObject* obj = getInterfaceObject(objectIndex);
if(obj)
obj->state((PropertyID)propertyId, data, length, resultData, resultLength);
{
if (obj->property((PropertyID)propertyId)->Type() == PDT_FUNCTION)
{
obj->state((PropertyID)propertyId, data, length, resultData, resultLength);
}
else
{
resultLength = 0; // We must not send a return code or any data fields
}
}
_appLayer.functionPropertyStateResponse(AckRequested, priority, hopType, asap, objectIndex, propertyId, resultData, resultLength);
_appLayer.functionPropertyStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectIndex, propertyId, resultData, resultLength);
}
void BauSystemB::individualAddressReadIndication(HopCountType hopType)
void BauSystemB::functionPropertyExtCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
uint8_t propertyId, uint8_t* data, uint8_t length)
{
uint8_t resultData[kFunctionPropertyResultBufferMaxSize];
uint8_t resultLength = 1; // we always have to include the return code at least
InterfaceObject* obj = getInterfaceObject(objectType, objectInstance);
if(obj)
{
PropertyDataType propType = obj->property((PropertyID)propertyId)->Type();
if (propType == PDT_FUNCTION)
{
// The first byte is reserved and 0 for PDT_FUNCTION
uint8_t reservedByte = data[0];
if (reservedByte != 0x00)
{
resultData[0] = ReturnCodes::DataVoid;
}
else
{
resultLength = sizeof(resultData); // tell the callee the maximum size of the buffer
obj->command((PropertyID)propertyId, data, length, resultData, resultLength);
// resultLength was modified by the callee
}
}
else if (propType == PDT_CONTROL)
{
uint8_t count = 1;
// write the event
obj->writeProperty((PropertyID)propertyId, 1, data, count);
if (count == 1)
{
// Read the current state (one byte only) for the response
obj->readProperty((PropertyID)propertyId, 1, count, &resultData[1]);
resultLength = count ? 2 : 1;
resultData[0] = count ? ReturnCodes::Success : ReturnCodes::DataVoid;
}
else
{
resultData[0] = ReturnCodes::AddressVoid;
}
}
else
{
resultData[0] = ReturnCodes::DataTypeConflict;
}
}
else
{
resultData[0] = ReturnCodes::GenericError;
}
_appLayer.functionPropertyExtStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, resultData, resultLength);
}
void BauSystemB::functionPropertyExtStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
uint8_t propertyId, uint8_t* data, uint8_t length)
{
uint8_t resultData[kFunctionPropertyResultBufferMaxSize];
uint8_t resultLength = sizeof(resultData); // tell the callee the maximum size of the buffer
InterfaceObject* obj = getInterfaceObject(objectType, objectInstance);
if(obj)
{
PropertyDataType propType = obj->property((PropertyID)propertyId)->Type();
if (propType == PDT_FUNCTION)
{
// The first byte is reserved and 0 for PDT_FUNCTION
uint8_t reservedByte = data[0];
if (reservedByte != 0x00)
{
resultData[0] = ReturnCodes::DataVoid;
}
else
{
resultLength = sizeof(resultData); // tell the callee the maximum size of the buffer
obj->state((PropertyID)propertyId, data, length, resultData, resultLength);
// resultLength was modified by the callee
}
}
else if (propType == PDT_CONTROL)
{
uint8_t count = 1;
// Read the current state (one byte only) for the response
obj->readProperty((PropertyID)propertyId, 1, count, &resultData[1]);
resultLength = count ? 2 : 1;
resultData[0] = count ? ReturnCodes::Success : ReturnCodes::DataVoid;
}
else
{
resultData[0] = ReturnCodes::DataTypeConflict;
}
}
else
{
resultData[0] = ReturnCodes::GenericError;
}
_appLayer.functionPropertyExtStateResponse(AckRequested, priority, hopType, asap, secCtrl, objectType, objectInstance, propertyId, resultData, resultLength);
}
void BauSystemB::individualAddressReadIndication(HopCountType hopType, const SecurityControl &secCtrl)
{
if (_deviceObj.progMode())
_appLayer.individualAddressReadResponse(AckRequested, hopType);
_appLayer.individualAddressReadResponse(AckRequested, hopType, secCtrl);
}
void BauSystemB::individualAddressWriteIndication(HopCountType hopType, uint16_t newaddress)
void BauSystemB::individualAddressWriteIndication(HopCountType hopType, const SecurityControl &secCtrl, uint16_t newaddress)
{
if (_deviceObj.progMode())
_deviceObj.induvidualAddress(newaddress);
}
void BauSystemB::groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, uint8_t * data, uint8_t dataLength, bool status)
void BauSystemB::individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t newIndividualAddress,
uint8_t* knxSerialNumber)
{
// If the received serial number matches our serial number
// then store the received new individual address in the device object
if (!memcmp(knxSerialNumber, _deviceObj.propertyData(PID_SERIAL_NUMBER), 6))
_deviceObj.induvidualAddress(newIndividualAddress);
}
void BauSystemB::individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* knxSerialNumber)
{
// If the received serial number matches our serial number
// then send a response with the serial number. The domain address is set to 0 for closed media.
// An open medium BAU has to override this method and provide a proper domain address.
if (!memcmp(knxSerialNumber, _deviceObj.propertyData(PID_SERIAL_NUMBER), 6))
{
uint8_t emptyDomainAddress[6] = {0x00};
_appLayer.IndividualAddressSerialNumberReadResponse(priority, hopType, secCtrl, emptyDomainAddress, knxSerialNumber);
}
}
void BauSystemB::groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t * data, uint8_t dataLength, bool status)
{
GroupObject& go = _groupObjTable.get(asap);
if (status)
@ -293,7 +611,7 @@ void BauSystemB::groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priorit
go.commFlag(Error);
}
void BauSystemB::groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, bool status)
void BauSystemB::groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, bool status)
{
GroupObject& go = _groupObjTable.get(asap);
if (status)
@ -302,18 +620,31 @@ void BauSystemB::groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority
go.commFlag(Error);
}
void BauSystemB::groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType)
void BauSystemB::groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl)
{
#ifdef USE_DATASECURE
DataSecurity requiredGoSecurity;
// Get security flags from Security Interface Object for this group object
requiredGoSecurity = _secIfObj.getGroupObjectSecurity(asap);
if (secCtrl.dataSecurity != requiredGoSecurity)
{
println("GroupValueRead: access denied due to wrong security flags");
return;
}
#endif
GroupObject& go = _groupObjTable.get(asap);
if (!go.communicationEnable() || !go.readEnable())
return;
uint8_t* data = go.valueRef();
_appLayer.groupValueReadResponse(AckRequested, asap, priority, hopType, data, go.sizeInTelegram());
_appLayer.groupValueReadResponse(AckRequested, asap, priority, hopType, secCtrl, data, go.sizeInTelegram());
}
void BauSystemB::groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType, uint8_t* data,
void BauSystemB::groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* data,
uint8_t dataLength)
{
GroupObject& go = _groupObjTable.get(asap);
@ -324,8 +655,20 @@ void BauSystemB::groupValueReadAppLayerConfirm(uint16_t asap, Priority priority,
updateGroupObject(go, data, dataLength);
}
void BauSystemB::groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType, uint8_t * data, uint8_t dataLength)
void BauSystemB::groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t * data, uint8_t dataLength)
{
#ifdef USE_DATASECURE
DataSecurity requiredGoSecurity;
// Get security flags from Security Interface Object for this group object
requiredGoSecurity = _secIfObj.getGroupObjectSecurity(asap);
if (secCtrl.dataSecurity != requiredGoSecurity)
{
println("GroupValueWrite: access denied due to wrong security flags");
return;
}
#endif
GroupObject& go = _groupObjTable.get(asap);
if (!go.communicationEnable() || !go.writeEnable())
@ -339,13 +682,14 @@ void BauSystemB::addSaveRestore(SaveRestore* obj)
_memory.addSaveRestore(obj);
}
bool BauSystemB::restartRequest(uint16_t asap)
bool BauSystemB::restartRequest(uint16_t asap, const SecurityControl secCtrl)
{
if (_appLayer.isConnected())
return false;
_restartState = Connecting; // order important, has to be set BEFORE connectRequest
_restartSecurity = secCtrl;
_appLayer.connectRequest(asap, SystemPriority);
_appLayer.deviceDescriptorReadRequest(AckRequested, SystemPriority, NetworkLayerParameter, asap, 0);
_appLayer.deviceDescriptorReadRequest(AckRequested, SystemPriority, NetworkLayerParameter, asap, secCtrl, 0);
return true;
}
@ -377,7 +721,7 @@ void BauSystemB::nextRestartState()
/* connection confirmed, we send restartRequest, but we wait a moment (sending ACK etc)... */
if (millis() - _restartDelay > 30)
{
_appLayer.restartRequest(AckRequested, SystemPriority, NetworkLayerParameter);
_appLayer.restartRequest(AckRequested, SystemPriority, NetworkLayerParameter, _restartSecurity);
_restartState = Restarted;
_restartDelay = millis();
}
@ -394,7 +738,7 @@ void BauSystemB::nextRestartState()
}
}
void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, uint16_t objectType,
void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t objectType,
uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength)
{
uint8_t operand;
@ -409,7 +753,7 @@ void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCoun
if (_deviceObj.progMode() && (objectType == OT_DEVICE) && (propertyId == PID_SERIAL_NUMBER))
{
// Send reply. testResult data is KNX serial number
_appLayer.systemNetworkParameterReadResponse(priority, hopType, objectType, propertyId,
_appLayer.systemNetworkParameterReadResponse(priority, hopType, secCtrl, objectType, propertyId,
testInfo, testInfoLength, (uint8_t*)_deviceObj.propertyData(PID_SERIAL_NUMBER), 6);
}
break;
@ -425,7 +769,7 @@ void BauSystemB::systemNetworkParameterReadIndication(Priority priority, HopCoun
}
}
void BauSystemB::systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, uint16_t objectType,
void BauSystemB::systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t objectType,
uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength, bool status)
{
}

View File

@ -6,8 +6,10 @@
#include "address_table_object.h"
#include "association_table_object.h"
#include "group_object_table_object.h"
#include "security_interface_object.h"
#include "application_program_object.h"
#include "application_layer.h"
#include "secure_application_layer.h"
#include "transport_layer.h"
#include "network_layer.h"
#include "data_link_layer.h"
@ -29,7 +31,8 @@ class BauSystemB : protected BusAccessUnit
void readMemory();
void writeMemory();
void addSaveRestore(SaveRestore* obj);
bool restartRequest(uint16_t asap);
bool restartRequest(uint16_t asap, const SecurityControl secCtrl);
uint8_t checkmasterResetValidity(EraseCode eraseCode, uint8_t channel);
void propertyValueRead(ObjectType objectType, uint8_t objectInstance, uint8_t propertyId,
uint8_t& numberOfElements, uint16_t startIndex,
@ -40,39 +43,54 @@ class BauSystemB : protected BusAccessUnit
protected:
virtual DataLinkLayer& dataLinkLayer() = 0;
void memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
void memoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint16_t memoryAddress, uint8_t* data) override;
void memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
void memoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint16_t memoryAddress) override;
void deviceDescriptorReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t descriptorType) override;
void restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap) override;
void authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, uint32_t key) override;
void userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number, uint32_t memoryAddress) override;
void userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t number,
void memoryExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* data) override;
void memoryExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress) override;
void deviceDescriptorReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t descriptorType) override;
void restartRequestIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, RestartType restartType, EraseCode eraseCode, uint8_t channel) override;
void authorizeIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint32_t key) override;
void userMemoryReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number, uint32_t memoryAddress) override;
void userMemoryWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t number,
uint32_t memoryAddress, uint8_t* memoryData) override;
void propertyDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
void propertyDescriptionReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t propertyIndex) override;
void propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
void propertyValueWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length) override;
void propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
void propertyValueExtWriteIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex, uint8_t* data, uint8_t length, bool confirmed);
void propertyValueReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex) override;
void functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
uint8_t propertyId, uint8_t* data, uint8_t length);
void functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, uint8_t objectIndex,
uint8_t propertyId, uint8_t* data, uint8_t length);
void individualAddressReadIndication(HopCountType hopType) override;
void individualAddressWriteIndication(HopCountType hopType, uint16_t newaddress) override;
void groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType,
void propertyValueExtReadIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
uint8_t propertyId, uint8_t numberOfElements, uint16_t startIndex) override;
void functionPropertyCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t* data, uint8_t length) override;
void functionPropertyStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, uint8_t objectIndex,
uint8_t propertyId, uint8_t* data, uint8_t length) override;
void functionPropertyExtCommandIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
uint8_t propertyId, uint8_t* data, uint8_t length) override;
void functionPropertyExtStateIndication(Priority priority, HopCountType hopType, uint16_t asap, const SecurityControl &secCtrl, ObjectType objectType, uint8_t objectInstance,
uint8_t propertyId, uint8_t* data, uint8_t length) override;
void individualAddressReadIndication(HopCountType hopType, const SecurityControl &secCtrl) override;
void individualAddressWriteIndication(HopCountType hopType, const SecurityControl &secCtrl, uint16_t newaddress) override;
void individualAddressSerialNumberWriteIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t newIndividualAddress,
uint8_t* knxSerialNumber) override;
void individualAddressSerialNumberReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint8_t* knxSerialNumber) override;
void groupValueWriteLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* data, uint8_t dataLength, bool status) override;
void groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, bool status) override;
void groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType) override;
void groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType,
void groupValueReadLocalConfirm(AckType ack, uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl, bool status) override;
void groupValueReadIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl) override;
void groupValueReadAppLayerConfirm(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* data, uint8_t dataLength) override;
void groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType,
void groupValueWriteIndication(uint16_t asap, Priority priority, HopCountType hopType, const SecurityControl &secCtrl,
uint8_t* data, uint8_t dataLength) override;
void systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, uint16_t objectType,
void systemNetworkParameterReadIndication(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t objectType,
uint16_t propertyId, uint8_t* testInfo, uint16_t testinfoLength) override;
void systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, uint16_t objectType,
void systemNetworkParameterReadLocalConfirm(Priority priority, HopCountType hopType, const SecurityControl &secCtrl, uint16_t objectType,
uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength, bool status) override;
void connectConfirm(uint16_t tsap) override;
@ -82,6 +100,8 @@ class BauSystemB : protected BusAccessUnit
void updateGroupObject(GroupObject& go, uint8_t* data, uint8_t length);
void nextRestartState();
virtual void doMasterReset(EraseCode eraseCode, uint8_t channel);
enum RestartState
{
Idle,
@ -97,10 +117,16 @@ class BauSystemB : protected BusAccessUnit
GroupObjectTableObject _groupObjTable;
ApplicationProgramObject _appProgram;
Platform& _platform;
#ifdef USE_DATASECURE
SecureApplicationLayer _appLayer;
SecurityInterfaceObject _secIfObj;
#else
ApplicationLayer _appLayer;
#endif
TransportLayer _transLayer;
NetworkLayer _netLayer;
bool _configured = true;
RestartState _restartState = Idle;
SecurityControl _restartSecurity;
uint32_t _restartDelay = 0;
};

View File

@ -84,3 +84,24 @@ uint32_t getInt(const uint8_t * data)
{
return (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
}
void sixBytesFromUInt64(uint64_t num, uint8_t* toByteArray)
{
toByteArray[0] = ((num >> 40) & 0xff);
toByteArray[1] = ((num >> 32) & 0xff);
toByteArray[2] = ((num >> 24) & 0xff);
toByteArray[3] = ((num >> 16) & 0xff);
toByteArray[4] = ((num >> 8) & 0xff);
toByteArray[5] = (num & 0xff);
}
uint64_t sixBytesToUInt64(uint8_t* data)
{
uint64_t l = 0;
for (uint8_t i = 0; i < 6; i++)
{
l = (l << 8) + data[i];
}
return l;
}

View File

@ -58,6 +58,7 @@ void print(int, int = DEC);
void print(unsigned int, int = DEC);
void print(long, int = DEC);
void print(unsigned long, int = DEC);
void print(unsigned long long, int = DEC);
void print(double);
void println(const char[]);
@ -67,6 +68,7 @@ void println(int, int = DEC);
void println(unsigned int, int = DEC);
void println(long, int = DEC);
void println(unsigned long, int = DEC);
void println(unsigned long long, int = DEC);
void println(double);
void println(void);
@ -85,3 +87,6 @@ uint8_t* pushByteArray(const uint8_t* src, uint32_t size, uint8_t* data);
uint16_t getWord(const uint8_t* data);
uint32_t getInt(const uint8_t* data);
void printHex(const char* suffix, const uint8_t *data, size_t length);
void sixBytesFromUInt64(uint64_t num, uint8_t* toByteArray);
uint64_t sixBytesToUInt64(uint8_t* data);

View File

@ -22,4 +22,6 @@
#define USE_CEMI_SERVER
#endif
#define USE_DATASECURE
#endif

View File

@ -151,3 +151,13 @@ const uint8_t* DataProperty::data()
{
return _data;
}
const uint8_t* DataProperty::data(uint16_t elementIndex)
{
if ((elementIndex == 0) || (elementIndex > _currentElements))
return nullptr;
elementIndex -= 1; // Starting from 0
uint16_t offset = elementIndex * ElementSize();
return _data + offset;
}

View File

@ -17,6 +17,7 @@ class DataProperty : public Property
virtual const uint8_t* restore(const uint8_t* buffer) override;
virtual uint16_t saveSize() override;
const uint8_t* data();
const uint8_t* data(uint16_t elementIndex);
private:
uint16_t _currentElements = 0;

View File

@ -9,8 +9,10 @@
DeviceObject::DeviceObject()
{
//Default to KNXA (0xFA)
uint8_t serialNumber[] = {0x00, 0xFA, 0x00, 0x00, 0x00, 0x00};
// Default to KNXA (0xFA)
// Note: ETS does not accept a SN 00FA00000000 in data secure mode.
// ETS says that 00FA00000000 looks "suspicious" in the log file.
uint8_t serialNumber[] = {0x00, 0xFA, 0x01, 0x02, 0x03, 0x04};
uint8_t hardwareType[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Property* properties[] =

View File

@ -54,6 +54,12 @@ void InterfaceObject::readPropertyDescription(uint8_t& propertyId, uint8_t& prop
}
}
void InterfaceObject::masterReset(EraseCode eraseCode, uint8_t channel)
{
// every interface object shall implement this
// However, for the time being we provide an empty default implementation
}
void InterfaceObject::readProperty(PropertyID id, uint16_t start, uint8_t& count, uint8_t* data)
{
Property* prop = property(id);
@ -101,7 +107,7 @@ void InterfaceObject::command(PropertyID id, uint8_t* data, uint8_t length, uint
prop->command(data, length, resultData, resultLength);
}
void InterfaceObject::state(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t resultLength)
void InterfaceObject::state(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength)
{
Property* prop = property(id);
if (prop == nullptr)
@ -190,3 +196,9 @@ const uint8_t* InterfaceObject::propertyData(PropertyID id)
DataProperty* prop = (DataProperty*)property(id);
return prop->data();
}
const uint8_t* InterfaceObject::propertyData(PropertyID id, uint16_t elementIndex)
{
DataProperty* prop = (DataProperty*)property(id);
return prop->data(elementIndex);
}

View File

@ -3,6 +3,7 @@
#include <stddef.h>
#include "property.h"
#include "save_restore.h"
#include "knx_types.h"
/** Enum for the type of an interface object. See Section 2.2 of knx:3/7/3 */
enum ObjectType
@ -49,6 +50,9 @@ enum ObjectType
/** File Server Object */
OT_FILE_SERVER = 13,
/** Security Interface Object */
OT_SECURITY = 17,
/** RF Medium Object */
OT_RF_MEDIUM = 19
};
@ -125,7 +129,7 @@ class InterfaceObject : public SaveRestore
*
* @param[out] resultData The result data for the function
*/
virtual void state(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t resultLength);
virtual void state(PropertyID id, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t &resultLength);
/**
* Read the Description of a property of the interface object. The output parameters are only valid if nuberOfElements is not zero.
*
@ -146,6 +150,10 @@ class InterfaceObject : public SaveRestore
*/
void readPropertyDescription(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access);
// every interface object shall implement this
// However, for the time being we provide an empty default implementation
virtual void masterReset(EraseCode eraseCode, uint8_t channel);
/**
* Gets property with PropertyID id if it exists and nullptr otherwise.
*/
@ -169,6 +177,7 @@ class InterfaceObject : public SaveRestore
}
const uint8_t* propertyData(PropertyID id);
const uint8_t* propertyData(PropertyID id, uint16_t elementIndex);
/**
* Gets const property with PropertyID id if it exists and nullptr otherwise.
*/

View File

@ -108,4 +108,4 @@ bool IpDataLinkLayer::sendBytes(uint8_t* bytes, uint16_t length)
return _platform.sendBytesMultiCast(bytes, length);
}
#endif
#endif

View File

@ -55,4 +55,4 @@ class KnxIpFrame
uint8_t* _data = 0;
uint16_t _dataLength;
};
#endif
#endif

View File

@ -22,8 +22,8 @@ KnxIpSearchResponse::KnxIpSearchResponse(IpParameterObject& parameters, DeviceOb
_deviceInfo.indiviudalAddress(parameters.propertyValue<uint16_t>(PID_KNX_INDIVIDUAL_ADDRESS));
_deviceInfo.projectInstallationIdentifier(parameters.propertyValue<uint16_t>(PID_PROJECT_INSTALLATION_ID));
_deviceInfo.serialNumber(deviceObject.propertyData(PID_SERIAL_NUMBER));
//_deviceInfo.routingMulticastAddress(parameters.propertyValue<uint32_t>(PID_ROUTING_MULTICAST_ADDRESS));
_deviceInfo.routingMulticastAddress(0);
_deviceInfo.routingMulticastAddress(parameters.propertyValue<uint32_t>(PID_ROUTING_MULTICAST_ADDRESS));
//_deviceInfo.routingMulticastAddress(0);
uint8_t mac_address[LEN_MAC_ADDRESS] = {0};
Property* prop = parameters.property(PID_MAC_ADDRESS);
@ -59,4 +59,4 @@ KnxIpSupportedServiceDIB& KnxIpSearchResponse::supportedServices()
{
return _supportedServices;
}
#endif
#endif

View File

@ -66,6 +66,31 @@ enum cEmiErrorCode
Value_temp_not_writeable = 0x0A, // The Property exists but can at this moment not be written with a new value (W)
};
// Unified return codes for KNX services and functions
// Note, that several older KNX services and functions do not use these return codes.
enum ReturnCodes
{
// Generic positive return codes
Success = 0x00, // service, function or command executed sucessfully
SuccessWithCrc = 0x01, // positive message confirmation, CRC over original data
// Generic negative return codes
MemoryError = 0xF1, // memory cannot be accessed or only with fault(s)
InvalidCommand = 0xF2, // server does not support the requested command. ets: also non-existing or protected resource
ImpossibleCommand = 0xF3, // command cannot be executed because a dependency is not fulfilled
ExceedsMaxApduLength = 0xF4, // data will not fit into a frame supported by this server
DataOverflow = 0xF5, // attempt to write data beyond what is reserved for the addressed resource
OutOfMinRange = 0xF6, // write value below minimum supported value
OutOfMaxRange = 0xF7, // write value exceeds maximum supported value
DataVoid = 0xF8, // request contains invalid data
TemporarilyNotAvailable = 0xF9, // data access not possible at this time
AccessWriteOnly = 0xFA, // read access to write-only resource
AccessReadOnly = 0xFB, // write access to read-only resource
AccessDenied = 0xFC, // access to recource is not allowed because of authorization/security
AddressVoid = 0xFD, // resource is not present, address does not exist
DataTypeConflict = 0xFE, // write access with wrong datatype (datapoint length)
GenericError = 0xFF // service, function or command failed
};
enum Repetition
{
NoRepitiion = 0,
@ -130,6 +155,20 @@ enum ApduType
// Application Layer Services on Point-to-point Connection-Oriented Communication Mode (mandatory)
// Application Layer Services on Point-to-point Connectionless Communication Mode (either optional or mandatory)
PropertyValueExtRead = 0x1CC,
PropertyValueExtResponse = 0x1CD,
PropertyValueExtWriteCon = 0x1CE,
PropertyValueExtWriteConResponse = 0x1CF,
PropertyValueExtWriteUnCon = 0x1D0,
PropertyExtDescriptionRead = 0x1D2,
PropertyExtDescriptionResponse = 0x1D3,
FunctionPropertyExtCommand = 0x1D4,
FunctionPropertyExtState = 0x1D5,
FunctionPropertyExtStateResponse = 0x1D6,
MemoryExtWrite = 0x1FB,
MemoryExtWriteResponse = 0x1FC,
MemoryExtRead = 0x1FD,
MemoryExtReadResponse = 0x1FE,
MemoryRead = 0x200,
MemoryResponse = 0x240,
MemoryWrite = 0x280,
@ -144,6 +183,7 @@ enum ApduType
DeviceDescriptorRead = 0x300,
DeviceDescriptorResponse = 0x340,
Restart = 0x380,
RestartMasterReset = 0x381,
AuthorizeRequest = 0x3d1,
AuthorizeResponse = 0x3d2,
KeyWrite = 0x3d3,
@ -153,4 +193,38 @@ enum ApduType
PropertyValueWrite = 0x3d7,
PropertyDescriptionRead = 0x3d8,
PropertyDescriptionResponse = 0x3d9,
// Secure Service
SecureService = 0x3F1
};
enum DataSecurity
{
none,
auth,
authConf
};
struct SecurityControl
{
bool toolAccess;
DataSecurity dataSecurity;
};
enum RestartType
{
BasicRestart = 0x0,
MasterReset = 0x1
};
enum EraseCode
{
Void = 0x00,
ConfirmedRestart = 0x01,
FactoryReset = 0x02,
ResetIA = 0x03,
ResetAP = 0x04,
ResetParam = 0x05,
ResetLinks = 0x06,
FactoryResetWithoutIA = 0x07
};

View File

@ -13,7 +13,7 @@ void Memory::readMemory()
if (_data != nullptr)
return;
uint16_t flashSize = 512;
uint16_t flashSize = 8192;
_data = _platform.getEepromBuffer(flashSize);
printHex("RESTORED ", _data, _metadataSize);
@ -428,4 +428,4 @@ void Memory::addNewUsedBlock(uint8_t* address, size_t size)
MemoryBlock* newUsedBlock = new MemoryBlock(address, size);
addToUsedList(newUsedBlock);
}
}

View File

@ -86,6 +86,8 @@ enum PropertyID
PID_VERSION = 25,
PID_MCB_TABLE = 27,
PID_ERROR_CODE = 28,
PID_OBJECT_INDEX = 29,
PID_DOWNLOAD_COUNTER = 30,
/** Properties in the Device Object */
PID_ROUTING_COUNT = 51,
@ -158,6 +160,20 @@ enum PropertyID
PID_MAX_INTERFACE_APDU_LENGTH = 68,
PID_MAX_LOCAL_APDU_LENGTH = 69,
/** Security Interface Object */
PID_SECURITY_MODE = 51, // Enable and disable the Security Mode
PID_P2P_KEY_TABLE = 52, // Security keys used for securing point-to-point and broadcast communication
PID_GRP_KEY_TABLE = 53, // Security keys used for securing standard mode group communication
PID_SECURITY_INDIVIDUAL_ADDRESS_TABLE = 54, // IAs and last valid sequence numbers of communication partners with secure links
PID_SECURITY_FAILURES_LOG = 55, // Provides security failure information
PID_TOOL_KEY = 56, // Stores the security information for the central MaC in S-Mode and Ctrl-Mode
PID_SECURITY_REPORT = 57, // KNX Data Security-related status and diagnostic information
PID_SECURITY_REPORT_CONTROL = 58, // Control the spontaneous communication of the security report through DMP_InterfaceObject-InfoReport_RCl
PID_SEQUENCE_NUMBER_SENDING = 59, // Sequence Number used for the next outgoing secure communication
PID_ZONE_KEY_TABLE = 60, // Security keys used for securing zone addressing communication
PID_GO_SECURITY_FLAGS = 61, // Defines the required security requirements for each group object
PID_ROLE_TABLE = 62, // Role table
PID_TOOL_SEQUENCE_NUMBER_SENDING = 250, // Sequence Number used for the next outgoing secure communication (Tool Access only, non-standardized!)
};
enum LoadState

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,154 @@
#pragma once
#include "application_layer.h"
#include <stdint.h>
#include "knx_types.h"
#include "apdu.h"
#include "bits.h"
#include "simple_map.h"
class DeviceObject;
class SecurityInterfaceObject;
class AssociationTableObject;
class AddressTableObject;
class BusAccessUnit;
/**
* This is an implementation of the application layer as specified in @cite knx:3/5/1.
* It provides methods for the BusAccessUnit to do different things and translates this
* call to an APDU and calls the correct method of the TransportLayer.
* It also takes calls from TransportLayer, decodes the submitted APDU and calls the coresponding
* methods of the BusAccessUnit class.
*/
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, AddressTableObject& addrTab, BusAccessUnit& bau);
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, const SecurityControl& secCtrl) override;
virtual void dataBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, const SecurityControl& secCtrl) override;
virtual void dataSystemBroadcastRequest(AckType ack, HopCountType hopType, Priority priority, APDU& apdu, const SecurityControl& secCtrl) override;
virtual void dataIndividualRequest(AckType ack, HopCountType hopType, Priority priority, uint16_t destination, APDU& apdu, const SecurityControl& secCtrl) override;
virtual void dataConnectedRequest(uint16_t tsap, Priority priority, APDU& apdu, const SecurityControl& secCtrl) override; // apdu must be valid until it was confirmed
private:
enum class AddrType : uint8_t
{
group,
individual,
unknown
};
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; }
};
uint32_t calcAuthOnlyMac(uint8_t* apdu, uint8_t apduLength, const uint8_t *key, uint8_t* iv, uint8_t* ctr0);
uint32_t calcConfAuthMac(uint8_t* associatedData, uint16_t associatedDataLength, uint8_t* apdu, uint8_t apduLength, const uint8_t* key, uint8_t* iv);
void block0(uint8_t* buffer, uint8_t* seqNum, uint16_t indSrcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, uint8_t extFrameFormat, uint8_t tpci, uint8_t apci, uint8_t payloadLength);
void blockCtr0(uint8_t* buffer, uint8_t* seqNum, uint16_t indSrcAddr, uint16_t dstAddr);
const uint8_t* securityKey(uint16_t addr, bool isGroupAddress);
uint16_t groupAddressIndex(uint16_t groupAddr); // returns 1-based index of address in group address table
uint16_t groupObjectIndex(uint16_t groupAddrIndex); // returns 1-based index of object in association table
uint8_t groupObjectSecurity(uint16_t groupObjectIndex);
uint64_t nextSequenceNumber(bool toolAccess);
void updateSequenceNumber(bool toolAccess, uint64_t seqNum);
uint64_t lastValidSequenceNumber(bool toolAcces, uint16_t srcAddr);
void updateLastValidSequence(bool toolAccess, uint16_t remoteAddr, uint64_t seqNo);
uint64_t getRandomNumber();
bool isSyncService(APDU& secureAsdu);
void sendSyncRequest(uint16_t dstAddr, bool dstAddrIsGroupAddr, const SecurityControl &secCtrl, bool systemBcast);
void sendSyncResponse(uint16_t dstAddr, bool dstAddrIsGroupAddr, const SecurityControl &secCtrl, uint64_t remoteNextSeqNum, bool systemBcast);
void receivedSyncRequest(uint16_t srcAddr, uint16_t dstAddr, bool dstAddrIsGroupAddr, const SecurityControl &secCtrl, uint8_t* seq, uint64_t challenge, bool systemBcast);
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, SecurityControl &secCtrl, bool systemBcast);
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 systemBcast);
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);
bool _syncReqBroadcastIncoming{false};
bool _syncReqBroadcastOutgoing{false};
uint32_t _lastSyncRes;
Map<Addr, uint64_t, 1> _pendingOutgoingSyncRequests; // Store challenges for outgoing sync requests
Map<Addr, uint64_t, 1> _pendingIncomingSyncRequests; // Store challenges for incoming sync requests
uint64_t _sequenceNumberToolAccess = 50;
uint64_t _sequenceNumber = 0;
uint64_t _lastValidSequenceNumberTool = 0;
uint64_t _lastValidSequenceNumber = 0;
SecurityInterfaceObject& _secIfObj;
DeviceObject& _deviceObj;
AddressTableObject& _addrTab;
};

View File

@ -0,0 +1,542 @@
#include "config.h"
#ifdef USE_DATASECURE
#include <cstring>
#include "security_interface_object.h"
#include "secure_application_layer.h"
#include "bits.h"
#include "data_property.h"
#include "callback_property.h"
#include "function_property.h"
// Our FDSK. It is never changed from ETS. This is the permanent default tool key that is restored on every factory reset of the device.
const uint8_t SecurityInterfaceObject::_fdsk[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
uint8_t SecurityInterfaceObject::_secReport[] = { 0x00, 0x00, 0x00 };
uint8_t SecurityInterfaceObject::_secReportCtrl[] = { 0x00, 0x00, 0x00 };
SecurityInterfaceObject::SecurityInterfaceObject()
{
Property* properties[] =
{
new DataProperty( PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t)OT_SECURITY ),
new CallbackProperty<SecurityInterfaceObject>(this, PID_LOAD_STATE_CONTROL, true, PDT_CONTROL, 1, ReadLv3 | WriteLv3,
// ReadCallback of PID_LOAD_STATE_CONTROL
[](SecurityInterfaceObject* obj, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t {
if (start == 0)
return 1;
data[0] = obj->_state;
return 1;
},
// WriteCallback of PID_LOAD_STATE_CONTROL
[](SecurityInterfaceObject* obj, uint16_t start, uint8_t count, const uint8_t* data) -> uint8_t {
obj->loadEvent(data);
return 1;
}),
new FunctionProperty<SecurityInterfaceObject>(this, PID_SECURITY_MODE,
// Command Callback of PID_SECURITY_MODE
[](SecurityInterfaceObject* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void {
uint8_t serviceId = data[1] & 0xff;
if (serviceId != 0)
{
resultData[0] = ReturnCodes::InvalidCommand;
resultLength = 1;
return;
}
if (length == 3)
{
uint8_t mode = data[2];
if (mode > 1)
{
resultData[0] = ReturnCodes::DataVoid;
resultLength = 1;
return;
}
obj->setSecurityMode(mode == 1);
resultData[0] = ReturnCodes::Success;
resultData[1] = serviceId;
resultLength = 2;
return;
}
resultData[0] = ReturnCodes::GenericError;
resultLength = 1;
},
// State Callback of PID_SECURITY_MODE
[](SecurityInterfaceObject* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void {
uint8_t serviceId = data[1] & 0xff;
if (serviceId != 0)
{
resultData[0] = ReturnCodes::InvalidCommand;
resultLength = 1;
return;
}
if (length == 2)
{
resultData[0] = ReturnCodes::Success;
resultData[1] = serviceId;
resultData[2] = obj->isSecurityModeEnabled() ? 1 : 0;
resultLength = 3;
return;
}
resultData[0] = ReturnCodes::GenericError;
resultLength = 1;
}),
new DataProperty( PID_P2P_KEY_TABLE, true, PDT_GENERIC_20, 1, ReadLv3 | WriteLv0 ), // written by ETS
new DataProperty( PID_GRP_KEY_TABLE, true, PDT_GENERIC_18, 50, ReadLv3 | WriteLv0 ), // written by ETS
new DataProperty( PID_SECURITY_INDIVIDUAL_ADDRESS_TABLE, true, PDT_GENERIC_08, 32, ReadLv3 | WriteLv0 ), // written by ETS
new FunctionProperty<SecurityInterfaceObject>(this, PID_SECURITY_FAILURES_LOG,
// Command Callback of PID_SECURITY_FAILURES_LOG
[](SecurityInterfaceObject* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void {
if (length != 3)
{
resultData[0] = ReturnCodes::DataVoid;
resultLength = 1;
return;
}
uint8_t id = data[1];
uint8_t info = data[2];
if (id == 0 && info == 0)
{
obj->_secAppLayer->clearFailureLog();
resultData[0] = ReturnCodes::Success;
resultData[1] = id;
resultLength = 2;
return;
}
resultData[0] = ReturnCodes::GenericError;
resultLength = 1;
},
// State Callback of PID_SECURITY_FAILURES_LOG
[](SecurityInterfaceObject* obj, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength) -> void {
if (length != 3)
{
resultData[0] = ReturnCodes::DataVoid;
resultLength = 1;
return;
}
uint8_t id = data[1];
uint8_t info = data[2];
// failure counters
if (id == 0 && info == 0)
{
resultData[0] = ReturnCodes::Success;
resultData[1] = id;
resultData[2] = info;
obj->_secAppLayer->getFailureCounters(&resultData[3]); // Put 8 bytes in the buffer
resultLength = 3 + 8;
return;
}
// query latest failure by index
else if(id == 1)
{
uint8_t maxBufferSize = resultLength; // Remember the maximum buffer size of the buffer that is provided to us
uint8_t index = info;
uint8_t numBytes = obj->_secAppLayer->getFromFailureLogByIndex(index, &resultData[2], maxBufferSize);
if ( numBytes > 0)
{
resultData[0] = ReturnCodes::Success;
resultData[1] = id;
resultData[2] = index;
resultLength += numBytes;
resultLength = 3 + numBytes;
return;
}
resultData[0] = ReturnCodes::DataVoid;
resultData[1] = id;
resultLength = 2;
return;
}
resultData[0] = ReturnCodes::GenericError;
resultLength = 1;
}),
new DataProperty( PID_TOOL_KEY, true, PDT_GENERIC_16, 1, ReadLv3 | WriteLv0, (uint8_t*) _fdsk ), // default is FDSK // ETS changes this property during programming from FDSK to some random key!
new DataProperty( PID_SECURITY_REPORT, true, PDT_BITSET8, 1, ReadLv3 | WriteLv0, _secReport ), // Not implemented
new DataProperty( PID_SECURITY_REPORT_CONTROL, true, PDT_BINARY_INFORMATION, 1, ReadLv3 | WriteLv0, _secReportCtrl ), // Not implemented
new DataProperty( PID_SEQUENCE_NUMBER_SENDING, true, PDT_GENERIC_06, 1, ReadLv3 | WriteLv0 ), // Updated by our device accordingly
new DataProperty( PID_ZONE_KEY_TABLE, true, PDT_GENERIC_19, 1, ReadLv3 | WriteLv0 ), // written by ETS
new DataProperty( PID_GO_SECURITY_FLAGS, true, PDT_GENERIC_01, 256, ReadLv3 | WriteLv0 ), // written by ETS
new DataProperty( PID_ROLE_TABLE, true, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0 ), // written by ETS
new DataProperty( PID_ERROR_CODE, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0, (uint8_t)E_NO_FAULT),
new DataProperty( PID_TOOL_SEQUENCE_NUMBER_SENDING, true, PDT_GENERIC_06, 1, ReadLv3 | WriteLv0 ) // Updated by our device accordingly (non-standardized!)
};
initializeProperties(sizeof(properties), properties);
}
void SecurityInterfaceObject::secureApplicationLayer(SecureApplicationLayer& secAppLayer)
{
_secAppLayer = &secAppLayer;
}
uint8_t* SecurityInterfaceObject::save(uint8_t* buffer)
{
buffer = pushByte(_state, buffer);
buffer = pushByte(_securityModeEnabled, buffer);
return InterfaceObject::save(buffer);
}
const uint8_t* SecurityInterfaceObject::restore(const uint8_t* buffer)
{
uint8_t state = 0;
buffer = popByte(state, buffer);
_state = (LoadState)state;
uint8_t securityModeEnabled = 0;
buffer = popByte(securityModeEnabled, buffer);
_securityModeEnabled = securityModeEnabled;
return InterfaceObject::restore(buffer);
}
uint16_t SecurityInterfaceObject::saveSize()
{
return 2 + InterfaceObject::saveSize();
}
void SecurityInterfaceObject::setSecurityMode(bool enabled)
{
print("Security mode set to: ");
println(enabled ? "enabled" : "disabled");
_securityModeEnabled = enabled;
}
bool SecurityInterfaceObject::isSecurityModeEnabled()
{
return _securityModeEnabled;
}
bool SecurityInterfaceObject::isLoaded()
{
return _state == LS_LOADED;
}
void SecurityInterfaceObject::loadEvent(const uint8_t* data)
{
switch (_state)
{
case LS_UNLOADED:
loadEventUnloaded(data);
break;
case LS_LOADING:
loadEventLoading(data);
break;
case LS_LOADED:
loadEventLoaded(data);
break;
case LS_ERROR:
loadEventError(data);
break;
default:
/* do nothing */
break;
}
}
void SecurityInterfaceObject::loadEventUnloaded(const uint8_t* data)
{
uint8_t event = data[0];
switch (event)
{
case LE_NOOP:
case LE_LOAD_COMPLETED:
case LE_ADDITIONAL_LOAD_CONTROLS:
case LE_UNLOAD:
break;
case LE_START_LOADING:
loadState(LS_LOADING);
break;
default:
loadState(LS_ERROR);
errorCode(E_GOT_UNDEF_LOAD_CMD);
}
}
void SecurityInterfaceObject::loadEventLoading(const uint8_t* data)
{
uint8_t event = data[0];
switch (event)
{
case LE_NOOP:
case LE_START_LOADING:
break;
case LE_LOAD_COMPLETED:
loadState(LS_LOADED);
break;
case LE_UNLOAD:
loadState(LS_UNLOADED);
break;
case LE_ADDITIONAL_LOAD_CONTROLS: // Not supported here
default:
loadState(LS_ERROR);
errorCode(E_GOT_UNDEF_LOAD_CMD);
}
}
void SecurityInterfaceObject::loadEventLoaded(const uint8_t* data)
{
uint8_t event = data[0];
switch (event)
{
case LE_NOOP:
case LE_LOAD_COMPLETED:
break;
case LE_START_LOADING:
loadState(LS_LOADING);
break;
case LE_UNLOAD:
loadState(LS_UNLOADED);
break;
case LE_ADDITIONAL_LOAD_CONTROLS:
loadState(LS_ERROR);
errorCode(E_INVALID_OPCODE);
break;
default:
loadState(LS_ERROR);
errorCode(E_GOT_UNDEF_LOAD_CMD);
}
}
void SecurityInterfaceObject::loadEventError(const uint8_t* data)
{
uint8_t event = data[0];
switch (event)
{
case LE_NOOP:
case LE_LOAD_COMPLETED:
case LE_ADDITIONAL_LOAD_CONTROLS:
case LE_START_LOADING:
break;
case LE_UNLOAD:
loadState(LS_UNLOADED);
break;
default:
loadState(LS_ERROR);
errorCode(E_GOT_UNDEF_LOAD_CMD);
}
}
void SecurityInterfaceObject::loadState(LoadState newState)
{
if (newState == _state)
return;
//beforeStateChange(newState);
_state = newState;
}
void SecurityInterfaceObject::errorCode(ErrorCode errorCode)
{
uint8_t data = errorCode;
Property* prop = property(PID_ERROR_CODE);
prop->write(data);
}
void SecurityInterfaceObject::masterReset(EraseCode eraseCode, uint8_t channel)
{
if (eraseCode == FactoryReset)
{
// TODO handle different erase codes
println("Factory reset of security interface object requested.");
setSecurityMode(false);
property(PID_TOOL_KEY)->write(1, 1, _fdsk);
}
}
const uint8_t* SecurityInterfaceObject::toolKey()
{
// There is only one tool key
const uint8_t* toolKey = propertyData(PID_TOOL_KEY);
return toolKey;
}
const uint8_t* SecurityInterfaceObject::p2pKey(uint16_t addressIndex)
{
if (!isLoaded())
return nullptr;
// Get number of entries for this property
uint16_t numElements = getNumberOfElements(PID_P2P_KEY_TABLE);
if (numElements > 0)
{
uint8_t elementSize = propertySize(PID_P2P_KEY_TABLE);
// Search for address index
uint8_t entry[elementSize]; // 2 bytes index + keysize (16 bytes) + 2 bytes(roles) = 20 bytes
for (int i = 1; i <= numElements; i++)
{
property(PID_P2P_KEY_TABLE)->read(i, 1, entry);
uint16_t index = (entry[0] << 8) | entry[1];
if (index > addressIndex)
{
return nullptr;
}
if (index == addressIndex)
{
return propertyData(PID_P2P_KEY_TABLE, i) + sizeof(index);
}
}
}
return nullptr;
}
const uint8_t* SecurityInterfaceObject::groupKey(uint16_t addressIndex)
{
if (!isLoaded())
return nullptr;
// Get number of entries for this property
uint16_t numElements = getNumberOfElements(PID_GRP_KEY_TABLE);
if (numElements > 0)
{
uint8_t elementSize = propertySize(PID_GRP_KEY_TABLE);
// Search for address index
uint8_t entry[elementSize]; // 2 bytes index + keysize (16 bytes) = 18 bytes
for (int i = 1; i <= numElements; i++)
{
property(PID_GRP_KEY_TABLE)->read(i, 1, entry);
uint16_t index = ((entry[0] << 8) | entry[1]);
if (index > addressIndex)
{
return nullptr;
}
if (index == addressIndex)
{
return propertyData(PID_GRP_KEY_TABLE, i) + sizeof(index);
}
}
}
return nullptr;
}
uint16_t SecurityInterfaceObject::indAddressIndex(uint16_t indAddr)
{
// Get number of entries for this property
uint16_t numElements = getNumberOfElements(PID_SECURITY_INDIVIDUAL_ADDRESS_TABLE);
if (numElements > 0)
{
uint8_t elementSize = propertySize(PID_SECURITY_INDIVIDUAL_ADDRESS_TABLE);
// Search for individual address
uint8_t entry[elementSize]; // 2 bytes address + 6 bytes seqno = 8 bytes
for (int i = 1; i <= numElements; i++)
{
property(PID_SECURITY_INDIVIDUAL_ADDRESS_TABLE)->read(i, 1, entry);
uint16_t addr = (entry[0] << 8) | entry[1];
if (addr == indAddr)
{
return i;
}
}
}
// Not found
return 0;
}
void SecurityInterfaceObject::setSequenceNumber(bool toolAccess, uint64_t seqNum)
{
uint8_t seqBytes[6] = {0x00};
sixBytesFromUInt64(seqNum, seqBytes);
if (toolAccess)
{
property(PID_TOOL_SEQUENCE_NUMBER_SENDING)->write(1, 1, seqBytes);
}
else
{
property(PID_SEQUENCE_NUMBER_SENDING)->write(1, 1, seqBytes);
}
}
uint16_t SecurityInterfaceObject::getNumberOfElements(PropertyID propId)
{
// Get number of entries for this property
uint16_t numElements = 0;
uint8_t data[sizeof(uint16_t)]; // is sizeof(_currentElements) which is uint16_t
uint8_t count = property(propId)->read(0, 1, data);
if (count > 0)
{
popWord(numElements, data);
}
return numElements;
}
uint64_t SecurityInterfaceObject::getLastValidSequenceNumber(uint16_t deviceAddr)
{
// Get number of entries for this property
uint16_t numElements = getNumberOfElements(PID_SECURITY_INDIVIDUAL_ADDRESS_TABLE);
if (numElements > 0)
{
uint8_t elementSize = propertySize(PID_SECURITY_INDIVIDUAL_ADDRESS_TABLE);
// Search for individual address
uint8_t entry[elementSize]; // 2 bytes address + 6 bytes seqno = 8 bytes
for (int i = 1; i <= numElements; i++)
{
property(PID_SECURITY_INDIVIDUAL_ADDRESS_TABLE)->read(i, 1, entry);
uint16_t addr = (entry[0] << 8) | entry[1];
if (addr == deviceAddr)
{
return sixBytesToUInt64(&entry[2]);
}
}
}
return 0;
}
void SecurityInterfaceObject::setLastValidSequenceNumber(uint16_t deviceAddr, uint64_t seqNum)
{
// Get number of entries for this property
uint16_t numElements = getNumberOfElements(PID_SECURITY_INDIVIDUAL_ADDRESS_TABLE);
if (numElements > 0)
{
uint8_t elementSize = propertySize(PID_SECURITY_INDIVIDUAL_ADDRESS_TABLE);
// Search for individual address
uint8_t entry[elementSize]; // 2 bytes address + 6 bytes seqno = 8 bytes
for (int i = 1; i <= numElements; i++)
{
property(PID_SECURITY_INDIVIDUAL_ADDRESS_TABLE)->read(i, 1, entry);
uint16_t addr = (entry[0] << 8) | entry[1];
if (addr == deviceAddr)
{
sixBytesFromUInt64(seqNum, &entry[2]);
property(PID_SECURITY_INDIVIDUAL_ADDRESS_TABLE)->write(i, 1, entry);
}
}
}
}
DataSecurity SecurityInterfaceObject::getGroupObjectSecurity(uint16_t index)
{
// security table uses same index as group object table
uint8_t data[propertySize(PID_GO_SECURITY_FLAGS)];
uint8_t count = property(PID_GO_SECURITY_FLAGS)->read(index, 1, data);
if (count > 0)
{
// write access flags, approved spec. AN158, p.97
bool conf = (data[0] & 2) == 2;
bool auth = (data[0] & 1) == 1;
return conf ? DataSecurity::authConf : auth ? DataSecurity::auth : DataSecurity::none;
}
return DataSecurity::none;
}
#endif

View File

@ -0,0 +1,66 @@
#pragma once
#include "config.h"
#ifdef USE_DATASECURE
#include "interface_object.h"
#include "knx_types.h"
class SecureApplicationLayer;
class SecurityInterfaceObject: public InterfaceObject
{
public:
SecurityInterfaceObject();
void secureApplicationLayer(SecureApplicationLayer& secAppLayer);
virtual void masterReset(EraseCode eraseCode, uint8_t channel) override;
bool isSecurityModeEnabled();
bool isLoaded();
const uint8_t* toolKey(); // returns single tool key (ETS)
const uint8_t* p2pKey(uint16_t addressIndex); // returns p2p key for IA index
const uint8_t* groupKey(uint16_t addressIndex); // returns group key for group address index
uint16_t indAddressIndex(uint16_t indAddr); // returns 1-based index of address in security IA table
void setSequenceNumber(bool toolAccess, uint64_t seqNum);
uint64_t getLastValidSequenceNumber(uint16_t deviceAddr);
void setLastValidSequenceNumber(uint16_t deviceAddr, uint64_t seqNum);
DataSecurity getGroupObjectSecurity(uint16_t index);
LoadState loadState();
uint8_t* save(uint8_t* buffer) override;
const uint8_t* restore(const uint8_t* buffer) override;
uint16_t saveSize() override;
private:
SecureApplicationLayer* _secAppLayer = nullptr;
void setSecurityMode(bool enabled);
void errorCode(ErrorCode errorCode);
void loadEvent(const uint8_t* data);
void loadEventUnloaded(const uint8_t* data);
void loadEventLoading(const uint8_t* data);
void loadEventLoaded(const uint8_t* data);
void loadEventError(const uint8_t* data);
void loadState(LoadState newState);
LoadState _state = LS_UNLOADED;
bool _securityModeEnabled {false};
uint16_t getNumberOfElements(PropertyID propId);
// Our FDSK
static const uint8_t _fdsk[];
static uint8_t _secReport[];
static uint8_t _secReportCtrl[];
};
#endif

131
src/knx/simple_map.h Normal file
View File

@ -0,0 +1,131 @@
#pragma once
// Provides a simple unordered map which is based on two arrays of different data types, namely K and V.
// One array is used for the keys, the other array is used for the values.
// Tracking of free/occupied slots in the arrays is realized by a bitmask of size uint64_t.
// As a result the maximum size of the map is 64 entries.
// If a non-primitive data type is required for the key by using a "class" or "struct",
// then the operator== has to be provided by that class/struct:
// bool operator ==(const K&) const { return true/false; }
template <typename K, typename V, int SIZE>
class Map
{
public:
Map()
{
static_assert (SIZE <= 64, "Map is too big! Max. 64 elements.");
}
void clear()
{
_validEntries = 0;
}
bool empty()
{
return (_validEntries == 0);
}
uint8_t size()
{
uint8_t size = 0;
for (uint8_t i = 0; i < SIZE; i++)
{
size += (((_validEntries >> i) & 0x01) == 0x01) ? 1 : 0;
}
return size;
}
bool insert(K key, V value)
{
uint8_t index = getNextFreeIndex();
if (index != noFreeEntryFoundIndex)
{
keys[index] = key;
values[index] = value;
_validEntries |= 1 << index;
return true;
}
// No free space
return false;
}
bool insertOrAssign(K key, V value)
{
// 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)
{
values[i] = value;
return true;
}
}
}
// Key does not exist, add it if enough space
return insert(key, value);
}
bool erase(K key)
{
for (uint8_t i = 0; i < SIZE; i++)
{
if ((_validEntries >> i) & 0x01)
{
if (keys[i] == key)
{
_validEntries &= ~(1 << i);
return true;
}
}
}
return false;
}
V* get(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];
}
}
}
return nullptr;
}
private:
uint8_t getNextFreeIndex()
{
for (uint8_t i = 0; i < SIZE; i++)
{
if (((_validEntries >> i) & 0x01) == 0)
{
return i;
}
}
return noFreeEntryFoundIndex;
}
uint64_t _validEntries{0};
K keys[SIZE];
V values[SIZE];
static constexpr uint8_t noFreeEntryFoundIndex = 255;
};

View File

@ -530,7 +530,19 @@ void TransportLayer::ackTimeoutIndication()
}
}
// Note: we should probably also add the TSAP as argument if would support multiple concurrent connections
uint8_t TransportLayer::getTpciSeqNum()
{
// Return seqNum that would be used for sending next frame
// together with the TPDU type.
return ((_seqNoSend & 0xF) << 2);
}
// Note: we should probably also add the TSAP as argument if would support multiple concurrent connections
uint16_t TransportLayer::getConnectionAddress()
{
return _connectionAddress;
}
void TransportLayer::loop()
{

View File

@ -56,6 +56,9 @@ public:
void disconnectRequest(uint16_t tsap, Priority priority);
// apdu must be valid until it was confirmed
void dataConnectedRequest(uint16_t tsap, Priority priority, APDU& apdu);
uint8_t getTpciSeqNum();
uint16_t getConnectionAddress();
#pragma endregion
#pragma region other

View File

@ -352,4 +352,4 @@ template <class P, class B> class KnxFacade : private SaveRestore
extern KnxFacade<Stm32Platform, Bau07B0> knx;
#elif __linux__
// no predefined global instance
#endif
#endif