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.