Printing out byte array as formatted text gives different outputs - C - c

I am trying to print out byte array as one byte at the time in hexadecimal format within for loop like this:
int my_function(void *data)
{
obuf = (str*)data;
int i;
for (i = 0; i < obuf->len; i++)
{
printf("%02X:", obuf->s[i]);
}
return 0;
}
str in this case is structure from Kamailio - review at http://www.asipto.com/pub/kamailio-devel-guide/#c05str
The expected output:
80:70:0F:80:00:00:96:00:1D:54:7D:7C:36:9D:1B:9A:20:BF:F9:68:E8:E8:E8:F8:68:98:E8:EE:E8:B4:7C:3C:34:74:74:64:74:69:2C:5A:3A:3A:3A:3A:3A:3A:32:24:43:AD:19:1D:1D:1D:1D:13:1D:1B:3B:60:AB:AB:AB:AB:AB:0A:BA:BA:BA:BA:B0:AB:AB:AB:AB:AB:0A:BA:BA:BA:BA:B9:3B:61:88:43:
What I am getting:
FFFFFF80:70:0F:FFFFFF80:00:00:FFFFFF96:00:1D:54:7D:7C:36:FFFFFF9D:1B:FFFFFF9A:20:FFFFFFBF:FFFFFFF9:68:FFFFFFE8:FFFFFFE8:FFFFFFE8:FFFFFFF8:68:FFFFFF98:FFFFFFE8:FFFFFFEE:FFFFFFE8:FFFFFFB4:7C:3C:34:74:74:64:74:69:2C:5A:3A:3A:3A:3A:3A:3A:32:24:43:FFFFFFAD:19:1D:1D:1D:1D:13:1D:1B:3B:60:FFFFFFAB:FFFFFFAB:FFFFFFAB:FFFFFFAB:FFFFFFAB:0A:FFFFFFBA:FFFFFFBA:FFFFFFBA:FFFFFFBA:FFFFFFB0:FFFFFFAB:FFFFFFAB:FFFFFFAB:FFFFFFAB:FFFFFFAB:0A:FFFFFFBA:FFFFFFBA:FFFFFFBA:FFFFFFBA:FFFFFFB9:3B:61:FFFFFF88:43:
Could someone please help me understand why there are some of bytes prefixed with FFFFFF and other aren't?
Thanks in advance

Looks like obuf->s[i] returns a signed value
You would need to cast it to a unsigned value to get rid of the FFF.. at start.
printf("%02X:", (unsigned char)(obuf->s[i]));

The problem appears with chars that have the most significant bit set (which are out of the proper pure ASCII set range 0-127). The key point is to consider chars as unsigned.
printf("%02X:", (unsigned char)(obuf->s[i]));
See this simple compilable repro C code:
#include <stdio.h>
#include <string.h>
struct _str {
char* s; /* pointer to the beginning of string (char array) */
int len; /* string length */
};
typedef struct _str str;
int my_function(void *data)
{
str* obuf;
int i;
obuf = (str*)data;
for (i = 0; i < obuf->len; i++) {
printf("%02X:", (unsigned char)(obuf->s[i]));
}
return 0;
}
int main(void)
{
char buf[2];
str s;
/* Test with ordinary ASCII string */
s.s = "Hello";
s.len = strlen(s.s);
my_function(&s);
printf("\n");
/* Test with char values with most significant bit set */
buf[0] = 0xF1;
buf[1] = 0x00;
s.s = buf;
s.len = 1;
my_function(&s);
return 0;
}
With MSVC, I get this output:
48:65:6C:6C:6F:
F1:

Related

define function with pointer input

I don't fully understand how to work with pointers.
Inside the function is where I need to write code to return the length of input string.
int mystrlen (const char *s)
{
char *s[1000], i;
for(i = 0; s[i] != '\0'; ++i);
printf("Length of string: %d, i");
return 0;
}
Could you tell me how to make it work?
Thank you!!
Remove char *s[1000], declare int i instead of char i, and return i rather than 0:
You need to remove the s inside the function body because it is "shadowing the variable" s that is a function parameter, meaning the s function parameter cannot be read at all.
Changing char i to int i will likely increase the range of possible values to return. If you pass a string with 128 characters in it, char i would result in returning -128 if it is a signed 8-bit type. int is guaranteed to be 16-bit, allowing for strings up to 32767 characters (more than enough for most common uses of a string length function).
You return i because otherwise the function is pointless; even if you print the value, you'd need a way to use the string length, and you can't do that if you don't return it from the function.
Corrected code with example:
#include <stdio.h>
int mystrlen(const char *s)
{
int i;
for (i = 0; s[i] != '\0'; ++i);
return i;
}
int main(void)
{
const char *s = "Hello world!";
int len = mystrlen(s);
printf("Length of string: %d\n", len);
return 0;
}
First of all, using pointers, as the number says, consist in using a reference instead of the actual variable, so if you pass a reference by parameter, you are not passing the actual value of it, just an address to it!
The correct code is:
#include <stdio.h>
int mystrlen (const char *s)
{
int i;
for( i = 0; s[i] != '\0'; ++i);
printf("Length of string: %d\n", i);
return 0;
}
void main(){
char *string = "Hello World";
mystrlen(string);
}
Another thing to point out is that you're trying to declare a const variable and change it. When you declare a const variable it should not change.

Validation system for openssl hmac code using nist vector values as input

I have wrote a c code which takes the input value of key and message makes call to openssl hmac functions and generate result of mac code.
Input values are collected from NIST Test Vectors
#define KEY_SIZE 11 // in bytes
#define MSG_SIZE 129 // in bytes
#include <stdio.h>
#include <string.h>
#include <openssl/hmac.h>
void str2hex(char *, char*, int);
int main() {
char *key, *msg;
unsigned char keyy[KEY_SIZE], msgt[MSG_SIZE], temp[4];
unsigned char* result;
unsigned int i, len = 20,Tlen = 10;
key = "";//values specified below
msg ="";//values specified below
/*CONVERT STRING TO HEX DIGITS - KEY*/
str2hex(key, keyy, KEY_SIZE);
//CONVERT STRING TO HEX DIGITS - MSG*//
str2hex(msg, msgt, MSG_SIZE);
result = (unsigned char*)malloc(sizeof(char) * len);
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
HMAC_Init_ex(&ctx, keyy, strlen(keyy), EVP_sha1(), NULL);
HMAC_Update(&ctx, (unsigned char*)&msgt, strlen(msgt));
HMAC_Final(&ctx, result, &len);
HMAC_CTX_cleanup(&ctx);
printf("HMAC digest: ");
for (i = 0; i < Tlen; i++)
printf("%02x", result[i]);
printf("\n");
free(result);
return 0;
}
//===================== string to hex conversion
================================//
void str2hex(char *str, char *hex, int len) {
int tt, ss;
unsigned char temp[4];
for (tt = 0, ss = 0; tt < len, ss < 2 * len; tt++, ss += 2) {
temp[0] = '0';
temp[1] = 'x';
temp[2] = str[ss];
temp[3] = str[ss + 1];
hex[tt] = (int) strtol(temp, NULL, 0);
}
}
//---------------------------------------------------------------------------------//
The first input given:
Key = 82f3b69a1bff4de15c33
Msg = fcd6d98bef45ed6850806e96f255fa0c8114b72873abe8f43c10bea7c1df706f10458e6d4e1c9201f057b8492fa10fe4b541d0fc9d41ef839acff1bc76e3fdfebf2235b5bd0347a9a6303e83152f9f8db941b1b94a8a1ce5c273b55dc94d99a171377969234134e7dad1ab4c8e46d18df4dc016764cf95a11ac4b491a2646be1
Output generated:
HMAC digest: 1ba0e66cf72efc349207
Nist_Mac = 1ba0e66cf72efc349207
It matches so success
But for the Second input
Key = 4766e6fe5dffc98a5c50
Msg = d68b828a153f5198c005ee36c0af2ff92e84907517f01d9b7c7993469df5c21078fa356a8c9715ece2414be94e10e547f32cbb8d0582523ed3bb0066046e51722094aa44533d2c876e82db402fbb00a6c2f2cc3487973dfc1674463e81e42a39d9402941f39b5e126bafe864ea1648c0a5be0a912697a87e4f8eabf79cbf130e
Output generated:
HMAC digest: ca96f112a79882074b63
Nist_Mac = 007e4504041a12f9e345
Its failing.If any one could check my code and kindly let me know what am i doing wrong it will be really helpfull.
You have two issues here.
The first is that you're using strlen on an array of characters that may contain a null byte. Since this function counts the number of bytes until it find a null byte, you won't get what you expect if your array contains a null byte (as is the case for your second example).
Instead of using strlen on the byte array to determine the length, use the actual length of the data. Since you're converting a string containing hex digits to bytes, the length of the byte array is half the length of the input string.
HMAC_Init_ex(&ctx, keyy, strlen(key)/2, EVP_sha1(), NULL);
HMAC_Update(&ctx, msgt, strlen(msg)/2);
Note also that you should pass msgt to HMAC_Update, not &msgt, as the latter is a pointer to an array.
The second issue is in your str2hex function. When you construct temp, you don't have enough space for a terminating null byte. This causes strtol, which expects a null-terminated string, to read past the end of the array. This invokes undefined behavior.
In this particular case you're "lucky" that it works, as the byte in memory that follows temp happens to contain either a null byte or a non-digit. You can't however depend on this behavior. Fix this by making temp one byte longer and explicitly setting that byte to 0. And while you're at it, you should also fix the signed / unsigned mismatch in your function arguments and change the type of temp to an unsigned char array.
void str2hex(char *, unsigned char*, int);
...
void str2hex(char *str, unsigned char *hex, int len) {
int tt, ss;
char temp[5];
for (tt = 0, ss = 0; tt < len, ss < 2 * len; tt++, ss += 2) {
temp[0] = '0';
temp[1] = 'x';
temp[2] = str[ss];
temp[3] = str[ss + 1];
temp[4] = 0;
hex[tt] = strtol(temp, NULL, 0);
}
}
At byte position 58 in the message, you have a 0x00 byte (null). Since you're doing an strlen(msgt), this results in 58 instead of 128. Excerpt from the documentation (emphasis mine):
The C library function size_t strlen(const char *str) computes the length of the string str up to, but not including the terminating null character.
Just use the proper length of the message and don't use string operations on char arrays that do not contain printable bytes.

Unsigned Char Concat In C

im trying to convert a string message to hex value in C.
For example if i have a message like "abc" i want to have it by 162636 etc. My code is below. In this code, i have to do some concat operation to store them all but now i can store only 36. How can i store them?
unsigned char swapNibbles(char x)
{
return ( (x & 0x0F)<<4 | (x & 0xF0)>>4 );
}
void encode(char *message, char password[40]) {
unsigned char *reversedInput = malloc(strlen(message));
for (int i = 0; i < strlen(message); ++i) {
reversedInput=swapNibbles(message[i]);
}
printf("%2x TERS ",reversedInput);
//unsigned char *bitwiseMessage = (unsigned char*)message;
//printf("DÜZ %s\n",bitwiseMessage);
//printf("TERS %u\n", swapNibbles(bitwiseMessage));
}
Edit
My solution for hex-encoding: IDEOne
If you want your text to be hex-encoded, you will have to allocate twice as much space as the original message:
"abc" (3 bytes) ==> "616263" (6 bytes)
So you will need:
unsigned char *reversedInput = malloc(2*strlen(message)+1); // +1 for the final NULL-terminator
#include <string.h>
#include <malloc.h>
char* HexEncode(char* txt)
{
char* hexTxt = calloc(2*strlen(txt)+1,1);
for(char* p=hexTxt; *txt; p+=2)
{
sprintf(p, "%02x", *txt++);
}
return hexTxt;
}
int main() {
char* hexText = HexEncode("Hello World");
printf("Hexed is %s\n", hexText);
free(hexText);
return 0;
}
Output
Hexed is 48656c6c6f20576f726c64

ASCII string to hexadecimal integers conversion

I want to convert an ascii string of 16 bytes into 16 bytes hexadecimal integers. Kindly help. Here is my code:
uint stringToByteArray(char *str,uint **array)
{
uint i, len=strlen(str) >> 1;
*array=(uint *)malloc(len*sizeof(uint));
//Conversion of str (string) into *array (hexadecimal)
return len;
}
If you are looking for printing integer numbers in hexadecimal form, this might help:
#include <stdio.h>
int main() {
/* define ASCII string */
/* note that char is an integer number type */
char s[] = "Hello World";
/* iterate buffer */
char *p;
for (p = s; p != s+sizeof(s); p++) {
/* print each integer in its hex representation */
printf("%02X", (unsigned char)(*p));
}
printf("\n");
return 0;
}
If all you want is to turn a char array to an array of 1-byte integer numbers, then you are already done. char already is an integral number type. You can use the buffer you already have, or use malloc/memcpy to copy the data to a new one.
You might want to have a look at the explicit width integer types defined in stdint.h, e.g., uint8_t for a one byte unsigned integer.
A C-"string" of 16 characters length is 16bytes!
To have it converted to a "byte"-array (of 16 entries lenght) you might like to do the following:
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* Copies all characters of str into a freshly allocated array pointed to by *parray. */
/* Returns the number of characters bytes copied and -1 on error. Sets errno accordingly. */
size_t stringToByteArray(const char * str, uint8_t **parray)
{
if (NULL == str)
{
errno = EINVAL;
return -1;
}
{
size_t size = strlen(str);
*parray = malloc(size * sizeof(**parray));
if (NULL == *parray)
{
errno = ENOMEM;
return -size;
}
for (size_t s = 0; s < size; ++s)
{
(*parray)[s] = str[s];
}
return size;
}
}
int main()
{
char str[] = "this is 16 bytes";
uint8_t * array = NULL;
ssize_t size = stringToByteArray(str, &array);
if (-1 == size)
{
perror("stringToByteArray() failed");
return EXIT_FAILURE;
}
/* Do what you like with array. */
free(array);
return EXIT_SUCCESS;
}

Returning an array from function

I am writing a function which takes in the integer value and the pointer to a character.
the function converts the integer value into binary and stores it in the char pointer.
the char pointer is 16 bytes long.
Snippet of code:
void int2bin(u_int16_t addr_IP, char *Binary)
{
int count;
printf("IP1add = %d \n", Binary);
for (count = 0; count < 16; count++) {
if(addr_IP>0)
*(Binary + 15-count) = addr_IP & 0x1 ? '1':'0';
else
*(Binary + 15-count) = '0';
addr_IP>>=1;
}
}
int main(int argc, char *argv[])
{
u_int16_t senderIP_16[], u_int16_t receiverIP_16[];
char sender_IP_hi[16], sender_IP_low[16];
int2bin(senderIP_16[0], &sender_IP_hi);
int2bin(senderIP_16[1], &sender_IP_low);
}
In the first call to the function, it returns correct values. But in the second pass, the value of first pass is appended to the second pass, i.e length of sender_IP_low becomes 32.
How can I resolve this?
Thanks
It looks like you're printing sender_IP_low as a string, and since it is not null-terminated, the print routine continues to print the adjacent buffer, sender_IP_hi. And you're probably just lucky that the print routine finds a zero and stops before a segmentation fault.
One quick fix is:
void int2bin(u_int16_t addr_IP, char *Binary) {
...
Binary[16] = 0; // terminate the string before returning
}
...
char sender_IP_hi[17], sender_IP_low[17]; // +1 for null terminator
Although, there are a few other things that could be fixed in your implementation, I just wanted to focus on an answer to your original question.
If you are printing the arrays with printf():
void int2bin(u_int16_t addr_IP, char *Binary)
{
int count;
printf("IP1add = %d \n", Binary);
for (count = 0; count < 16; count++) {
if(addr_IP>0)
*(Binary + 15-count) = addr_IP & 0x1 ? '1':'0';
else
*(Binary + 15-count) = '0';
addr_IP>>=1;
}
// Put the NULL char in the last position
Binary[16] = '\0';
}
int main(int argc, char *argv[])
{
u_int16_t senderIP_16[], u_int16_t receiverIP_16[];
// One more char for storing the terminator character
char sender_IP_hi[17], sender_IP_low[17];
int2bin(senderIP_16[0], &sender_IP_hi);
int2bin(senderIP_16[1], &sender_IP_low);
}

Resources