0

I am currently working on a project that will eventually implement a hmac-sha1 system. Right now I am fairly close to the beginning of the project, so I am just working on getting my sha1 function to play nice with one another. The one I am currently having issues with is calling the function that handles the sha1 iterations.

So I have a function that takes in an unsigned char array, and the state variables for sha1, it then, in a for loop, will send the char array(converted to 16 byte unsigned integer array) to the interation function a total of 80 times.

void sha1Block( unsigned char data[ 64 ], SHA1State *state )
for (int i = 0; i < 80; i++) {
        sha1Iteration(*((unsigned int *)data), &a, &b, &c, &d, &e, i); // This is my issue
    }

Unfortunately, in my class, we never discussed how to convert char arrays into integer arrays, so trying to convert an unsigned char array of 64 characters to 16 unsigned integers is causing me many issues.

This is the iteration function that is being called:

void sha1Iteration( unsigned int data[ 16 ], unsigned int *a, unsigned int *b,
unsigned int *c, unsigned int *d, unsigned int *e, int i )

I have managed, so far, to get everything is this function more or less working to the point it is not throwing errors, so I really just need some assistance figuring out how to convert the array of 64 unsigned characters to an array of 16 unsigned integers

  • How to go about doing this will depend upon how `sha1Iteration` is using the data. Can you please _edit_ your post and add the entire `sha1Iteration` function? – Craig Estey Nov 07 '20 at 19:46

1 Answers1

1

It would be tempting to suggest that you've just had one extra asterisk and removing it would make your code work correctly:

sha1Iteration((unsigned int *)data, ...

 

But unfortunately it is not possible to cast an arbitrary character pointer to unsigned int pointer in C due to two reasons: it would violate two rules: alignment and strict aliasing. While it might work on some compilers and in debug builds, it is most likely horribly broken when optimization is enabled (e.g. crash the entire process if data happens to be misaligned for unsigned int type).

Therefore you need to carefully implement it so that

  • if the machine endianness is correct for the algorithm,

    • either memcpy each 4 bytes to unsigned intuint32_t value individually, or
    • memcpy the entire buffer to array of uint32_ts
  • or use bitshifts and ors to construct uint32_ts from consecutive bytes, i.e. something like

    uint32_t value = (uint32_t)data[0]       | (uint32_t)data[1] << 8 | 
                     (uint32_t)data[2] << 16 | (uint32_t)data[3] << 24;
    
  • Hi, so I mostly(?) understand what you mean, though I have never covered the use of uint32_t but from what I understand, they store guaranteed 32 bits, but since I need to convert a 64 byte array of chars I would need a total of 16 of these in an array. But I then would need to convert(?) the array of uint32_t value[16] to unsigned integer array which is what my sha1Iteration function requires( I can't change this) – Josh Avery Nov 07 '20 at 22:17
  • @JoshAvery An unsigned int is not guaranteed to hold 32 bits, it can be anything. `uint32_t` guarantees exact 32 bit representation and that's what you should use for an algorithm like this. And if you **really** cannot change the `sha1Iteration` function *at all*, then you **must** make a copy of the entire array to an array of `uint32_t`, so make a loop that advances the index for the uint32_t array and for the character array and do for example the bitshift copy for each of the 16 items. – Antti Haapala -- Слава Україні Nov 08 '20 at 09:23
  • @JoshAvery to be more precise, since `unsigned int` can be anything from 16 bits upwards, and you *do* need (exactly) 32-bit integers for this algorithm, use 'uint32_t`. – Antti Haapala -- Слава Україні Nov 09 '20 at 05:54