|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
blob.c
Abstract:
Generic blob manipulators for the IIS cryptographic package.
The following routines are exported by this module:
IISCryptoReadBlobFromRegistry IISCryptoWriteBlobToRegistry IISCryptoIsValidBlob IISCryptoFreeBlob IISCryptoCompareBlobs IISCryptoCloneBlobFromRawData IISCryptoCreateCleartextBlob IcpCreateBlob
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 IISCryptoReadBlobFromRegistry( OUT PIIS_CRYPTO_BLOB * ppBlob, IN HKEY hRegistryKey, IN LPCTSTR pszRegistryValueName )
/*++
Routine Description:
This routine creates a new blob, reading the blob out of the registry.
Arguments:
ppBlob - Receives a pointer to the newly created blob if successful.
hRegistryKey - An open handle to a registry key.
pszRegistryValueName - The name of the REG_BINARY registry value containing the blob.
Return Value:
HRESULT - Completion status, 0 if successful, !0 otherwise.
--*/
{
HRESULT result; PIIS_CRYPTO_BLOB blob; long status; DWORD type; long length;
//
// Sanity check.
//
DBG_ASSERT( IcpGlobals.Initialized ); DBG_ASSERT( ppBlob != NULL ); DBG_ASSERT( hRegistryKey != NULL ); DBG_ASSERT( pszRegistryValueName != NULL );
//
// Setup our locals so we know how to cleanup on exit.
//
blob = NULL;
//
// Determine the size of the blob.
//
length = 0;
status = RegQueryValueEx( hRegistryKey, pszRegistryValueName, NULL, &type, NULL, ( LPDWORD )&length );
if( status != NO_ERROR ) { result = RETURNCODETOHRESULT(status); goto fatal; }
//
// Allocate a new blob.
//
blob = IcpAllocMemory( length );
if( blob == NULL ) { result = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); goto fatal; }
//
// Read the blob.
//
status = RegQueryValueEx( hRegistryKey, pszRegistryValueName, NULL, &type, (LPBYTE)blob, ( LPDWORD )&length );
if( status != NO_ERROR ) { result = RETURNCODETOHRESULT(status); goto fatal; }
//
// Validate the blob.
//
if( !IISCryptoIsValidBlob( blob ) ) { result = HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ); goto fatal; }
//
// Success!
//
*ppBlob = blob;
UpdateBlobsCreated(); return NO_ERROR;
fatal:
if( blob != NULL ) { IcpFreeMemory( blob ); }
DBG_ASSERT( FAILED(result) ); return result;
} // IISCryptoReadBlobFromRegistry
HRESULT WINAPI IISCryptoWriteBlobToRegistry( IN PIIS_CRYPTO_BLOB pBlob, IN HKEY hRegistryKey, IN LPCTSTR pszRegistryValueName )
/*++
Routine Description:
This routine writes the given blob to the given registry location.
Arguments:
pBlob - A pointer to the blob to write.
hRegistryKey - An open handle to a registry key.
pszRegistryValueName - The name of the REG_BINARY registry value that will receive the blob.
Return Value:
HRESULT - Completion status, 0 if successful, !0 otherwise.
--*/
{
long status;
//
// Sanity check.
//
DBG_ASSERT( IcpGlobals.Initialized ); DBG_ASSERT( pBlob != NULL ); DBG_ASSERT( IISCryptoIsValidBlob( pBlob ) ); DBG_ASSERT( hRegistryKey != NULL ); DBG_ASSERT( pszRegistryValueName != NULL );
//
// Write the blob.
//
status = RegSetValueEx( hRegistryKey, pszRegistryValueName, 0, REG_BINARY, (LPBYTE)pBlob, IISCryptoGetBlobLength( pBlob ) );
return RETURNCODETOHRESULT(status);
} // IISCryptoWriteBlobToRegistry
BOOL WINAPI IISCryptoIsValidBlob( IN PIIS_CRYPTO_BLOB pBlob )
/*++
Routine Description:
This routine determines if the specified blob is indeed a valid blob.
Arguments:
pBlob - The blob to validate.
Return Value:
BOOL - TRUE if the blob is valid, FALSE otherwise.
--*/
{
PIC_BLOB blob; BOOL result;
//
// Sanity check.
//
DBG_ASSERT( IcpGlobals.Initialized ); DBG_ASSERT( pBlob != NULL );
//
// Validate the signature.
//
blob = (PIC_BLOB)pBlob;
switch( blob->Header.BlobSignature ) {
case KEY_BLOB_SIGNATURE : case PUBLIC_KEY_BLOB_SIGNATURE : case DATA_BLOB_SIGNATURE : case HASH_BLOB_SIGNATURE : case CLEARTEXT_BLOB_SIGNATURE : result = TRUE; break;
default : result = FALSE; break;
}
if( result && blob->Header.BlobSignature != CLEARTEXT_BLOB_SIGNATURE ) {
//
// Validate some of the blob internal structure. Note that we
// don't validate the internal structure of the cleartext blobs,
// as they do not conform to the normal IC_BLOB structure.
//
if( blob->DataLength == 0 || blob->Header.BlobDataLength != CALC_BLOB_DATA_LENGTH( blob->DataLength, blob->SignatureLength ) ) {
result = FALSE;
}
}
return result;
} // IISCryptoIsValidBlob
BOOL WINAPI IISCryptoIsValidBlob2( IN PIIS_CRYPTO_BLOB pBlob )
/*++
Routine Description:
This routine determines if the specified blob is indeed a valid blob.
Arguments:
pBlob - The blob to validate.
Return Value:
BOOL - TRUE if the blob is valid, FALSE otherwise.
--*/
{
PIC_BLOB2 blob; BOOL result;
//
// Sanity check.
//
DBG_ASSERT( IcpGlobals.Initialized ); DBG_ASSERT( pBlob != NULL );
//
// Validate the signature.
//
blob = (PIC_BLOB2)pBlob;
switch( blob->Header.BlobSignature ) {
case SALT_BLOB_SIGNATURE : result = TRUE; break;
default : result = FALSE; break;
}
if( result ) {
//
// Validate some of the blob internal structure. Note that we
// don't validate the internal structure of the cleartext blobs,
// as they do not conform to the normal IC_BLOB structure.
//
if( blob->DataLength == 0 || blob->Header.BlobDataLength != CALC_BLOB_DATA_LENGTH2( blob->DataLength, blob->SaltLength ) ) {
result = FALSE;
}
}
return result;
} // IISCryptoIsValidBlob2
HRESULT WINAPI IISCryptoFreeBlob( IN PIIS_CRYPTO_BLOB pBlob )
/*++
Routine Description:
This routine frees all resources associated with the given blob. After this routine completes, the blob is unusable.
Arguments:
pBlob - The blob to free.
Return Value:
HRESULT - Completion status, 0 if successful, !0 otherwise.
--*/
{
//
// Sanity check.
//
DBG_ASSERT( IcpGlobals.Initialized ); DBG_ASSERT( pBlob != NULL ); DBG_ASSERT( IISCryptoIsValidBlob( pBlob ) );
//
// Corrupt the structure signature before freeing the blob.
//
*(PCHAR)(&pBlob->BlobSignature) = 'X';
//
// Free the resources.
//
IcpFreeMemory( pBlob );
//
// Success!
//
UpdateBlobsFreed(); return NO_ERROR;
} // IISCryptoFreeBlob
HRESULT WINAPI IISCryptoFreeBlob2( IN PIIS_CRYPTO_BLOB pBlob )
/*++
Routine Description:
This routine frees all resources associated with the given blob. After this routine completes, the blob is unusable.
Arguments:
pBlob - The blob to free.
Return Value:
HRESULT - Completion status, 0 if successful, !0 otherwise.
--*/
{
//
// Sanity check.
//
DBG_ASSERT( IcpGlobals.Initialized ); DBG_ASSERT( pBlob != NULL ); DBG_ASSERT( IISCryptoIsValidBlob2( pBlob ) );
//
// Corrupt the structure signature before freeing the blob.
//
*(PCHAR)(&pBlob->BlobSignature) = 'X';
//
// Free the resources.
//
IcpFreeMemory( pBlob );
//
// Success!
//
UpdateBlobsFreed(); return NO_ERROR;
} // IISCryptoFreeBlob2
BOOL WINAPI IISCryptoCompareBlobs( IN PIIS_CRYPTO_BLOB pBlob1, IN PIIS_CRYPTO_BLOB pBlob2 )
/*++
Routine Description:
This routine compares two blobs to determine if they are identical.
Arguments:
pBlob1 - Pointer to a blob.
pBlob2 - Pointer to another blob.
Return Value:
BOOL - TRUE if the blobs match, FALSE otherwise, or if the blobs are invalid.
--*/
{
//
// Sanity check.
//
DBG_ASSERT( IcpGlobals.Initialized ); DBG_ASSERT( pBlob1 != NULL ); DBG_ASSERT( pBlob2 != NULL ); DBG_ASSERT( IISCryptoIsValidBlob( pBlob1 ) ); DBG_ASSERT( IISCryptoIsValidBlob( pBlob2 ) );
//
// Just do a straight memory compare of the two blobs.
//
if( memcmp( pBlob1, pBlob2, sizeof(*pBlob1) ) == 0 ) { return TRUE; }
//
// No match.
//
return FALSE;
} // IISCryptoCompareBlobs
HRESULT WINAPI IISCryptoCloneBlobFromRawData( OUT PIIS_CRYPTO_BLOB * ppBlob, IN PBYTE pRawBlob, IN DWORD dwRawBlobLength )
/*++
Routine Description:
This routine makes a copy of a blob from raw data. The raw data buffer may be unaligned.
Arguments:
ppBlob - Receives a pointer to the newly created blob if successful.
pRawBlob - Pointer to the raw blob data.
dwRawBlobLength - Length of the raw blob data.
Return Value:
HRESULT - Completion status, 0 if successful, !0 otherwise.
--*/
{
PIIS_CRYPTO_BLOB newBlob; IIS_CRYPTO_BLOB UNALIGNED *unalignedBlob; DWORD blobLength;
//
// Sanity check.
//
DBG_ASSERT( ppBlob != NULL ); DBG_ASSERT( pRawBlob != NULL );
//
// Allocate space for the new blob.
//
unalignedBlob = (IIS_CRYPTO_BLOB UNALIGNED *)pRawBlob; blobLength = IISCryptoGetBlobLength( unalignedBlob );
if( blobLength != dwRawBlobLength ) { return HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); }
newBlob = IcpAllocMemory( blobLength ); if( newBlob != NULL ) {
//
// Clone it. The (PCHAR) casts are necessary to force the compiler
// to copy BYTE-wise.
//
RtlCopyMemory( (PCHAR)newBlob, (PCHAR)unalignedBlob, blobLength );
//
// Validate its contents.
//
if( IISCryptoIsValidBlob( newBlob ) ) {
*ppBlob = newBlob;
UpdateBlobsCreated(); return NO_ERROR;
}
IcpFreeMemory( newBlob ); return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
}
return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
} // IISCryptoCloneBlobFromRawData
HRESULT WINAPI IISCryptoCloneBlobFromRawData2( OUT PIIS_CRYPTO_BLOB * ppBlob, IN PBYTE pRawBlob, IN DWORD dwRawBlobLength )
/*++
Routine Description:
This routine makes a copy of a blob from raw data. The raw data buffer may be unaligned.
Arguments:
ppBlob - Receives a pointer to the newly created blob if successful.
pRawBlob - Pointer to the raw blob data.
dwRawBlobLength - Length of the raw blob data.
Return Value:
HRESULT - Completion status, 0 if successful, !0 otherwise.
--*/
{
PIIS_CRYPTO_BLOB newBlob; IIS_CRYPTO_BLOB UNALIGNED *unalignedBlob; DWORD blobLength;
//
// Sanity check.
//
DBG_ASSERT( ppBlob != NULL ); DBG_ASSERT( pRawBlob != NULL );
//
// Allocate space for the new blob.
//
unalignedBlob = (IIS_CRYPTO_BLOB UNALIGNED *)pRawBlob; blobLength = IISCryptoGetBlobLength( unalignedBlob );
if( blobLength != dwRawBlobLength ) { return HRESULT_FROM_WIN32( ERROR_INVALID_DATA ); }
newBlob = IcpAllocMemory( blobLength ); if( newBlob != NULL ) {
//
// Clone it. The (PCHAR) casts are necessary to force the compiler
// to copy BYTE-wise.
//
RtlCopyMemory( (PCHAR)newBlob, (PCHAR)unalignedBlob, blobLength );
//
// Validate its contents.
//
if( IISCryptoIsValidBlob2( newBlob ) ) {
*ppBlob = newBlob;
UpdateBlobsCreated(); return NO_ERROR;
}
IcpFreeMemory( newBlob ); return HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
}
return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
} // IISCryptoCloneBlobFromRawData2
HRESULT WINAPI IISCryptoCreateCleartextBlob( OUT PIIS_CRYPTO_BLOB * ppBlob, IN PBYTE pBlobData, IN DWORD dwBlobDataLength )
/*++
Routine Description:
This routine creates a cleartext blob containing the specified data.
Arguments:
ppBlob - Receives a pointer to the newly created blob if successful.
pBlobData - Pointer to the blob data.
dwBlobDataLength - Length of the blob data.
Return Value:
HRESULT - Completion status, 0 if successful, !0 otherwise.
--*/
{
PIIS_CRYPTO_BLOB blob;
//
// Sanity check.
//
DBG_ASSERT( ppBlob != NULL ); DBG_ASSERT( pBlobData != NULL );
//
// Allocate space for the new blob.
//
blob = IcpAllocMemory( dwBlobDataLength + sizeof(*blob) );
if( blob != NULL ) {
//
// Initialize the blob.
//
blob->BlobSignature = CLEARTEXT_BLOB_SIGNATURE; blob->BlobDataLength = dwBlobDataLength;
RtlCopyMemory( blob + 1, pBlobData, dwBlobDataLength );
*ppBlob = blob;
UpdateBlobsCreated(); return NO_ERROR;
}
return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
} // IISCryptoCreateCleartextBlob
PIC_BLOB IcpCreateBlob( IN DWORD dwBlobSignature, IN DWORD dwDataLength, IN DWORD dwSignatureLength OPTIONAL )
/*++
Routine Description:
This routine creates a new blob.
Arguments:
dwBlobSignature - The structure signature for the new blob.
dwDataLength - The data length for the blob.
dwSignatureLength - The length of the digital signature, 0 if there is no signature for this blob. This value cannot be CLEARTEXT_BLOB_SIGNATURE; cleartext blobs are "special".
Return Value:
PIC_BLOB - Pointer to the newly created blob if successful, NULL otherwise.
--*/
{
PIC_BLOB blob; DWORD blobDataLength;
//
// Sanity check.
//
DBG_ASSERT( dwBlobSignature == KEY_BLOB_SIGNATURE || dwBlobSignature == PUBLIC_KEY_BLOB_SIGNATURE || dwBlobSignature == DATA_BLOB_SIGNATURE || dwBlobSignature == HASH_BLOB_SIGNATURE );
//
// Allocate storage for the blob.
//
blobDataLength = CALC_BLOB_DATA_LENGTH( dwDataLength, dwSignatureLength ); blob = IcpAllocMemory( blobDataLength + sizeof(IIS_CRYPTO_BLOB) );
if( blob != NULL ) {
//
// Initialize the blob.
//
blob->Header.BlobSignature = dwBlobSignature; blob->Header.BlobDataLength = blobDataLength;
blob->DataLength = dwDataLength; blob->SignatureLength = dwSignatureLength;
}
return blob;
} // IcpCreateBlob
PIC_BLOB2 IcpCreateBlob2( IN DWORD dwBlobSignature, IN DWORD dwDataLength, IN DWORD dwSaltLength OPTIONAL )
/*++
Routine Description:
This routine creates a new blob.
Arguments:
dwBlobSignature - The structure signature for the new blob.
dwDataLength - The data length for the blob.
dwSaltLength - The length of the random salt
Return Value:
PIC_BLOB2 - Pointer to the newly created blob if successful, NULL otherwise.
--*/
{
PIC_BLOB2 blob; DWORD blobDataLength;
//
// Sanity check.
//
DBG_ASSERT( dwBlobSignature == SALT_BLOB_SIGNATURE );
//
// Allocate storage for the blob.
//
blobDataLength = CALC_BLOB_DATA_LENGTH( dwDataLength, dwSaltLength ); blob = IcpAllocMemory( blobDataLength + sizeof(IIS_CRYPTO_BLOB) );
if( blob != NULL ) {
//
// Initialize the blob.
//
blob->Header.BlobSignature = dwBlobSignature; blob->Header.BlobDataLength = blobDataLength;
blob->DataLength = dwDataLength; blob->SaltLength = dwSaltLength;
}
return blob;
} // IcpCreateBlob2
//
// Private functions.
//
|