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.
728 lines
16 KiB
728 lines
16 KiB
/*++
|
|
|
|
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_
|
|
|