zLib inflate() hangs while uncompressing buffer - zlib

I use zLib 1.2.7, taken from here. I have compiled it in Microsoft Visual Studio 2010 as a static library and added it to my project.
I need to decompress some binary data compressed with deflate algorithm. Here it is:
unsigned char rawData[114] =
{
0x00, 0x00, 0x00, 0x00, 0x15, 0x82, 0x05, 0x9D, 0x62, 0x91, 0x9A, 0x86, 0x26, 0xF3, 0x45, 0xBF,
0xE1, 0x69, 0x19, 0xA8, 0x80, 0x21, 0x08, 0x43, 0xF1, 0xEF, 0xCC, 0x01, 0x68, 0x4E, 0x3C, 0x06,
0x59, 0x6D, 0x90, 0xB2, 0x1F, 0xC3, 0x87, 0xC2, 0xBF, 0xC0, 0x90, 0xBE, 0x1F, 0x11, 0xB6, 0xD7,
0xB7, 0x06, 0x18, 0x32, 0x5F, 0x80, 0x8F, 0x09, 0xF1, 0x81, 0xF2, 0xB8, 0xC8, 0x9E, 0x71, 0xB7,
0xC9, 0x73, 0x7E, 0x88, 0x02, 0xD0, 0x9C, 0x65, 0xB0, 0x34, 0xD3, 0x97, 0x33, 0xE8, 0x80, 0x2D,
0x09, 0xC6, 0x5B, 0x03, 0x4D, 0x39, 0x73, 0x74, 0x1B, 0xAD, 0x19, 0x9D, 0xF0, 0xCA, 0x6F, 0xBD,
0xA4, 0xD5, 0x33, 0x6E, 0xDF, 0x1F, 0x11, 0x8A, 0xC5, 0xA2, 0x1C, 0x99, 0xE2, 0xDB, 0xBF, 0x7C,
0x0E, 0x8B
};
This block of data was captured from SPDY session. And this is my uncompress code (SPDY_dictionary_txt can be found on previous link):
INT APIENTRY WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd )
{
z_stream zStream = { 0 };
DWORD Length = sizeof(rawData);
zStream.zalloc = Z_NULL;
zStream.zfree = Z_NULL;
zStream.opaque = Z_NULL;
inflateInit(&zStream);
zStream.avail_in = Length;
zStream.next_in = rawData;
DWORD dwUsed = 0;
DWORD dwSize = 5 * 1024;
LPBYTE lpDecompressed = NULL;
BOOL triedDictionary = FALSE;
BOOL uncompressed = TRUE;
lpDecompressed = (LPBYTE)calloc(dwSize, 1);
do
{
zStream.next_out = (LPBYTE)((DWORD_PTR)lpDecompressed + dwUsed);
zStream.avail_out = dwSize - dwUsed;
int zlib_rv = inflate(&zStream, Z_NO_FLUSH); // <-- THIS HANGS!
if (zlib_rv == Z_NEED_DICT)
{
if (triedDictionary)
{
uncompressed = FALSE;
break;
}
triedDictionary = TRUE;
inflateSetDictionary(&zStream, SPDY_dictionary_txt, sizeof(SPDY_dictionary_txt));
}
if (zlib_rv < 0)
{
uncompressed = FALSE;
break;
}
dwUsed += dwSize - dwUsed - zStream.avail_out;
}
while (zStream.avail_in);
if(!uncompressed)
{
OutputDebugString("Could not decompress buffer.\n");
}
else
{
OutputDebugString("Buffer was decompressed.\n");
}
Sleep(1000);
return 0;
}
I started to debug this code and found out that it hangs on the first inflate() call. What is this? Is this a bug in zLib or maybe my code is wrong?

The code you downloaded is not the original zlib code. It was modified by someone to compile "without warnings and errors" and bugs may have been introduced in the process. You need to download the original and correct code from zlib.net. The code you downloaded has, for example, a commit on May 31, 2014 with the log message "Corrected infinite loop errors in inflate.c and infback.c". You should be more careful about downloading code from strangers.
Note that the data provided in the question is not the result of zlib compression, and would be immediately rejected by inflate() upon reading the first two bytes as not even being a zlib header. You must be using some other input data to get your code to "hang". You need to provide the actual data that caused the issue in order for anyone to be able to help you.
About your code: you do not need to update next_out and avail_out inside the loop as you are doing, since inflate() already does that. You can compute dwUsed when the loop exits as dwSize - zStream.avail_out. You also need to check the return code from inflate() to make sure that it returns Z_STREAM_END when done, otherwise the stream was not complete. You should not abort on Z_BUF_ERROR, but rather provide more output space or more input. See this example for how inflate() and deflate() are used, and read the documentation in zlib.h.

Related

I am printing list of Latin letters of ogonek in c using unicode

#include <stdio.h>
#include <wchar.h>
#include <locale.h>
int main()
{ int i;
setlocale(LC_CTYPE,"de_DE.UTF-8");
wchar_t cA[256] = {
0xC498, 0xC4AE, 0xC5B2, 0xC482, 0xC496, 0xC48E, 0xC898, 0xC89A, 0xC48A, 0xC4A0, 0xC4B9, 0xC5BB, 0xC7B8, 0xC485, 0xC499, 0xCAF,
0xC5B3, 0xC483, 0xC497, 0xC48F, 0xC899, 0xC89B, 0xC48B, 0xC587, 0xC49A, 0xC4A1, 0xC4BA, 0xC5BC, 0x20, 0x21, 0x22, 0x23,
0xC582, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0X3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43,
0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53,
0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0xE1B5BE, 0x5D, 0xC581, 0x5F, 0xC484, 0x61, 0x62, 0x63,
0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73,
0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xC2AB, 0xC5AF, 0xC2BB, 0x013D, 0XC4A6,0xC3A1, 0xC3A0, 0xC3A9, 0xC3A8, 0xC3AD, 0xC3AC, 0xC3B3, 0xC3B2, 0xC3BA, 0xC3B9, 0xC391, 0xC387, 0xC59E, 0xC39F, 0xC2A1, 0xC5B8,
0xC3A2, 0xC3A4, 0xC3AA, 0xC3AB, 0xC3AE, 0xC3AF, 0xC3B4, 0xC3B6, 0xC3BB, 0xC3BC, 0xC3B1, 0xC3A7, 0xC59F, 0xC49F, 0xC4B1, 0xC3BF,
0xC4B6, 0xC585, 0xC2A9, 0xC4A2, 0xC49E, 0xC49B, 0xC588, 0xC591, 0xC590, 0xE282AC, 0xC2A3, 0x24, 0xC480, 0xC492, 0xC4AB, 0XC5AA,
0xC4B7, 0xC2B9, 0xC4BB, 0xC4A3, 0xC4BC, 0xC4B0, 0xC584, 0xC5B1, 0xC5B0, 0xC2BF, 0xC4BE, 0xC2B0, 0xC481, 0xC493, 0xC4AB, 0xC5AB,
0xC381, 0xC380, 0xC389, 0xC388, 0xC38D, 0xC38C, 0xC393, 0xC392, 0xC39A, 0xC399, 0xC598, 0xC48C, 0xC5A0, 0xC5BD, 0xC390, 0xC4BF,
0xC382, 0xC384, 0xC38A, 0xC38B, 0xC38E, 0xC38F, 0xC394, 0xC396, 0xC39B, 0xC39C, 0xC599, 0xC48D, 0xC5A1, 0xC5BE, 0xC491, 0xC580,
0xC383, 0xC385, 0xC386, 0xC592, 0xC5B7, 0xC39D, 0xC395, 0xC398, 0xC39E, 0xC58A, 0xC594, 0xC486, 0xC59A, 0xC5B9, 0xC5A6, 0xC3B0,
0xC3A3, 0xC3A5, 0xC3A6, 0xC593, 0xC5B5, 0xC3BD, 0xC3B5, 0xC3B8, 0xC3BE, 0xC58B, 0xC595, 0xC487, 0xC59B, 0xC5BA, 0xC5A7, 0xC4A7,
};
for( i=0;i<252;i++){
wprintf(L"%lc\n", (unsigned char)cA[i]);
}
return 0;
}
I have tried by writing setlocale, but even though it is showing different symbols.I need it to print the correct symbols. Eg. for 0xC498 it is printing ÿ instead of Ę.
In the function wprintf, you are typecasting the wchar_t
(equivalent to uint16_t) to unsigned char (equivalent to
uint8_t). Hence, you are losing half of the information every time
you are printing something.
I think you have an incorrect set of uni-code for the Latin characters. Please follow the chart https://en.wikipedia.org/wiki/Latin_script_in_Unicode and try again.
Meanwhile, wprintf(L"%lc\n", (wchar_t)0x0118); will give you the character you are looking for.

Shellcode crashing target PE

I am currently attempting to patch a target x86 PE file from the disk with a tool, patch.exe.
purpose
The purpose of this tool will be to eventually write/insert a multi-function payload into the target executable, who's purpose is to track the position of certain frames inside a game which I created.
background
I am doing this by mapping the file into memory with PAGE_READWRITE protection flag. After locating the RVA of foobar(...) function from memory, I am replacing the call to this function with a JMP (0xE9) instruction followed by the RVA of the payload shellcode (which is previously appended to a new section I have created within the target PE file beforehand).
When the shellcode simply contains the following bytes
unsigned char shellcode[16] = {0x33, 0xc0, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc}
which translates to the following C function
unsigned long basic_ret() { return 0; }
the target executable successfully executes
problem
however, if I try to include another function (0xDEADBEEF) within the code
unsigned char shellcode[32] =
{
0x6a, 0x0b, 0x68, 0x9c, 0xc2, 0xf4, 0x00, 0x6a, 0x0a, 0x68, 0xa8, 0xc2, 0xf4, 0x00, 0x68, 0xb4,
0xc2, 0xf4, 0x00, 0xb8, 0xef, 0xeb, 0xda, 0xed, 0xff, 0xd0, 0x83, 0xc4, 0x14, 0xc3, 0xcc, 0xcc
};
which translates to the following C function (a simple JMP taking 3 arguments on the stack, to another function)
int simple_jmp()
{
typedef int (*_jmp_target)(void*, int, void*);
_jmp_target jmp_target = (_jmp_target) 0xDEADBEEF;
return jmp_target (0, 5, 0);
}
where jmp_target is filled by patch.exe with the RVA to a function previously referred to, which was inserted into the new section of the target PE.
When the the target executable is executed, this time, it reaches some type of violation/crash (confirmed by the presence of WerFault.exe alongside its execution).
What is the reason for this problem, what am I missing?
diagnostics
When I observe the patched bytes in memory (of the mapped PE file), I can see that 0xdeadbeef is replaced by 0x0dc3f4de which is the same address from which the inserted function shellcode starts. At this point, I assumed there would be no crash, little to my surprise - crash!

how to print the s_uuid of ext2 superblock in C

I create a variable to store the value of superblock's s_uuid. But I get trouble into how to print this variable like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx in this form. I tried to use printf in %x and %s to print my variable, but it doesn't work.
I want to know how the UUID stores in file system and how I can print it in console instead of wrong encoding.
The s_uuid is defined in the superblock as:
u8 s_uuid[16];
In order to print this to the console in the above format:
uint8_t s_uuid[16] = {0xf3, 0x58, 0x6b, 0xaf, 0xb5, 0xaa, 0x49, 0xb5,
0x8d, 0x6c, 0x05, 0x69, 0x28, 0x4c, 0x63, 0x9f};
printf("%02x%02x%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
s_uuid[0], s_uuid[1], s_uuid[2], s_uuid[3], s_uuid[4], s_uuid[5], s_uuid[6], s_uuid[7],
s_uuid[8], s_uuid[9], s_uuid[10], s_uuid[11], s_uuid[12], s_uuid[13], s_uuid[14], s_uuid[15]);

ARM: reading modbus data through UART fails

I am trying to read a register from an RS485 adapter using a UART connection on an ARM board with no success
Machines
ARM board: CM-T335 - TI AM335x Computer-on-Module http://www.compulab.co.il/products/computer-on-modules/cm-t335/
PC: x86 machine running Ubuntu
Slave device: Elnet Pico (Energy power meter) - works as a modbus slave and sends energy statuses to master when requested using the modbus protocol http://elnet.feniks-pro.com/documents/User_manual/Elnet%20Pico%20-%20User%20Manual.pdf
Connectors
RX/TX cable
SENA RS485 adapter: http://www.senanetworks.com/download/datasheet/ds_ltc100.pdf
Male - Male COM adapter: http://i.ebayimg.com/images/i/300758549547-0-1/s-l1000.jpg
ultra mini serial to DB9 cable: https://cdn3.yawarra.com.au/wp-content/uploads/Ultra-mini-serial-DB9-adapter_600x600.jpg
Slave device connected to ARM board
Energy power meter <--rx/tx cable--> SENA RS485 Adapter <--Serial Male/Male adapter + Serial to mini serial cable --> ARM board mini-serial port
see images of the setup:
https://ibin.co/3CCvTVPPIUWQ.jpg
https://ibin.co/3CCvhrr3CQjr.jpg
https://ibin.co/3CCw5uNqTW8B.jpg
https://ibin.co/3CCvuys1tUgt.jpg
Device tree used: am335x-sbc-t335.dts
Device tree resources: http://get-album.com/dts/
Slave device connected to PC
Energy power meter <--2 wire rx/tx--> SENA RS485 Adapter <--> PC
note: The mini serial port on the board is the same port that is used for serial-console communication (on baud 115200) - and this works with no problems
Below is a c code that reads the first register from the connected slave device with the use of libmodbus library
libmodbus_test.c - reading and printing the first reigster from the device:
#include <sys/types.h>
#include <string.h>
#include <modbus.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define MODBUS_DEVICE "/dev/ttyS2"
#define MODBUS_STOP_BIT 1
#define MODBUS_DATA_BIT 8
#define MODBUS_START_BIT 1
#define MODBUS_PARITY 'N'
int main(int argc, char *argv[]) {
const char *dev_path = MODBUS_DEVICE;
uint16_t result[2];
int slave_nr = 31, baud = 9600;
modbus_t *mb;
if (argc == 2) {
dev_path=argv[1];
}
mb = modbus_new_rtu(dev_path, baud, MODBUS_PARITY, MODBUS_DATA_BIT, MODBUS_STOP_BIT);
if (mb == NULL) {
printf("error creating libmodbus rtu\n");
return -1;
}
printf("created new rtu...\n");
modbus_set_debug(mb, 1);
if (modbus_connect(mb) < 0 ){
printf("modbus error: %s\n", modbus_strerror(errno));
modbus_close(mb);
modbus_free(mb);
return -1;
}
modbus_set_slave(mb, slave_nr);
printf("ModBus connected !\n");
if (modbus_read_registers(mb, 0x1, 2, result) < 0) {
printf("error reading bits: %s\n", modbus_strerror(errno));
modbus_close(mb);
modbus_free(mb);
return -1;
}
printf("successfully red integer: %d: %X (hex)\n", result[0], result[0]);
modbus_free(mb);
return 0;
}
[output from running libmodbus_test on PC]
root#cm-debian:~/new# modbus gcc -I /usr/local/include/modbus libmodbus_test.c -o libmodbus_test -lmodbus
root#cm-debian:~/new# ./libmodbus_test /dev/ttyS2
created new rtu...
Opening /dev/ttyS2 at 9600 bauds (N, 8, 1)
ModBus connected !
[1F][03][00][01][00][02][96][75]
Waiting for a confirmation...
<1F><03><04><00><DD><00><DD><54><51>
successfully red integer: 221: DD (hex)
[output from running libmodbus_test on the ARM board]
root#cm-debian:~/new# gcc -I /usr/include/modbus/ libmodbus_test.c -o libmodbus_test -lmodbus
root#cm-debian:~/new# ./libmodbus_test /dev/ttyO0
created new rtu...
Opening /dev/ttyO0 at 9600 bauds (N, 8, 1)
ModBus connected !
[1F][03][00][01][00][02][96][75]
Waiting for a confirmation...
ERROR Connection timed out: select
when executing libmodbus_test from the ARM board, select() always returns 0
while running the same program on PC, it works just fine => the slave device returns data.
An attempt using termios also failed with similar results
termios_test.c
#include <sys/select.h>
#include <termios.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <string.h>
#include <stdint.h>
#include <linux/serial.h>
#include <sys/ioctl.h>
static const uint8_t table_crc_hi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
};
/* Table of CRC values for low-order byte */
static const uint8_t table_crc_lo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};
void calc_crc(uint8_t *buffer, ssize_t length, uint8_t *crc_hi_arg, uint8_t *crc_lo_arg) {
uint8_t crc_hi = 0xff;
uint8_t crc_lo = 0xff;
unsigned int i;
while (length--) {
i = crc_hi ^ *buffer++;
crc_hi = crc_lo ^ table_crc_hi[i];
crc_lo = table_crc_lo[i];
}
*crc_hi_arg = crc_hi;
*crc_lo_arg = crc_lo;
}
int main(int argc, char **argv){
char *dev_path = "/dev/ttyS2";
if (argc == 2) {
dev_path = argv[1];
}
uint8_t write_data[8];
int fd,write_len,select_ret, bytes_avail, status;
struct termios config;
char c;
uint8_t crc_hi, crc_lo;
fd_set activefs, tmpfs;;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec= 500000;
fd = open(dev_path, O_RDWR | O_NOCTTY | O_NDELAY | O_EXCL);
if (fd == -1){
perror("open");
return 1;
}
FD_ZERO(&tmpfs);
FD_SET(fd, &tmpfs);
printf("opened device\n");
if (tcgetattr(fd, &config) < 0) { close(fd); return -1 }
if (cfsetispeed(&config, B9600) < 0 || cfsetospeed(&config, B9600) < 0) {
printf("cant setting speed!\n");
close(fd);
return 1;
}
config.c_cflag |= (CREAD | CLOCAL);
config.c_cflag &=~ CSIZE;
config.c_cflag &=~ CSTOPB;
config.c_cflag &=~ PARENB;
config.c_cflag |= CS8;
config.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
config.c_iflag &= ~INPCK;
config.c_iflag &= ~(IXON | IXOFF| IXANY);
config.c_oflag &= ~OPOST;
config.c_cc[VMIN] = 0;
config.c_cc[VTIME] = 0;
if (tcsetattr(fd, TCSANOW, &config) < 0) {
printf("cant apply config!\n");
close(fd);
return 1;
}
write_data[0] = 0x1f; // slave addr
write_data[1] = 0x03; // function
write_data[2] = 0x00; // data address of first coil (8b)
write_data[3] = 0x01; // data address of first coil (8b)
write_data[4] = 0x00; // num of coils requested
write_data[5] = 0x01; // num of coils requested
calc_crc(write_data, 6, &crc_hi, &crc_lo);
write_data[6] = crc_hi;
write_data[7] = crc_lo;
printf("data: [0x%x][0x%x][0x%x][0x%x][0x%x][0x%x][0x%x][0x%x]", write_data[0], write_data[1], write_data[2], write_data[3], write_data[4], write_data[5], write_data[6], write_data[7]);
while (1) {
sleep(1);
write_len= write(fd, write_data, 8);
activefs = tmpfs;
select_ret = select(1, &activefs, NULL, NULL, &timeout);
if (select_ret < 0) {
perror("select");
return 1;
}
if (select_ret > 0) {
printf("select returned %d\n", select_ret);
if (read(fd, &c, 1) < 0) {
perror("read");
} else {
printf("received: %d\n", c);
}
}
}
}
[output from termios.c on the ARM board]
root#cm-debian:~/new# ./termios /dev/ttyO0
opened device
... select keeps returning 0
[output from termios.c on PC]
$ gcc -o termios_test termios_test.c
$ ./termios_test /dev/ttyS2
opened device
data: [0x1f][0x3][0x0][0x1][0x0][0x1][0xd6][0x74]select returned 1
received: 31
select returned 1
Never mind the values, there IS a data exchange and that's what I want to achieve using the board
I tried passing RS485 attributes via pcntl, but the same results happened
termios_rs485_test.c: http://pastebin.com/RWtHtjLF
The connection between the board and the PC is done through the ultra mini serial to DB9 cable and I can successfully read/write data from and to the board. How come reading data from the RS485 adapter never succeeds? where should I be looking in order to get closer a solution?
Here are some info about the board / drivers / etc
root#cm-debian:~/modbus# uname -a
Linux cm-debian 4.4.0-cm-t335-5.1 #98 SMP Thu Sep 1 15:12:31 IDT 2016 armv7l GNU/Linux
root#cm-debian:~/new# dmesg | grep -i --color '\(serial\|tty\|uart\)'
[ 0.000000] Kernel command line: console=ttyO0,115200n8 root=ubi0:rootfs rw rootfstype=ubifs ubi.mtd=rootfs
[ 0.771007] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
[ 0.780286] omap_uart 44e09000.serial: no wakeirq for uart0
[ 0.780329] of_get_named_gpiod_flags: can't parse 'rts-gpio' property of node '/ocp/serial#44e09000[0]'
[ 0.780960] 44e09000.serial: ttyO0 at MMIO 0x44e09000 (irq = 155, base_baud = 3000000) is a OMAP UART0
[ 1.543031] console [ttyO0] enabled
[ 1.550036] omap_uart 48022000.serial: no wakeirq for uart1
[ 1.556099] of_get_named_gpiod_flags: can't parse 'rts-gpio' property of node '/ocp/serial#48022000[0]'
[ 1.556764] 48022000.serial: ttyO1 at MMIO 0x48022000 (irq = 156, base_baud = 3000000) is a OMAP UART1
[ 2.953486] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
[ 2.973176] usb usb1: SerialNumber: musb-hdrc.0.auto
[ 3.572722] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 6.689030] systemd[1]: Expecting device dev-ttyO0.device...
[ 7.210727] systemd[1]: Starting system-getty.slice.
[ 7.235407] systemd[1]: Created slice system-getty.slice.
[ 7.241302] systemd[1]: Starting system-serial\x2dgetty.slice.
[ 7.265277] systemd[1]: Created slice system-serial\x2dgetty.slice.
[ 7.925632] systemd[1]: Starting LSB: controls configuration of serial ports...
[ 8.485680] systemd[1]: Started LSB: controls configuration of serial ports.
[ 14.840532] pinctrl-single 44e10800.pinmux: pin 44e10978.0 already requested by 48022000.serial; cannot claim for 481cc000.can
[ 14.895866] pinctrl-single 44e10800.pinmux: pin 44e10980.0 already requested by 48022000.serial; cannot claim for 481d0000.can
root#cm-debian:~/modbus# setserial -a /dev/ttyO0
/dev/ttyO0, Line 0, UART: undefined, Port: 0x0000, IRQ: 155
Baud_base: 3000000, close_delay: 50, divisor: 0
closing_wait: 3000
Flags: spd_normal
root#cm-debian:~/new# setserial -a /dev/ttyS2
/dev/ttyS2, Line 2, UART: unknown, Port: 0x0000, IRQ: 0
Baud_base: 0, close_delay: 50, divisor: 0
closing_wait: 3000
Flags: spd_normal
root#cm-debian:~/new# setserial -a /dev/ttyS1
/dev/ttyS1, Line 1, UART: unknown, Port: 0x0000, IRQ: 0
Baud_base: 0, close_delay: 50, divisor: 0
closing_wait: 3000
Flags: spd_normal
root#cm-debian:~/new# setserial -a /dev/ttyS0
/dev/ttyS0, Line 0, UART: unknown, Port: 0x0000, IRQ: 0
Baud_base: 0, close_delay: 50, divisor: 0
closing_wait: 3000
Flags: spd_normal
root#cm-debian:~/modbus# lsmod
Module Size Used by
sha256_generic 9731 1
hmac 2866 1
drbg 13731 1
ctr 3673 2
ccm 7928 2
arc4 2000 2
wl12xx 57190 0
wlcore 180594 1 wl12xx
mac80211 605465 2 wl12xx,wlcore
cfg80211 492985 2 mac80211,wlcore
snd_soc_davinci_mcasp 15953 2
snd_soc_tlv320aic23_i2c 2092 1
snd_soc_simple_card 7474 0
snd_soc_tlv320aic23 10191 1 snd_soc_tlv320aic23_i2c
snd_soc_edma 1309 1 snd_soc_davinci_mcasp
snd_soc_core 158330 5 snd_soc_davinci_mcasp,snd_soc_edma,snd_soc_tlv320aic23_i2c,snd_soc_tlv320aic23,snd_soc_simple_card
snd_pcm_dmaengine 5548 1 snd_soc_core
snd_pcm 92743 4 snd_soc_davinci_mcasp,snd_soc_core,snd_soc_tlv320aic23,snd_pcm_dmaengine
c_can_platform 6650 0
c_can 9638 1 c_can_platform
wlcore_spi 5086 0
can_dev 12315 1 c_can
ti_am335x_adc 5635 0
snd_timer 21413 1 snd_pcm
kfifo_buf 3452 1 ti_am335x_adc
snd 55936 3 snd_soc_core,snd_timer,snd_pcm
industrialio 40286 2 ti_am335x_adc,kfifo_buf
evdev 13187 0
omap_wdt 5293 0
soundcore 1339 1 snd
root#cm-debian:~/new# cat /proc/cpuinfo
processor : 0
model name : ARMv7 Processor rev 2 (v7l)
BogoMIPS : 597.60
Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x3
CPU part : 0xc08
CPU revision : 2
Hardware : Generic AM33XX (Flattened Device Tree)
Revision : 0000
Serial : 0000000000000000
root#cm-debian:~/new# cat /proc/consoles
ttyO0 -W- (EC p ) 250:0
root#cm-debian:/etc# cat debian_version
8.2
Any help is well appreciated
Thanks
UPDATE
While the ultra mini serial to DB9 cable is connected to the board, I ran termios_test.c and while running, I inserted a metal piece in the middle pin of the cable (the TX) and I could see garbage data showing on the screen (sometimes!). I plugged the male-male adapter to the cable and touched the middle pin again, and I could see garbage data again.
Another thing I've done is connecting the slave device to to the SENA RS485 adapter, and use the metal piece on the pins, the middle pin of the adapter, when touching the metal, makes the TX led turn on. no pins would turn on the RX led. When connecting that RS485 adapter to the PC's COM port, sending data to that port would make the RX led flash. I am beginning to suspect that the board is not writing to the RS485 adapter correctly, or that pins are not mapped correctly. Where should I go from here? might this be really a software issue?
There are two software issues found in the termios_test.c. First issue was related to missed tcgetattr(). Second one is what the first parameter to select() must be 1, not fd+1. Now they fixed and the code still don't work with SENA RS485.
Artless Noise suggested to connect ARM board to PC and check if UART on ARM board is properly configured. Smokie connected ARM to PC using ultra mini serial to DB9 cable and confirmed that termios_test.c can send and receive data to windows PC.
For now, I assumed than the problem is with physical connection of ARM to SENA. Ultra mini serial to DB9 cable used to connect ARM to PC is a crosscable. It connect ARM RX pin to PC TX pin and vice versa. SENA RS485 adapter is intended to be connected to PC directly without any cables. It has direct connetion: PC TX pin connected to SENA TX pin and PC RX pin to SENA RX pin. ARM is connected to SENA using ultra mini serial to DB9 cable and male - male COM adapter. Male - Male COM adapter doesn't change pin order, so TX pin became TX pin. So in the connection ARM TX pin became wrong connected to SENA RX pin.
In order to make schematic work, COM null modem cable must be used instead of Male - Male COM adapter. It basic pinout might be following:
ARM side SENA side
TXT pin 3 <--> RXD pin 2
RXD pin 2 <--> TXT pin 3
GND <--> GND
RTS pin 7 (leave unconnected) +-> RTS pin 7
|
CTS pin 8 (leave unconnected) +-> CTS pin 8
|
DTR pin 4 (leave unconnected) +--> DTR pin 4 (to emulate the same behavior as PC does)
DCD pin 1 (leave unconnected) (leave unconnected) DCD pin 1
DSR pin 6 (leave unconnected) (leave unconnected) DSR pin 6
If SENA use hardware flow control, then RTS and DTR inputs must be connected to CTS output. If not, they might left unconnected. I suggest to connect RXD, TXD and GND signals first, and if that won't work, connect RTS, CTS and DTR pins.
It is possible to connect RTS and CTS pins to ARM to implement hardware flow control, but that doesn't make sence. Because SENA RS485 TX/RX speed is the same as UART speed. Anyway, the following changes should be made: install R44 and R45 (which is not installed on ARM board) and modify RTS/CTS pins in the ARM board DTS file (now they used as I2C1 pins) and setup UART in software to use flow control.
In case if someone claim UART on ARM you will see unexpected characters in the the data flow (for example you will see SENA TX pin blinks during ARM boot, if ARM using UART0 as console). Or you will see 'login:' or 'login incorrect' stings in the data flow if getty using UART. Also ARM boot ROM could print some strings to UART and you cannot disable that behaviour. U-boot might use UART as console and output banner strings. Be ready that such data will go into RS485 and somehow affect it's work.

nettle twofish CBC

I had not problems with using nettle's twofish with standard ecb mode however i'm not sure what's wrong with this cbc mode? The decrypted message will not match the original. (using some hardcoded values like iv just for test purposes).
https://www.lysator.liu.se/~nisse/nettle/nettle.html
const uint8_t key[TWOFISH_KEY_SIZE] = {
0xea, 0xad, 0xdd, 0x6c, 0x32, 0x5a, 0xdc, 0x4f, 0x01, 0x5b, 0x4c,
0xde, 0xbb, 0x45, 0xc9, 0xe5, 0x5a, 0xb7, 0x5f, 0x3b, 0x01, 0x9a,
0xf8, 0x39, 0xd0, 0x74, 0x05, 0xeb, 0xf1, 0xaa, 0xa7, 0x67};
const uint8_t src[TWOFISH_BLOCK_SIZE] = {
0x3a, 0x53, 0xec, 0xae, 0xc0, 0xcf, 0xd3, 0xd8,
0xae, 0x05, 0x5d, 0xc0, 0x07, 0x3c, 0x04, 0x0d};
const uint8_t iv[TWOFISH_BLOCK_SIZE] = {
0xa0, 0xfb, 0x59, 0x3d, 0x70, 0x98, 0xdf, 0x8f,
0xff, 0xa0, 0x3b, 0xd5, 0xc5, 0x8b, 0x2c, 0x45};
uint8_t encrypted[TWOFISH_BLOCK_SIZE];
uint8_t decrypted[TWOFISH_BLOCK_SIZE];
struct CBC_CTX(struct twofish_ctx, TWOFISH_BLOCK_SIZE) ctx;
twofish256_set_key(&ctx.ctx, key);
CBC_SET_IV(&ctx, iv);
CBC_ENCRYPT(&ctx, twofish_encrypt, TWOFISH_BLOCK_SIZE, encrypted, src);
CBC_DECRYPT(&ctx, twofish_decrypt, TWOFISH_BLOCK_SIZE, decrypted,
encrypted);
for(int i = 0; i < TWOFISH_BLOCK_SIZE; i++) {
printf("\n%hhX\n", src[i]);
printf("%hhX\n", encrypted[i]);
printf("%hhX\n-------------------", decrypted[i]);
}
James is right: you need to set the IV again before decryption. From the Nettle documentation:
The final ciphertext block processed is copied into iv before returning, so that large message be processed be a sequence of calls to cbc_encrypt.
I.e. the IV inside the crypto context is lost and replaced by the last block of ciphertext. Hence you need to set it to the correct value again.
Nettle is a low level library, so this construct makes sense; higher level libraries may use streaming or assume that you always provide the complete plaintext/ciphertext in the call.

Resources