windows-nt/Source/XPSP1/NT/inetsrv/iis/inc/icrypt.hxx

729 lines
15 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
icrypt.hxx
Abstract:
C++ wrappers around the IISCrypto APIs.
This module contains the declarations for one base class and three
derived classes:
IIS_CRYPTO_BASE
|
+--- IIS_CRYPTO_STORAGE
|
+--- IIS_CRYPTO_EXCHANGE_BASE
|
+--- IIS_CRYPTO_EXCHANGE_CLIENT
|
+--- IIS_CRYPTO_EXCHANGE_SERVER
IIS_CRYPTO_BASE is a general base class, containing the crypto
provider handle, as well as the key exchange and signature handles.
This class also provides a couple of member functions used by the
derived classes.
IIS_CRYPTO_STORAGE is used by applications that need to store or
transfer data in a secure manner. This class provides services
for data encryption and descryption.
IIS_CRYPTO_EXCHANGE_BASE is a general base class for the key
exchange classes.
IIS_CRYPTO_EXCHANGE_CLIENT is used by the client (i.e. sending)
side of the multi-phase key exchange protocol.
IIS_CRYPTO_EXCHANGE_SERVER is used by the server (i.e. receiving)
side of the multi-phase key exchange protocol.
The multi-phase key exchange protocol consists of the following
steps:
Phase 1 (client.1):
1. Export public key exchange and signature blobs.
2. Send blobs to server.
Phase 2 (server.1):
1. Import client's public key exchange and signature blobs.
2. Export public key exchange and signature blobs.
3. Send blobs to client.
4. Generate random session key (call it Ka).
5. Encrypt session key with client's key exchange key.
6. Send encrypted session key to client.
Phase 3 (client.2):
1. Import server's public key exchange and signature blobs.
2. Import encrypted session key.
3. Generate random session key (call it Kb).
4. Encrypt session key with server's key exchange key.
5. Send encrypted session key to server.
6. Generate hash containing Ka, Kb, and string "Phase 3".
7. Send hash to the server.
Phase 4 (server.2):
1. Import encrypted session key.
2. Validate client's hash.
3. Generate hash containing Kb and string "Phase 4".
4. Send hash to the client.
Phase 5 (client.3):
1. Validate server's hash.
The end result is that each side has two session keys: one for
sending encrypted data, one for receiving encrypted data. Each of
these keys is represented by a IIS_CRYPTO_STORAGE class.
A few notes about the Win32 crypto APIs, IE4, and impersonating
threads...
IE4 has changed the relationship between crypto key containers and
security context. In the pre-IE4 days, whenever an application
acquired a crypto context, the crypto APIs opened the necessary
registry keys and kept them open until the context was released.
With IE4 installed (actually this is an issue with the Protected
Storage service that's installed with IE4) the crypto container
registry keys are NOT opened when the context is aquired, they are
are opened on demand when they're first needed. This causes much
grief for us, as we may acquire the crypto context in one security
context then try to import/whatever in another security context.
The hack (er, solution) implemented in these classes is to try the
import/whatever operation in the current security context. If that
operation fails and the current thread has an impersonation token,
then we "revert to self" and retry the operation.
This solution has the blessing of the NT crypto team (specifically,
Jeff Spelman).
Author:
Keith Moore (keithmo) 02-Dec-1996
Revision History:
--*/
#ifndef _ICRYPT_HXX_
#define _ICRYPT_HXX_
//
// Get the IIS Crypto stuff.
//
#include <iiscrypt.h>
//
// The base crypto class. This class contains the provider handle
// and the public (key exchange & signature) handles. This is intended
// as a base class for IIS_CRYPTO_STORAGE and IIS_CRYPTO_EXCHANGE_BASE.
//
class IIS_CRYPTO_BASE {
public:
//
// Constructor/destructor.
//
IIS_CRYPTO_BASE();
~IIS_CRYPTO_BASE();
//
// Static method to open a crypto container by name. This method
// performs all of the games necessary to open a container, even
// if we're running in an impersonated security context.
//
static
HRESULT
GetCryptoContainerByName(
OUT HCRYPTPROV * phProv,
IN LPTSTR pszContainerName,
IN DWORD dwAdditionalFlags,
IN BOOL fApplyAcl
);
//
// Initialize the crypto context.
//
HRESULT
Initialize(
IN HCRYPTPROV hProv = CRYPT_NULL,
IN HCRYPTKEY hKeyExchangeKey = CRYPT_NULL,
IN HCRYPTKEY hSignatureKey = CRYPT_NULL,
IN BOOL fUseMachineKeyset = FALSE
);
HRESULT
Initialize2(
IN HCRYPTPROV hProv = CRYPT_NULL
);
//
// Query the key exchange key as a public key blob.
//
HRESULT
GetKeyExchangeKeyBlob(
OUT PIIS_CRYPTO_BLOB * ppKeyExchangeKeyBlob
);
//
// Query the signature key as a public key blob.
//
HRESULT
GetSignatureKeyBlob(
OUT PIIS_CRYPTO_BLOB * ppSignatureKeyBlob
);
//
// Accessors.
//
HCRYPTPROV
QueryProviderHandle()
{
return m_hProv;
}
protected:
//
// A handle to a crypto service provider.
//
HCRYPTPROV m_hProv;
BOOL m_fCloseProv;
//
// A handle to our key exchange key.
//
HCRYPTKEY m_hKeyExchangeKey;
//
// A handle to our signature key.
//
HCRYPTKEY m_hSignatureKey;
#if DBG
//
// Validate object state.
//
BOOL
ValidateState();
BOOL
ValidateState2();
#endif
//
// Wrappers around the corresponding IISCryptoXxx() routines that
// Do The Right Thing when the current thread has an impersonation
// token.
//
static
HRESULT
SafeImportSessionKeyBlob(
OUT HCRYPTKEY * phSessionKey,
IN PIIS_CRYPTO_BLOB pSessionKeyBlob,
IN HCRYPTPROV hProv,
IN HCRYPTKEY hSignatureKey
);
static
HRESULT
SafeImportSessionKeyBlob2(
OUT HCRYPTKEY * phSessionKey,
IN PIIS_CRYPTO_BLOB pSessionKeyBlob,
IN HCRYPTPROV hProv,
IN LPSTR pszPasswd
);
static
HRESULT
SafeExportSessionKeyBlob(
OUT PIIS_CRYPTO_BLOB * ppSessionKeyBlob,
IN HCRYPTPROV hProv,
IN HCRYPTKEY hSessionKey,
IN HCRYPTKEY hKeyExchangeKey
);
static
HRESULT
SafeExportSessionKeyBlob2(
OUT PIIS_CRYPTO_BLOB * ppSessionKeyBlob,
IN HCRYPTPROV hProv,
IN HCRYPTKEY hSessionKey,
IN LPSTR pszPasswd
);
static
HRESULT
SafeEncryptDataBlob(
OUT PIIS_CRYPTO_BLOB * ppDataBlob,
IN PVOID pBuffer,
IN DWORD dwBufferLength,
IN DWORD dwRegType,
IN HCRYPTPROV hProv,
IN HCRYPTKEY hSessionKey
);
static
HRESULT
SafeEncryptDataBlob2(
OUT PIIS_CRYPTO_BLOB * ppDataBlob,
IN PVOID pBuffer,
IN DWORD dwBufferLength,
IN DWORD dwRegType,
IN HCRYPTPROV hProv,
IN HCRYPTKEY hSessionKey
);
//
// Thread token manipulators.
//
static
HRESULT
GetThreadImpersonationToken(
OUT HANDLE * Token
);
static
HRESULT
SetThreadImpersonationToken(
IN HANDLE Token
);
static
BOOL
AmIRunningInTheLocalSystemContext(
VOID
);
}; // IIS_CRYPTO_BASE
class IIS_CRYPTO_STORAGE : public IIS_CRYPTO_BASE {
public:
//
// Constructor/destructor.
//
IIS_CRYPTO_STORAGE();
~IIS_CRYPTO_STORAGE();
//
// Initialize the crypto context, generating a new (random) session
// key.
//
HRESULT
Initialize(
IN BOOL fUseMachineKeyset = FALSE,
IN HCRYPTPROV hProv = CRYPT_NULL
);
//
// Initialize the crypto context, importing the session key from the
// given session key blob.
//
HRESULT
Initialize(
IN PIIS_CRYPTO_BLOB pSessionKeyBlob,
IN BOOL fUseMachineKeyset = FALSE,
IN HCRYPTPROV hProv = CRYPT_NULL
);
//
// Initialize the crypto context, using pre-created provider,
// session, key exchange, and signature keys.
//
HRESULT
Initialize(
IN HCRYPTPROV hProv,
IN HCRYPTKEY hSessionKey,
IN HCRYPTKEY hKeyExchangeKey,
IN HCRYPTKEY hSignatureKey,
IN BOOL fUseMachineKeyset = FALSE
);
//
// Query the session key as a session key blob.
//
HRESULT
GetSessionKeyBlob(
OUT PIIS_CRYPTO_BLOB * ppSessionKeyBlob
);
//
// Encrypt data into a data blob.
//
virtual
HRESULT
EncryptData(
OUT PIIS_CRYPTO_BLOB * ppDataBlob,
IN PVOID pBuffer,
IN DWORD dwBufferLength,
IN DWORD dwRegType
);
//
// Decrypt data from a data blob.
//
virtual
HRESULT
DecryptData(
OUT PVOID * ppBuffer,
OUT LPDWORD pdwBufferLength,
OUT LPDWORD pdwRegType,
IN PIIS_CRYPTO_BLOB pDataBlob
);
protected:
//
// A handle to the session key.
//
HCRYPTKEY m_hSessionKey;
#if DBG
//
// Validate object state.
//
virtual
BOOL
ValidateState();
#endif
}; // IIS_CRYPTO_STORAGE
class IIS_CRYPTO_STORAGE2 : public IIS_CRYPTO_STORAGE {
public:
//
// Constructor/destructor.
//
IIS_CRYPTO_STORAGE2(){}
~IIS_CRYPTO_STORAGE2(){}
//
// Initialize the crypto context, generating a new (random) session
// key.
//
HRESULT
Initialize(
IN HCRYPTPROV hProv = CRYPT_NULL
);
//
// Initialize the crypto context, importing the session key from the
// given session key blob.
//
HRESULT
Initialize(
IN PIIS_CRYPTO_BLOB pSessionKeyBlob,
IN LPSTR pszPasswd,
IN HCRYPTPROV hProv = CRYPT_NULL
);
HRESULT
GetSessionKeyBlob(
IN LPSTR pszPasswd,
OUT PIIS_CRYPTO_BLOB * ppSessionKeyBlob
);
//
// Encrypt data into a data blob.
//
HRESULT
EncryptData(
OUT PIIS_CRYPTO_BLOB * ppDataBlob,
IN PVOID pBuffer,
IN DWORD dwBufferLength,
IN DWORD dwRegType
);
//
// Decrypt data from a data blob.
//
HRESULT
DecryptData(
OUT PVOID * ppBuffer,
OUT LPDWORD pdwBufferLength,
OUT LPDWORD pdwRegType,
IN PIIS_CRYPTO_BLOB pDataBlob
);
#if DBG
//
// Validate object state.
//
BOOL
ValidateState();
#endif
}; // IIS_CRYPTO_STORAGE
class IIS_CRYPTO_EXCHANGE_BASE : public IIS_CRYPTO_BASE {
public:
//
// Constructor/destructor.
//
IIS_CRYPTO_EXCHANGE_BASE();
~IIS_CRYPTO_EXCHANGE_BASE();
//
// Accessors for the keys we create. Note that once the calling
// application assumes ownership for one of these keys, it is the
// application's responsibility to close it.
//
HCRYPTKEY
AssumeClientSessionKey()
{
HCRYPTKEY hTmp;
hTmp = m_hClientSessionKey;
m_hClientSessionKey = CRYPT_NULL;
return hTmp;
}
HCRYPTKEY
AssumeServerSessionKey()
{
HCRYPTKEY hTmp;
hTmp = m_hServerSessionKey;
m_hServerSessionKey = CRYPT_NULL;
return hTmp;
}
protected:
//
// Create the phase 3 and 4 hash values.
//
HRESULT
CreatePhase3Hash(
OUT PIIS_CRYPTO_BLOB * ppHashBlob
);
HRESULT
CreatePhase4Hash(
OUT PIIS_CRYPTO_BLOB * ppHashBlob
);
//
// Various keys we create/import.
//
HCRYPTKEY m_hServerSessionKey;
HCRYPTKEY m_hClientSessionKey;
private:
//
// Helper function for creating hash values.
//
HRESULT
CreateHashWorker(
OUT PIIS_CRYPTO_BLOB * ppHashBlob,
IN BOOL fPhase3
);
}; // IIS_CRYPTO_EXCHANGE_BASE
class IIS_CRYPTO_EXCHANGE_CLIENT : public IIS_CRYPTO_EXCHANGE_BASE {
public:
//
// Constructor/destructor.
//
IIS_CRYPTO_EXCHANGE_CLIENT();
~IIS_CRYPTO_EXCHANGE_CLIENT();
//
// The guts of the client-side multi-phase key exchange protocol.
//
HRESULT
ClientPhase1(
OUT PIIS_CRYPTO_BLOB * ppClientKeyExhangeKeyBlob,
OUT PIIS_CRYPTO_BLOB * ppClientSignatureKeyBlob
);
HRESULT
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
);
HRESULT
ClientPhase3(
IN PIIS_CRYPTO_BLOB pServerHashBlob
);
//
// Accessors for the server keys we import. Note that once the calling
// application assumes ownership for one of these keys, it is the
// application's responsibility to close it.
//
HCRYPTKEY
AssumeServerKeyExchangeKey()
{
HCRYPTKEY hTmp;
hTmp = m_hServerKeyExchangeKey;
m_hServerKeyExchangeKey = CRYPT_NULL;
return hTmp;
}
HCRYPTKEY
AssumeServerSignatureKey()
{
HCRYPTKEY hTmp;
hTmp = m_hServerSignatureKey;
m_hServerSignatureKey = CRYPT_NULL;
return hTmp;
}
protected:
//
// Server-side keys we'll import.
//
HCRYPTKEY m_hServerKeyExchangeKey;
HCRYPTKEY m_hServerSignatureKey;
}; // IIS_CRYPTO_EXCHANGE_CLIENT
class IIS_CRYPTO_EXCHANGE_SERVER : public IIS_CRYPTO_EXCHANGE_BASE {
public:
//
// Constructor/destructor.
//
IIS_CRYPTO_EXCHANGE_SERVER();
~IIS_CRYPTO_EXCHANGE_SERVER();
//
// The guts of the server-side multi-phase key exchange protocol.
//
HRESULT
ServerPhase1(
IN PIIS_CRYPTO_BLOB pClientKeyExchangeKeyBlob,
IN PIIS_CRYPTO_BLOB pClientSignatureKeyBlob,
OUT PIIS_CRYPTO_BLOB * ppServerKeyExchangeKeyBlob,
OUT PIIS_CRYPTO_BLOB * ppServerSignatureKeyBlob,
OUT PIIS_CRYPTO_BLOB * ppServerSessionKeyBlob
);
HRESULT
ServerPhase2(
IN PIIS_CRYPTO_BLOB pClientSessionKeyBlob,
IN PIIS_CRYPTO_BLOB pClientHashBlob,
OUT PIIS_CRYPTO_BLOB * ppServerHashBlob
);
//
// Accessors for the client keys we import. Note that once the calling
// application assumes ownership for one of these keys, it is the
// application's responsibility to close it.
//
HCRYPTKEY
AssumeClientKeyExchangeKey()
{
HCRYPTKEY hTmp;
hTmp = m_hClientKeyExchangeKey;
m_hClientKeyExchangeKey = CRYPT_NULL;
return hTmp;
}
HCRYPTKEY
AssumeClientSignatureKey()
{
HCRYPTKEY hTmp;
hTmp = m_hClientSignatureKey;
m_hClientSignatureKey = CRYPT_NULL;
return hTmp;
}
protected:
//
// Client-side keys we'll import.
//
HCRYPTKEY m_hClientKeyExchangeKey;
HCRYPTKEY m_hClientSignatureKey;
}; // IIS_CRYPTO_EXCHANGE_SERVER
#endif // _ICRYPT_HXX_