1 (edited by SteffenL 2013-08-21 17:26:26)

Topic: Generating HMAC-SHA1 digest corrupts memory?

Hello,

I'm seeing memory corruption when generating HMAC-SHA1 digests. This results in a crash or simply incorrect digests.

I also see in the debugger that macType has changed to '6' (54) after calling HmacSetKey. Not sure if that's normal.

Please see code and memory dumps below. Solution/Project files are attached.

Thank you in advance!

Environment

CyaSSL embedded SSL: v2.7.0 from the Github repo (clean, upgraded to VC++ 2012).
Compiler: Visual C++ 2012, update 3.
OS: Windows 8 (x64).

Testing was done using the "Debug" configuration.

Update #1

test1 reads from a file, and shows wrong results.

test2 initializes an array in memory. The result is correct, but the program crashes during debugging:

Run-Time Check Failure #2 - Stack around the variable 'key' was corrupted.

Code:

#include <cyassl/ctaocrypt/hmac.h>
#include <stdio.h>

#pragma comment(lib, "cyassl.lib")

void dump(const unsigned char* data, unsigned int length)
{
    int i = 0;
    for (; i < 20; ++i) {
        printf("%02x", data[i]);
    }
}

unsigned char* readFile(const char* filePath, size_t* fileSize) {
    FILE* fp;
    size_t n;
    size_t totalRead = 0;
    unsigned char* input;

    if (!(fp = fopen(filePath, "rb")))
        return 0;

    fseek(fp, 0, SEEK_END);
    *fileSize = ftell(fp);
    fseek(fp, 0, SEEK_SET);

    input = (unsigned char*)malloc(*fileSize);
    while ((n = fread(input + totalRead, 1, 512, fp)) > 0) {
        totalRead += n;
    }

    return input;
}

void test1()
{
    unsigned char key[] = "0123456789abcdefghij";
    unsigned char input[249];
    unsigned char hash[SHA_DIGEST_SIZE];
    Hmac sha1;
    size_t keyLength;
    size_t inputLength;

    printf("--- Test 1 ---\n");

    memset(hash, 0xaa, SHA_DIGEST_SIZE); // Look for 0xaa in memory dump
    memset(&sha1, 0, sizeof(sha1));

    keyLength = strlen((char*)key);
    inputLength = sizeof(input);
    memset(input, 0, sizeof(input));

    HmacSetKey(&sha1, SHA, key, keyLength);
    HmacUpdate(&sha1, input, inputLength);
    HmacFinal(&sha1, hash);

    printf("Input length: %u bytes\n", inputLength);
    printf("Hash: ");
    dump(hash, sizeof(hash));
    printf("\n");
}

void test2()
{
    unsigned char key[] = "0123456789abcdefghij";
    unsigned char* input;
    unsigned char hash[SHA_DIGEST_SIZE];
    Hmac sha1;
    size_t keyLength;
    size_t inputLength;

    printf("--- Test 2 ---\n");

    memset(hash, 0xaa, SHA_DIGEST_SIZE); // Look for 0xaa in memory dump
    memset(&sha1, 0, sizeof(sha1));

    keyLength = strlen((char*)key);
    input = readFile("test.bin", &inputLength);

    HmacSetKey(&sha1, SHA, key, keyLength);
    HmacUpdate(&sha1, input, inputLength);
    HmacFinal(&sha1, hash);

    printf("Input length: %u bytes\n", inputLength);
    printf("Hash: ");
    dump(hash, sizeof(hash));
    printf("\n");
}

int main()
{
    test1();
    test2();
}

Update #2

test1:
Dump of input before calling HmacSetKey:

0x00CFF948  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ....................
0x00CFF95C  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ....................
0x00CFF970  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ....................
0x00CFF984  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ....................
0x00CFF998  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ....................
0x00CFF9AC  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ....................

Dump again, but after calling HmacSetKey:

0x00CFF948  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ....................
0x00CFF95C  00 00 00 00 00 00 00 00 6c 6d 6e 6f 68 69 6a 6b 64 65 3d 3e  ........lmnohijkde=>
0x00CFF970  3f 38 39 3a 3b 34 35 36 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c  ?89:;456\\\\\\\\\\\\
0x00CFF984  5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c  \\\\\\\\\\\\\\\\\\\\
0x00CFF998  5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 00 00 00 00 00 00 00 00  \\\\\\\\\\\\........
0x00CFF9AC  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ....................

input was overwritten.

test2:
Dump of key before calling HmacSetKey:

0x010FFD98  30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 67 68 69 6a  0123456789abcdefghij
0x010FFDAC  00 cc cc cc cc cc cc cc b3 8c 7e 8c 8c fe 0f 01 a8 15 c5 00  .ÌÌÌÌÌÌÌ.Œ~ŒŒþ..¨.Å.
0x010FFDC0  00 00 00 00 00 00 00 00 00 e0 1d 7f cc cc cc cc cc cc cc cc  .........à..ÌÌÌÌÌÌÌÌ
0x010FFDD4  cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc  ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ
0x010FFDE8  cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc  ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ
0x010FFDFC  cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc  ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ

Dump again, but after calling HmacSetKey:

0x010FFD98  30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66 6c 6d 6e 6f  0123456789abcdeflmno
0x010FFDAC  68 69 6a 6b 64 65 3d 3e 3f 38 39 3a 3b 34 35 36 5c 5c 5c 5c  hijkde=>?89:;456\\\\
0x010FFDC0  5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c  \\\\\\\\\\\\\\\\\\\\
0x010FFDD4  5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c 5c  \\\\\\\\\\\\\\\\\\\\
0x010FFDE8  cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc  ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ
0x010FFDFC  cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc  ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ

key was overwritten.

Update #3

After replacing CyaSSL's HMAC-SHA1 implemention with the one from the following page, all problems disappeared. No crashing, and the digests are correct.

http://www.aarongifford.com/computers/sha.html

Post's attachments

ConsoleApplication2_src.zip 3.59 kb, 1 downloads since 2013-08-20 

You don't have the permssions to download the attachments of this post.

Share

Re: Generating HMAC-SHA1 digest corrupts memory?

Hi Steffen,

Can you check to make sure you have the same preprocessor flags set in both your CyaSSL project file as well as your ConsoleApplication2 project file?  A mismatch in these will cause the internal Sha structure sizes to differ, thus causing problems.

Thanks,
Chris