Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

641 lines
11 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
hash.c
Abstract:
Hash manipulators for the IIS cryptographic package.
The following routines are exported by this module:
IISCryptoCreateHash
IISCryptoDestroyHash
IISCryptoHashData
IISCryptoHashSessionKey
IISCryptoExportHashBlob
IcpGetHashLength
Author:
Keith Moore (keithmo) 02-Dec-1996
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
//
// Private constants.
//
//
// Private types.
//
//
// Private globals.
//
//
// Private prototypes.
//
//
// Public functions.
//
HRESULT
WINAPI
IISCryptoCreateHash(
OUT HCRYPTHASH * phHash,
IN HCRYPTPROV hProv
)
/*++
Routine Description:
This routine creates a new hash object.
Arguments:
phHash - Receives the hash handle if successful.
hProv - A handle to a crypto service provider.
Return Value:
HRESULT - Completion status, 0 if successful, !0 otherwise.
--*/
{
//
// Sanity check.
//
DBG_ASSERT( IcpGlobals.Initialized );
DBG_ASSERT( phHash != NULL );
DBG_ASSERT( hProv != CRYPT_NULL );
//
// Short-circuit if cryptography is disabled.
//
if( !IcpGlobals.EnableCryptography ) {
if( hProv == DUMMY_HPROV ) {
*phHash = DUMMY_HHASH;
return NO_ERROR;
} else {
return RETURNCODETOHRESULT( ERROR_INVALID_PARAMETER );
}
}
//
// Create the hash object.
//
if( CryptCreateHash(
hProv,
IC_HASH_ALG,
CRYPT_NULL,
0,
phHash
) ) {
UpdateHashCreated();
return NO_ERROR;
}
return IcpGetLastError();
} // IISCryptoCreateHash
HRESULT
WINAPI
IISCryptoDestroyHash(
IN HCRYPTHASH hHash
)
/*++
Routine Description:
This routine destroys the specified hash object.
Arguments:
hHash - The hash object to destroy.
Return Value:
HRESULT - Completion status, 0 if successful, !0 otherwise.
--*/
{
//
// Sanity check.
//
DBG_ASSERT( IcpGlobals.Initialized );
DBG_ASSERT( hHash != CRYPT_NULL );
//
// Short-circuit if cryptography is disabled.
//
if( !IcpGlobals.EnableCryptography ) {
if( hHash == DUMMY_HHASH ) {
return NO_ERROR;
} else {
return RETURNCODETOHRESULT( ERROR_INVALID_PARAMETER );
}
}
//
// Destroy it.
//
if( CryptDestroyHash(
hHash
) ) {
UpdateHashDestroyed();
return NO_ERROR;
}
return IcpGetLastError();
} // IISCryptoDestroyHash
HRESULT
WINAPI
IISCryptoHashData(
IN HCRYPTHASH hHash,
IN PVOID pBuffer,
IN DWORD dwBufferLength
)
/*++
Routine Description:
This routine adds the specified data to the hash.
Arguments:
hHash - A hash object handle.
pBuffer - Pointer to the buffer to add to the hash.
dwBufferLength - The buffer length.
Return Value:
HRESULT - Completion status, 0 if successful, !0 otherwise.
--*/
{
//
// Sanity check.
//
DBG_ASSERT( IcpGlobals.Initialized );
DBG_ASSERT( hHash != CRYPT_NULL );
DBG_ASSERT( pBuffer != NULL );
DBG_ASSERT( dwBufferLength > 0 );
//
// Short-circuit if cryptography is disabled.
//
if( !IcpGlobals.EnableCryptography ) {
if( hHash == DUMMY_HHASH ) {
return NO_ERROR;
} else {
return RETURNCODETOHRESULT( ERROR_INVALID_PARAMETER );
}
}
//
// Hash it.
//
if( CryptHashData(
hHash,
(BYTE *)pBuffer,
dwBufferLength,
0
) ) {
return NO_ERROR;
}
return IcpGetLastError();
} // IISCryptoHashData
HRESULT
WINAPI
IISCryptoHashSessionKey(
IN HCRYPTHASH hHash,
IN HCRYPTKEY hSessionKey
)
/*++
Routine Description:
This routine adds the given key object to the hash.
Arguments:
hHash - A hash object handle.
hSessionKey - The session key to add to the hash.
Return Value:
HRESULT - Completion status, 0 if successful, !0 otherwise.
--*/
{
//
// Sanity check.
//
DBG_ASSERT( IcpGlobals.Initialized );
DBG_ASSERT( hHash != CRYPT_NULL );
DBG_ASSERT( hSessionKey != CRYPT_NULL );
//
// Short-circuit if cryptography is disabled.
//
if( !IcpGlobals.EnableCryptography ) {
if( hHash == DUMMY_HHASH &&
hSessionKey == DUMMY_HSESSIONKEY ) {
return NO_ERROR;
} else {
return RETURNCODETOHRESULT( ERROR_INVALID_PARAMETER );
}
}
//
// Hash it.
//
if( CryptHashSessionKey(
hHash,
hSessionKey,
0
) ) {
return NO_ERROR;
}
return IcpGetLastError();
} // IISCryptoHashSessionKey
HRESULT
WINAPI
IISCryptoExportHashBlob(
OUT PIIS_CRYPTO_BLOB * ppHashBlob,
IN HCRYPTHASH hHash
)
/*++
Routine Description:
This routine exports a hash object into a hash blob. Note that unlike
the other blobs created by this package, hash blobs are not encrypted,
nor do they have corresponding digital signatures.
Arguments:
ppHashBlob - Will receive a pointer to the newly created hash blob
if successful.
hHash - The hash object to export.
Return Value:
HRESULT - Completion status, 0 if successful, !0 otherwise.
--*/
{
HRESULT result;
DWORD hashLength;
DWORD hashLengthLength;
PIC_BLOB blob;
//
// Sanity check.
//
DBG_ASSERT( IcpGlobals.Initialized );
DBG_ASSERT( ppHashBlob != NULL );
DBG_ASSERT( hHash != CRYPT_NULL );
//
// Short-circuit if cryptography is disabled.
//
if( !IcpGlobals.EnableCryptography ) {
if( hHash == DUMMY_HHASH ) {
return IISCryptoCreateCleartextBlob(
ppHashBlob,
(PVOID)"",
1
);
} else {
return RETURNCODETOHRESULT( ERROR_INVALID_PARAMETER );
}
}
//
// Setup our locals so we know how to cleanup on exit.
//
blob = NULL;
//
// Determine the length of the hash.
//
hashLengthLength = sizeof(hashLength);
if( !CryptGetHashParam(
hHash,
HP_HASHSIZE,
(BYTE *)&hashLength,
&hashLengthLength,
0
) ) {
result = IcpGetLastError();
goto fatal;
}
//
// Create a new blob.
//
blob = IcpCreateBlob(
HASH_BLOB_SIGNATURE,
hashLength,
0
);
if( blob == NULL ) {
result = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
goto fatal;
}
//
// Get the hash data.
//
if( !CryptGetHashParam(
hHash,
HP_HASHVAL,
BLOB_TO_DATA(blob),
&hashLength,
0
) ) {
result = IcpGetLastError();
goto fatal;
}
DBG_ASSERT( hashLength == blob->DataLength );
//
// Success!
//
DBG_ASSERT( IISCryptoIsValidBlob( (PIIS_CRYPTO_BLOB)blob ) );
*ppHashBlob = (PIIS_CRYPTO_BLOB)blob;
UpdateBlobsCreated();
return NO_ERROR;
fatal:
if( blob != NULL ) {
IcpFreeMemory( blob );
}
DBG_ASSERT( FAILED(result) );
return result;
} // IISCryptoExportHashBlob
IIS_CRYPTO_API
HRESULT
WINAPI
IISCryptoCacheHashLength(
IN HCRYPTPROV hProv
)
/*++
Routine Description:
This routine calls IcpGetHashLength to cache the hash size.
Arguments:
hProv - A handle to a crypto service provider.
Return Value:
HRESULT
--*/
{
DWORD dwDummy = 0;
return IcpGetHashLength( &dwDummy, hProv );
}
HRESULT
IcpGetHashLength(
OUT LPDWORD pdwHashLength,
IN HCRYPTPROV hProv
)
/*++
Routine Description:
This routine determines the digital signature length used by the
given provider. Since we always use the default provider, and
we always use the same hash algorithm, we can retrieve this once,
store it globally, then use that value.
Arguments:
pdwHashLength - Receives the hash length if successful.
hProv - A handle to a crypto service provider.
Return Value:
HRESULT - Completion status, 0 if successful, !0 otherwise.
--*/
{
HRESULT result;
HCRYPTHASH hash;
//
// Sanity check.
//
DBG_ASSERT( IcpGlobals.Initialized );
DBG_ASSERT( IcpGlobals.EnableCryptography );
DBG_ASSERT( pdwHashLength != NULL );
DBG_ASSERT( hProv != CRYPT_NULL );
//
// If the hash length has already been calculated, just use it.
//
if( IcpGlobals.HashLength > 0 ) {
*pdwHashLength = IcpGlobals.HashLength;
return NO_ERROR;
}
//
// Grab the global lock, then check again, just in case another
// thread has already done it.
//
IcpAcquireGlobalLock();
if( IcpGlobals.HashLength > 0 ) {
*pdwHashLength = IcpGlobals.HashLength;
IcpReleaseGlobalLock();
return NO_ERROR;
}
//
// Setup our locals so we know how to cleanup on exit.
//
hash = CRYPT_NULL;
//
// Create a hash object.
//
result = IISCryptoCreateHash(
&hash,
hProv
);
if( FAILED(result) ) {
goto fatal;
}
//
// Hash some random data.
//
if( !CryptHashData(
hash,
(BYTE *)"IIS",
4,
0
) ) {
result = IcpGetLastError();
goto fatal;
}
//
// Attempt to sign the hash to get its length.
//
if( !CryptSignHash(
hash,
AT_SIGNATURE,
NULL,
0,
NULL,
&IcpGlobals.HashLength
) ) {
result = IcpGetLastError();
goto fatal;
}
//
// Success!
//
*pdwHashLength = IcpGlobals.HashLength;
IcpReleaseGlobalLock();
DBG_REQUIRE( SUCCEEDED( IISCryptoDestroyHash( hash ) ) );
return NO_ERROR;
fatal:
if( hash != CRYPT_NULL ) {
DBG_REQUIRE( SUCCEEDED( IISCryptoDestroyHash( hash ) ) );
}
IcpReleaseGlobalLock();
DBG_ASSERT( FAILED(result) );
return result;
} // IcpGetHashLength
//
// Private functions.
//