Converting / Parsing C++ byte struct to Go - c++

I am reading some data packets in Go, where the fields are C++ data types. I tried parsing the data but I am reading garbage values.
Here is a small example - the data spec sheet for a particular datatype is as follows in C++,
struct CarTelemetryData
{
uint16 m_speed;
uint8 m_throttle;
int8 m_steer;
uint8 m_brake;
uint8 m_clutch;
int8 m_gear;
uint16 m_engineRPM;
uint8 m_drs;
uint8 m_revLightsPercent;
uint16 m_brakesTemperature[4];
uint16 m_tyresSurfaceTemperature[4];
uint16 m_tyresInnerTemperature[4];
uint16 m_engineTemperature;
float m_tyresPressure[4];
};
And below is what I have defined in Go
type CarTelemetryData struct {
Speed uint16
Throttle uint8
Steer int8
Brake uint8
Clutch uint8
Gear int8
EngineRPM uint16
DRS uint8
RevLightsPercent uint8
BrakesTemperature [4]uint16
TyresSurfaceTemperature [4]uint16
TyresInnerTemperature [4]uint16
EngineTemperature uint16
TyresPressure [4]float32
}
For the actual un-marshalling, I am doing this -
func decodePayload(dataStruct interface{}, payload []byte) {
dataReader := bytes.NewReader(payload[:])
binary.Read(dataReader, binary.LittleEndian, dataStruct)
}
payload := make([]byte, 2048)
s.conn.ReadFromUDP(payload[:])
telemetryData := &data.CarTelemetryData{}
s.PacketsRcvd += 1
decodePayload(telemetryData, payload)
I suspect that this is because the datatypes are not equivalent and there is some conversion issue while reading the bytes into Go data-types, whereas they have been originally packages as C++. How can I deal with this?
Note: I don't have any control over the data that is sent, this is sent by a third party service.

The issue you're facing has to do with the alignment of struct members. You can read more about it here but, in short, the C++ compiler will sometimes add padding bytes in order to maintain the natural alignment expected by the architecture. If that alignment is not used, it may cause degraded performance or even an access violation.
For x86/x64, for example, the alignment of most types will usually (but not necessarily guaranteed to) be the same as the size. We can see that
#include <cstdint>
#include <type_traits>
std::size_t offsets[] = {
std::alignment_of_v<std::uint8_t>,
std::alignment_of_v<std::uint16_t>,
std::alignment_of_v<std::uint32_t>,
std::alignment_of_v<std::uint64_t>,
std::alignment_of_v<__uint128_t>,
std::alignment_of_v<std::int8_t>,
std::alignment_of_v<std::int16_t>,
std::alignment_of_v<std::int32_t>,
std::alignment_of_v<std::int64_t>,
std::alignment_of_v<__int128_t>,
std::alignment_of_v<float>,
std::alignment_of_v<double>,
std::alignment_of_v<long double>,
std::alignment_of_v<void*>,
};
compiles to
offsets:
.quad 1
.quad 2
.quad 4
.quad 8
.quad 16
.quad 1
.quad 2
.quad 4
.quad 8
.quad 16
.quad 4
.quad 8
.quad 16
.quad 8
Due to these (and other) implementation details, it may be advisable to not rely on the internal representation. In some cases, however, other methods may not be fast enough (such as serializing field by field), or you may not be able to change the C++ code, like OP.
binary.Read expects packed data, but C++ will use padding. We need to either use a compiler-dependent directive such as #pragma pack(1) or add padding the Go struct. The first is not an option for OP, so we'll use the second.
We can use the offsetof macro to determine the offset of a struct member relative to the struct itself. We can do something like
#include <array>
#include <cstddef>
#include <cstdint>
using int8 = std::int8_t;
using uint8 = std::uint8_t;
using uint16 = std::uint16_t;
struct CarTelemetryData {
uint16 m_speed;
uint8 m_throttle;
int8 m_steer;
uint8 m_brake;
uint8 m_clutch;
int8 m_gear;
uint16 m_engineRPM;
uint8 m_drs;
uint8 m_revLightsPercent;
uint16 m_brakesTemperature[4];
uint16 m_tyresSurfaceTemperature[4];
uint16 m_tyresInnerTemperature[4];
uint16 m_engineTemperature;
float m_tyresPressure[4];
};
// C++ has no reflection (yet) so we need to list every member
constexpr auto offsets = std::array{
offsetof(CarTelemetryData, m_speed),
offsetof(CarTelemetryData, m_throttle),
offsetof(CarTelemetryData, m_steer),
offsetof(CarTelemetryData, m_brake),
offsetof(CarTelemetryData, m_clutch),
offsetof(CarTelemetryData, m_gear),
offsetof(CarTelemetryData, m_engineRPM),
offsetof(CarTelemetryData, m_drs),
offsetof(CarTelemetryData, m_revLightsPercent),
offsetof(CarTelemetryData, m_brakesTemperature),
offsetof(CarTelemetryData, m_tyresSurfaceTemperature),
offsetof(CarTelemetryData, m_tyresInnerTemperature),
offsetof(CarTelemetryData, m_engineTemperature),
offsetof(CarTelemetryData, m_tyresPressure),
};
constexpr auto sizes = std::array{
sizeof(CarTelemetryData::m_speed),
sizeof(CarTelemetryData::m_throttle),
sizeof(CarTelemetryData::m_steer),
sizeof(CarTelemetryData::m_brake),
sizeof(CarTelemetryData::m_clutch),
sizeof(CarTelemetryData::m_gear),
sizeof(CarTelemetryData::m_engineRPM),
sizeof(CarTelemetryData::m_drs),
sizeof(CarTelemetryData::m_revLightsPercent),
sizeof(CarTelemetryData::m_brakesTemperature),
sizeof(CarTelemetryData::m_tyresSurfaceTemperature),
sizeof(CarTelemetryData::m_tyresInnerTemperature),
sizeof(CarTelemetryData::m_engineTemperature),
sizeof(CarTelemetryData::m_tyresPressure),
};
constexpr auto computePadding() {
std::array<std::size_t, offsets.size()> result;
std::size_t expectedOffset = 0;
for (std::size_t i = 0; i < offsets.size(); i++) {
result.at(i) = offsets.at(i) - expectedOffset;
expectedOffset = offsets.at(i) + sizes.at(i);
}
return result;
}
auto padding = computePadding();
which compiles to (constexpr FTW)
padding:
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 1
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 2
So, on x86, we need one byte before EngineRPM and two bytes before TyresPressure.
So, let's check if that works.
C++:
#include <cstddef>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <span>
using int8 = std::int8_t;
using uint8 = std::uint8_t;
using uint16 = std::uint16_t;
struct CarTelemetryData {
uint16 m_speed;
uint8 m_throttle;
int8 m_steer;
uint8 m_brake;
uint8 m_clutch;
int8 m_gear;
uint16 m_engineRPM;
uint8 m_drs;
uint8 m_revLightsPercent;
uint16 m_brakesTemperature[4];
uint16 m_tyresSurfaceTemperature[4];
uint16 m_tyresInnerTemperature[4];
uint16 m_engineTemperature;
float m_tyresPressure[4];
};
int main() {
CarTelemetryData data = {
.m_speed = 1,
.m_throttle = 2,
.m_steer = 3,
.m_brake = 4,
.m_clutch = 5,
.m_gear = 6,
.m_engineRPM = 7,
.m_drs = 8,
.m_revLightsPercent = 9,
.m_brakesTemperature = {10, 11, 12, 13},
.m_tyresSurfaceTemperature = {14, 15, 16, 17},
.m_tyresInnerTemperature = {18, 19, 20, 21},
.m_engineTemperature = 22,
.m_tyresPressure = {23, 24, 25, 26},
};
std::cout << "b := []byte{" << std::hex << std::setfill('0');
for (auto byte : std::as_bytes(std::span(&data, 1))) {
std::cout << "0x" << std::setw(2) << static_cast<unsigned>(byte)
<< ", ";
}
std::cout << "}";
}
results in
b := []byte{0x01, 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x00, 0x07, 0x00, 0x08, 0x09, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x41, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x00, 0xc8, 0x41, 0x00, 0x00, 0xd0, 0x41, }
Let's use that in Go:
// Type your code here, or load an example.
// Your function name should start with a capital letter.
package main
import (
"bytes"
"encoding/binary"
"fmt"
)
type CarTelemetryData struct {
Speed uint16
Throttle uint8
Steer int8
Brake uint8
Clutch uint8
Gear int8
_ uint8
EngineRPM uint16
DRS uint8
RevLightsPercent uint8
BrakesTemperature [4]uint16
TyresSurfaceTemperature [4]uint16
TyresInnerTemperature [4]uint16
EngineTemperature uint16
_ uint16
TyresPressure [4]float32
}
func main() {
b := []byte{0x01, 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x00, 0x07, 0x00, 0x08, 0x09, 0x0a, 0x00, 0x0b, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x41, 0x00, 0x00, 0xc0, 0x41, 0x00, 0x00, 0xc8, 0x41, 0x00, 0x00, 0xd0, 0x41}
var dataStruct CarTelemetryData
dataReader := bytes.NewReader(b[:])
binary.Read(dataReader, binary.LittleEndian, &dataStruct)
fmt.Printf("%+v", dataStruct)
}
which prints
{Speed:1 Throttle:2 Steer:3 Brake:4 Clutch:5 Gear:6 _:0 EngineRPM:7 DRS:8 RevLightsPercent:9 BrakesTemperature:[10 11 12 13] TyresSurfaceTemperature:[14 15 16 17] TyresInnerTemperature:[18 19 20 21] EngineTemperature:22 _:0 TyresPressure:[23 24 25 26]}
Take the padding bytes out and it fails.

Related

Reading Hex from file, printf %x showing leading ff values

I have a file 'data.dat' with 26 hex byte values:
22 49 E1 09 62 18 42 8C 66 10 B0 11 84 9C 00 FF E0 40 1F F8 60 07 FE 2C 03 FF
I am trying to read these into c++ and print the hex values to the terminal with:
const int msgbuflen = 26;
char message [msgbuflen];
const char* filenameIn = "data.dat";
FILE* fpIn = fopen(filenameIn, "rb");
if (!fpIn) {
perror("ERROR: INPUT FILE CANNOT BE OPENED\n");
exit(EXIT_FAILURE);
}
for (i=0; i<msgbuflen; i++){ // clear the buffer
message[i] = '0';
}
size_t ret_code = fread(message, sizeof(unsigned char), msgbuflen, fpIn);
for(int i = 0; i < msgbuflen; i++){
printf("message[%d] : 0x%x\n", i, message[i]);
}
fclose (fpIn);
When run the output for some of the bytes have 3 leading ff values:
message[0] : 0x22
message[1] : 0x49
message[2] : 0xffffffe1
message[3] : 0x9
message[4] : 0x62
message[5] : 0x18
message[6] : 0x42
message[7] : 0xffffff8c
message[8] : 0x66
message[9] : 0x10
message[10] : 0xffffffb0
message[11] : 0x11
message[12] : 0xffffff84
message[13] : 0xffffff9c
message[14] : 0x0
message[15] : 0xffffffff
message[16] : 0xffffffe0
message[17] : 0x40
message[18] : 0x1f
message[19] : 0xfffffff8
message[20] : 0x60
message[21] : 0x7
message[22] : 0xfffffffe
message[23] : 0x2c
message[24] : 0x3
message[25] : 0xffffffff
Why do these leading f's occur? for example message[2] : 0xffffffe1
I have tried formatting the output of the printf hex %x with 0x%01x but it makes no difference to the terminal output. Checking the sizeof each element in the char array, they are still 1 byte as expected:
printf("sizeof(message[2]) : %ld\n", sizeof(message[2]) );
%> sizeof(message[2]) : 1
I am now wondering if this is a formatting problem? There does not appear to be any more than 1 byte in each message element (as expected).
Using std::hex with cout produces the same issue.
This is because char is a signed integer on your machine, so 0xFF becomes -1. As %x prints an int, which is 32-bits, it gets sign-extended to 0xFFFFFFFF which is a 32-bit -1.
If you store as an unsigned char, you will not have this problem:
#include <cstdio>
int main() {
unsigned char message[] = {0x22, 0x49, 0xE1, 0x09, 0x62, 0x18, 0x42, 0x8C, 0x66, 0x10, 0xB0, 0x11, 0x84, 0x9C, 0x00, 0xFF, 0xE0, 0x40, 0x1F, 0xF8, 0x60, 0x07, 0xFE, 0x2C, 0x03, 0xFF };
int msgbuflen = sizeof(message)/sizeof(message[0]);
for(int i = 0; i < msgbuflen; i++){
printf("message[%d] : 0x%x\n", i, message[i]);
}
}
Produces:
Program returned: 0
message[0] : 0x22
message[1] : 0x49
message[2] : 0xe1
message[3] : 0x9
message[4] : 0x62
message[5] : 0x18
message[6] : 0x42
message[7] : 0x8c
message[8] : 0x66
message[9] : 0x10
message[10] : 0xb0
message[11] : 0x11
message[12] : 0x84
message[13] : 0x9c
message[14] : 0x0
message[15] : 0xff
message[16] : 0xe0
message[17] : 0x40
message[18] : 0x1f
message[19] : 0xf8
message[20] : 0x60
message[21] : 0x7
message[22] : 0xfe
message[23] : 0x2c
message[24] : 0x3
message[25] : 0xff
Godbolt: https://godbolt.org/z/oxPqnYqMq
Alternatively, you can just cast each char to unsigned char:
for(int i = 0; i < msgbuflen; i++){
printf("message[%d] : 0x%x\n", i, (unsigned char)message[i]);
}
Or in somewhat more current C++ (not using "C" style arrays) and a well defined unsigned 8 bits datatype. (char can be either signed or unsigned depending on the platform you are working on)
#include <array>
#include <iostream>
#include <sstream>
#include <cstdint>
#include <format>
// simulated opening of a std::ifstream
auto open_file()
{
static std::array<std::uint8_t,26> data
{
0x22, 0x49, 0xE1, 0x09, 0x62, 0x18, 0x42, 0x8C, 0x66, 0x10,
0xB0, 0x11, 0x84, 0x9C, 0x00, 0xFF, 0xE0, 0x40, 0x1F, 0xF8,
0x60, 0x07, 0xFE, 0x2C, 0x03, 0xFF
};
std::istringstream is(std::string{ data.begin(), data.end() });
return is;
}
int main()
{
std::array<std::uint8_t, 26> buffer;
auto is = open_file();
// get doesn't have an overload for std::uint8_t*
// so check if sizeof char matches sizeof std::uint8_t
static_assert(sizeof(char) == sizeof(std::uint8_t));
is.get(reinterpret_cast<char*>(buffer.data()), buffer.size());
for (const auto byte : buffer)
{
std::cout << std::format("0x{:x} ", byte);
}
return 0;
}

casting 115bit data to union of bitfields gets erroneous results

I'm trying to cast a 115bit data to a union of bitfields and getting a wrong result.
Setup
I have two types of data:
Configuration: data[62:0]
addr[113:107]
type[114]
RawBits: lowBits[63:0]
highBits[115:64]
So I defined the following bitfields and union:
typedef struct RawBits {
unsigned long int lowBits:64;
unsigned long int highBits:51;
unsigned long int reserved :13;
} __attribute__((packed))rawBits;
typedef struct Configuration {
unsigned long int data : 62;
unsigned long int addr : 7;
unsigned long int type : 1;
unsigned long int reserved : 58;
} __attribute__((packed))Configuration ;
typedef union Instruction {
RawBits bits;
Configuration configuration;
} __attribute__((packed))Instruction;
As data I used:
uint8_t configuration_test[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00,
And to convert the buffer to the union type I used simple casting:
Instruction *instruction = (Instruction *)configuration_test;
Expected result
instruction->bits->lowBits = 0xfffffffffffffffc
instruction->bits->highBits = 0x00000000000001fc
instruction->bits->reserved = 0x0000000000000000
instruction->configuration->data = 0x3fffffffffffffff
instruction->configuration->addr = 0x000000000000007f
instruction->configuration->type = 0x0000000000000000
instruction->configuration->reserved = 0x0000000000000000
Real result
instruction->bits->lowBits = 0xfcffffffffffffff
instruction->bits->highBits = 0x0004010000000000
instruction->bits->reserved = 0x000000000000001f
instruction->configuration->data = 0x3cffffffffffffff
instruction->configuration->addr = 0x0000000000000003
instruction->configuration->type = 0x0000000000000000
instruction->configuration->reserved = 0x0003f00400000000

Allocate a type to a uint8_t value

In my project I read the unique ID from an RFID tag, the result is in the form uint8_t TagRead[4].
The result is compared with a number of predefined tag ID values to establish which tag has been read.
For example:
uint8_t RED1[4] = { 0x73, 0xD5, 0xB7, 0xAC };
uint8_t RED2[4] = { 0x7E, 0x27, 0x49, 0x4E };
uint8_t RED3[4] = { 0x02, 0xFD, 0x06, 0x40 };
uint8_t GREEN1[4] = { 0xAB, 0xEC, 0x68, 0x80 };
uint8_t GREEN2[4] = { 0xEE, 0x20, 0x50, 0x4E };
uint8_t GREEN3[4] = { 0x27, 0x06, 0x40, 0x73 };
if (*((uint32_t *)TagRead) == *((uint32_t *)RED2)) {
// RED2 tag has been read
}
else if (*((uint32_t *)TagRead) == *((uint32_t *)GREEN3)) {
// GREEN3 tag has been read
}
My question relates to being able to assign a type/category to a group of tags so that an action can be performed based on the colour of the tag that has been scanned.
It may be that when a RED tag is scanned we switch on a red LED and when a GREEN tag is scanned we switch on a blue LED.
Because there are approximately 50 tags of each colour, I don't want to to have to list all the tag names in the If statement. Instead, is it possible to assign the colour to the tag?
It would then be possible to do:
If scanned tag is of type RED, do red action.
If scanned tag is of type GREEN do green action.
Thanks for your help.
You can create a structure with id and a color enum:
enum class Color { red, green };
struct Tag
{
uint8_t id[4];
Color color;
};
Tag RED1 = { { 0x73, 0xD5, 0xB7, 0xAC }, Color::red } ;
Tag RED2 = { { 0x7E, 0x27, 0x49, 0x4E }, Color::red } ;
Tag RED3 = { { 0x02, 0xFD, 0x06, 0x40 }, Color::red } ;
Tag GREEN1 = { { 0xAB, 0xEC, 0x68, 0x80 }, Color::green } ;
Tag GREEN2 = { { 0xEE, 0x20, 0x50, 0x4E }, Color::green } ;
Tag GREEN3 = { { 0x27, 0x06, 0x40, 0x73 }, Color::green } ;
void test(Tag tag)
{
if (tag.color == Color::red)
{
//
}
else if (tag.color == Color::green)
{
}
}
First, your comparison is undefined behaviour. The right way to go is with a std::memcmp. You also need to take care of endianness.
In order to attach properties (like color) to your tags, simply define a struct:
struct rfid_tag
{
uint8_t value[4];
enum { ... } color;
};
Once you got a struct, you can enrich it with operator== so you can use std::find() to lookup the appropriate tag in one line:
#include <iostream>
#include <array>
#include <algorithm>
#include <cstring>
struct rfid_tag
{
enum color_type { red = 10, blue = 11 };
std::array<uint8_t, 4> value;
color_type color;
};
bool operator==(std::array<uint8_t, 4> const& tagvalue, rfid_tag const& rhs)
{
return std::memcmp(tagvalue.data(), rhs.value.data(), rhs.value.size()) == 0;
}
bool operator==(rfid_tag const& lhs, std::array<uint8_t, 4> const& tagvalue)
{
return tagvalue == lhs;
}
static const std::array<rfid_tag, 3> known_tags = {
rfid_tag{ { 0x00, 0x01, 0x02, 0x03 }, rfid_tag::red },
rfid_tag{ { 0x10, 0x11, 0x12, 0x13 }, rfid_tag::blue },
rfid_tag{ { 0x20, 0x21, 0x22, 0x23 }, rfid_tag::red }
};
int main()
{
const std::array<uint8_t, 4> tag_to_find{ 0x10, 0x11, 0x12, 0x13 };
std::cout << std::find(begin(known_tags), end(known_tags), tag_to_find)->color << "\n"; // outputs "11" as expected
}
demo
There are multiple ways.
You could write a struct which contains your tag along with your color, like this:
struct ColoredTag
{
uint8_t[4] value;
std::string color;
} typename ColoredTag_t;
ColoredTag_t RED1 = {{ 0x73, 0xD5, 0xB7, 0xAC }, "Red"};
ColoredTag_t RED2 = {{ 0x7E, 0x27, 0x49, 0x4E }, "Red"};
ColoredTag_t RED3 = {{ 0x02, 0xFD, 0x06, 0x40 }, "Red"};
ColoredTag_t GREEN1 = {{ 0xAB, 0xEC, 0x68, 0x80 }, "Green"};
ColoredTag_t GREEN2 = {{ 0xEE, 0x20, 0x50, 0x4E }, "Green"};
ColoredTag_t GREEN3 = {{ 0x27, 0x06, 0x40, 0x73 }, "Green"};
Or, you can use a std::map to assign a color to a tag, like this
std map<uint8_t[4], std::string> tags;
public void fillTags()
{
tags[RED1] = "Red";
tags[RED2] = "Red";
//...
}
std::string getColor(uint8_t tag)
{
return tags[tag];
}
There might be some more solutions for this issue, but these are the ones that came to my mind first.

Function returning wrong value in lpc824

I am working on porting an application running on Arduino Mega to LPC824. The following piece of code is working differently for both the platforms.
/**
* Calculation of CMAC
*/
void cmac(const uint8_t* data, uint8_t dataLength) {
uint8_t trailer[1] = {0x80};
uint8_t bytes[_lenRnd];
uint8_t temp[_lenRnd];
memcpy(temp, data, dataLength);
concatArray(temp, dataLength, trailer, 1);
dataLength ++;
addPadding(temp, dataLength);
memcpy(bytes, _sk2, _lenRnd);
xorBytes(bytes,temp,_lenRnd);
aes128_ctx_t ctx;
aes128_init(_sessionkey, &ctx);
uint8_t* chain = aes128_enc_sendMode(bytes, _lenRnd, &ctx, _ivect);
Board_UARTPutSTR("chain\n\r");
printBytes(chain, 16, true);
memcpy(_ivect, chain, _lenRnd);
//memcpy(_ivect, aes128_enc_sendMode(bytes,_lenRnd,&ctx,_ivect), _lenRnd);
memcpy(_cmac,_ivect, _lenRnd);
Board_UARTPutSTR("Initialization vector\n\r");
printBytes(_ivect, 16, true);
}
I am expecting a value like {0x5d, 0xa8, 0x0f, 0x1f, 0x1c, 0x03, 0x7f, 0x16, 0x7e, 0xe5, 0xfd, 0xf3, 0x45, 0xb7, 0x73, 0xa2} for the chain variable. But the follow function is working differently. The print inside the function has the correct value which I want ({5d, 0xa8, 0x0f, 0x1f, 0x1c, 0x03, 0x7f, 0x16, 0x7e, 0xe5, 0xfd, 0xf3, 0x45, 0xb7, 0x73, 0xa2}).
But when the function returns chain is having a different value, compared to what I am expecting, I get the following value for chain {0x00, 0x20, 0x00, 0x10, 0x03, 0x01, 0x00, 0x00, 0xd5, 0x00, 0x00, 0x00, 0xd7, 0x00, 0x00, 0x00}
Inside the function, the result is correct. But it returns a wrong value to the function which called it. Why is it happening so ?
uint8_t* aes128_enc_sendMode(unsigned char* data, unsigned short len, aes128_ctx_t* key,
const unsigned char* iv) {
unsigned char tmp[16];
uint8_t chain[16];
unsigned char c;
unsigned char i;
memcpy(chain, iv, 16);
while (len >= 16) {
memcpy(tmp, data, 16);
//xorBytes(tmp,chain,16);
for (i = 0; i < 16; i++) {
tmp[i] = tmp[i] ^ chain[i];
}
aes128_enc(tmp, key);
for (i = 0; i < 16; i++) {
//c = data[i];
data[i] = tmp[i];
chain[i] = tmp[i];
}
len -= 16;
data += 16;
}
Board_UARTPutSTR("Chain!!!:");
printBytes(chain, 16, true);
return chain;
}
A good start with an issue like this is to delete as much as you can while reproducing the error, with a minimal code example the answer is typically clear. I have done that for you here.
uint8_t* aes128_enc_sendMode(void) {
uint8_t chain[16];
return chain;
}
The chain variable is a local to the function, it ceases to be defined once the function exists. Accessing a pointer to that variable causes undefined behaviour, don't do it.
In practice the pointer to the array still exists and points to an arbitrary block of memory. This block of memory is no longer reserved and can be overwritten at any time.
I suspect it works for the AVR because it is a simple 8 bit chip and that piece of memory was sitting unmolested by the time you used it. The ARM would have used greater optimisations, possibly running the full array on registers, so the data doesn't survive the transition.
tldr; You need to malloc() any arrays that you want to live past the function's exit. Be careful, malloc and embedded systems go together like diesel and styrofoam, it gets messy real quick.

Send Hex Bytes To A Serial Port

I am attempting to send hexadecimal bytes to a serial com port. The issue is that the segment that sends the command apparently wants a system string instead of an integer (error C2664 "cannot convert parameter 1 from 'int' to 'System::String ^'). I have looked for a way to send an integer instead but have had no luck. (I have tried sending string representations of the hexadecimal values, but the device did not recognize the commands)
Main part of Code
private: System::Void poll_Click(System::Object^ sender, System::EventArgs^ e)
{
int i, end;
double a = 1.58730159;
String^ portscan = "port";
String^ translate;
std::string portresponse [65];
std::fill_n(portresponse, 65, "Z");
for (i=1;i<64;i++)
{
if(this->_serialPort->IsOpen)
{
// Command 0 generator
int y = 2;
y += i;
int command0[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, dectohex(i), 0x00, 0x00, dectohex(y)};
for (end=0;end<10;end++)
{
this->_serialPort->WriteLine(command0[end]);
}
translate = (this->_serialPort->ReadLine());
MarshalString(translate, portresponse [i]);
if(portresponse [i] != "Z")
{
comboBox7->Items->Add(i);
}
this->progressBar1->Value=a;
a += 1.58730159;
}
}
}
Here is the function dectohex:
int dectohex(int i)
{
int x = 0;
char hex_array[10];
sprintf (hex_array, "0x%02X", i);
string hex_string(hex_array);
x = atoi(hex_string.c_str());
return x;
}
This is what solved my problem, courtesy of Jochen Kalmbach
auto data = gcnew array<System::Byte> { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x00, 0xBD };
_serialPort->Write(data, 0, data->Length);
Replaced this
this->_serialPort->WriteLine(command0[end]);
You cannot sent an integer over a serial line.... you can only sent BYTES (7-8 bit)!
You need to choose what you want to do:
Sent characters: So the "number" 12 will be converted into the bytes
_serialPort->Write(12.ToString());
// => 0x49, 0x50
Sent the integer (4 bytes) as little endian
auto data = System::BitConverter::GetBytes(12);
_serialPort->Write(data, 0, data->Length);
// => 0x0c, 0x00, 0x00, 0x00
Or you write just a single byte:
auto data = gcnew array<System::Byte> { 12 };
_serialPort->Write(data, 0, data->Length);
// => 0x0c
Or write an byte array:
auto data = gcnew array<System::Byte> { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02, 0xBF, 0x00, 0x00, 0xBD };
_serialPort->Write(data, 0, data->Length);
// => 0xFF 0xFF 0xFF 0xFF 0xFF 0x02 0xBF 0x00 0x00 0xBD