mirror of
https://github.com/thelsing/knx.git
synced 2025-05-25 01:16:44 +02:00
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 commit0c8358692a
. * Revert "Revert "Merge master into feat_datasecure"" This reverts commitaa59253785
. * 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:
parent
8cfd67662f
commit
96884f768e
5
examples/knx-demo/.gitignore
vendored
5
examples/knx-demo/.gitignore
vendored
@ -1,5 +1,2 @@
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
.vscode
|
||||
|
7
examples/knx-demo/.vscode/extensions.json
vendored
7
examples/knx-demo/.vscode/extensions.json
vendored
@ -1,7 +0,0 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
]
|
||||
}
|
@ -26,7 +26,7 @@ build_flags =
|
||||
|
||||
;--- ESP8266 -----------------------------------------------
|
||||
[env:nodemcuv2]
|
||||
platform = espressif8266
|
||||
platform = espressif8266@2.2.3
|
||||
board = nodemcuv2
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
|
@ -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 =
|
||||
|
@ -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
196
examples/knx-linux/fdsk.cpp
Normal 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
37
examples/knx-linux/fdsk.h
Normal 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];
|
||||
};
|
@ -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));
|
||||
|
@ -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
569
src/knx/aes.c
Normal 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
90
src/knx/aes.h
Normal 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
12
src/knx/aes.hpp
Normal 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
@ -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;
|
||||
};
|
||||
|
183
src/knx/bau.cpp
183
src/knx/bau.cpp
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
157
src/knx/bau.h
157
src/knx/bau.h
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -22,4 +22,6 @@
|
||||
#define USE_CEMI_SERVER
|
||||
#endif
|
||||
|
||||
#define USE_DATASECURE
|
||||
|
||||
#endif
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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[] =
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -108,4 +108,4 @@ bool IpDataLinkLayer::sendBytes(uint8_t* bytes, uint16_t length)
|
||||
|
||||
return _platform.sendBytesMultiCast(bytes, length);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -55,4 +55,4 @@ class KnxIpFrame
|
||||
uint8_t* _data = 0;
|
||||
uint16_t _dataLength;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
1282
src/knx/secure_application_layer.cpp
Normal file
1282
src/knx/secure_application_layer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
154
src/knx/secure_application_layer.h
Normal file
154
src/knx/secure_application_layer.h
Normal 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;
|
||||
};
|
542
src/knx/security_interface_object.cpp
Normal file
542
src/knx/security_interface_object.cpp
Normal 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
|
||||
|
66
src/knx/security_interface_object.h
Normal file
66
src/knx/security_interface_object.h
Normal 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
131
src/knx/simple_map.h
Normal 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;
|
||||
};
|
@ -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()
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user