Defining a 128-bit integer in C - c

To represent this value, I am following the definition:
#define NUM_BITS 128
typedef unsigned char BigInt[NUM_BITS/8];
That is, a value of type BigInt must be represented by an array of bytes, interpreted as a single 128-bit integer, in two's complement and following the little-endian order.
For example, {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, which represents the integer value 1.
I've been thinking of doing a function like that:
void big_val (BigInt res, long val);
Which would be an attribution with extension. The big_val function assigns res the value provided by l (a signed long), correctly extended to 128 bits.
I was thinking of, for example, getting the most significant byte, getting the sign of the number, through y = val & 0xFF000000; and repeat this byte for another 8 times to form my array. But how could I get the bytes which represents the numbers without the signal?
That's what I've done so far:
void big_val(BigInt res, long val){
long y;
y = val&0xFF000000;
for(int i = 8; i < 16; i++){
res[i] = y;
}
}
(To anyone who has seen this post some minutes ago, I accidentally deleted it instead of editing, sorry)

Assign byte by byte, one byte at a time.
void BigInt_init_from_long(BigInt res, long val){
size_t i;
bool negative = val < 0;
for (i = 0; i < sizeof(long); ++i) {
res[i] = val & 0xff;
val >>= 8;
}
for (; i < NUM_BITS/8; ++i) {
res[i] = negative ? 0xff : 0; // sign extension
}
}

Related

How to split a variable that contains 32 Hex-values into 32 Bytes in C? [duplicate]

how can I convert a hex string to a uint8_t array?
My string is 02012B1530A6E3958A98530031902003876940000000000CDF9844173BE512AFFFFFFE11DBBA1F00079387800E13012E11FC017FFFFFFFFE39C10F40
and I want to convert it into this array:
uint8_t array_uint[] = {0x02, 0x01, 0x2B, 0x15, 0x30, 0xA6, 0xE3, 0x95, 0x8A, 0x98, 0x53, 0x00, 0x31, 0x90, 0x20, 0x03, 0x87, 0x69, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xDF, 0x98, 0x44, 0x17, 0x3B, 0xE5, 0x12, 0xAF, 0xFF, 0xFF, 0xFE, 0x11, 0xDB, 0xBA, 0x1F, 0x00, 0x07, 0x93, 0x87, 0x80, 0x0E, 0x13, 0x01, 0x2E, 0x11, 0xFC, 0x01, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x39, 0xC1, 0x0F, 0x40};
Thank you for your help!
You can use sscanf() to convert 2 bytes at a time from the source string into the destination array:
#include <stdint.h>
#include <stdio.h>
size_t convert_hex(uint8_t *dest, size_t count, const char *src) {
size_t i;
int value;
for (i = 0; i < count && sscanf(src + i * 2, "%2x", &value) == 1; i++) {
dest[i] = value;
}
return i;
}
Note however that this approach may be inefficient, with a quadratic time complexity, on architectures where the standard library computes the length of the source string for each call to sscanf(). Using an intermediary array solves this problem:
#include <stdint.h>
#include <stdio.h>
size_t convert_hex(uint8_t *dest, size_t count, const char *src) {
char buf[3];
size_t i;
int value;
for (i = 0; i < count && *src; i++) {
buf[0] = *src++;
buf[1] = '\0';
if (*src) {
buf[1] = *src++;
buf[2] = '\0';
}
if (sscanf(buf, "%x", &value) != 1)
break;
dest[i] = value;
}
return i;
}
Storing the conversion result directly into the dest array is easy:
#include <stdint.h>
#include <stdio.h>
size_t convert_hex(uint8_t *dest, size_t count, const char *src) {
char buf[3];
size_t i;
for (i = 0; i < count && *src; i++) {
buf[0] = *src++;
buf[1] = '\0';
if (*src) {
buf[1] = *src++;
buf[2] = '\0';
}
if (sscanf(buf, "%hhx", &dest[i]) != 1)
break;
}
return i;
}
Purists may argue that %hhx expects a pointer to an unsigned char instead of a uint8_t so the format should be "%"SCNx8 or "%2"SCNx8, defined in <inttypes.h>, but these alternatives are less readable and unnecessary as type uint8_t is always identical to type unsigned char on architectures where it is defined.
The first thing you need to learn is that decimal, hexadecimal or even octal are just how the binary numbers stored in the computer memory are presented. Once you store the bytes in your array, they aren't really hexadecimal anymore.
Now for how to solve your problem: You need to extract two characters at a time, then convert each character to the corresponding integer value, and use bit-shirt and bit-or to combine them into a single byte value.
Converting the digits 0 to 9 into their corresponding value is easy, since the C specification say that they must be encoded contiguously (i.e. '0' must come right before '1' and so on). That means you can use simple subtraction with '0' to get the numeric value ('0' - '0' == 0, '1' - '0' == 1 etc.).
The letters A to F are harder through, because there are many different possible encodings, including some that doesn't place letters contiguously. With that said, the most common encoding ASCII do is doing that, which means on most system you can use the same "trick" as for the decimal digits.
Then how to combine them, the first value needs to be shifted up (to the left) by four bits, and then bitwised OR'ed with the second value.
The result of that should be a single byte whose value is the same as the two hexadecimal digits from the string. Append this value to the array.
With
char data[] = "02012B1530A6E3958A98530031902003876940000000000CDF9844173BE512AFFFFFFE11DBBA1F00079387800E13012E11FC017FFFFFFFFE39C10F40";
char *p = data;
first byte is
(hexdigit(p[0]) << 4) + hexdigit(p[1])
You can loop the above expression with
do {
uint8_t value = (hexdigit(p[0]) << 4) + hexdigit(p[1]);
p += 2;
} while (*p);
for all the values (make sure data has an even number of characters).
The function hexdigit() (implementation is left as an exercise) converts '0' to 0, '1' to 1, ..., 'a' to 10, 'A' to 10, ...

How to concatenate the hexadecimal data in an array in C

I have my data field as follows DATA = 0x02 0x01 0x02 0x03 0x04 0x05 0x06 0x07 Now I want to concatenate this data as follows DATA = 0x01020304050607. How can I do it using C program. I found a program in C for concatenation of data in an array and the program is as follows:
#include<stdio.h>
int main(void)
{
int num[3]={1, 2, 3}, n1, n2, new_num;
n1 = num[0] * 100;
n2 = num[1] * 10;
new_num = n1 + n2 + num[2];
printf("%d \n", new_num);
return 0;
}
For the hexadecimal data in the array how can I manipulate the above program to concatenate the hexadecimal data?
You need a 64 bit variable num as result, instead of 10 as factor you need 16, and instead of 100 as factor, you need 256.
But if your data is provided as an array of bytes, then you can simply insert complete bytes, i.e. repeatedly shifting by 8 bits (meaning a factor of 256):
int main(void)
{
uint8_t data[8] = { 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
unsigned long long num = 0;
for (int i=0; i<8; i++) {
num <<=8; // shift by a complete byte, equal to num *= 256
num |= data[i]; // write the respective byte
}
printf("num is %016llx\n",num);
return 0;
}
Output:
num is 0201020304050607
Lest say you have input like
int DATA[8] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
If you want output like 0x0001020304050607, to store this resultant output you need one variable of unsigned long long type. For e.g
int main(void) {
int DATA[8] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
int ele = sizeof(DATA)/sizeof(DATA[0]);
unsigned long long mask = 0x00;
for(int row = 0; row < ele; row++) {
mask = mask << 8;/* every time left shifted by 8(0x01-> 0000 0001) times */
mask = DATA[row] | mask; /* put at correct location */
}
printf("%016llx\n",mask);
return 0;
}
Here's some kind of hack that writes your data directly into an integer, without any bitwise operators:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
uint64_t numberize(const uint8_t from[8]) {
uint64_t r = 0;
uint8_t *p = &r;
#if '01' == 0x4849 // big endian
memcpy(p, from, 8);
#else // little endian
for (int i=7; i >= 0; --i)
*p++ = from[i];
#endif
return r;
}
int main() {
const uint8_t data[8] = { 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
printf("result is %016llx\n", numberize(data));
return 0;
}
This does work and outputs this independently of the endianness of your machine:
result is 0201020304050607
The compile-time endianness test was taken from this SO answer.

Slice up an uint8_t array

Let's say that I have an array of 16 uint8_t as follows:
uint8_t array[] = {0x13, 0x01, 0x4E, 0x52, 0x31, 0x4A, 0x35, 0x36, 0x4C, 0x11, 0x21, 0xC6, 0x3C, 0x73, 0xC2, 0x41};
This array stores the data contained in a 128 bits register of an external peripheral. Some of the information it represents are stored on 2, 3, 8, 12 bits ... and so on.
What is the best and elegant way to slice it up and bit mask the information I need? (The problem is that some things that I need overlaps the length of one cell of the array)
If that can help, this snippet I wrote converts the whole array into a char* string. But casting this into an int is not option because.. well 16 bytes.
int i;
char str[33];
for(i = 0; i < sizeof(array) / sizeof(*array) ; i++) {
sprintf(str+2*i,"%02hX",array[i]);
}
puts(str);
13014E52314A35364C1121C63C73C241
Actually such problem also occures when trying to parse all kind of bitstreams, like video or image files or compressed data by algorithms like LZ*. So the approach used there is to implement a bitstream reader.
But in your case the bit sequence is fixed length and quite short, so one way is to manually check the field values using bitwise operations.
Or you can use this function that I just wrote, which can extract arbitrary number of bits from a uint8 array, starting from desired bit position:
uint32_t extract_bits(uint8_t *arr, unsigned int bit_index, unsigned int bit_count)
{
/* Assert that we are not requested to extract more than 32 bits */
uint32_t result = 0;
assert(bit_count <= sizeof(result)*8 && arr != NULL);
/* You can additionally check if you are trying to extract bits exceeding the 16 byte range */
assert(bit_index + bit_count <= 16 * 8);
unsigned int arr_id = bit_index / 8;
unsigned int bit_offset = bit_index % 8;
if (bit_offset > 0) {
/* Extract first 'unaligned_bit_count' bits, which happen to be non-byte-aligned.
* When we do extract those bits, the remaining will be byte-aligned so
* we will thread them in different manner.
*/
unsigned int unaligned_bit_count = 8 - bit_offset;
/* Check if we need less than the remaining unaligned bits */
if (bit_count < unaligned_bit_count) {
result = (arr[arr_id] >> bit_offset) & ((1 << bit_count) - 1);
return result;
}
/* We need them all */
result = arr[arr_id] >> bit_offset;
bit_count -= unaligned_bit_count;
/* Move to next byte element */
arr_id++;
}
while (bit_count > 0) {
/* Try to extract up to 8 bits per iteration */
int bits_to_extract = bit_count > 8 ? 8 : bit_count;
if (bits_to_extract < 8) {
result = (result << bits_to_extract) | (arr[arr_id] & ((1 << bits_to_extract)-1));
}else {
result = (result << bits_to_extract) | arr[arr_id];
}
bit_count -= bits_to_extract;
arr_id++;
}
return result;
}
Here is example of how it is used.
uint32_t r;
/* Extracts bits [7..8] and places them as most significant bits of 'r' */
r = extract_bits(arr, 7, 2)
/* Extracts bits [4..35] and places them as most significant bits of 'r' */
r = extract_bits(arr, 4, 32);
/* Visualize */
printf("slice=%x\n", r);
And then the visualisation of r is up to you. They can either be represented as hex dwords, characters, or however you decide.

How to do math with a number represented as an array in C?

I have some unsigned char array. I want to represent a big number and add a number to this big number.
So for example I have these six elements:
0x00, 0x00, 0x00, 0x00, 0x00, 0xdf
I want to add 0x11 and get
0x00, 0x00, 0x00, 0x00, 0x00, 0xf0
So, if I add 0x10 after, I should have
0x00, 0x00, 0x00, 0x01, 0x00
Could I do it with binary operations or something another but without loops? My array could be much larger than six elements.
You sum each pair of bytes from the source arrays and if the result is larger then 0xFF you carry 1 to the next byte. A loop is required.
//Adds B to A, Len is the amount of bytes that will be added.
//Make sure that Len <= size of A
void Add(unsigned char *A, unsigned char *B, int Len)
{
int Carry = 0;
//Work backwards because the high byte of your array holds the least significant byte.
for (int i = Len - 1; i >= 0; i--)
{
int Temp = (int) A[i] + B[i];
A[i] = (Temp + Carry) & 0xFF;
if ((Temp + Carry) > 0xFF)
Carry = 1;
else
Carry = 0;
}
}

AES mixColumns error

Now I am learning cryptograpgy. So, (for practice and for fun), I have decided to implement AES. I got stuck in one point (mixing columns here is my code):
typedef vector< vector<short> > vvector;
short mixBox[4][4] =
{
{0x02, 0x03, 0x01, 0x01},
{0x01, 0x02, 0x03, 0x01},
{0x01, 0x01, 0x02, 0x03},
{0x03, 0x01, 0x01, 0x02}
};
short gfMultiply(short h1, short h2)
{
//h1 can 0x01, 0x02 or 0x03
}
void mixColumns(vvector & v)
{
vvector res(v.begin(), v.end());
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
v[i][j] = 0x00;
for(int i=0; i<4; i++)
for(int j=0; j<4; j++)
for(int k=0; k<4; k++)
v[i][j] = v[i][j] ^ gfMultiply(mixBox[i][k], res[k][j]);
}
Theoretically, I understood multiplication gf(2^8), but for implementing algorithm, i have problems. I referred to this site. But either I can not understand some point or I am doing something wrong. In wikipedia I have read this:
"The multiplication operation is defined as: multiplication by 1 means
no change, multiplication by 2 means shifting to the left, and
multiplication by 3 means shifting to the left and then performing xor
with the initial unshifted value. After shifting, a conditional xor
with 0x1B should be performed if the shifted value is larger than
0xFF."
Assuming above I have implemented this:
short gfMultiply(short h1, short h2)
{
//h1 can 0x01, 0x02 or 0x03
short r;
if(h1==0x01)
return h2;
if(h1==0x02)
r = (h2<<1);
else
r = (h2<<1)^h2;
if(r>0xFF)
r = r^0x1b;
return r;
}
But results are incorrect, when I am testing. What I am doing wrong here?
Sorry, for bug. I have fixed it by myself, this is the correct one:
short gfMultiply(short h1, short h2)
{
//h1 can 0x01, 0x02 or 0x03
short r;
if(h1==0x01)
return h2;
if(h1==0x02)
{
r = (h2<<1);
if(r>0xFF)
r = r^0x11b;
}
else
{
r = (h2<<1);
if(r>0xFF)
r = r^0x11b;
r = r^h2;
}
return r;
}

Resources