decoding and encoding kiss diagnostic messages as aprs messages

master
Mateusz Lubecki 2024-05-07 21:26:13 +02:00
rodzic 73ab9cac33
commit 6a0766e22c
5 zmienionych plików z 295 dodań i 6 usunięć

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -0,0 +1,115 @@
/*
* kiss_communication_aprsmsg.h
*
* Created on: May 5, 2024
* Author: mateusz
*/
#ifndef KISS_COMMUNICATION_KISS_COMMUNICATION_APRSMSG_H_
#define KISS_COMMUNICATION_KISS_COMMUNICATION_APRSMSG_H_
#include <stdint.h>
typedef enum kiss_communication_aprsmsg_transport_t {
/**
* Transport KISS diagnostic messages as plain unencrypted hex-string
* which looks like
* HSxxxxxxxxxxxxxxxxxxxxxxxxx
* Where 'HS' is a prefix and all 'x' are binary data. Because of
* size limit of message content lenght, which is 67 characters,
* this payload can have no more than 32 bytes. Each byte is
* encoded in two characters + 'HS' prefix
*/
APRSMSG_TRANSPORT_HEXSTRING,
/**
* Transport KISS diagnostic messages, encrypted using AES128 cipher
* in ECB mode and then put into message as a hex string. It looks
* like that
* Pyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
* Where 'P' is contant prefix. 'yy' is a two-character salt to protect
* agains problems with electronic codebook mode. The rest of 'x' is exactly
* 62 characters, what resembles:
* - 58 hexstring characters / 29 bytes of KISS diagnostic message,
* - 4 hextring characters / 2 bytes of the salt (two characters)
*
* An example:
* 06FF1122334455000000000000000000000000000000000000000000006D6E - clear message in binary
* - 06FF11223344550000000 (...) - KISS message padded with zeros to 58 characters / 29 bytes
* - 6D6E - four characters / 2 bytes of salt
*
* da1044bfccd776eb8b717ec3f945a4b799616a3bf4bf5ba08ba1f2d39301e5f0 - encrypted with AES128-ECB
*
* Pmnda1044bfccd776eb8b717ec3f945a4b799616a3bf4bf5ba08ba1f2d39301e5f0 - encrypted & transported
* - P - constant prefix
* - 'mn' - two characters of salt
* - 'da1044bf (...)' ebcrypted message
*
* Internally the controller holds salt value from last UDS request in RTC backup register as a 16bit word.
* Each request is checked and a salt value cannot be smaller than the previous one, the check is done by
* 'converting' two character into one uint16_t value in way presented below"
* 'mn' - 'm' 0x6D, 'n' 0x6E => 0x6D6E
* Value of the salt could be reverted only if it is bigger than 0x7A00 ('~' as a first char), but it may
* be reverted only if 0x2100 < new_salt_value < 0x2200. In another words: reverted salt must have '!'
* as a first character.
*
* Because UDS requests and responses are transmitted as APRS text message salt must contain only printable
* characters (of course except tab and space)
*
* Responses generated by the controller also contains salt, which is
*
*
*/
APRSMSG_TRANSPORT_ENCRYPTED_HEXSTRING,
/**
* Just an echo request
*/
APRSMSG_TRANSPORT_ECHO,
/**
* Unallowed salt value
*/
APRSMSG_TRANSPORT_ERROR_SALT,
/**
* Transport type is known to the application, but it is not implemented yet.
*/
APRSMSG_TRANSPORT_ERROR_UNSUPPORTED,
APRSMSG_TRANSPORT_UNINITIALIZED
} kiss_communication_aprsmsg_transport_t;
/**
*
* @param message_payload
* @param message_payload_ln
* @return
*/
kiss_communication_aprsmsg_transport_t kiss_communication_aprsmsg_check_type(uint8_t * message_payload, uint16_t message_payload_ln);
/**
*
* @param message_payload pointer to characters buffer with APRS text message, containing encoded UDS diag request
* @param message_payload_ln length of buffer pointed by message_payload. processing will be done until first non-hex character (non 0-9 / a-f) or this length
* @param output_binary_buffer pointer to binary buffer where decoded data will be copied to.
* @param output_ln
* @return length of decoded UDS request or zero if message_payload doesn't contain valid hexstring with UDS request
*/
uint16_t kiss_communication_aprsmsg_decode_hexstring(uint8_t * message_payload, uint16_t message_payload_ln, uint8_t * output_binary_buffer, uint16_t output_ln);
/**
*
* @param input_binary_buffer
* @param input_ln
* @param output_message
* @param output_message_max_ln
* @return
*/
uint16_t kiss_communication_aprsmsg_encode_hexstring(uint8_t * input_binary_buffer, uint16_t input_ln, uint8_t * output_message, uint16_t output_message_max_ln);
#endif /* KISS_COMMUNICATION_KISS_COMMUNICATION_APRSMSG_H_ */

Wyświetl plik

@ -8,8 +8,8 @@
#ifndef SOFTWARE_VERSION_H_
#define SOFTWARE_VERSION_H_
#define SW_VER "EB05"
#define SW_DATE "27042024"
#define SW_VER "EC00"
#define SW_DATE "05052024"
#define SW_KISS_PROTO "B"
extern const char software_version_str[5];

Wyświetl plik

@ -0,0 +1,163 @@
/*
* kiss_communication_aprsmsg.c
*
* Created on: May 5, 2024
* Author: mateusz
*/
#include "kiss_communication/kiss_communication_aprsmsg.h"
#define KISS_COMMUNICATION_APRSMSG_DEC_CURRENT_CHAR *(message_payload + payload_it)
#define KISS_COMMUNICATION_APRSMSG_DEC_NEXT_CHAR *(message_payload + payload_it + 1)
#define KISS_COMMUNICATION_APRSMSG_DEC_OUTPUT_IT ((payload_it - 1) / 2)
#define KISS_COMMUNICATION_APRSMSG_IS_DIGIT(c) ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
#define KISS_COMMUNICATION_APRSMSG_ENC_OUTPUT_L_IT(i) (((i + 1) * 2) + 1)
#define KISS_COMMUNICATION_APRSMSG_ENC_OUTPUT_H_IT(i) ((i + 1) * 2)
#define KISS_COMMUNICATION_APRSMSG_GET_CHAR(b) kiss_communication_aprsmsg_tohexstr_lookup_table[b]
static uint8_t kiss_communication_aprsmsg_lookup_table[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
-1, -1, -1, -1, -1, -1, -1,
10, 11, 12, 13, 14, 15,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1,
10, 11, 12, 13, 14, 15};
static uint8_t kiss_communication_aprsmsg_tohexstr_lookup_table[] =
{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
/**
*
* @param message_payload
* @param message_payload_ln
* @return
*/
kiss_communication_aprsmsg_transport_t kiss_communication_aprsmsg_check_type(uint8_t * message_payload, uint16_t message_payload_ln)
{
kiss_communication_aprsmsg_transport_t out;
if (variant_validate_is_within_ram(message_payload) == 1 && message_payload_ln > 6) {
}
return out;
}
/**
*
* @param message_payload pointer to characters buffer with APRS text message, containing encoded UDS diag request
* @param message_payload_ln length of buffer pointed by message_payload. processing will be done until first non-hex character (non 0-9 / a-f) or this length
* @param output_binary_buffer pointer to binary buffer where decoded data will be copied to.
* @param output_ln
* @return length of decoded UDS request or zero if message_payload doesn't contain valid hexstring with UDS request
*/
uint16_t kiss_communication_aprsmsg_decode_hexstring(uint8_t * message_payload, uint16_t message_payload_ln, uint8_t * output_binary_buffer, uint16_t output_ln)
{
uint8_t out = 0;
// iterator to go through 'message_payload' input buffer
uint16_t payload_it = 0;
// high nibble
uint8_t hn = 0;
// low nibble
uint8_t ln = 0;
// checck if input string is located in legoit RAM memory
if (variant_validate_is_within_ram(message_payload) == 1 && message_payload_ln > 6) {
// check second time of string begins with 'HS'
if (KISS_COMMUNICATION_APRSMSG_DEC_CURRENT_CHAR == 'H' && KISS_COMMUNICATION_APRSMSG_DEC_NEXT_CHAR == 'S') {
// move iterator to begining of hex-characters
payload_it += 2;
while (payload_it < message_payload_ln) {
// check if current char resembles hex base number
if (KISS_COMMUNICATION_APRSMSG_IS_DIGIT(KISS_COMMUNICATION_APRSMSG_DEC_CURRENT_CHAR) == 0) {
break; // if not break conversion
}
if (KISS_COMMUNICATION_APRSMSG_DEC_OUTPUT_IT >= output_ln) {
break; // no more room for output data
}
hn = KISS_COMMUNICATION_APRSMSG_DEC_CURRENT_CHAR;
ln = KISS_COMMUNICATION_APRSMSG_DEC_NEXT_CHAR;
// calculate index to lookup table basing on current character
const uint8_t index_hn = hn - 0x30u;
// calculate index to lookup table basing on current character
const uint8_t index_ln = ln - 0x30u;
// conveted byte
const uint8_t converted_byte = (kiss_communication_aprsmsg_lookup_table[index_hn] * 0x10u) +
kiss_communication_aprsmsg_lookup_table[index_ln];
// put converted byte into output array
output_binary_buffer[KISS_COMMUNICATION_APRSMSG_DEC_OUTPUT_IT] = converted_byte;
payload_it += 2;
}
// go through
out = KISS_COMMUNICATION_APRSMSG_DEC_OUTPUT_IT;
}
}
return out;
}
uint16_t kiss_communication_aprsmsg_encode_hexstring(uint8_t * input_binary_buffer, uint16_t input_ln, uint8_t * output_message, uint16_t output_message_max_ln)
{
uint16_t out = 0;
// iterator across input buffer
uint16_t iterator = 0;
// expected lenght of output buffer. Prefix 'HS', then hex encoded binary data and null termimator at the end
const uint16_t expected_output_ln = 2 + (input_ln * 2) + 1;
// if output buffer is big enought to fit
if (output_message_max_ln > expected_output_ln) {
// make a room for output data
memset(output_message, 0x00, expected_output_ln);
// put prefix
*output_message = 'H';
*(output_message + 1) = 'S';
while (iterator < input_ln) {
// extract high and low nibbled for processed byte
const uint8_t low_nibble = input_binary_buffer[iterator] & 0xFu;
const uint8_t high_nibble = (input_binary_buffer[iterator] & 0xF0u) >> 4;
output_message[KISS_COMMUNICATION_APRSMSG_ENC_OUTPUT_L_IT(iterator)] = KISS_COMMUNICATION_APRSMSG_GET_CHAR(low_nibble);
output_message[KISS_COMMUNICATION_APRSMSG_ENC_OUTPUT_H_IT(iterator)] = KISS_COMMUNICATION_APRSMSG_GET_CHAR(high_nibble);
out = KISS_COMMUNICATION_APRSMSG_ENC_OUTPUT_L_IT(iterator) + 1;
iterator++;
}
}
return out;
}

Wyświetl plik

@ -25,7 +25,7 @@
#include <stm32l4xx_ll_crc.h>
#endif
/**
/** EBxx
* STM32L476RE, 512KB flash mem, last flash memory page
* 0x0807F800 - 0x0807FFFF; 2 K; Page 383
*
@ -36,9 +36,20 @@
*
*/
#define CONFIG_SECTION_FIRST_START 0x0801E800
#define CONFIG_SECTION_SECOND_START 0x0801F000
#define CONFIG_SECTION_DEFAULT_START 0x0801E000
/** ECxx
* STM32L476RE, 512KB flash mem, last flash memory page
* 0x0807F800 - 0x0807FFFF; 2 K; Page 383
*
* __config_section_default_start = 0x08030000;
__config_section_first_start = 0x08030800;
__config_section_second_start = 0x08031000;
__config_section_third_start = 0x0801F800;
*
*/
#define CONFIG_SECTION_FIRST_START 0x08030800 //0x0801E800
#define CONFIG_SECTION_SECOND_START 0x08031000 //0x0801F000
#define CONFIG_SECTION_DEFAULT_START 0x08030000 //0x0801E000
#define CONFIG_MODE_PGM_CNTR 0x0
#define CONFIG_MODE_OFSET 0x20 // Current size: 0x14, free: 0x0C