Copying unsigned char array to uint32_t, and vice versa - c

I'm trying to iteratively copy an unsigned char array to a uint_32t variable (in 4 byte blocks), perform some operation on the uint_32t variable, and copy it back to the unsigned char array.
Here's my code:
unsigned char byteArray[len]
for (int i=0; i<len; i+=4) {
uint32_t tmpInt = 0;
memcpy(&tmpInt, byteArray+(i*4), sizeof(uint32_t));
// do some operation on tmpInt here
memcpy((void*)(byteArray+(i*4)), &tmpInt, sizeof(uint32_t));
}
It doesn't work though. What's wrong, and how can I achieve what I want to do?

The problem is that you are adding 4 to i with each iteration and multiplying by 4. You should be using byteArray + i.
Also, as #WeatherVane pointed out below, your loop would be more consistent with a sizeof():
for (int i = 0; i < len; i += sizeof(uint32_t)).

As others pointed out you are doing too much by incrementing i as well as multiplying it by the size of your target.
On top of this
the code shown might run into a buffer overflow issue reading beyond the source array.
the sizeof operator evaluates to size_t not int.
the code repeats defining the size of the target independently several times.
Fixing all, the result might look like this:
unsigned char byte_array[len];
typedef uint32_t target_type;
const size_t s = sizeof (target_type);
for (size_t i = 0; i < (len/s)*s; i += s) {
target_type target;
memcpy(&target, byte_array + i, s);
// do some operation on target here
memcpy(byte_array + i, &target, s);
}
To avoid the typedef just define the target outside of the for-loop:
unsigned char byte_array[len];
{
uint32_t target;
const size_t s = sizeof target;
for (size_t i = 0; i < (len/s)*s; i += s) {
memcpy(&target, byte_array + i, s);
// do some operation on target here
memcpy(byte_array + i, &target, s);
}
}
An equivalent to
byte_array + i
would be
&byte_array[i]
which might be more intuitively to read.
To avoid the "strange" (len/s)*s one could step away from using an index at all, but use a pointer instead:
for (unsigned char p = byte_array; p < byte_array + len; p += s) {
memcpy(&target, p, s);
// do some operation on target here
memcpy(p, &target, s);
}
In my opinion this is a more elegant solution.

Related

How to alter pointer value within a function in C

I was wondering if you could help me overcome a hurdle I've run into with my C syntax. I have written the function:
binary_and_trim(char *password, unsigned *key1, unsigned *key2)
that has achieved the goal of converting a provided string into binary and trimmed off the leading zero. I have assigned my key1 and key2 pointers to the correct indexes. But then, when I return to the main function the values are all lost.
I believe that the problem is that when I pass the *key1/*key2 pointers to the function it only receives a copy of them. But, as I am new to C, I don't know how to fix it?
I created a for loop to help me test/debug.
#include <stdio.h>
#include <string.h>
void binary_and_trim(char *password, unsigned *key1, unsigned *key2);
unsigned int get_n_bits(unsigned *bits, int width, int index);
int main(int argc, const char * argv[]) {
unsigned *key1 = NULL;
unsigned *key2 = NULL;
binary_and_trim("password", key1, key2);
//This test fails with a EXC_BAD_ACCESS error
for(int i = 0 ; i < 28; i++){
printf("key1[%d] %u key2[%d] %d\n", i, key1[i], i, (key2 + i));
}
}
void binary_and_trim(char *password, unsigned *key1, unsigned *key2){
char c;
int count = 0;
unsigned tmp;
unsigned long len = strlen(password);
unsigned trimmedbinary[len * 7];
for(int i = 0; i < len; i++){
c = *(password + i);
for( int j = 6; j >= 0; j--) {
tmp = 0;
if(c >> j & 1){
tmp = 1;
}
*(trimmedbinary + count) = tmp;
count++;
}
}
key1 = trimmedbinary;
key2 = &trimmedbinary[28];
//This test works correctly!!!
for(int i = 0 ; i < 28; i++){
printf("key1[%d] %d key2[%d] %d\n", i, *(key1 + i), i, *(key2 + i));
}
}
I believe that the problem is that when I pass the *key1/*key2 pointers to the function it only receives a copy of them.
Yes, exactly. Pointers are just integers and integers get copied. You solve this with a pointer to a pointer, a "double pointer".
However, there is another problem. trimmedbinary is using stack/automatic memory. "Automatic" meaning it will be freed once the function exits. Once the function returns key1 and key2 will point at freed memory. trimmedbinary must be declared in heap/dynamic memory with malloc.
void binary_and_trim(char *password, unsigned int **key1, unsigned int **key2){
unsigned int *trimmedbinary = malloc(len * 7 * sizeof(unsigned int));
...
*key1 = trimmedbinary;
*key2 = &trimmedbinary[28];
for(int i = 0 ; i < 28; i++) {
printf("key1[%d] %u, key2[%d] %u\n", i, (*key1)[i], i, (*key2)[i]);
}
return;
}
And call it as binary_and_trim("password", &key1, &key2);
Update: I answered the question about how to alter the pointer value, but I have not noticed the memory issue in the code. Please refer to this answer instead.
Pointers are variables themselves. You may already know that with a pointer, you can change the value stored in the variable the pointer points to. Therefore, you need to use a pointer to a pointer to change the value (the memory address) stored in the pointer.
Change your function signature to:
void binary_and_trim(char *password, unsigned **key1, unsigned **key2)
Call with:
binary_and_trim("password", &key1, &key2);
and replace key1 and key2 to *key1 and *key2 in the function definition.
Your problem is that the variable you use to fill with your keys data trimmedbinary is allocated only for the scope of the function binary_and_trim. That said, when you print inside the function
void binary_and_trim(char *password, unsigned **key1, unsigned **key2){
...
unsigned trimmedbinary[len * 7]; // <--
...
*key1 = trimmedbinary; // <--
*key2 = &trimmedbinary[28]; // <--
//This test works correctly!!!
for(int i = 0 ; i < 28; i++){
printf("key1[%d] %d key2[%d] %d\n", i, *(key1 + i), i, *(key2 + i));
}
}
it just works because the data your key1 pointer is trying to access is still there.
However, when you return from your function back to main, key1 and key2 still point back to the buffer you initialized inside binary_and_trim, which is no longer valid because is out of scope.
I suggest you create a buffer in main and pass it as a parameter,
int main(int argc, const char * argv[]) {
const char* password = "password";
unsigned long len = strlen(password);
unsigned buffer[len * 7]; // <-- Add buffer here
unsigned *key1 = NULL;
unsigned *key2 = NULL;
binary_and_trim(password, &key1, &key2, &buffer, len * 7);
//This test succeeds
for(int i = 0 ; i < 28; i++){
printf("key1[%d] %u key2[%d] %d\n", i, key1[i], i, (key2 + i));
}
}
void binary_and_trim(char *password, unsigned **key1, unsigned **key2, unsigned** buffer, size_t buff_size){
char c;
int count = 0;
unsigned tmp;
...
//Use *buffer instead of trimmedbinary
//Check if buff_size matches len(password) * 7
or alternatively, make the buffer heap allocated (dont forget to free() later).
I believe that the problem is that when I pass the *key1/*key2
pointers to the function it only receives a copy of them.
Already altered in code as well.
Wow! Thank you EVERYONE! I finally got it up and running (after 4 hours of beating my head against the wall). I can't begin to say how clutch you all are.
I'm realizing I have tons to learn about the granular memory access of C (I'm used to Java). I can't wait to be an actual WIZARD like you all!

Store unsigned short inside a char*?

Here is my following code, in my for loop I'm trying to store an unsigned short int inside of the char* memory created by malloc. I'm indexing to do this and I would like to keep it that way if possible.
However, inside myMemory when printing out a sizeof(myMemory[0]) or even printing out the address myMemory[0] itself, it seems that the integer value of p is being stored, not the unsigned short int. The integer itself is correct, but the byte size is 1, not 2, hence not an unsigned short int.
char* myMemory;
typedef unsigned short int R;
void main(){
R *p:
myMemory = malloc(65536)
for (int i = 0; i<36;i++){
myMemory[i] = p;
i++;
myMemory[i] = p;
p++;
p++;
}
printf("testing size of an index %d\n",sizeof(myMemory[2]));
}
I think you're looking for
char* myMemory = malloc(sizeof(*p) * 36);
for (int i=0; i<36; ++i) {
memcpy(myMemory+i, p, sizeof(*p));
i += sizeof(*p);
++p;
}
But you could simply use
char* myMemory = malloc(sizeof(*p) * 36);
memcpy(myMemory, p, sizeof(*p) * 36);
p += 36;
Note that incrementing a pointer causes it to move forward to the next element, so ++p advanced the pointer by sizeof(*p) bytes, and p += 36 advances it by sizeof(*p) * 36 bytes.

C - Write access violation

I have an error at the last line, in nullString, a function setting all the string to '\0' with a simple for()
void function ( unsigned char inputArray[], size_t inputSize )
{
size_t cellSize;
if (inputSize <= 256)
cellSize = 1;
else
cellSize = ceil(inputSize / 2 / 256) + 1;
// Sub Box
unsigned char subBox[255];
for (size_t line = 0; line < 255; line++)
subBox[line] = 0;
generate_SubBox(subBox, key);
// Sub Box
// Sub Box reverse
unsigned char subBox_Inverse[255];
for (size_t line = 0; line < 255; line++)
subBox_Inverse[line] = 0;
generate_SubBox_Inverse(subBox_Inverse, subBox, key);
// Sub Box reverse
unsigned char* inputArray2 = NULL;
inputArray2 = malloc(sizeof(unsigned char)* inputSize / 2);
verifyMalloc(inputArray2);
nullString(inputArray2, inputSize / 2);
unsigned char string_temp[3] = { 0 };
size_t w = 0;
for (size_t i = 0; i < inputSize / 2; i++)
{
string_temp[0] = inputArray[w];
string_temp[1] = inputArray[w + 1];
inputArray2[i] = strtoll(string_temp, NULL, 16);
w += 2;
}
}
I tried neutralizing line per line all instructions coming before nullString() by commenting them but it doesn't change anything.
If I neutralize nullString, the error comes after, at
inputArray2[i] = strtoll(...)
Hope you've got the answer :)
Thanks in advance !
EDIT:
Here is nullString:
void nullString(unsigned char input[], size_t length)
{
for (size_t x = 0; x < length; x++)
input[x] = '\0';
}
I commented all the instructions before nullString, the error is still there.
I also verified variables and they all look like good
EDIT 2:
verifyMalloc:
void verifyMalloc(int* pointer)
{
if (pointer == NULL)
{
perror("Erreur");
Sleep(15000);
exit(0);
}
}
Everything we're seeing is seriously hinting at you forgetting to #include <stdlib.h> (and ignoring the warnings resulting from that).
This is what might happens when you use malloc() without including stdlib.h in the same file:
the compiler consider the malloc() function to be declared implicitly, which means it is assuming that it's return types is int (instead of *void).
This might work when sizeof (int) is the same as sizeof (*void). But when int is 32-bits while pointers are 64-bits then the address returned by malloc() might lose half of it's bits and point to an invalid address.
Try using
void bzero(void *s, size_t n); or
void *memset(void *s, int c, size_t n);
instead of your nullString() and for()something[x]=0 loops.
Then, this does not make all of the array zeroed:
unsigned char string_temp[3] = { 0 };
This makes
string[0] = 0;
string[1] = god_knows;
string[2] = god_knows_not;
so either - unsigned char string_temp[3] = {0,0,0};
or bzero(string_temp,3);
Consequently, when you do this:
string_temp[0] = inputArray[w];
string_temp[1] = inputArray[w + 1];
inputArray2[i] = strtoll(string_temp, NULL, 16);
strtoll() will be guessing when to stop. No guarantee this would be at string_temp[2].
Then, this should be enough:
unsigned char* inputArray2 = malloc(sizeof(unsigned char) * inputSize / 2);
inputArray2 will be NULL if malloc failed, or a valid pointer if it succeeded.
You may want to check your inputSize / this_and_that arithmetics. Does it really deliver what you expect? You might be surprised by division result of integer operands.
This also looks suspicious:
inputArray2[i] = strtoll(string_temp, NULL, 16);
strtoll returns longlong integer but your inputArray2 is of unsigned char type. So you are trying to store 8 bytes (sizeof longlong = 8) and you reserved place only for one (sizeof char = 1)
Redeclare your inputArray2 as long long
long long *inputArray2 = malloc(sizeof(long long) * inputSize /2 );
And try this with memset():
size_t size = sizeof(long long) * inputSize/2;
//Do you really need long long? You are storing max three digits. uint_8 will be enough
long long* inputArray2 = malloc(size);
memset(inputArray2, 0, size);

Increment Char Array Pointer

Is it possible to increment/advance a char array like I can a char pointer?
For example I can do this for a char pointer:
while (*cPtr)
printf("c=%c\n", *(cPtr++));
But I am not able to do this:
// char cArray[] = "abcde";
while (*cArray)
printf("c=%c\n", *(cArray++)); // Compile error: 19 26 [Error] lvalue required as increment operand
The purpose is to be able to iterate over a char array when I dont know the length of the array. My thinking is that I just want to advance till I find a null character I guess unless theres an easier way?
char a[] = "abcde";
int index = -1;
while (a[++index])
printf("c=%c\n", a[index]);
Is it possible to increment/advance a char array like I can a char pointer?
Unlike pointers, arrays are not lvalues and you can't modify it. That's a major difference between arrays and pointers.
Do something like that:
char cArray[] = "abc def";
char *p = &cArray[0];
while (*p)
printf("c=%c\n", *(p++));
You can do:
for(int i = 0; i < 5; i++) // if you know the length
printf("c=%c\n", a[i]);
or get the size with sizeof() and replace i < 5 with i < size:
int size = (sizeof(a) / sizeof(*a))
I have used this with success under keil uVision:
char buffer[512];
uint8_t var[512]; // uint8_t = integer 8bit
for(int i = 0; i < 128; i = i + 4)
sprintf(&buffer[i],"%03d,", var[y]); //this will put 4 bytes in buffer
Better way to do this:
char buffer[128];
uint8_t int_buffer[24]; // gets updated in an interrupt - some sensors values
uint8_t i = 0;
uint8_t PrintSize = 0;
while(/*myFile is smaller than 1Mb..*/)
{
PrintSize = 0;
i = 0;
while(i < 23)
{
PrintSize += sprintf(buffer + PrintSize,"%01d,",int_buffer[i]);
i++;
}
PrintSize += sprintf(buffer + PrintSize,"%01d\n", int_buffer[23]);
//write buffer to a file in my app
}
File content is like this:
41,1,210,243,120,0,210,202,170,0,14,28,0,0,0,1,85,0,5,45,0,0,0,1
40,1,215,255,119,0,215,255,170,0,14,37,0,0,0,1,85,0,5,46,0,0,0,1

Adding Zero padding to an array

I am doing a GHASH for the AES-GCM implementation.
and i need to implement this
where v is the bit length of the final block of A, u is the bit length of the final block of C, and || denotes concatenation of bit strings.
How can I do the concatenation of A block to fill in the zeros padding from v to 128 bit, as I do not know the length of the whole block of A.
So I just take the A block and XOR it with an array of 128 bits
void GHASH(uint8_t H[16], uint8_t len_A, uint8_t A_i[len_A], uint8_t len_C,
uint8_t C_i[len_C], uint8_t X_i[16]) {
uint8_t m;
uint8_t n;
uint8_t i;
uint8_t j;
uint8_t zeros[16] = {0};
if (i == m + n) {
for(j=16; j>=0; j--){
C_i[j] = C_i[j] ^ zeros[j]; //XOR with zero array to fill in 0 of length 128-u
tmp[j] = X_i[j] ^ C_i[j]; // X[m+n+1] XOR C[i] left shift by (128bit-u) and store into tmp
gmul(tmp, H, X_i); //Do Multiplication of tmp to H and store into X
}
}
I am pretty sure that I am not correct. But I have no idea how to do it.
It seems to me that you've got several issues here, and conflating them is a big part of the problem. It'll be much easier when you separate them.
First: passing in a parameter of the form uint8_t len_A, uint8_t A_i[len_A] is not proper syntax and won't give you what you want. You're actually getting uint8_t len_A, uint8_t * A_i, and the length of A_i is determined by how it was declared on the level above, not how you tried to pass it in. (Note that uint8_t * A and uint8_t A[] are functionally identical here; the difference is mostly syntactic sugar for the programmer.)
On the level above, since I don't know if it was declared by malloc() or on the stack, I'm not going to get fancy with memory management issues. I'm going to use local storage for my suggestion.
Unit clarity: You've got a bad case going on here: bit vs. byte vs. block length. Without knowing the core algorithm, it appears to me that the undeclared m & n are block lengths of A & C; i.e., A is m blocks long, and C is n blocks long, and in both cases the last block is not required to be full length. You're passing in len_A & len_C without telling us (or using them in code so we can see) whether they're the bit length u/v, the byte length of A_i/C_i, or the total length of A/C, in bits or bytes or blocks. Based on the (incorrect) declaration, I'm assuming they're the length of A_i/C_i in bytes, but it's not obvious... nor is it the obvious thing to pass. By the name, I would have guessed it to be the length of A/C in bits. Hint: if your units are in the names, it becomes obvious when you try to add bitLenA to byteLenB.
Iteration control: You appear to be passing in 16-byte blocks for the i'th iteration, but not passing in i. Either pass in i, or pass in the full A & C instead of A_i & C_i. You're also using m & n without setting them or passing them in; the same issue applied. I'll just pretend they're all correct at the moment of use and let you fix that.
Finally, I don't understand the summation notation for the i=m+n+1 case, in particular how len(A) & len(C) are treated, but you're not asking about that case so I'll ignore it.
Given all that, let's look at your function:
void GHASH(uint8_t H[], uint8_t len_A, uint8_t A_i[], uint8_t len_C, uint8_t C_i[], uint8_t X_i[]) {
uint8_t tmpAC[16] = {0};
uint8_t tmp[16];
uint8_t * pAC = tmpAC;
if (i == 0) { // Initialization case
for (j=0; j<len_A; ++j) {
X_i[j] = 0;
}
return;
} else if (i < m) { // Use the input memory for A
pAC = A_i;
} else if (i == m) { // Use temp memory init'ed to 0; copy in A as far as it goes
for (j=0; j<len_A; ++j) {
pAC[j] = A_i[j];
}
} else if (i < m+n) { // Use the input memory for C
pAC = C_i;
} else if (i == m+n) { // Use temp memory init'ed to 0; copy in C as far as it goes
for (j=0; j<len_A; ++j) {
pAC[j] = C_i[j];
}
} else if (i == m+n+1) { // Do something unclear to me. Maybe this?
// Use temp memory init'ed to 0; copy in len(A) & len(C)
pAC[0] = len_A; // in blocks? bits? bytes?
pAC[1] = len_C; // in blocks? bits? bytes?
}
for(j=16; j>=0; j--){
tmp[j] = X_i[j] ^ pAC[j]; // X[m+n+1] XOR A or C[i] and store into tmp
gmul(tmp, H, X_i); //Do Multiplication of tmp to H and store into X
}
}
We only copy memory in the last block of A or C, and use local memory for the copy. Most blocks are handled with a single pointer copy to point to the correct bit of input memory.
if you don't care about every little bit of efficiency (i assume this is to experiment, and not for real use?) just reallocate and pad (in practice, you could round up and calloc when you first declare these):
size_t round16(size_t n) {
// if n isn't a multiple of 16, round up to next multiple
if (n % 16) return 16 * (1 + n / 16);
return n;
}
size_t realloc16(uint8_t **data, size_t len) {
// if len isn't a multiple of 16, extend with 0s to next multiple
size_t n = round16(len);
*data = realloc(*data, n);
for (size_t i = len; i < n; ++i) (*data)[i] = 0;
return n;
}
void xor16(uint8_t *result, uint8_t *a, uint8_t *b) {
// 16 byte xor
for (size_t i = 0; i < 16; ++i) result[i] = a[i] ^ b[i];
}
void xorandmult(uint8_t *x, uint8_t *data, size_t n, unint8_t *h) {
// run along the length of the (extended) data, xoring and mutliplying
uint8_t tmp[16];
for (size_t i = 0; i < n / 16; ++i) {
xor16(tmp, x, data+i*16);
multgcm(x, h, tmp);
}
}
void ghash(uint8_t *x, uint8_t **a, size_t len_a, uint8_t **c, size_t len_c, uint8_t *h) {
size_t m = realloc16(a, len_a);
xorandmult(x, *a, m, h);
size_t n = realloc16(c, len_c);
xorandmult(x, *c, n, h);
// then handle lengths
}
uint8_t x[16] = {0};
ghash(x, &a, len_a, &c, len_c, h);
disclaimer - no expert, just skimmed the spec. code uncompiled, unchecked, and not intended for "real" use. also, the spec supports arbitrary (bit) lengths, but i assume you're working in bytes.
also, i am still not sure i am answering the right question.

Resources