|
|
@ -41,10 +41,10 @@
|
|
|
|
#define DEBUG_PRINTF(...)
|
|
|
|
#define DEBUG_PRINTF(...)
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct sRSessionKeyMaterial* RSessionKeyMaterial;
|
|
|
|
typedef struct sRSessionKeyMaterial* RSessionKeyMaterial;
|
|
|
|
|
|
|
|
|
|
|
|
struct sRSessionKeyMaterial {
|
|
|
|
struct sRSessionKeyMaterial
|
|
|
|
|
|
|
|
{
|
|
|
|
uint32_t keyId;
|
|
|
|
uint32_t keyId;
|
|
|
|
RSecurityAlgorithm secAlgo;
|
|
|
|
RSecurityAlgorithm secAlgo;
|
|
|
|
RSignatureAlgorithm sigAlgo;
|
|
|
|
RSignatureAlgorithm sigAlgo;
|
|
|
@ -52,7 +52,8 @@ struct sRSessionKeyMaterial {
|
|
|
|
int keyLength;
|
|
|
|
int keyLength;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct sRSession {
|
|
|
|
struct sRSession
|
|
|
|
|
|
|
|
{
|
|
|
|
uint32_t spduNumber;
|
|
|
|
uint32_t spduNumber;
|
|
|
|
|
|
|
|
|
|
|
|
int protocolVersion; /* default is 2 */
|
|
|
|
int protocolVersion; /* default is 2 */
|
|
|
@ -94,7 +95,8 @@ printBuffer(uint8_t* buffer, int bufSize)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < bufSize; i++) {
|
|
|
|
for (i = 0; i < bufSize; i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
printf("%02x ", buffer[i]);
|
|
|
|
printf("%02x ", buffer[i]);
|
|
|
|
if ((((i + 1) % 16) == 0) || (i + 1 == bufSize))
|
|
|
|
if ((((i + 1) % 16) == 0) || (i + 1 == bufSize))
|
|
|
|
printf(" (%i)\n", i + 1);
|
|
|
|
printf(" (%i)\n", i + 1);
|
|
|
@ -107,7 +109,8 @@ RSessionKeyMaterial_create(uint32_t keyId, uint8_t* key, int keyLength, RSecurit
|
|
|
|
{
|
|
|
|
{
|
|
|
|
RSessionKeyMaterial self = (RSessionKeyMaterial) GLOBAL_CALLOC(1, sizeof(struct sRSessionKeyMaterial));
|
|
|
|
RSessionKeyMaterial self = (RSessionKeyMaterial) GLOBAL_CALLOC(1, sizeof(struct sRSessionKeyMaterial));
|
|
|
|
|
|
|
|
|
|
|
|
if (self) {
|
|
|
|
if (self)
|
|
|
|
|
|
|
|
{
|
|
|
|
self->keyId = keyId;
|
|
|
|
self->keyId = keyId;
|
|
|
|
self->keyLength = keyLength;
|
|
|
|
self->keyLength = keyLength;
|
|
|
|
self->secAlgo = secAlgo;
|
|
|
|
self->secAlgo = secAlgo;
|
|
|
@ -115,10 +118,12 @@ RSessionKeyMaterial_create(uint32_t keyId, uint8_t* key, int keyLength, RSecurit
|
|
|
|
|
|
|
|
|
|
|
|
self->key = (uint8_t*) GLOBAL_MALLOC(keyLength);
|
|
|
|
self->key = (uint8_t*) GLOBAL_MALLOC(keyLength);
|
|
|
|
|
|
|
|
|
|
|
|
if (self->key) {
|
|
|
|
if (self->key)
|
|
|
|
|
|
|
|
{
|
|
|
|
memcpy(self->key, key, keyLength);
|
|
|
|
memcpy(self->key, key, keyLength);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
GLOBAL_FREEMEM(self);
|
|
|
|
GLOBAL_FREEMEM(self);
|
|
|
|
self = NULL;
|
|
|
|
self = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -130,7 +135,8 @@ RSessionKeyMaterial_create(uint32_t keyId, uint8_t* key, int keyLength, RSecurit
|
|
|
|
void
|
|
|
|
void
|
|
|
|
RSessionKeyMaterial_destroy(RSessionKeyMaterial self)
|
|
|
|
RSessionKeyMaterial_destroy(RSessionKeyMaterial self)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (self) {
|
|
|
|
if (self)
|
|
|
|
|
|
|
|
{
|
|
|
|
GLOBAL_FREEMEM(self->key);
|
|
|
|
GLOBAL_FREEMEM(self->key);
|
|
|
|
GLOBAL_FREEMEM(self);
|
|
|
|
GLOBAL_FREEMEM(self);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -141,11 +147,12 @@ RSession_create()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
UdpSocket udpSocket = UdpSocket_create();
|
|
|
|
UdpSocket udpSocket = UdpSocket_create();
|
|
|
|
|
|
|
|
|
|
|
|
if (udpSocket) {
|
|
|
|
if (udpSocket)
|
|
|
|
|
|
|
|
{
|
|
|
|
RSession self = (RSession) GLOBAL_CALLOC(1, sizeof(struct sRSession));
|
|
|
|
RSession self = (RSession) GLOBAL_CALLOC(1, sizeof(struct sRSession));
|
|
|
|
|
|
|
|
|
|
|
|
if (self) {
|
|
|
|
if (self)
|
|
|
|
|
|
|
|
{
|
|
|
|
self->socket = udpSocket;
|
|
|
|
self->socket = udpSocket;
|
|
|
|
self->socketLock = Semaphore_create(1);
|
|
|
|
self->socketLock = Semaphore_create(1);
|
|
|
|
|
|
|
|
|
|
|
@ -178,7 +185,8 @@ RSession_setSecurity(RSession self, RSecurityAlgorithm secAlgo, RSignatureAlgori
|
|
|
|
RSessionError
|
|
|
|
RSessionError
|
|
|
|
RSession_setLocalAddress(RSession self, const char* localAddress, int localPort)
|
|
|
|
RSession_setLocalAddress(RSession self, const char* localAddress, int localPort)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (self->localAddress) {
|
|
|
|
if (self->localAddress)
|
|
|
|
|
|
|
|
{
|
|
|
|
GLOBAL_FREEMEM(self->localAddress);
|
|
|
|
GLOBAL_FREEMEM(self->localAddress);
|
|
|
|
self->localAddress = NULL;
|
|
|
|
self->localAddress = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -205,8 +213,10 @@ RSession_setMulticastTtl(RSession self, int ttl)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
RSessionError err = R_SESSION_ERROR_OK;
|
|
|
|
RSessionError err = R_SESSION_ERROR_OK;
|
|
|
|
|
|
|
|
|
|
|
|
if (self->socket) {
|
|
|
|
if (self->socket)
|
|
|
|
if (!UdpSocket_setMulticastTtl(self->socket, ttl)) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!UdpSocket_setMulticastTtl(self->socket, ttl))
|
|
|
|
|
|
|
|
{
|
|
|
|
err = R_SESSION_ERROR_SET_FAILED;
|
|
|
|
err = R_SESSION_ERROR_SET_FAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -220,7 +230,8 @@ RSession_setMulticastTtl(RSession self, int ttl)
|
|
|
|
RSessionError
|
|
|
|
RSessionError
|
|
|
|
RSession_setRemoteAddress(RSession self, const char* remoteAddress, int remotePort)
|
|
|
|
RSession_setRemoteAddress(RSession self, const char* remoteAddress, int remotePort)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (self->remoteAddress) {
|
|
|
|
if (self->remoteAddress)
|
|
|
|
|
|
|
|
{
|
|
|
|
GLOBAL_FREEMEM(self->remoteAddress);
|
|
|
|
GLOBAL_FREEMEM(self->remoteAddress);
|
|
|
|
self->remoteAddress = NULL;
|
|
|
|
self->remoteAddress = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -234,8 +245,8 @@ RSession_setRemoteAddress(RSession self, const char* remoteAddress, int remotePo
|
|
|
|
RSessionError
|
|
|
|
RSessionError
|
|
|
|
RSession_start(RSession self)
|
|
|
|
RSession_start(RSession self)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (self->socket) {
|
|
|
|
if (self->socket)
|
|
|
|
|
|
|
|
{
|
|
|
|
bool success = false;
|
|
|
|
bool success = false;
|
|
|
|
|
|
|
|
|
|
|
|
if (self->localAddress)
|
|
|
|
if (self->localAddress)
|
|
|
@ -248,7 +259,8 @@ RSession_start(RSession self)
|
|
|
|
else
|
|
|
|
else
|
|
|
|
return R_SESSION_ERROR_SET_FAILED;
|
|
|
|
return R_SESSION_ERROR_SET_FAILED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
return R_SESSION_ERROR_NO_SOCKET;
|
|
|
|
return R_SESSION_ERROR_NO_SOCKET;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -258,7 +270,8 @@ RSession_stop(RSession self)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Semaphore_wait(self->socketLock);
|
|
|
|
Semaphore_wait(self->socketLock);
|
|
|
|
|
|
|
|
|
|
|
|
if (self->socket) {
|
|
|
|
if (self->socket)
|
|
|
|
|
|
|
|
{
|
|
|
|
Socket_destroy((Socket)self->socket);
|
|
|
|
Socket_destroy((Socket)self->socket);
|
|
|
|
self->socket = NULL;
|
|
|
|
self->socket = NULL;
|
|
|
|
|
|
|
|
|
|
|
@ -266,7 +279,8 @@ RSession_stop(RSession self)
|
|
|
|
|
|
|
|
|
|
|
|
return R_SESSION_ERROR_OK;
|
|
|
|
return R_SESSION_ERROR_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
Semaphore_post(self->socketLock);
|
|
|
|
Semaphore_post(self->socketLock);
|
|
|
|
|
|
|
|
|
|
|
|
return R_SESSION_ERROR_NO_SOCKET;
|
|
|
|
return R_SESSION_ERROR_NO_SOCKET;
|
|
|
@ -374,19 +388,20 @@ decodeInt16FixedSize(int16_t* outValue, uint8_t* buffer, int bufPos)
|
|
|
|
static bool
|
|
|
|
static bool
|
|
|
|
lookupKey(RSession self, uint32_t keyId, uint8_t** key, int* keySize, RSecurityAlgorithm* secAlgo, RSignatureAlgorithm* sigAlgo)
|
|
|
|
lookupKey(RSession self, uint32_t keyId, uint8_t** key, int* keySize, RSecurityAlgorithm* secAlgo, RSignatureAlgorithm* sigAlgo)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (keyId == 0) {
|
|
|
|
if (keyId == 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("Invalid key ID");
|
|
|
|
DEBUG_PRINTF("Invalid key ID");
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (self->currentKeyId != keyId) {
|
|
|
|
if (self->currentKeyId != keyId)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (RSession_setActiveKey(self, keyId) != R_SESSION_ERROR_OK) {
|
|
|
|
if (RSession_setActiveKey(self, keyId) != R_SESSION_ERROR_OK)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("unknown key-ID %u", keyId);
|
|
|
|
DEBUG_PRINTF("unknown key-ID %u", keyId);
|
|
|
|
/* TODO audit-log? */
|
|
|
|
/* TODO audit-log? */
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
*key = self->currentKey;
|
|
|
|
*key = self->currentKey;
|
|
|
@ -414,29 +429,34 @@ parseSessionMessage(RSession self, uint8_t* buffer, int msgSize, RSessionPayload
|
|
|
|
/* SI */
|
|
|
|
/* SI */
|
|
|
|
uint8_t payloadType = buffer[bufPos++];
|
|
|
|
uint8_t payloadType = buffer[bufPos++];
|
|
|
|
|
|
|
|
|
|
|
|
if ((payloadType == 0xa2) || (payloadType == 0xa1) || (payloadType == 0xa0)) {
|
|
|
|
if ((payloadType == 0xa2) || (payloadType == 0xa1) || (payloadType == 0xa0))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* known payload */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("unknown payload type %i", payloadType);
|
|
|
|
DEBUG_PRINTF("unknown payload type %i", payloadType);
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int sessionHeaderLength = buffer[bufPos++];
|
|
|
|
int sessionHeaderLength = buffer[bufPos++];
|
|
|
|
|
|
|
|
|
|
|
|
if ((msgSize < (sessionHeaderLength + 4)) || (sessionHeaderLength < 10)) {
|
|
|
|
if ((msgSize < (sessionHeaderLength + 4)) || (sessionHeaderLength < 10))
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("message too small");
|
|
|
|
DEBUG_PRINTF("message too small");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (buffer[bufPos++] != 0x80) {
|
|
|
|
if (buffer[bufPos++] != 0x80)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("protocol error");
|
|
|
|
DEBUG_PRINTF("protocol error");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int commonSessionHeaderLength = buffer[bufPos++];
|
|
|
|
int commonSessionHeaderLength = buffer[bufPos++];
|
|
|
|
|
|
|
|
|
|
|
|
if (commonSessionHeaderLength < 10) {
|
|
|
|
if (commonSessionHeaderLength < 10)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("common session header too small");
|
|
|
|
DEBUG_PRINTF("common session header too small");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -453,7 +473,8 @@ parseSessionMessage(RSession self, uint8_t* buffer, int msgSize, RSessionPayload
|
|
|
|
int16_t protocolVersion = 0;
|
|
|
|
int16_t protocolVersion = 0;
|
|
|
|
bufPos = decodeInt16FixedSize(&protocolVersion, buffer, bufPos);
|
|
|
|
bufPos = decodeInt16FixedSize(&protocolVersion, buffer, bufPos);
|
|
|
|
|
|
|
|
|
|
|
|
if (protocolVersion == 1) {
|
|
|
|
if (protocolVersion == 1)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* parse version 1 common header parts */
|
|
|
|
/* parse version 1 common header parts */
|
|
|
|
|
|
|
|
|
|
|
|
/* TimeOfCurrentKey */
|
|
|
|
/* TimeOfCurrentKey */
|
|
|
@ -469,12 +490,14 @@ parseSessionMessage(RSession self, uint8_t* buffer, int msgSize, RSessionPayload
|
|
|
|
RSignatureAlgorithm sigAlgo = (RSignatureAlgorithm) buffer[bufPos++];
|
|
|
|
RSignatureAlgorithm sigAlgo = (RSignatureAlgorithm) buffer[bufPos++];
|
|
|
|
|
|
|
|
|
|
|
|
/* Check if algorithms match the configured algorithms */
|
|
|
|
/* Check if algorithms match the configured algorithms */
|
|
|
|
if (secAlgo != self->secAlgo) {
|
|
|
|
if (secAlgo != self->secAlgo)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("encryption algorithm doesn't match with configuration");
|
|
|
|
DEBUG_PRINTF("encryption algorithm doesn't match with configuration");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (sigAlgo != self->sigAlgo) {
|
|
|
|
if (sigAlgo != self->sigAlgo)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("signature algorithm(%i) doesn't match with configuration(%i)", sigAlgo, self->sigAlgo);
|
|
|
|
DEBUG_PRINTF("signature algorithm(%i) doesn't match with configuration(%i)", sigAlgo, self->sigAlgo);
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -488,14 +511,18 @@ parseSessionMessage(RSession self, uint8_t* buffer, int msgSize, RSessionPayload
|
|
|
|
uint8_t* key = NULL;
|
|
|
|
uint8_t* key = NULL;
|
|
|
|
int keySize = 0;
|
|
|
|
int keySize = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (sigAlgo != R_SESSION_SIG_ALGO_NONE) {
|
|
|
|
if (sigAlgo != R_SESSION_SIG_ALGO_NONE)
|
|
|
|
if (lookupKey(self, keyId, &key, &keySize, &secAlgo, &sigAlgo) == false) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (lookupKey(self, keyId, &key, &keySize, &secAlgo, &sigAlgo) == false)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - key not found");
|
|
|
|
DEBUG_PRINTF("ERROR - key not found");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (secAlgo != R_SESSION_SEC_ALGO_NONE) {
|
|
|
|
else if (secAlgo != R_SESSION_SEC_ALGO_NONE)
|
|
|
|
if (lookupKey(self, keyId, &key, &keySize, &secAlgo, &sigAlgo) == false) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (lookupKey(self, keyId, &key, &keySize, &secAlgo, &sigAlgo) == false)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - key not found");
|
|
|
|
DEBUG_PRINTF("ERROR - key not found");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -508,7 +535,8 @@ parseSessionMessage(RSession self, uint8_t* buffer, int msgSize, RSessionPayload
|
|
|
|
/* parse payload elements */
|
|
|
|
/* parse payload elements */
|
|
|
|
uint32_t payloadEnd = bufPos + payloadLength;
|
|
|
|
uint32_t payloadEnd = bufPos + payloadLength;
|
|
|
|
|
|
|
|
|
|
|
|
if (payloadEnd > (uint32_t)msgSize) {
|
|
|
|
if (payloadEnd > (uint32_t)msgSize)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - payload size field invalid");
|
|
|
|
DEBUG_PRINTF("ERROR - payload size field invalid");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -516,42 +544,54 @@ parseSessionMessage(RSession self, uint8_t* buffer, int msgSize, RSessionPayload
|
|
|
|
uint8_t signatureBuffer[128];
|
|
|
|
uint8_t signatureBuffer[128];
|
|
|
|
|
|
|
|
|
|
|
|
/* Check signature */
|
|
|
|
/* Check signature */
|
|
|
|
if (sigAlgo != R_SESSION_SIG_ALGO_NONE) {
|
|
|
|
if (sigAlgo != R_SESSION_SIG_ALGO_NONE)
|
|
|
|
if (key) {
|
|
|
|
{
|
|
|
|
if (RSessionCrypto_createHMAC(buffer, payloadEnd, key, keySize, signatureBuffer, 32)) {
|
|
|
|
if (key)
|
|
|
|
if (buffer[payloadEnd] != 0x85) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (RSessionCrypto_createHMAC(buffer, payloadEnd, key, keySize, signatureBuffer, 32))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (buffer[payloadEnd] != 0x85)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - no signature found");
|
|
|
|
DEBUG_PRINTF("ERROR - no signature found");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
if (sigAlgo == R_SESSION_SIG_ALGO_HMAC_SHA256_128) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (sigAlgo == R_SESSION_SIG_ALGO_HMAC_SHA256_128)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* TODO is payloadEnd +2 correct? */
|
|
|
|
/* TODO is payloadEnd +2 correct? */
|
|
|
|
if (memcmp(signatureBuffer, buffer + payloadEnd + 1, 16)) {
|
|
|
|
if (memcmp(signatureBuffer, buffer + payloadEnd + 1, 16))
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - signature not matching!");
|
|
|
|
DEBUG_PRINTF("ERROR - signature not matching!");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (sigAlgo == R_SESSION_SIG_ALGO_HMAC_SHA256_256) {
|
|
|
|
else if (sigAlgo == R_SESSION_SIG_ALGO_HMAC_SHA256_256)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* TODO is payloadEnd +2 correct? */
|
|
|
|
/* TODO is payloadEnd +2 correct? */
|
|
|
|
if (memcmp(signatureBuffer, buffer + payloadEnd + 1, 32)) {
|
|
|
|
if (memcmp(signatureBuffer, buffer + payloadEnd + 1, 32))
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - signature not matching!");
|
|
|
|
DEBUG_PRINTF("ERROR - signature not matching!");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - failed to calculate HMAC!");
|
|
|
|
DEBUG_PRINTF("ERROR - failed to calculate HMAC!");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - key not found!");
|
|
|
|
DEBUG_PRINTF("ERROR - key not found!");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
while ((uint32_t)bufPos < payloadEnd) {
|
|
|
|
while ((uint32_t)bufPos < payloadEnd)
|
|
|
|
|
|
|
|
{
|
|
|
|
int payloadElementType = buffer[bufPos++];
|
|
|
|
int payloadElementType = buffer[bufPos++];
|
|
|
|
|
|
|
|
|
|
|
|
bool simulation;
|
|
|
|
bool simulation;
|
|
|
@ -570,10 +610,11 @@ parseSessionMessage(RSession self, uint8_t* buffer, int msgSize, RSessionPayload
|
|
|
|
DEBUG_PRINTF("ASDU %02x sim: %i APPID: %04x length: %i", payloadElementType, simulation, appId, asduLength);
|
|
|
|
DEBUG_PRINTF("ASDU %02x sim: %i APPID: %04x length: %i", payloadElementType, simulation, appId, asduLength);
|
|
|
|
|
|
|
|
|
|
|
|
if (payloadElementType == 0x81 ||
|
|
|
|
if (payloadElementType == 0x81 ||
|
|
|
|
payloadElementType == 0x82) {
|
|
|
|
payloadElementType == 0x82)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* user payload */
|
|
|
|
/* user payload */
|
|
|
|
|
|
|
|
|
|
|
|
//TODO copy ASDU payload to ???
|
|
|
|
/* TODO copy ASDU payload to ??? */
|
|
|
|
handler(handlerParam, appId, buffer + bufPos, asduLength);
|
|
|
|
handler(handlerParam, appId, buffer + bufPos, asduLength);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else {
|
|
|
@ -582,9 +623,9 @@ parseSessionMessage(RSession self, uint8_t* buffer, int msgSize, RSessionPayload
|
|
|
|
|
|
|
|
|
|
|
|
bufPos += asduLength;
|
|
|
|
bufPos += asduLength;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (protocolVersion == 2) {
|
|
|
|
else if (protocolVersion == 2)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* parse version 2 common header parts */
|
|
|
|
/* parse version 2 common header parts */
|
|
|
|
|
|
|
|
|
|
|
|
/* TimeOfCurrentKey */
|
|
|
|
/* TimeOfCurrentKey */
|
|
|
@ -605,15 +646,18 @@ parseSessionMessage(RSession self, uint8_t* buffer, int msgSize, RSessionPayload
|
|
|
|
uint32_t keyId;
|
|
|
|
uint32_t keyId;
|
|
|
|
bufPos = decodeUInt32FixedSize(&keyId, buffer, bufPos);
|
|
|
|
bufPos = decodeUInt32FixedSize(&keyId, buffer, bufPos);
|
|
|
|
|
|
|
|
|
|
|
|
if (keyId != 0) {
|
|
|
|
if (keyId != 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* get key material associated with the key ID */
|
|
|
|
/* get key material associated with the key ID */
|
|
|
|
|
|
|
|
|
|
|
|
if (lookupKey(self, keyId, &key, &keySize, &secAlgo, &sigAlgo) == false) {
|
|
|
|
if (lookupKey(self, keyId, &key, &keySize, &secAlgo, &sigAlgo) == false)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - key not found");
|
|
|
|
DEBUG_PRINTF("ERROR - key not found");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - invalid key ID");
|
|
|
|
DEBUG_PRINTF("ERROR - invalid key ID");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -627,7 +671,8 @@ parseSessionMessage(RSession self, uint8_t* buffer, int msgSize, RSessionPayload
|
|
|
|
|
|
|
|
|
|
|
|
DEBUG_PRINTF("IV: size = %i\n", ivLen);
|
|
|
|
DEBUG_PRINTF("IV: size = %i\n", ivLen);
|
|
|
|
|
|
|
|
|
|
|
|
if (ivLen > 0) {
|
|
|
|
if (ivLen > 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
iv = buffer + bufPos;
|
|
|
|
iv = buffer + bufPos;
|
|
|
|
bufPos += ivLen;
|
|
|
|
bufPos += ivLen;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -642,7 +687,8 @@ parseSessionMessage(RSession self, uint8_t* buffer, int msgSize, RSessionPayload
|
|
|
|
/* parse payload elements */
|
|
|
|
/* parse payload elements */
|
|
|
|
uint32_t payloadEnd = bufPos + payloadLength;
|
|
|
|
uint32_t payloadEnd = bufPos + payloadLength;
|
|
|
|
|
|
|
|
|
|
|
|
if (payloadEnd > (uint32_t)msgSize) {
|
|
|
|
if (payloadEnd > (uint32_t)msgSize)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - payload size field invalid");
|
|
|
|
DEBUG_PRINTF("ERROR - payload size field invalid");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -650,71 +696,88 @@ parseSessionMessage(RSession self, uint8_t* buffer, int msgSize, RSessionPayload
|
|
|
|
uint8_t signatureBuffer[128];
|
|
|
|
uint8_t signatureBuffer[128];
|
|
|
|
|
|
|
|
|
|
|
|
/* Check signature */
|
|
|
|
/* Check signature */
|
|
|
|
if (sigAlgo != R_SESSION_SIG_ALGO_NONE) {
|
|
|
|
if (sigAlgo != R_SESSION_SIG_ALGO_NONE)
|
|
|
|
if (key) {
|
|
|
|
{
|
|
|
|
if (RSessionCrypto_createHMAC(buffer, payloadEnd, key, keySize, signatureBuffer, 32)) {
|
|
|
|
if (key)
|
|
|
|
if (buffer[payloadEnd] != 0x85) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (RSessionCrypto_createHMAC(buffer, payloadEnd, key, keySize, signatureBuffer, 32))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (buffer[payloadEnd] != 0x85)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - no signature found");
|
|
|
|
DEBUG_PRINTF("ERROR - no signature found");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
if (sigAlgo == R_SESSION_SIG_ALGO_HMAC_SHA256_128) {
|
|
|
|
{
|
|
|
|
|
|
|
|
if (sigAlgo == R_SESSION_SIG_ALGO_HMAC_SHA256_128)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* TODO is payloadEnd +2 correct? */
|
|
|
|
/* TODO is payloadEnd +2 correct? */
|
|
|
|
if (memcmp(signatureBuffer, buffer + payloadEnd + 1, 16)) {
|
|
|
|
if (memcmp(signatureBuffer, buffer + payloadEnd + 1, 16))
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - signature not matching!");
|
|
|
|
DEBUG_PRINTF("ERROR - signature not matching!");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (sigAlgo == R_SESSION_SIG_ALGO_HMAC_SHA256_256) {
|
|
|
|
else if (sigAlgo == R_SESSION_SIG_ALGO_HMAC_SHA256_256)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* TODO is payloadEnd +2 correct? */
|
|
|
|
/* TODO is payloadEnd +2 correct? */
|
|
|
|
if (memcmp(signatureBuffer, buffer + payloadEnd + 1, 32)) {
|
|
|
|
if (memcmp(signatureBuffer, buffer + payloadEnd + 1, 32))
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - signature not matching!");
|
|
|
|
DEBUG_PRINTF("ERROR - signature not matching!");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - failed to calculate HMAC!");
|
|
|
|
DEBUG_PRINTF("ERROR - failed to calculate HMAC!");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - key not found!");
|
|
|
|
DEBUG_PRINTF("ERROR - key not found!");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Check signature and decrypt application layer */
|
|
|
|
/* Check signature and decrypt application layer */
|
|
|
|
if (secAlgo != R_SESSION_SEC_ALGO_NONE) {
|
|
|
|
if (secAlgo != R_SESSION_SEC_ALGO_NONE)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* Check for HMAC */
|
|
|
|
/* Check for HMAC */
|
|
|
|
if (payloadEnd + 18 <= (uint32_t)msgSize) {
|
|
|
|
if (payloadEnd + 18 <= (uint32_t)msgSize)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (self->payloadBuffer == NULL)
|
|
|
|
if (self->payloadBuffer == NULL)
|
|
|
|
self->payloadBuffer = (uint8_t*)GLOBAL_MALLOC(65000);
|
|
|
|
self->payloadBuffer = (uint8_t*)GLOBAL_MALLOC(65000);
|
|
|
|
|
|
|
|
|
|
|
|
if (self->payloadBuffer) {
|
|
|
|
if (self->payloadBuffer)
|
|
|
|
//TODO check MMAC tag
|
|
|
|
{
|
|
|
|
uint8_t* mac = buffer + payloadEnd + 2;
|
|
|
|
uint8_t* mac = buffer + payloadEnd + 2;
|
|
|
|
int macSize = buffer[payloadEnd + 1];
|
|
|
|
int macSize = buffer[payloadEnd + 1];
|
|
|
|
|
|
|
|
|
|
|
|
int payloadSize = payloadEnd - payloadStartPos;
|
|
|
|
int payloadSize = payloadEnd - payloadStartPos;
|
|
|
|
|
|
|
|
|
|
|
|
if (RSessionCrypto_gcmAuthAndDecrypt(key, keySize, iv, ivLen, buffer, payloadStartPos, payloadStart, payloadSize, self->payloadBuffer, mac, macSize)) {
|
|
|
|
if (RSessionCrypto_gcmAuthAndDecrypt(key, keySize, iv, ivLen, buffer, payloadStartPos, payloadStart, payloadSize, self->payloadBuffer, mac, macSize))
|
|
|
|
|
|
|
|
{
|
|
|
|
memcpy(buffer + bufPos, self->payloadBuffer, payloadSize);
|
|
|
|
memcpy(buffer + bufPos, self->payloadBuffer, payloadSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - auth and decrypt failed!");
|
|
|
|
DEBUG_PRINTF("ERROR - auth and decrypt failed!");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - sec algo - message too small!");
|
|
|
|
DEBUG_PRINTF("ERROR - sec algo - message too small!");
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
while ((uint32_t)bufPos < payloadEnd) {
|
|
|
|
while ((uint32_t)bufPos < payloadEnd)
|
|
|
|
|
|
|
|
{
|
|
|
|
int payloadElementType = buffer[bufPos++];
|
|
|
|
int payloadElementType = buffer[bufPos++];
|
|
|
|
|
|
|
|
|
|
|
|
bool simulation;
|
|
|
|
bool simulation;
|
|
|
@ -733,20 +796,23 @@ parseSessionMessage(RSession self, uint8_t* buffer, int msgSize, RSessionPayload
|
|
|
|
DEBUG_PRINTF("ASDU %02x sim: %i APPID: %04x length: %i", payloadElementType, simulation, appId, asduLength);
|
|
|
|
DEBUG_PRINTF("ASDU %02x sim: %i APPID: %04x length: %i", payloadElementType, simulation, appId, asduLength);
|
|
|
|
|
|
|
|
|
|
|
|
if (payloadElementType == 0x81 ||
|
|
|
|
if (payloadElementType == 0x81 ||
|
|
|
|
payloadElementType == 0x82) {
|
|
|
|
payloadElementType == 0x82)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* user payload */
|
|
|
|
/* user payload */
|
|
|
|
|
|
|
|
|
|
|
|
//TODO copy ASDU payload to ???
|
|
|
|
//TODO copy ASDU payload to ???
|
|
|
|
handler(handlerParam, appId, buffer + bufPos, asduLength);
|
|
|
|
handler(handlerParam, appId, buffer + bufPos, asduLength);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("unexpected payload type! (expect 81h (GOOSE) or 82h (SV))");
|
|
|
|
DEBUG_PRINTF("unexpected payload type! (expect 81h (GOOSE) or 82h (SV))");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bufPos += asduLength;
|
|
|
|
bufPos += asduLength;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("only protocol version 1 and 2 supported (received version %i)", protocolVersion);
|
|
|
|
DEBUG_PRINTF("only protocol version 1 and 2 supported (received version %i)", protocolVersion);
|
|
|
|
goto exit_error;
|
|
|
|
goto exit_error;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -775,7 +841,8 @@ encodePacket(RSession self, uint8_t payloadType, uint8_t* buffer, int bufPos, RS
|
|
|
|
|
|
|
|
|
|
|
|
RSessionPayloadElement element = elements;
|
|
|
|
RSessionPayloadElement element = elements;
|
|
|
|
|
|
|
|
|
|
|
|
while (element) {
|
|
|
|
while (element)
|
|
|
|
|
|
|
|
{
|
|
|
|
payloadLength += 6; /* payload type, simulation, APPID, length */
|
|
|
|
payloadLength += 6; /* payload type, simulation, APPID, length */
|
|
|
|
payloadLength += element->payloadSize;
|
|
|
|
payloadLength += element->payloadSize;
|
|
|
|
|
|
|
|
|
|
|
@ -815,7 +882,8 @@ encodePacket(RSession self, uint8_t payloadType, uint8_t* buffer, int bufPos, RS
|
|
|
|
/* TimeToNextKey */
|
|
|
|
/* TimeToNextKey */
|
|
|
|
bufPos = encodeInt16FixedSize((int16_t)self->timeToNextKey, buffer, bufPos);
|
|
|
|
bufPos = encodeInt16FixedSize((int16_t)self->timeToNextKey, buffer, bufPos);
|
|
|
|
|
|
|
|
|
|
|
|
if (self->protocolVersion == 1) {
|
|
|
|
if (self->protocolVersion == 1)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* encryption algorithm */
|
|
|
|
/* encryption algorithm */
|
|
|
|
buffer[bufPos++] = (uint8_t) self->secAlgo; /* 0 = none */
|
|
|
|
buffer[bufPos++] = (uint8_t) self->secAlgo; /* 0 = none */
|
|
|
|
|
|
|
|
|
|
|
@ -825,7 +893,10 @@ encodePacket(RSession self, uint8_t payloadType, uint8_t* buffer, int bufPos, RS
|
|
|
|
/* Key ID */
|
|
|
|
/* Key ID */
|
|
|
|
bufPos = encodeUInt32FixedSize(self->currentKeyId, buffer, bufPos);
|
|
|
|
bufPos = encodeUInt32FixedSize(self->currentKeyId, buffer, bufPos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else { /* protocol version 2 */
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
/* protocol version 2 */
|
|
|
|
|
|
|
|
|
|
|
|
/* Key ID */
|
|
|
|
/* Key ID */
|
|
|
|
bufPos = encodeUInt32FixedSize(self->currentKeyId, buffer, bufPos);
|
|
|
|
bufPos = encodeUInt32FixedSize(self->currentKeyId, buffer, bufPos);
|
|
|
|
self->secAlgo = self->currentSecAlgo;
|
|
|
|
self->secAlgo = self->currentSecAlgo;
|
|
|
@ -834,21 +905,24 @@ encodePacket(RSession self, uint8_t payloadType, uint8_t* buffer, int bufPos, RS
|
|
|
|
DEBUG_PRINTF("PV: 2 sec-algo: %i sig-algo: %i\n", self->secAlgo, self->sigAlgo);
|
|
|
|
DEBUG_PRINTF("PV: 2 sec-algo: %i sig-algo: %i\n", self->secAlgo, self->sigAlgo);
|
|
|
|
|
|
|
|
|
|
|
|
/* IV */
|
|
|
|
/* IV */
|
|
|
|
if (self->secAlgo != R_SESSION_SEC_ALGO_NONE) {
|
|
|
|
if (self->secAlgo != R_SESSION_SEC_ALGO_NONE)
|
|
|
|
/* TODO get and encode IV (initialization vector) */
|
|
|
|
{
|
|
|
|
|
|
|
|
/* create and encode IV (initialization vector) */
|
|
|
|
|
|
|
|
|
|
|
|
buffer[bufPos++] = 12;
|
|
|
|
buffer[bufPos++] = 12;
|
|
|
|
|
|
|
|
|
|
|
|
iv = buffer + bufPos;
|
|
|
|
iv = buffer + bufPos;
|
|
|
|
ivSize = 12;
|
|
|
|
ivSize = 12;
|
|
|
|
|
|
|
|
|
|
|
|
if (RSessionCrypto_createRandomData(iv, ivSize) == false) {
|
|
|
|
if (RSessionCrypto_createRandomData(iv, ivSize) == false)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - Failed to create random IV");
|
|
|
|
DEBUG_PRINTF("ERROR - Failed to create random IV");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bufPos += ivSize;
|
|
|
|
bufPos += ivSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
buffer[bufPos++] = 0; /* empty initialization vector */
|
|
|
|
buffer[bufPos++] = 0; /* empty initialization vector */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -861,8 +935,8 @@ encodePacket(RSession self, uint8_t payloadType, uint8_t* buffer, int bufPos, RS
|
|
|
|
/* encode user payload elements */
|
|
|
|
/* encode user payload elements */
|
|
|
|
element = elements;
|
|
|
|
element = elements;
|
|
|
|
|
|
|
|
|
|
|
|
while (element) {
|
|
|
|
while (element)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* payload type ? (according to example in annex G) */
|
|
|
|
/* payload type ? (according to example in annex G) */
|
|
|
|
buffer[bufPos++] = element->payloadType;
|
|
|
|
buffer[bufPos++] = element->payloadType;
|
|
|
|
|
|
|
|
|
|
|
@ -882,15 +956,15 @@ encodePacket(RSession self, uint8_t payloadType, uint8_t* buffer, int bufPos, RS
|
|
|
|
element = element->nextElement;
|
|
|
|
element = element->nextElement;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (self->sigAlgo != R_SESSION_SIG_ALGO_NONE) {
|
|
|
|
if (self->sigAlgo != R_SESSION_SIG_ALGO_NONE)
|
|
|
|
|
|
|
|
{
|
|
|
|
int signatureCoveredLength = bufPos - startPos;
|
|
|
|
int signatureCoveredLength = bufPos - startPos;
|
|
|
|
|
|
|
|
|
|
|
|
DEBUG_PRINTF("Signature: %i", signatureCoveredLength);
|
|
|
|
DEBUG_PRINTF("Signature: %i", signatureCoveredLength);
|
|
|
|
|
|
|
|
|
|
|
|
/* add signature */
|
|
|
|
/* add signature */
|
|
|
|
if (self->sigAlgo == R_SESSION_SIG_ALGO_HMAC_SHA256_256) {
|
|
|
|
if (self->sigAlgo == R_SESSION_SIG_ALGO_HMAC_SHA256_256)
|
|
|
|
|
|
|
|
{
|
|
|
|
buffer[bufPos++] = 0x85;
|
|
|
|
buffer[bufPos++] = 0x85;
|
|
|
|
buffer[bufPos++] = 16;
|
|
|
|
buffer[bufPos++] = 16;
|
|
|
|
|
|
|
|
|
|
|
@ -898,7 +972,8 @@ encodePacket(RSession self, uint8_t payloadType, uint8_t* buffer, int bufPos, RS
|
|
|
|
|
|
|
|
|
|
|
|
bufPos += 32;
|
|
|
|
bufPos += 32;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (self->sigAlgo == R_SESSION_SIG_ALGO_HMAC_SHA256_128) {
|
|
|
|
else if (self->sigAlgo == R_SESSION_SIG_ALGO_HMAC_SHA256_128)
|
|
|
|
|
|
|
|
{
|
|
|
|
buffer[bufPos++] = 0x85;
|
|
|
|
buffer[bufPos++] = 0x85;
|
|
|
|
buffer[bufPos++] = 16;
|
|
|
|
buffer[bufPos++] = 16;
|
|
|
|
//buffer[bufPos++] = 0x20; /* 32 octets */
|
|
|
|
//buffer[bufPos++] = 0x20; /* 32 octets */
|
|
|
@ -907,14 +982,16 @@ encodePacket(RSession self, uint8_t payloadType, uint8_t* buffer, int bufPos, RS
|
|
|
|
|
|
|
|
|
|
|
|
bufPos += 16;
|
|
|
|
bufPos += 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - unsupported signature type");
|
|
|
|
DEBUG_PRINTF("ERROR - unsupported signature type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int payloadEndPos = bufPos;
|
|
|
|
int payloadEndPos = bufPos;
|
|
|
|
|
|
|
|
|
|
|
|
if (self->secAlgo != R_SESSION_SEC_ALGO_NONE) {
|
|
|
|
if (self->secAlgo != R_SESSION_SEC_ALGO_NONE)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* create signature and encrypt payload */
|
|
|
|
/* create signature and encrypt payload */
|
|
|
|
|
|
|
|
|
|
|
|
buffer[bufPos++] = 0x85;
|
|
|
|
buffer[bufPos++] = 0x85;
|
|
|
@ -929,10 +1006,12 @@ encodePacket(RSession self, uint8_t payloadType, uint8_t* buffer, int bufPos, RS
|
|
|
|
|
|
|
|
|
|
|
|
DEBUG_PRINTF("===> encrypt ====");
|
|
|
|
DEBUG_PRINTF("===> encrypt ====");
|
|
|
|
|
|
|
|
|
|
|
|
if (RSessionCrypto_gcmEncryptAndTag(self->currentKey, self->currentKeySize, iv, ivSize, buffer + startPos, addPartSize, buffer + encryptedPartStartPos, encryptedPartSize, buffer + bufPos, 16) == false) {
|
|
|
|
if (RSessionCrypto_gcmEncryptAndTag(self->currentKey, self->currentKeySize, iv, ivSize, buffer + startPos, addPartSize, buffer + encryptedPartStartPos, encryptedPartSize, buffer + bufPos, 16) == false)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("ERROR - encryption failed");
|
|
|
|
DEBUG_PRINTF("ERROR - encryption failed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
bufPos += 16;
|
|
|
|
bufPos += 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -948,19 +1027,21 @@ encodePacket(RSession self, uint8_t payloadType, uint8_t* buffer, int bufPos, RS
|
|
|
|
RSessionError
|
|
|
|
RSessionError
|
|
|
|
RSession_sendMessage(RSession self, RSessionProtocol_SPDU_ID spduId, bool simulation, uint16_t appId, uint8_t* payload, int payloadSize)
|
|
|
|
RSession_sendMessage(RSession self, RSessionProtocol_SPDU_ID spduId, bool simulation, uint16_t appId, uint8_t* payload, int payloadSize)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (self->socket == NULL) {
|
|
|
|
if (self->socket == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
self->socket = UdpSocket_create();
|
|
|
|
self->socket = UdpSocket_create();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (self->sendBuffer == NULL) {
|
|
|
|
if (self->sendBuffer == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
self->sendBuffer = (uint8_t*) GLOBAL_MALLOC(self->bufferSize);
|
|
|
|
self->sendBuffer = (uint8_t*) GLOBAL_MALLOC(self->bufferSize);
|
|
|
|
|
|
|
|
|
|
|
|
if (self->sendBuffer == NULL)
|
|
|
|
if (self->sendBuffer == NULL)
|
|
|
|
return R_SESSION_ERROR_OUT_OF_MEMORY;
|
|
|
|
return R_SESSION_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (self->socket) {
|
|
|
|
if (self->socket)
|
|
|
|
|
|
|
|
{
|
|
|
|
struct sRSessionPayloadElement element;
|
|
|
|
struct sRSessionPayloadElement element;
|
|
|
|
|
|
|
|
|
|
|
|
element.simulation = simulation;
|
|
|
|
element.simulation = simulation;
|
|
|
@ -976,15 +1057,17 @@ RSession_sendMessage(RSession self, RSessionProtocol_SPDU_ID spduId, bool simula
|
|
|
|
printBuffer(self->sendBuffer, msgSize);
|
|
|
|
printBuffer(self->sendBuffer, msgSize);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
if (UdpSocket_sendTo(self->socket, self->remoteAddress, self->remotePort, self->sendBuffer, msgSize)) {
|
|
|
|
if (UdpSocket_sendTo(self->socket, self->remoteAddress, self->remotePort, self->sendBuffer, msgSize))
|
|
|
|
|
|
|
|
{
|
|
|
|
return R_SESSION_ERROR_OK;
|
|
|
|
return R_SESSION_ERROR_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
return R_SESSION_ERROR_FAILED_TO_SEND;
|
|
|
|
return R_SESSION_ERROR_FAILED_TO_SEND;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
return R_SESSION_ERROR_NO_SOCKET;
|
|
|
|
return R_SESSION_ERROR_NO_SOCKET;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -992,10 +1075,12 @@ RSession_sendMessage(RSession self, RSessionProtocol_SPDU_ID spduId, bool simula
|
|
|
|
void
|
|
|
|
void
|
|
|
|
RSession_setBufferSize(RSession self, uint16_t bufferSize)
|
|
|
|
RSession_setBufferSize(RSession self, uint16_t bufferSize)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (bufferSize > 127) {
|
|
|
|
if (bufferSize > 127)
|
|
|
|
|
|
|
|
{
|
|
|
|
self->bufferSize = bufferSize;
|
|
|
|
self->bufferSize = bufferSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
self->bufferSize = 128;
|
|
|
|
self->bufferSize = 128;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1005,13 +1090,16 @@ RSession_receiveMessage(RSession self, RSessionPayloadElementHandler handler, vo
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Semaphore_wait(self->socketLock);
|
|
|
|
Semaphore_wait(self->socketLock);
|
|
|
|
|
|
|
|
|
|
|
|
if (self->socket) {
|
|
|
|
if (self->socket)
|
|
|
|
|
|
|
|
{
|
|
|
|
char ipAddrBuf[128];
|
|
|
|
char ipAddrBuf[128];
|
|
|
|
|
|
|
|
|
|
|
|
if (self->sendBuffer == NULL) {
|
|
|
|
if (self->sendBuffer == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
self->sendBuffer = (uint8_t*) GLOBAL_MALLOC(self->bufferSize);
|
|
|
|
self->sendBuffer = (uint8_t*) GLOBAL_MALLOC(self->bufferSize);
|
|
|
|
|
|
|
|
|
|
|
|
if (self->sendBuffer == NULL) {
|
|
|
|
if (self->sendBuffer == NULL)
|
|
|
|
|
|
|
|
{
|
|
|
|
Semaphore_post(self->socketLock);
|
|
|
|
Semaphore_post(self->socketLock);
|
|
|
|
|
|
|
|
|
|
|
|
return R_SESSION_ERROR_OUT_OF_MEMORY;
|
|
|
|
return R_SESSION_ERROR_OUT_OF_MEMORY;
|
|
|
@ -1024,17 +1112,19 @@ RSession_receiveMessage(RSession self, RSessionPayloadElementHandler handler, vo
|
|
|
|
|
|
|
|
|
|
|
|
Semaphore_post(self->socketLock);
|
|
|
|
Semaphore_post(self->socketLock);
|
|
|
|
|
|
|
|
|
|
|
|
if (msgSize < 1) {
|
|
|
|
if (msgSize < 1)
|
|
|
|
|
|
|
|
{
|
|
|
|
DEBUG_PRINTF("RESSSION: Failed to receive message");
|
|
|
|
DEBUG_PRINTF("RESSSION: Failed to receive message");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return R_SESSION_ERROR_FAILED_TO_RECEIVE;
|
|
|
|
return R_SESSION_ERROR_FAILED_TO_RECEIVE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
return parseSessionMessage(self, self->sendBuffer, msgSize, handler, parameter);
|
|
|
|
return parseSessionMessage(self, self->sendBuffer, msgSize, handler, parameter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
Semaphore_post(self->socketLock);
|
|
|
|
Semaphore_post(self->socketLock);
|
|
|
|
|
|
|
|
|
|
|
|
return R_SESSION_ERROR_NO_SOCKET;
|
|
|
|
return R_SESSION_ERROR_NO_SOCKET;
|
|
|
@ -1046,14 +1136,16 @@ RSession_addKey(RSession self, uint32_t keyId, uint8_t* key, int keyLength, RSec
|
|
|
|
{
|
|
|
|
{
|
|
|
|
RSessionKeyMaterial keyMaterial = RSessionKeyMaterial_create(keyId, key, keyLength, secAlgo, sigAlgo);
|
|
|
|
RSessionKeyMaterial keyMaterial = RSessionKeyMaterial_create(keyId, key, keyLength, secAlgo, sigAlgo);
|
|
|
|
|
|
|
|
|
|
|
|
if (keyMaterial) {
|
|
|
|
if (keyMaterial)
|
|
|
|
|
|
|
|
{
|
|
|
|
Semaphore_wait(self->keyListLock);
|
|
|
|
Semaphore_wait(self->keyListLock);
|
|
|
|
LinkedList_add(self->keyList, keyMaterial);
|
|
|
|
LinkedList_add(self->keyList, keyMaterial);
|
|
|
|
Semaphore_post(self->keyListLock);
|
|
|
|
Semaphore_post(self->keyListLock);
|
|
|
|
|
|
|
|
|
|
|
|
return R_SESSION_ERROR_OK;
|
|
|
|
return R_SESSION_ERROR_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
return R_SESSION_ERROR_OUT_OF_MEMORY;
|
|
|
|
return R_SESSION_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1063,10 +1155,12 @@ getKeyById(RSession self, uint32_t keyId)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
LinkedList keyElem = LinkedList_getNext(self->keyList);
|
|
|
|
LinkedList keyElem = LinkedList_getNext(self->keyList);
|
|
|
|
|
|
|
|
|
|
|
|
while (keyElem) {
|
|
|
|
while (keyElem)
|
|
|
|
|
|
|
|
{
|
|
|
|
RSessionKeyMaterial keyMaterial = (RSessionKeyMaterial) LinkedList_getData(keyElem);
|
|
|
|
RSessionKeyMaterial keyMaterial = (RSessionKeyMaterial) LinkedList_getData(keyElem);
|
|
|
|
|
|
|
|
|
|
|
|
if (keyMaterial->keyId == keyId) {
|
|
|
|
if (keyMaterial->keyId == keyId)
|
|
|
|
|
|
|
|
{
|
|
|
|
return keyMaterial;
|
|
|
|
return keyMaterial;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1085,18 +1179,21 @@ RSession_removeKey(RSession self, uint32_t keyId)
|
|
|
|
|
|
|
|
|
|
|
|
RSessionKeyMaterial keyMaterial = getKeyById(self, keyId);
|
|
|
|
RSessionKeyMaterial keyMaterial = getKeyById(self, keyId);
|
|
|
|
|
|
|
|
|
|
|
|
if (keyMaterial) {
|
|
|
|
if (keyMaterial)
|
|
|
|
|
|
|
|
{
|
|
|
|
LinkedList_remove(self->keyList, keyMaterial);
|
|
|
|
LinkedList_remove(self->keyList, keyMaterial);
|
|
|
|
|
|
|
|
|
|
|
|
RSessionKeyMaterial_destroy(keyMaterial);
|
|
|
|
RSessionKeyMaterial_destroy(keyMaterial);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
retVal = R_SESSION_ERROR_INVALID_KEY;
|
|
|
|
retVal = R_SESSION_ERROR_INVALID_KEY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Semaphore_post(self->keyListLock);
|
|
|
|
Semaphore_post(self->keyListLock);
|
|
|
|
|
|
|
|
|
|
|
|
if (self->currentKeyId == keyId) {
|
|
|
|
if (self->currentKeyId == keyId)
|
|
|
|
|
|
|
|
{
|
|
|
|
/* active key removed! */
|
|
|
|
/* active key removed! */
|
|
|
|
self->currentKeyId = 0;
|
|
|
|
self->currentKeyId = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1130,14 +1227,16 @@ RSession_setActiveKey(RSession self, uint32_t keyId)
|
|
|
|
|
|
|
|
|
|
|
|
RSessionKeyMaterial keyMaterial = getKeyById(self, keyId);
|
|
|
|
RSessionKeyMaterial keyMaterial = getKeyById(self, keyId);
|
|
|
|
|
|
|
|
|
|
|
|
if (keyMaterial) {
|
|
|
|
if (keyMaterial)
|
|
|
|
|
|
|
|
{
|
|
|
|
self->currentKeySize = keyMaterial->keyLength;
|
|
|
|
self->currentKeySize = keyMaterial->keyLength;
|
|
|
|
self->currentKey = keyMaterial->key;
|
|
|
|
self->currentKey = keyMaterial->key;
|
|
|
|
self->currentKeyId = keyMaterial->keyId;
|
|
|
|
self->currentKeyId = keyMaterial->keyId;
|
|
|
|
self->currentSecAlgo = keyMaterial->secAlgo;
|
|
|
|
self->currentSecAlgo = keyMaterial->secAlgo;
|
|
|
|
self->currentSigAlgo = keyMaterial->sigAlgo;
|
|
|
|
self->currentSigAlgo = keyMaterial->sigAlgo;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
retVal = R_SESSION_ERROR_INVALID_KEY;
|
|
|
|
retVal = R_SESSION_ERROR_INVALID_KEY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -1149,7 +1248,8 @@ RSession_setActiveKey(RSession self, uint32_t keyId)
|
|
|
|
void
|
|
|
|
void
|
|
|
|
RSession_destroy(RSession self)
|
|
|
|
RSession_destroy(RSession self)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (self) {
|
|
|
|
if (self)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (self->socket)
|
|
|
|
if (self->socket)
|
|
|
|
Socket_destroy((Socket)self->socket);
|
|
|
|
Socket_destroy((Socket)self->socket);
|
|
|
|
|
|
|
|
|
|
|
@ -1183,4 +1283,3 @@ RSession_getSocket(RSession self)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return (Socket)self->socket;
|
|
|
|
return (Socket)self->socket;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|