windows-nt/Source/XPSP1/NT/ds/win32/ntcrypto/randlib/vlhash.c
2020-09-26 16:20:57 +08:00

230 lines
4.8 KiB
C

/*++
Copyright (c) 1998 Microsoft Corporation
Abstract:
Build up a "Very Large Hash" based on arbitrary sized input data
of size cbData specified by the pvData buffer.
This implementation updates a 640bit hash, which is internally based on
multiple invocations of a modified SHA-1 which doesn't implement endian
conversion internally.
Author:
Scott Field (sfield) 24-Sep-98
--*/
#ifndef KMODE_RNG
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#else
#include <ntifs.h>
#include <windef.h>
#endif // KMODE_RNG
#include <sha.h>
#include "vlhash.h"
#ifdef KMODE_RNG
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, VeryLargeHashUpdate)
#endif // ALLOC_PRAGMA
#endif // KMODE_RNG
BOOL
VeryLargeHashUpdate(
IN VOID *pvData, // data from perfcounters, user supplied, etc.
IN DWORD cbData,
IN OUT BYTE VeryLargeHash[A_SHA_DIGEST_LEN * 4]
)
{
//
// pointers to 1/4 size chunks of seed pointed to by VeryLargeHash
//
DWORD cbSeedChunk;
PBYTE pSeed1;
PBYTE pSeed2;
PBYTE pSeed3;
PBYTE pSeed4;
//
// pointers to 1/4 size chunks of data pointed to by pData
//
DWORD cbDataChunk;
PBYTE pData1;
PBYTE pData2;
PBYTE pData3;
PBYTE pData4;
//
// pointers to individual intermediate hash within IntermediateHashes
//
PBYTE IHash1;
PBYTE IHash2;
PBYTE IHash3;
PBYTE IHash4;
BYTE IntermediateHashes[ A_SHA_DIGEST_LEN * 4 ];
//
// pointer to output hash within VeryLargeHash buffer.
//
PBYTE OutputHash;
A_SHA_CTX shaContext;
#ifdef KMODE_RNG
PAGED_CODE();
#endif // KMODE_RNG
//
// check parameters
//
if( VeryLargeHash == NULL || pvData == NULL )
return FALSE;
//
// break up input blocks into 1/4 size chunks.
//
cbSeedChunk = A_SHA_DIGEST_LEN;
cbDataChunk = cbData / 4;
if( cbDataChunk == 0 )
return FALSE;
pSeed1 = VeryLargeHash;
pSeed2 = pSeed1 + cbSeedChunk;
pData1 = (PBYTE)pvData;
pData2 = pData1 + cbDataChunk;
IHash1 = IntermediateHashes;
IHash2 = IHash1 + A_SHA_DIGEST_LEN;
//
// round 1
//
A_SHAInit( &shaContext );
A_SHAUpdateNS( &shaContext, pSeed1, cbSeedChunk );
A_SHAUpdateNS( &shaContext, pData1, cbDataChunk );
A_SHAUpdateNS( &shaContext, pSeed2, cbSeedChunk );
A_SHAUpdateNS( &shaContext, pData2, cbDataChunk );
A_SHAFinalNS( &shaContext, IHash1 );
//
// round 2
//
A_SHAInit( &shaContext );
A_SHAUpdateNS( &shaContext, pSeed2, cbSeedChunk );
A_SHAUpdateNS( &shaContext, pData2, cbDataChunk );
A_SHAUpdateNS( &shaContext, pSeed1, cbSeedChunk );
A_SHAUpdateNS( &shaContext, pData1, cbDataChunk );
A_SHAFinalNS( &shaContext, IHash2 );
pSeed3 = pSeed2 + cbSeedChunk;
pSeed4 = pSeed3 + cbSeedChunk;
pData3 = pData2 + cbDataChunk;
pData4 = pData3 + cbDataChunk;
IHash3 = IHash2 + A_SHA_DIGEST_LEN;
IHash4 = IHash3 + A_SHA_DIGEST_LEN;
//
// round 3
//
A_SHAInit( &shaContext );
A_SHAUpdateNS( &shaContext, pSeed3, cbSeedChunk );
A_SHAUpdateNS( &shaContext, pData3, cbDataChunk );
A_SHAUpdateNS( &shaContext, pSeed4, cbSeedChunk );
A_SHAUpdateNS( &shaContext, pData4, cbDataChunk );
A_SHAFinalNS( &shaContext, IHash3 );
//
// round 4
//
A_SHAInit( &shaContext );
A_SHAUpdateNS( &shaContext, pSeed4, cbSeedChunk );
A_SHAUpdateNS( &shaContext, pData4, cbDataChunk );
A_SHAUpdateNS( &shaContext, pSeed3, cbSeedChunk );
A_SHAUpdateNS( &shaContext, pData3, cbDataChunk );
A_SHAFinalNS( &shaContext, IHash4 );
//
// round 5
//
OutputHash = VeryLargeHash;
A_SHAInit( &shaContext );
A_SHAUpdateNS( &shaContext, IHash1, A_SHA_DIGEST_LEN );
A_SHAUpdateNS( &shaContext, IHash3, A_SHA_DIGEST_LEN );
A_SHAFinalNS( &shaContext, OutputHash );
//
// round 6
//
OutputHash += A_SHA_DIGEST_LEN;
A_SHAInit( &shaContext );
A_SHAUpdateNS( &shaContext, IHash2, A_SHA_DIGEST_LEN );
A_SHAUpdateNS( &shaContext, IHash4, A_SHA_DIGEST_LEN );
A_SHAFinalNS( &shaContext, OutputHash );
//
// round 7
//
OutputHash += A_SHA_DIGEST_LEN;
A_SHAInit( &shaContext );
A_SHAUpdateNS( &shaContext, IHash3, A_SHA_DIGEST_LEN );
A_SHAUpdateNS( &shaContext, IHash1, A_SHA_DIGEST_LEN );
A_SHAFinalNS( &shaContext, OutputHash );
//
// round 8
//
OutputHash += A_SHA_DIGEST_LEN;
A_SHAInit( &shaContext );
A_SHAUpdateNS( &shaContext, IHash4, A_SHA_DIGEST_LEN );
A_SHAUpdateNS( &shaContext, IHash2, A_SHA_DIGEST_LEN );
A_SHAFinalNS( &shaContext, OutputHash );
RtlZeroMemory( &shaContext, sizeof(shaContext) );
RtlZeroMemory( IntermediateHashes, sizeof(IntermediateHashes) );
return TRUE;
}