unsigned characters and sprintf() C - c

I have this code:
int main(){
char buffer[1024];
char port = 1;
int length = 255;
char * record = "$TAG ,0 ,89 ,0, 1\n";
if(length < 0 || length > 255){
printf("Error - length out of range for an unsigned char.\n");
exit(1);
}
snprintf(buffer, 1024, "%c%c%s", port, (unsigned char) length, record);
int port_rc = buffer[0];
int length_rc = buffer[1];
printf("port_rc: %d\n",port_rc);
printf("length_rc: %d\n",length_rc);
return 0;
}
Output when I run it:
port_rc: 1
length_rc: -1
I think I am missing something here in terms of snprintf() as i'm not seeing the 255 value when reading the array it created back. My guess is that snprintf() is promoting the variable 'length' to an int or something. Does anyone know how I can achieve this?
Thanks.

I don't think you can use sprintf() to store 255 into the buffer. The buffer argument to sprintf() is a char array. Whether char is signed or unsigned by default is implementation-defined; see Is char signed or unsigned by default?. If 255 is greater than CHAR_MAX, trying to store 255 results in undefined behavior; if the implementation defaults to signed then CHAR_MAX will probably be 127.
I suggest not using sprintf() to store numbers into the buffer. Declare it as:
unsigned char buffer[127];
Then you can do:
buffer[0] = port;
buffer[1] = length;
snprintf((char *)(buffer + 2), sizeof buffer - 2, "%s", record);

"Be careful, though," when judging such a "solution."
In my humble, the root problem – in your original post - is that the variables port_rc and length_rc should have been declared as unsigned integers. You do not want a value such as $FF to be erroneously "sign-extended" to become $FFFFFFFF == -1 ...
Your "solution" is quite different from the original because, as you see, it now stores into both buffer[0] and buffer[1] before then retrieving and examining those values!

WORKING SOLUTION:
int main(){
unsigned char buffer[1024];
char port = 1;
int length = 255;
char * record = "$TAG ,0 ,89 ,0, 1\n";
if(length < 0 || length > 255){
printf("Error - length out of range for an unsigned char.\n");
exit(1);
}
buffer[0] = port;
buffer[1] = length;
snprintf((char *)(buffer), sizeof buffer - 2, "%c%c%s", port,length,record);
int port_rc = buffer[0];
int length_rc = buffer[1];
char char_first = buffer[2];
printf("port_rc: %d\n",port_rc);
printf("length_rc: %d\n",length_rc);
printf("char_first: %c\n",char_first);
return 0;
}
RETURNS:
port_rc: 1
length_rc: 255
char_first: $

Related

reading a big bin-file(~2mb) in c

I want to read a bin-file with a size under 2mb.
At the moment my code for reading the bin file looks like this:
edit:
#define MAX_BYTES_IN_FILE 500000 // ~ 2mb
#define ERROR_FILE 1
int get_byte_from_file(FILE *stream, unsigned char *dataarray) {
int counter = 0;
while ((dataarray[counter] = fgetc(stream)) != EOF) {
counter += 1;
}
return counter;
}
Main looks like this for the example use of the function.
int main(int argc, char **argv) {
FILE *datei;
unsigned int number_of_bytes;
unsigned char *dataarray;
dataarray = (unsigned char *)malloc(sizeof(unsigned char) * MAX_BYTES_IN_FILE);
datei = fopen(argv[1], "rb");
number_of_bytes = get_byte_from_file(datei, dataarray);
for (int i = 0; i < number_of_bytes; i++)
printf("%x ", dataarray[i]);
return 0;
}
Maybe I did a simple mistake but cant see it the error is still: Segmentation fault (core dumped)
This line is sufficient to crash your program:
while ((dataarray[counter] = fgetc(stream)) != EOF) {
Let's go through it step by step:
fgetc(stream) reads a byte and returns its value or EOF. Because a byte can have any possible value, fgetc() returns a larger int, which can hold an EOF value that is distinct from any byte value that might be found in the file.
You assign this int value to an unsigned char. An EOF value will be truncated to this datatype.
The value of the assignment is of type unsigned char, and the converted EOF value is not equal to EOF anymore. Thus, the comparison always fails, and your program keeps fetching data until the buffer overruns and nasty things begin to happen.
You need to store the result of fgetc() in an int variable until you've checked that it is indeed not the EOF value.
Maybe something like this.
void *readfile(FILE *fi, long *filesize)
{
void *buff;
fseek(fi, 0, SEEK_END);
*filesize = ftell(fi);
fseek(fi, 0, SEEK_SET);
buff = malloc(*filesize);
if(buff)
{
fread(buff, 1, *filesize, fi);
}
return buff;
}
You need to add error checks- I did not as it is only the idea.
And your usage:
int main(int argc, char **argv) {
FILE *datei;
long number_of_bytes;
unsigned char *dataarray;
datei=fopen(argv[1],"rb");
dataarray = readfile(datei, &number_of_bytes);
for (int i=0;dataarray && i<number_of_bytes;i++)
printf("%hhx ",dataarray[i]);
return 0;
}
The reason you get a segmentation fault is your allocation is incorrect: you allocate MAX_BYTES_IN_FILE bytes instead of unsigned int elements. As allocated, the array has only MAX_BYTES_IN_FILE / sizeof(unsigned int) elements, whereas the file is probably MAX_BYTES_IN_FILE * sizeof(unsigned int) bytes long.
You are reading bytes from the file (values between 0 and 255) but you use unsigned int elements. What is the logic? Does the file contain 32-bit values or individual bytes?
Once you can confirm that the file contents is exactly the same as the representation of the array in memory, you can use fread() to read the whole file in a single call.

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.

Converting integer to unsigned char* (int 221 to "\xdd")

I have a function which takes unsigned char* as input.
Say for example that I have:
unsigned char* data = (unsigned char*) "\xdd";
int a = 221;
How can I convert my integer a to unsigned char* such that data and my converted a is indistinguishable?
I have tried playing around with sprintf but without any luck, I'm not sure how to handle the "\x" part.
Since 221 is not guaranteed to be a valid value for a char type, the closest thing you can do is:
int a = 221;
unsigned char buffer[10];
sprintf((char*)buffer, "%c", a);
Here's an example program and its output:
#include <stdio.h>
int main()
{
unsigned char* data = (unsigned char*) "\xdd";
int a = 221;
unsigned char buffer[10];
sprintf((char*)buffer, "%c", a);
printf("%d\n", buffer[0] == data[0]);
printf("%d\n", buffer[0]);
printf("%d\n", data[0]);
}
Output:
1
221
221
Update
Perhaps I misunderstood your question. You can also use:
int a = 221;
unsigned char buffer[10] = {0};
buffer[0] = a;
As stated the question does not make sense and is not possible - you don't actually want to convert to const char *, which is a pointer type. Instead you want to convert into an array of chars and then take the address of that array by using its name.
int x = 221;
char buf[5];
snprintf(buf, sizeof buf, "\\x%.2x", x);
/* now pass buf to whatever function you want, e.g.: */
puts(buf);

Encrypting and decrypting a message with Blowfish

Here is a basic code of encryping and decrypting a message:
#include <stdio.h>
#include <openssl/blowfish.h>
#include <string.h>
//gcc cryptage.c -o cryptage -lcrypto
int main(){
BF_KEY *key = malloc(sizeof(BF_KEY));
unsigned char *crypt_key = "Key of encryption";
const unsigned char *in = "Message to encrypt";
int len = strlen(crypt_key);
unsigned char *out = malloc(sizeof(char)*len);
unsigned char *result = malloc(sizeof(char)*len);
//Defining encryption key
BF_set_key(key, len, crypt_key);
//Encryption
BF_ecb_encrypt(in, out, key, BF_ENCRYPT);
//Décryption
BF_ecb_encrypt(out, result, key, BF_DECRYPT);
fprintf(stdout,"Result: %s\n",result);
return 0;
}
My problem is the result i get. It's always a String of 8 caracters, no more.
Can you please help me encrypt and decrypt the full message?
Thank you!
As #WhozCraig says, do things 8 bytes at a time.
The data to encrypt should be viewed as a byte array and not a C string.
So consider the string to encrypt with the \0 and padded with random data to form a byte array that is a multiple of 8.
Call encrypt multiple times, encrypting 8 bytes per iteration.
To decrypt, call decryption the same number of iterations. Note that the result buffer may need to be sized up to a multiple of 8.
const unsigned char *in = "Message to encrypt";
size_t InSize = strlen(in) + 1;
int KeyLen = strlen(crypt_key);
size_t OutSize = (InSize + 7) & (~7);
unsigned char *out = malloc(Outsize);
unsigned char *outnext = out;
//Defining encryption key
BF_set_key(key, KeyLen, crypt_key);
//Encryption
while (InSize >= 8) {
BF_ecb_encrypt(in, outnext, key, BF_ENCRYPT);
in += 8;
outnext += 8;
InSize -= 8;
}
if (Insize > 0) { // Cope with non-octal length
unsigned char buf8[8];
memcpy(buf8, in, InSize);
for (i=InSize; i<8; i++) {
buf8[i] = rand();
}
BF_ecb_encrypt(buf8, outnext, key, BF_ENCRYPT);
}
//Décryption
unsigned char *result = malloc(OutSize);
unsigned char *resultNext = result;
while (OutSize) {
BF_ecb_encrypt(out, resultNext, key, BF_DECRYPT);
out += 8;
resultNext += 8;
OutSize -= 8;
}
fprintf(stdout,"Result: %s\n",result);
// No need to print the random bytes that were generated.
return 0;
}
Not quite comfortable have a known byte (\0) encoded in the last block. A different length indication may be prudent.

How to convert unsigned int(u16) into string value(char *)?

I need to convert u16(unsigned int -2 byte) value into string (not ascii).
How to convert unsigned int(u16) into string value(char *)?
/* The max value of a uint16_t is 65k, which is 5 chars */
#ifdef WE_REALLY_WANT_A_POINTER
char *buf = malloc (6);
#else
char buf[6];
#endif
sprintf (buf, "%u", my_uint16);
#ifdef WE_REALLY_WANT_A_POINTER
free (buf);
#endif
Update: If we do not want to convert the number to text, but to an actual string (for reasons that elude my perception of common sense), it can be done simply by:
char *str = (char *) (intptr_t) my_uint16;
Or, if you are after a string that is at the same address:
char *str = (char *) &my_uint16;
Update: For completeness, another way of presenting an uint16_t is as a series of four hexadecimal digits, requiring 4 chars. Skipping the WE_REALLY_WANT_A_POINTER ordeal, here's the code:
const char hex[] = "0123456789abcdef";
char buf[4];
buf[0] = hex[my_uint16 & f];
buf[1] = hex[(my_uint16 >> 4) & f];
buf[2] = hex[(my_uint16 >> 8) & f];
buf[3] = hex[my_uint16 >> 12];
A uint16_t value only requires two unsigned char objects to describe it. Whether the higher byte comes first or last depends on the endianness of your platform:
// if your platform is big-endian
uint16_t value = 0x0A0B;
unsigned char buf[2];
buf[0] = (value >> 8); // 0x0A comes first
buf[1] = value;
// if your platform is little-endian
uint16_t value = 0x0A0B;
unsigned char buf[2];
buf[0] = value;
buf[1] = (value >> 8); // 0x0A comes last
It's not entirely clear what you want to do, but it sounds to me that what you want is a simple cast.
uint16_t val = 0xABCD;
char* string = (char*) &val;
Beware that the string in general is not a 0-byte terminated C-string, so don't do anything dangerous with it.
You can use sprintf:
sprintf(str, "%u", a); //a is your number ,str will contain your number as string

Resources