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.
463 lines
8.8 KiB
463 lines
8.8 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
exchange.cxx
|
|
|
|
Abstract:
|
|
|
|
This module implements the IIS_CRYPTO_EXCHANGE_CLIENT class.
|
|
|
|
Author:
|
|
|
|
Keith Moore (keithmo) 02-Dec-1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
|
|
//
|
|
// Private constants.
|
|
//
|
|
|
|
|
|
//
|
|
// Private types.
|
|
//
|
|
|
|
|
|
//
|
|
// Private globals.
|
|
//
|
|
|
|
|
|
//
|
|
// Private prototypes.
|
|
//
|
|
|
|
|
|
//
|
|
// Public functions.
|
|
//
|
|
|
|
|
|
IIS_CRYPTO_EXCHANGE_CLIENT::IIS_CRYPTO_EXCHANGE_CLIENT()
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
IIS_CRYPTO_EXCHANGE_CLIENT class constructor.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Just put the member variables into known states.
|
|
//
|
|
|
|
m_hServerKeyExchangeKey = CRYPT_NULL;
|
|
m_hServerSignatureKey = CRYPT_NULL;
|
|
|
|
} // IIS_CRYPTO_EXCHANGE_CLIENT::IIS_CRYPTO_EXCHANGE_CLIENT
|
|
|
|
|
|
IIS_CRYPTO_EXCHANGE_CLIENT::~IIS_CRYPTO_EXCHANGE_CLIENT()
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
IIS_CRYPTO_EXCHANGE_CLIENT class destructor.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Close any open keys.
|
|
//
|
|
|
|
CLOSE_KEY( m_hServerKeyExchangeKey );
|
|
CLOSE_KEY( m_hServerSignatureKey );
|
|
|
|
} // IIS_CRYPTO_EXCHANGE_CLIENT::~IIS_CRYPTO_EXCHANGE_CLIENT
|
|
|
|
|
|
HRESULT
|
|
IIS_CRYPTO_EXCHANGE_CLIENT::ClientPhase1(
|
|
OUT PIIS_CRYPTO_BLOB * ppClientKeyExchangeKeyBlob,
|
|
OUT PIIS_CRYPTO_BLOB * ppClientSignatureKeyBlob
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Performs client-side phase 1 of the multi-phase key exchange protocol.
|
|
|
|
Arguments:
|
|
|
|
ppClientKeyExchangeKeyBlob - Receives a pointer to the client's key
|
|
exchange key public blob if successful. It is the client's
|
|
responsibility to (somehow) transmit this to the server.
|
|
|
|
ppClientSignatureKeyBlob - Receives a pointer to the client's signature
|
|
public blob if successful. It is the client's responsibility to
|
|
(somehow) transmit this to the server.
|
|
|
|
Return Value:
|
|
|
|
HRESULT - Completion status, 0 if successful, !0 otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HRESULT result;
|
|
PIIS_CRYPTO_BLOB keyExchangeKeyBlob;
|
|
PIIS_CRYPTO_BLOB signatureKeyBlob;
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
|
|
DBG_ASSERT( ValidateState() );
|
|
DBG_ASSERT( ppClientKeyExchangeKeyBlob != NULL );
|
|
DBG_ASSERT( ppClientSignatureKeyBlob != NULL );
|
|
|
|
//
|
|
// Setup our locals so we know how to cleanup on exit.
|
|
//
|
|
|
|
keyExchangeKeyBlob = NULL;
|
|
signatureKeyBlob = NULL;
|
|
|
|
//
|
|
// Export the key exchange key blob.
|
|
//
|
|
|
|
result = ::IISCryptoExportPublicKeyBlob(
|
|
&keyExchangeKeyBlob,
|
|
m_hProv,
|
|
m_hKeyExchangeKey
|
|
);
|
|
|
|
if( FAILED(result) ) {
|
|
goto fatal;
|
|
}
|
|
|
|
//
|
|
// Export the signature key blob.
|
|
//
|
|
|
|
result = ::IISCryptoExportPublicKeyBlob(
|
|
&signatureKeyBlob,
|
|
m_hProv,
|
|
m_hSignatureKey
|
|
);
|
|
|
|
if( FAILED(result) ) {
|
|
goto fatal;
|
|
}
|
|
|
|
//
|
|
// Success!
|
|
//
|
|
|
|
DBG_ASSERT( keyExchangeKeyBlob != NULL );
|
|
DBG_ASSERT( signatureKeyBlob != NULL );
|
|
|
|
*ppClientKeyExchangeKeyBlob = keyExchangeKeyBlob;
|
|
*ppClientSignatureKeyBlob = signatureKeyBlob;
|
|
|
|
return NO_ERROR;
|
|
|
|
fatal:
|
|
|
|
FREE_BLOB( keyExchangeKeyBlob );
|
|
FREE_BLOB( signatureKeyBlob );
|
|
|
|
DBG_ASSERT( FAILED(result) );
|
|
return result;
|
|
|
|
} // IIS_CRYPTO_EXCHANGE_CLIENT::ClientPhase1
|
|
|
|
|
|
HRESULT
|
|
IIS_CRYPTO_EXCHANGE_CLIENT::ClientPhase2(
|
|
IN PIIS_CRYPTO_BLOB pServerKeyExchangeKeyBlob,
|
|
IN PIIS_CRYPTO_BLOB pServerSignatureKeyBlob,
|
|
IN PIIS_CRYPTO_BLOB pServerSessionKeyBlob,
|
|
OUT PIIS_CRYPTO_BLOB * ppClientSessionKeyBlob,
|
|
OUT PIIS_CRYPTO_BLOB * ppClientHashBlob
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Performs client-side phase 2 of the multi-phase key exchange protocol.
|
|
|
|
Arguments:
|
|
|
|
pServerKeyExchangeKeyBlob - Pointer to the server's key exchange
|
|
public key blob.
|
|
|
|
pServerSignatureKeyBlob - Pointer to the server's signature public
|
|
key blob.
|
|
|
|
pServerSessionKeyBlob - Pointer to the server's session key
|
|
blob.
|
|
|
|
ppClientSessionKeyBlob - Receives a pointer to the client's
|
|
session key blob if successful.
|
|
|
|
ppClientHashBlob - Receives a pointer to the client's hash
|
|
blob if successful.
|
|
|
|
Return Value:
|
|
|
|
HRESULT - Completion status, 0 if successful, !0 otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HRESULT result;
|
|
PIIS_CRYPTO_BLOB sessionKeyBlob;
|
|
PIIS_CRYPTO_BLOB hashBlob;
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
|
|
DBG_ASSERT( ValidateState() );
|
|
DBG_ASSERT( pServerKeyExchangeKeyBlob != NULL );
|
|
DBG_ASSERT( IISCryptoIsValidBlob( pServerKeyExchangeKeyBlob ) );
|
|
DBG_ASSERT( pServerSignatureKeyBlob != NULL );
|
|
DBG_ASSERT( IISCryptoIsValidBlob( pServerSignatureKeyBlob ) );
|
|
DBG_ASSERT( pServerSessionKeyBlob != NULL );
|
|
DBG_ASSERT( IISCryptoIsValidBlob( pServerSessionKeyBlob ) );
|
|
DBG_ASSERT( ppClientSessionKeyBlob != NULL );
|
|
DBG_ASSERT( ppClientHashBlob != NULL );
|
|
|
|
//
|
|
// Setup our locals so we know how to cleanup on exit.
|
|
//
|
|
|
|
sessionKeyBlob = NULL;
|
|
hashBlob = NULL;
|
|
|
|
//
|
|
// Import the server's keys.
|
|
//
|
|
|
|
DBG_ASSERT( m_hServerKeyExchangeKey == CRYPT_NULL );
|
|
result = ::IISCryptoImportPublicKeyBlob(
|
|
&m_hServerKeyExchangeKey,
|
|
pServerKeyExchangeKeyBlob,
|
|
m_hProv
|
|
);
|
|
|
|
if( FAILED(result) ) {
|
|
goto fatal;
|
|
}
|
|
|
|
DBG_ASSERT( m_hServerSignatureKey == CRYPT_NULL );
|
|
result = ::IISCryptoImportPublicKeyBlob(
|
|
&m_hServerSignatureKey,
|
|
pServerSignatureKeyBlob,
|
|
m_hProv
|
|
);
|
|
|
|
if( FAILED(result) ) {
|
|
goto fatal;
|
|
}
|
|
|
|
DBG_ASSERT( m_hServerSessionKey == CRYPT_NULL );
|
|
result = SafeImportSessionKeyBlob(
|
|
&m_hServerSessionKey,
|
|
pServerSessionKeyBlob,
|
|
m_hProv,
|
|
m_hServerSignatureKey
|
|
);
|
|
|
|
if( FAILED(result) ) {
|
|
goto fatal;
|
|
}
|
|
|
|
//
|
|
// Generate our local session key.
|
|
//
|
|
|
|
DBG_ASSERT( m_hClientSessionKey == CRYPT_NULL );
|
|
result = ::IISCryptoGenerateSessionKey(
|
|
&m_hClientSessionKey,
|
|
m_hProv
|
|
);
|
|
|
|
if( FAILED(result) ) {
|
|
goto fatal;
|
|
}
|
|
|
|
//
|
|
// Export it.
|
|
//
|
|
|
|
result = SafeExportSessionKeyBlob(
|
|
&sessionKeyBlob,
|
|
m_hProv,
|
|
m_hClientSessionKey,
|
|
m_hServerKeyExchangeKey
|
|
);
|
|
|
|
if( FAILED(result) ) {
|
|
goto fatal;
|
|
}
|
|
|
|
//
|
|
// Create the phase 3 hash blob.
|
|
//
|
|
|
|
result = CreatePhase3Hash(
|
|
&hashBlob
|
|
);
|
|
|
|
if( FAILED(result) ) {
|
|
goto fatal;
|
|
}
|
|
|
|
//
|
|
// Success!
|
|
//
|
|
|
|
*ppClientSessionKeyBlob = sessionKeyBlob;
|
|
*ppClientHashBlob = hashBlob;
|
|
|
|
return NO_ERROR;
|
|
|
|
fatal:
|
|
|
|
FREE_BLOB( sessionKeyBlob );
|
|
FREE_BLOB( hashBlob );
|
|
|
|
DBG_ASSERT( FAILED(result) );
|
|
return result;
|
|
|
|
} // IIS_CRYPTO_EXCHANGE_CLIENT::ClientPhase2
|
|
|
|
|
|
HRESULT
|
|
IIS_CRYPTO_EXCHANGE_CLIENT::ClientPhase3(
|
|
IN PIIS_CRYPTO_BLOB pServerHashBlob
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Performs client-side phase 3 of the multi-phase key exchange protocol.
|
|
|
|
Arguments:
|
|
|
|
pServerHashBlob - Pointer to the server's hash blob.
|
|
|
|
Return Value:
|
|
|
|
HRESULT - Completion status, 0 if successful, !0 otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
HRESULT result;
|
|
PIIS_CRYPTO_BLOB hashBlob;
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
|
|
DBG_ASSERT( ValidateState() );
|
|
DBG_ASSERT( pServerHashBlob != NULL );
|
|
DBG_ASSERT( IISCryptoIsValidBlob( pServerHashBlob ) );
|
|
|
|
//
|
|
// Setup our locals so we know how to cleanup on exit.
|
|
//
|
|
|
|
hashBlob = NULL;
|
|
|
|
//
|
|
// Create the phase 4 hash blob.
|
|
//
|
|
|
|
result = CreatePhase4Hash(
|
|
&hashBlob
|
|
);
|
|
|
|
if( FAILED(result) ) {
|
|
goto fatal;
|
|
}
|
|
|
|
//
|
|
// Compare this blob with the one we got from the server.
|
|
// If they match, then the exchange is complete.
|
|
//
|
|
|
|
if( !::IISCryptoCompareBlobs(
|
|
pServerHashBlob,
|
|
hashBlob
|
|
) ) {
|
|
|
|
result = ERROR_INVALID_DATA;
|
|
goto fatal;
|
|
|
|
}
|
|
|
|
//
|
|
// Success!
|
|
//
|
|
|
|
FREE_BLOB(hashBlob);
|
|
|
|
return NO_ERROR;
|
|
|
|
fatal:
|
|
|
|
FREE_BLOB(hashBlob);
|
|
|
|
DBG_ASSERT( FAILED(result) );
|
|
return result;
|
|
|
|
} // IIS_CRYPTO_EXCHANGE_CLIENT::ClientPhase3
|
|
|
|
|
|
//
|
|
// Private functions.
|
|
//
|
|
|