|
/*
|
|
Copyright (c) 2003, Dominik Reichl <dominik.reichl@t-online.de>
|
|
All rights reserved.
|
|
|
|
LICENSE TERMS
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
* Redistributions of source code must retain the above copyright notice, this
|
|
list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation
|
|
and/or other materials provided with the distribution.
|
|
* Neither the name of ReichlSoft nor the names of its contributors may be used
|
|
to endorse or promote products derived from this software without specific
|
|
prior written permission.
|
|
|
|
DISCLAIMER
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
// A very small self-test.
|
|
|
|
#include "selftest.h"
|
|
|
|
#include "md2.h"
|
|
#include "md5.h"
|
|
|
|
static const UWORD8 MD2HASH_NUMBERS[16] = {
|
|
0xd5, 0x97, 0x6f, 0x79, 0xd8, 0x3d, 0x3a, 0x0d,
|
|
0xc9, 0x80, 0x6c, 0x3c, 0x66, 0xf3, 0xef, 0xd8 };
|
|
static const UWORD8 MD5HASH_NOTHING[16] = {
|
|
0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
|
|
0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e };
|
|
static const UWORD8 MD5HASH_NUMBERS[16] = {
|
|
0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
|
|
0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a };
|
|
static const UWORD8 MD5HMAC_PAD[16] = {
|
|
0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
|
|
0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 };
|
|
|
|
bool rhSelfTest()
|
|
{
|
|
UWORD8 pBuf[128];
|
|
UINTPREF uErrors = 0;
|
|
CHashAlgorithm *pAlgo = NULL;
|
|
CHMAC *pHMAC = NULL;
|
|
RH_DATA_INFO rhData;
|
|
UINTPREF u;
|
|
|
|
printf("ReHash self-test started."); rhNewLine();
|
|
|
|
rhData.pszFileName = "Test";
|
|
rhData.uDataLen = 0;
|
|
|
|
// Test if the types were compiled correctly
|
|
printf("Testing types..."); rhNewLine();
|
|
u = _rhTestTypes();
|
|
if(u != 0)
|
|
{
|
|
if(u != 1)
|
|
{
|
|
printf("%u-bit type not defined correctly.", u); rhNewLine();
|
|
}
|
|
else
|
|
{
|
|
printf("Preferred type not defined correctly."); rhNewLine();
|
|
}
|
|
|
|
uErrors++;
|
|
}
|
|
else
|
|
{
|
|
printf("Types test passed."); rhNewLine();
|
|
}
|
|
|
|
printf("Testing MD2 hash..."); rhNewLine();
|
|
pAlgo = new CMD2Hash;
|
|
if(pAlgo == NULL)
|
|
{
|
|
printf("Error: Cannot select MD2 algorihtm."); rhNewLine();
|
|
uErrors++;
|
|
}
|
|
else
|
|
{
|
|
pAlgo->Init(&rhData);
|
|
pAlgo->Update((UWORD8 *)"12345678901234567890123456789012345678901234567890123456789012345678901234567890", 80);
|
|
pAlgo->Final();
|
|
pAlgo->GetHash(pBuf);
|
|
if(memcmp(pBuf, MD2HASH_NUMBERS, 16) != 0)
|
|
{
|
|
printf("Error: MD2 hash not correct for numbers vector."); rhNewLine();
|
|
uErrors++;
|
|
}
|
|
|
|
delete pAlgo;
|
|
pAlgo = NULL;
|
|
}
|
|
printf("MD2 test finished."); rhNewLine();
|
|
|
|
printf("Testing MD5 hash..."); rhNewLine();
|
|
pAlgo = new CMD5Hash;
|
|
if(pAlgo == NULL)
|
|
{
|
|
printf("Error: Cannot select MD5 algorithm."); rhNewLine();
|
|
uErrors++;
|
|
}
|
|
else // MD5 loaded successfully
|
|
{
|
|
pAlgo->Init(&rhData);
|
|
pAlgo->Final();
|
|
pAlgo->GetHash(pBuf);
|
|
if(memcmp(pBuf, MD5HASH_NOTHING, 16) != 0)
|
|
{
|
|
printf("Error: MD5 hash not correct for vector <nothing>."); rhNewLine();
|
|
uErrors++;
|
|
}
|
|
|
|
pAlgo->Init(&rhData);
|
|
pAlgo->Update((UWORD8 *)"12345678901234567890123456789012345678901234567890123456789012345678901234567890", 80);
|
|
pAlgo->Final();
|
|
pAlgo->GetHash(pBuf);
|
|
if(memcmp(pBuf, MD5HASH_NUMBERS, 16) != 0)
|
|
{
|
|
printf("Error: MD5 hash not correct for the numbers vector."); rhNewLine();
|
|
uErrors++;
|
|
}
|
|
|
|
pHMAC = new CHMAC;
|
|
pHMAC->SetHashAlgorithm(pAlgo);
|
|
memset(pBuf, 0xAA, 16);
|
|
pHMAC->SetKey(pBuf, 16);
|
|
pHMAC->Init(&rhData);
|
|
memset(pBuf, 0xDD, 50);
|
|
pHMAC->Update(pBuf, 50);
|
|
pHMAC->Final();
|
|
pHMAC->GetHash(pBuf);
|
|
|
|
if(memcmp(pBuf, MD5HMAC_PAD, 16) != 0)
|
|
{
|
|
printf("Error: MD5-HMAC not correct for 0xAA-0xDD vector."); rhNewLine();
|
|
uErrors++;
|
|
}
|
|
|
|
delete pHMAC; pHMAC = NULL;
|
|
|
|
delete pAlgo; pAlgo = NULL;
|
|
}
|
|
printf("MD5 test finished."); rhNewLine();
|
|
|
|
rhNewLine();
|
|
printf("----------------------------------------------------------------");
|
|
rhNewLine();
|
|
printf("There were %u errors.", uErrors);
|
|
rhNewLine();
|
|
|
|
if(uErrors == 0) return true;
|
|
return false;
|
|
}
|
|
|
|
// For ReHash it's essential that the types UWORD8, UWORD16, UWORD32 and
|
|
// UWORD64 are defined correctly
|
|
// This function should not output anything to the console
|
|
UINTPREF _rhTestTypes()
|
|
{
|
|
UWORD8 u8; UWORD16 u16; UWORD32 u32; UWORD64 u64; UINTPREF upref;
|
|
|
|
u8 = 0xFF; // Simple arithmetic test
|
|
if((u8 - 1) != 0xFE) return 8;
|
|
u8++; // Overflow test
|
|
if(u8 != 0) return 8;
|
|
u8 = 0x80; u8 <<= 1; // Shift test
|
|
if(u8 != 0) return 8;
|
|
u8 >>= 1; // Unshift bit loss test
|
|
if(u8 != 0) return 8;
|
|
u8 = 0; u8--; // Negative overflow test
|
|
if(u8 != 0xFF) return 8;
|
|
|
|
u16 = 0xFFFF; // Simple arithmetic test
|
|
if((u16 - 1) != 0xFFFE) return 16;
|
|
u16++; // Overflow test
|
|
if(u16 != 0) return 16;
|
|
u16 = 0x8000; u16 <<= 1; // Shift test
|
|
if(u16 != 0) return 16;
|
|
u16 >>= 1; // Unshift bit loss test
|
|
if(u16 != 0) return 16;
|
|
u16 = 0; u16--; // Negative overflow test
|
|
if(u16 != 0xFFFF) return 16;
|
|
|
|
u32 = CONST32(0xFFFFFFFF); // Simple arithmetic test
|
|
if((u32 - 1) != CONST32(0xFFFFFFFE)) return 32;
|
|
u32++; // Overflow test
|
|
if(u32 != 0) return 32;
|
|
u32 = CONST32(0x80000000); u32 <<= 1; // Shift test
|
|
if(u32 != 0) return 32;
|
|
u32 >>= 1; // Unshift bit loss test
|
|
if(u32 != 0) return 32;
|
|
u32 = 0; u32--; // Negative overflow test
|
|
if(u32 != CONST32(0xFFFFFFFF)) return 32;
|
|
|
|
u64 = CONST64(0xFFFFFFFFFFFFFFFF); // Simple arithmetic test
|
|
if((u64 - 1) != CONST64(0xFFFFFFFFFFFFFFFE)) return 64;
|
|
u64++; // Overflow test
|
|
if(u64 != 0) return 64;
|
|
u64 = CONST64(0x8000000000000000); u64 <<= 1; // Shift test
|
|
if(u64 != 0) return 64;
|
|
u64 >>= 1; // Unshift bit loss test
|
|
if(u64 != 0) return 64;
|
|
u64 = 0; u64--; // Negative overflow test
|
|
if(u64 != CONST64(0xFFFFFFFFFFFFFFFF)) return 64;
|
|
|
|
// Some tests for the preferred variable type
|
|
upref = 0xFF; upref++; // Must not overflow here
|
|
if(upref == 0) return 1;
|
|
upref = 0xFFFF; upref++; // Must not overflow here
|
|
if(upref == 0) return 1;
|
|
upref = 0; upref--; // Test negative overflow
|
|
if(upref <= 0xFFFF) return 1;
|
|
upref = 1 << 31; // Test shifting
|
|
if(upref == 0) return 1;
|
|
|
|
return 0;
|
|
}
|