785 lines
22 KiB
C++
785 lines
22 KiB
C++
|
// CryptCtx.cpp -- Cryptographic Context class implementation
|
||
|
|
||
|
// (c) Copyright Schlumberger Technology Corp., unpublished work, created
|
||
|
// 1999. This computer program includes Confidential, Proprietary
|
||
|
// Information and is a Trade Secret of Schlumberger Technology Corp. All
|
||
|
// use, disclosure, and/or reproduction is prohibited unless authorized
|
||
|
// in writing. All Rights Reserved.
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
|
||
|
#include <algorithm>
|
||
|
|
||
|
#include <malloc.h> // for _alloca
|
||
|
|
||
|
#include <scuOsExc.h>
|
||
|
|
||
|
#include <cciPubKey.h>
|
||
|
#include <cciPriKey.h>
|
||
|
#include <cciKeyPair.h>
|
||
|
|
||
|
#include "LoginId.h"
|
||
|
#include "ACntrFinder.h"
|
||
|
#include "Secured.h"
|
||
|
#include "ILoginTask.h"
|
||
|
#include "NILoginTsk.h"
|
||
|
#include "SesKeyCtx.h"
|
||
|
#include "PubKeyCtx.h"
|
||
|
#include "HashCtx.h"
|
||
|
#include "CryptCtx.h"
|
||
|
#include "Uuid.h"
|
||
|
#include "PromptUser.h"
|
||
|
#include "AlignedBlob.h"
|
||
|
|
||
|
#include "scarderr.h" // must be last for now
|
||
|
|
||
|
using namespace std;
|
||
|
using namespace scu;
|
||
|
using namespace cci;
|
||
|
|
||
|
|
||
|
/////////////////////////// LOCAL/HELPER /////////////////////////////////
|
||
|
|
||
|
namespace
|
||
|
{
|
||
|
WORD const dwHandleIdKeyContext = 13;
|
||
|
WORD const dwHandleIdHashContext = 7;
|
||
|
|
||
|
template<class T>
|
||
|
HANDLE_TYPE
|
||
|
AddHandle(auto_ptr<T> &rapObject,
|
||
|
CHandleList &rhl)
|
||
|
{
|
||
|
HANDLE_TYPE handle = rhl.Add(rapObject.get());
|
||
|
rapObject.release();
|
||
|
|
||
|
return handle;
|
||
|
}
|
||
|
|
||
|
CardFinder::DialogDisplayMode
|
||
|
DefaultDialogMode(bool fGuiEnabled)
|
||
|
{
|
||
|
using CardFinder::DialogDisplayMode;
|
||
|
|
||
|
return fGuiEnabled
|
||
|
? CardFinder::DialogDisplayMode::ddmIfNecessary
|
||
|
: CardFinder::DialogDisplayMode::ddmNever;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
IsEmpty(CContainer &rcntr)
|
||
|
{
|
||
|
return !rcntr->KeyPairExists(ksExchange) &&
|
||
|
!rcntr->KeyPairExists(ksSignature);
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
IsProtected(CKeyPair const &rhkp)
|
||
|
{
|
||
|
bool fIsProtected = false;
|
||
|
|
||
|
CCard hcard(rhkp->Card());
|
||
|
if (hcard->IsProtectedMode())
|
||
|
fIsProtected = true;
|
||
|
else
|
||
|
{
|
||
|
if (hcard->IsPKCS11Enabled())
|
||
|
{
|
||
|
CPrivateKey hprikey(rhkp->PrivateKey());
|
||
|
if (hprikey && hprikey->Private())
|
||
|
fIsProtected = true;
|
||
|
else
|
||
|
{
|
||
|
CPublicKey hpubkey(rhkp->PublicKey());
|
||
|
if (hpubkey && hpubkey->Private())
|
||
|
fIsProtected = true;
|
||
|
else
|
||
|
{
|
||
|
CCertificate hcert(rhkp->Certificate());
|
||
|
fIsProtected = (hcert && hcert->Private());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return fIsProtected;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
IsProtected(CContainer &rhcntr)
|
||
|
{
|
||
|
return IsProtected(rhcntr->GetKeyPair(ksExchange)) ||
|
||
|
IsProtected(rhcntr->GetKeyPair(ksSignature));
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
/////////////////////////// PUBLIC /////////////////////////////////
|
||
|
|
||
|
// Types
|
||
|
// C'tors/D'tors
|
||
|
CryptContext::CryptContext(CSpec const &rcspec,
|
||
|
PVTableProvStruc const pVTable,
|
||
|
bool fGuiEnabled,
|
||
|
bool fCreateContainer,
|
||
|
bool fEphemeralContainer)
|
||
|
: CHandle(),
|
||
|
m_dwOwnerThreadId(GetCurrentThreadId()),
|
||
|
m_hacntr(),
|
||
|
m_fEphemeralContainer(fEphemeralContainer),
|
||
|
m_fGuiEnabled(fGuiEnabled),
|
||
|
m_hwnd(0),
|
||
|
m_hlKeys(dwHandleIdKeyContext),
|
||
|
m_hlHashes(dwHandleIdHashContext),
|
||
|
m_auxcontext(),
|
||
|
m_ce(),
|
||
|
m_apabCachedAlg()
|
||
|
{
|
||
|
if (pVTable && pVTable->FuncReturnhWnd)
|
||
|
(reinterpret_cast<CRYPT_RETURN_HWND>(pVTable->FuncReturnhWnd))(&m_hwnd);
|
||
|
// An ephemeral container cannot be "created"
|
||
|
if (m_fEphemeralContainer && fCreateContainer)
|
||
|
throw scu::OsException(ERROR_INVALID_PARAMETER);
|
||
|
|
||
|
if (fCreateContainer)
|
||
|
CreateNewContainer(rcspec);
|
||
|
else
|
||
|
OpenExistingContainer(rcspec);
|
||
|
}
|
||
|
|
||
|
CryptContext::~CryptContext()
|
||
|
{
|
||
|
if (m_hacntr)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
m_hacntr = 0;
|
||
|
}
|
||
|
catch (...)
|
||
|
{
|
||
|
// don't allow exceptions to propagate out of destructor
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Operators
|
||
|
// Operations
|
||
|
|
||
|
HCRYPTHASH
|
||
|
CryptContext::Add(auto_ptr<CHashContext> &rapHashCtx)
|
||
|
{
|
||
|
return AddHandle(rapHashCtx, m_hlHashes);
|
||
|
}
|
||
|
|
||
|
HCRYPTKEY
|
||
|
CryptContext::Add(auto_ptr<CKeyContext> &rapKeyCtx)
|
||
|
{
|
||
|
return AddHandle(rapKeyCtx, m_hlKeys);
|
||
|
}
|
||
|
|
||
|
HCRYPTKEY
|
||
|
CryptContext::Add(auto_ptr<CPublicKeyContext> &rapPublicKeyCtx)
|
||
|
{
|
||
|
return AddHandle(rapPublicKeyCtx, m_hlKeys);
|
||
|
|
||
|
}
|
||
|
|
||
|
HCRYPTKEY
|
||
|
CryptContext::Add(auto_ptr<CSessionKeyContext> &rapSessionKeyCtx)
|
||
|
{
|
||
|
return AddHandle(rapSessionKeyCtx, m_hlKeys);
|
||
|
}
|
||
|
|
||
|
auto_ptr<CHashContext>
|
||
|
CryptContext::CloseHash(HCRYPTHASH const hHash)
|
||
|
{
|
||
|
return auto_ptr<CHashContext>(reinterpret_cast<CHashContext *>(m_hlHashes.Close(hHash)));
|
||
|
}
|
||
|
|
||
|
auto_ptr<CKeyContext>
|
||
|
CryptContext::CloseKey(HCRYPTKEY const hKey)
|
||
|
{
|
||
|
return auto_ptr<CKeyContext>(reinterpret_cast<CKeyContext *>(m_hlKeys.Close(hKey)));
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CryptContext::CntrEnumerator(ContainerEnumerator const &rce)
|
||
|
{
|
||
|
m_ce = rce;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CryptContext::EnumAlgorithms(DWORD dwParam,
|
||
|
DWORD dwFlags,
|
||
|
bool fPostAdvanceIterator,
|
||
|
AlignedBlob &rabAlgInfo)
|
||
|
{
|
||
|
bool fFirst = dwFlags & CRYPT_FIRST;
|
||
|
|
||
|
if (fFirst)
|
||
|
m_apabCachedAlg = auto_ptr<AlignedBlob>(0);
|
||
|
|
||
|
if (!m_apabCachedAlg.get())
|
||
|
{
|
||
|
DWORD dwDataLen;
|
||
|
bool bSkip;
|
||
|
do
|
||
|
{
|
||
|
if (CryptGetProvParam(m_auxcontext(),
|
||
|
dwParam,
|
||
|
NULL,
|
||
|
&dwDataLen,
|
||
|
dwFlags) == CRYPT_FAILED)
|
||
|
throw scu::OsException(GetLastError());
|
||
|
|
||
|
BYTE *pbAlgInfo = reinterpret_cast<BYTE *>(_alloca(dwDataLen));
|
||
|
|
||
|
if (CryptGetProvParam(m_auxcontext(),
|
||
|
dwParam,
|
||
|
pbAlgInfo,
|
||
|
&dwDataLen,
|
||
|
dwFlags) == CRYPT_FAILED)
|
||
|
throw scu::OsException(GetLastError());
|
||
|
|
||
|
m_apabCachedAlg =
|
||
|
auto_ptr<AlignedBlob>(new AlignedBlob(pbAlgInfo, dwDataLen));
|
||
|
|
||
|
// Override SIGN and KEYX and algorithms not suported
|
||
|
ALG_ID algid = (PP_ENUMALGS == dwParam)
|
||
|
? reinterpret_cast<PROV_ENUMALGS *>(m_apabCachedAlg->Data())->aiAlgid
|
||
|
: reinterpret_cast<PROV_ENUMALGS_EX *>(m_apabCachedAlg->Data())->aiAlgid;
|
||
|
|
||
|
switch (GET_ALG_CLASS(algid))
|
||
|
{
|
||
|
case ALG_CLASS_SIGNATURE: // fall-through intentional
|
||
|
case ALG_CLASS_KEY_EXCHANGE:
|
||
|
if (PP_ENUMALGS == dwParam)
|
||
|
{
|
||
|
PROV_ENUMALGS *pAlgEnum =
|
||
|
reinterpret_cast<PROV_ENUMALGS *>(m_apabCachedAlg->Data());
|
||
|
pAlgEnum->dwBitLen = 1024;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PROV_ENUMALGS_EX *pAlgEnum =
|
||
|
reinterpret_cast<PROV_ENUMALGS_EX *>(m_apabCachedAlg->Data());
|
||
|
|
||
|
pAlgEnum->dwDefaultLen =
|
||
|
pAlgEnum->dwMinLen =
|
||
|
pAlgEnum->dwMaxLen = 1024;
|
||
|
}
|
||
|
bSkip = false;
|
||
|
break;
|
||
|
|
||
|
case ALG_CLASS_HASH:
|
||
|
bSkip = (!CHashContext::IsSupported(algid));
|
||
|
break;
|
||
|
|
||
|
case ALG_CLASS_DATA_ENCRYPT:
|
||
|
bSkip = false;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
m_apabCachedAlg = auto_ptr<AlignedBlob>(0);
|
||
|
bSkip = true;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwFlags = dwFlags & ~CRYPT_FIRST;
|
||
|
|
||
|
} while (bSkip);
|
||
|
}
|
||
|
|
||
|
rabAlgInfo = m_apabCachedAlg.get()
|
||
|
? *m_apabCachedAlg
|
||
|
: AlignedBlob();
|
||
|
|
||
|
if (fPostAdvanceIterator)
|
||
|
m_apabCachedAlg = auto_ptr<AlignedBlob>(0);
|
||
|
}
|
||
|
|
||
|
|
||
|
auto_ptr<CPublicKeyContext>
|
||
|
CryptContext::ImportPrivateKey(Blob const &rblbMsPrivateKey,
|
||
|
DWORD dwKeySpec,
|
||
|
bool fExportable,
|
||
|
HCRYPTKEY hEncKey)
|
||
|
{
|
||
|
Secured<HAdaptiveContainer> hsacntr(m_hacntr);
|
||
|
|
||
|
auto_ptr<CPublicKeyContext>
|
||
|
apKeyCtx(ImportPublicKey(rblbMsPrivateKey, dwKeySpec));
|
||
|
|
||
|
BYTE const *pbKeyData = 0;
|
||
|
DWORD dwKeyDataLen = 0;
|
||
|
if (hEncKey || m_fEphemeralContainer)
|
||
|
{
|
||
|
// Export the key in plain text by importing to the aux provider
|
||
|
// and then exporting.
|
||
|
HCRYPTKEY hAuxKey;
|
||
|
AlignedBlob abMsPrivateKey(rblbMsPrivateKey);
|
||
|
if (!CryptImportKey(m_auxcontext(),
|
||
|
abMsPrivateKey.Data(),
|
||
|
abMsPrivateKey.Length(), hEncKey,
|
||
|
CRYPT_EXPORTABLE, &hAuxKey))
|
||
|
throw scu::OsException(GetLastError());
|
||
|
|
||
|
if (!m_fEphemeralContainer)
|
||
|
{
|
||
|
// Export the key in plain text
|
||
|
if (!CryptExportKey(m_auxcontext(), NULL, PRIVATEKEYBLOB, 0, NULL,
|
||
|
&dwKeyDataLen))
|
||
|
throw scu::OsException(GetLastError());
|
||
|
|
||
|
// Define pb to avoid "const" cast problems due to
|
||
|
// rblbMsPrivateKey.data below
|
||
|
BYTE *pb = reinterpret_cast<BYTE *>(_alloca(dwKeyDataLen));
|
||
|
if (!CryptExportKey(m_auxcontext(), NULL, PRIVATEKEYBLOB, 0, pb,
|
||
|
&dwKeyDataLen))
|
||
|
throw scu::OsException(GetLastError());
|
||
|
pbKeyData = pb;
|
||
|
|
||
|
// Scrub the key imported into the aux provider. To do this,
|
||
|
// the auxillary key must be destroyed and another key be put
|
||
|
// (generated) in its place.
|
||
|
if (!CryptDestroyKey(hAuxKey))
|
||
|
throw scu::OsException(GetLastError());
|
||
|
|
||
|
hAuxKey = NULL;
|
||
|
if (!CryptGenKey(m_auxcontext(), dwKeySpec, 0, &hAuxKey))
|
||
|
throw scu::OsException(GetLastError());
|
||
|
|
||
|
if (!CryptDestroyKey(hAuxKey))
|
||
|
throw scu::OsException(GetLastError());
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pbKeyData = rblbMsPrivateKey.data();
|
||
|
dwKeyDataLen = rblbMsPrivateKey.length();
|
||
|
}
|
||
|
|
||
|
if (!m_fEphemeralContainer)
|
||
|
{
|
||
|
// Now continue importing the key that's now in plain text.
|
||
|
MsRsaPrivateKeyBlob msprikb(pbKeyData, dwKeyDataLen);
|
||
|
|
||
|
apKeyCtx->ImportPrivateKey(msprikb, fExportable);
|
||
|
}
|
||
|
|
||
|
return apKeyCtx;
|
||
|
}
|
||
|
|
||
|
auto_ptr<CPublicKeyContext>
|
||
|
CryptContext::ImportPublicKey(Blob const &rblbMsPublicKey,
|
||
|
DWORD dwKeySpec)
|
||
|
{
|
||
|
Secured<HAdaptiveContainer> hsacntr(m_hacntr);
|
||
|
|
||
|
auto_ptr<CPublicKeyContext>
|
||
|
apKeyCtx(new CPublicKeyContext(m_auxcontext(), *this,
|
||
|
dwKeySpec, false));
|
||
|
|
||
|
if (m_fEphemeralContainer)
|
||
|
apKeyCtx->AuxPublicKey(AlignedBlob(rblbMsPublicKey));
|
||
|
else
|
||
|
{
|
||
|
MsRsaPublicKeyBlob mspubkb(rblbMsPublicKey.data(),
|
||
|
rblbMsPublicKey.length());
|
||
|
apKeyCtx->ImportPublicKey(mspubkb);
|
||
|
}
|
||
|
|
||
|
return apKeyCtx;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CryptContext::Login(LoginIdentity const &rlid)
|
||
|
{
|
||
|
Secured<HCardContext> hscardctx(AdaptiveContainer()->CardContext());
|
||
|
|
||
|
Login(rlid, hscardctx);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CryptContext::Pin(LoginIdentity const &rlid,
|
||
|
char const *pszPin)
|
||
|
{
|
||
|
Secured<HCardContext> hscardctx(AdaptiveContainer()->CardContext());
|
||
|
|
||
|
// TO DO: Support Entrust
|
||
|
if (pszPin)
|
||
|
hscardctx->Login(rlid, NonInteractiveLoginTask(string(pszPin)));
|
||
|
else
|
||
|
hscardctx->ClearLogin(rlid);
|
||
|
}
|
||
|
|
||
|
// Remove (destroy) the container from the card
|
||
|
void
|
||
|
CryptContext::RemoveContainer()
|
||
|
{
|
||
|
Secured<HCardContext> hscardctx(AdaptiveContainer()->CardContext());
|
||
|
|
||
|
CContainer hcntr(m_hacntr->TheCContainer());
|
||
|
|
||
|
DeleteContainer(hscardctx, hcntr);
|
||
|
|
||
|
m_hacntr = 0; // disconnect from container
|
||
|
}
|
||
|
|
||
|
// Generate a key, string it in the context
|
||
|
HCRYPTKEY
|
||
|
CryptContext::GenerateKey(ALG_ID algid,
|
||
|
DWORD dwFlags)
|
||
|
{
|
||
|
// TO DO: Revisit this method, implement as a manager/factory?
|
||
|
|
||
|
HCRYPTKEY hKey = 0;
|
||
|
auto_ptr<CKeyContext> apKey;
|
||
|
|
||
|
bool bError = false;
|
||
|
DWORD dwErrorCode = NO_ERROR;
|
||
|
|
||
|
//
|
||
|
// Verify the parameters.
|
||
|
//
|
||
|
switch(algid)
|
||
|
{
|
||
|
case AT_KEYEXCHANGE:
|
||
|
case AT_SIGNATURE:
|
||
|
{
|
||
|
if (dwFlags & (CRYPT_CREATE_SALT | CRYPT_NO_SALT | CRYPT_PREGEN))
|
||
|
throw scu::OsException(NTE_BAD_FLAGS);
|
||
|
|
||
|
Secured<HAdaptiveContainer> hsacntr(m_hacntr);
|
||
|
|
||
|
apKey =
|
||
|
auto_ptr<CKeyContext>(new CPublicKeyContext(m_auxcontext(),
|
||
|
*this,
|
||
|
algid,
|
||
|
false));
|
||
|
apKey->Generate(algid, dwFlags);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
apKey =
|
||
|
auto_ptr<CKeyContext>(new CSessionKeyContext(m_auxcontext()));
|
||
|
apKey->Generate(algid, dwFlags);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hKey = Add(apKey);
|
||
|
|
||
|
return hKey;
|
||
|
}
|
||
|
|
||
|
// Load an external Session Key.
|
||
|
auto_ptr<CSessionKeyContext>
|
||
|
CryptContext::UseSessionKey(BYTE const *pbKeyBlob,
|
||
|
DWORD cbKeyBlobLen,
|
||
|
HCRYPTKEY hAuxImpKey,
|
||
|
DWORD dwFlags)
|
||
|
{
|
||
|
// TO DO: Revisit this method, really necessary??
|
||
|
|
||
|
auto_ptr<CSessionKeyContext>
|
||
|
apKeyCtx(new CSessionKeyContext(m_auxcontext()));
|
||
|
|
||
|
if (!apKeyCtx.get())
|
||
|
throw scu::OsException(NTE_NO_MEMORY);
|
||
|
|
||
|
// Decrypt key blob if encrypted with Key Exchange Key
|
||
|
// otherwise forward blob to Auxiliary CSP directly
|
||
|
ALG_ID const *pAlgId =
|
||
|
reinterpret_cast<ALG_ID const *>(&pbKeyBlob[sizeof(BLOBHEADER)]);
|
||
|
|
||
|
if (CALG_RSA_KEYX == *pAlgId)
|
||
|
{
|
||
|
// Get Key exchange key
|
||
|
// TO DO: Shouldn't this be getting a private key?
|
||
|
auto_ptr<CPublicKeyContext>
|
||
|
apXKey(new CPublicKeyContext(m_auxcontext(), *this,
|
||
|
AT_KEYEXCHANGE));
|
||
|
|
||
|
// Decrypt key blob
|
||
|
// TO DO: Support multiple key sizes
|
||
|
Blob EncryptedKey(pbKeyBlob + sizeof BLOBHEADER + sizeof ALG_ID,
|
||
|
128);
|
||
|
Blob DecryptedKey(apXKey->Decrypt(EncryptedKey));
|
||
|
|
||
|
// Recreate the blob
|
||
|
Blob DecryptedBlob(pbKeyBlob, sizeof BLOBHEADER + sizeof ALG_ID);
|
||
|
|
||
|
// we must trim out 64 bytes of the random data from the simple
|
||
|
// blob and then terminate it. (Termination occurs by making the
|
||
|
// n-1 byte = 0x02 and the nth byte = 0x00.) This is necessary
|
||
|
// in order to import this blob into the CSP.
|
||
|
DecryptedBlob.append(DecryptedKey.data(),
|
||
|
(DecryptedKey.length() / 2) - 2);
|
||
|
BYTE bTerminationBytes[] = { 0x02, 0x00 };
|
||
|
DecryptedBlob.append(bTerminationBytes, sizeof bTerminationBytes);
|
||
|
|
||
|
// Load Decrypted blob into key context
|
||
|
apKeyCtx->LoadKey(DecryptedBlob.data(),
|
||
|
DecryptedBlob.length(), 0, dwFlags);
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Load Encrypted blob into key context
|
||
|
apKeyCtx->LoadKey(pbKeyBlob, cbKeyBlobLen, hAuxImpKey, dwFlags);
|
||
|
}
|
||
|
|
||
|
// Import decrypted blob into Auxiliary CSP
|
||
|
apKeyCtx->ImportToAuxCSP();
|
||
|
|
||
|
return apKeyCtx;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Access
|
||
|
HAdaptiveContainer
|
||
|
CryptContext::AdaptiveContainer() const
|
||
|
{
|
||
|
if (!m_hacntr)
|
||
|
throw scu::OsException(ERROR_INVALID_PARAMETER);
|
||
|
|
||
|
return m_hacntr;
|
||
|
}
|
||
|
|
||
|
HCRYPTPROV
|
||
|
CryptContext::AuxContext() const
|
||
|
{
|
||
|
return m_auxcontext();
|
||
|
}
|
||
|
|
||
|
HCardContext
|
||
|
CryptContext::CardContext() const
|
||
|
{
|
||
|
return AdaptiveContainer()->CardContext();
|
||
|
}
|
||
|
|
||
|
ContainerEnumerator
|
||
|
CryptContext::CntrEnumerator(bool fReset)
|
||
|
{
|
||
|
if (fReset)
|
||
|
{
|
||
|
if (m_hacntr)
|
||
|
m_ce = ContainerEnumerator(list<HCardContext>(1, m_hacntr->CardContext()));
|
||
|
else
|
||
|
{
|
||
|
CardEnumerator ce;
|
||
|
m_ce = ContainerEnumerator(*(ce.Cards()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return m_ce;
|
||
|
}
|
||
|
|
||
|
CHashContext *
|
||
|
CryptContext::LookupHash(HCRYPTHASH hHash)
|
||
|
{
|
||
|
return reinterpret_cast<CHashContext *>(m_hlHashes[hHash]);
|
||
|
}
|
||
|
|
||
|
CKeyContext *
|
||
|
CryptContext::LookupKey(HCRYPTKEY hKey)
|
||
|
{
|
||
|
return reinterpret_cast<CKeyContext *>(m_hlKeys[hKey]);
|
||
|
}
|
||
|
|
||
|
CPublicKeyContext *
|
||
|
CryptContext::LookupPublicKey(HCRYPTKEY hKey)
|
||
|
{
|
||
|
return reinterpret_cast<CPublicKeyContext *>(LookupChecked(hKey, KT_PUBLICKEY));
|
||
|
}
|
||
|
|
||
|
CSessionKeyContext *
|
||
|
CryptContext::LookupSessionKey(HCRYPTKEY hKey)
|
||
|
{
|
||
|
return reinterpret_cast<CSessionKeyContext *>(LookupChecked(hKey, KT_SESSIONKEY));
|
||
|
}
|
||
|
|
||
|
HWND
|
||
|
CryptContext::Window() const
|
||
|
{
|
||
|
HWND hwndActive = m_hwnd;
|
||
|
|
||
|
// Find a window if the designated one isn't valid. If the
|
||
|
// designated one is NULL, don't use the result of GetActiveWindow
|
||
|
// because the mouse is locked when displaying a dialog box using
|
||
|
// that as the parent window from certain applications (IE and
|
||
|
// Outlook Express).
|
||
|
return (m_hwnd && !IsWindow(m_hwnd))
|
||
|
? GetActiveWindow()
|
||
|
: m_hwnd;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Predicates
|
||
|
bool
|
||
|
CryptContext::GuiEnabled() const
|
||
|
{
|
||
|
return m_fGuiEnabled;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
CryptContext::IsEphemeral() const
|
||
|
{
|
||
|
return m_fEphemeralContainer;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Static Variables
|
||
|
|
||
|
/////////////////////////// PROTECTED /////////////////////////////////
|
||
|
|
||
|
// C'tors/D'tors
|
||
|
// Operators
|
||
|
// Operations
|
||
|
// Access
|
||
|
// Predicates
|
||
|
// Static Variables
|
||
|
|
||
|
|
||
|
/////////////////////////// PRIVATE /////////////////////////////////
|
||
|
|
||
|
// C'tors/D'tors
|
||
|
// Operators
|
||
|
// Operations
|
||
|
|
||
|
// Create and open a new container (named by rcspec). If the
|
||
|
// container does exist, then it must be empty.
|
||
|
void
|
||
|
CryptContext::CreateNewContainer(CSpec const &rcspec)
|
||
|
{
|
||
|
ASSERT (!m_hacntr);
|
||
|
|
||
|
// Find the card in the reader specified.
|
||
|
CardFinder cardfinder(DefaultDialogMode(GuiEnabled()), Window());
|
||
|
|
||
|
CSpec csReader(rcspec);
|
||
|
csReader.SetReader(rcspec.Reader());
|
||
|
|
||
|
Secured<HCardContext> hscardctx(cardfinder.Find(csReader));
|
||
|
|
||
|
// Default the container name a UUID (GUID) if it wasn't supplied.
|
||
|
string sCntrToCreate(rcspec.CardId());
|
||
|
if (sCntrToCreate.empty())
|
||
|
{
|
||
|
Uuid uuid;
|
||
|
sCntrToCreate = AsString(uuid.AsUString());
|
||
|
}
|
||
|
|
||
|
AdaptiveContainerKey Key(hscardctx, sCntrToCreate);
|
||
|
m_hacntr = AdaptiveContainer::Find(Key); // find the existing one
|
||
|
if (m_hacntr && !IsEmpty(m_hacntr->TheCContainer()))
|
||
|
throw scu::OsException(NTE_TOKEN_KEYSET_STORAGE_FULL);
|
||
|
|
||
|
if (hscardctx->Card()->IsProtectedMode())
|
||
|
Login(User, hscardctx);
|
||
|
|
||
|
if (!m_hacntr)
|
||
|
m_hacntr = HAdaptiveContainer(Key);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
CryptContext::DeleteContainer(Secured<HCardContext> &rhscardctx,
|
||
|
CContainer &rhcntr)
|
||
|
{
|
||
|
if (IsProtected(rhcntr))
|
||
|
Login(User, rhscardctx);
|
||
|
|
||
|
AdaptiveContainer::Discard(AdaptiveContainerKey(rhscardctx,
|
||
|
rhcntr->Name()));
|
||
|
rhcntr->Delete();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CryptContext::Login(LoginIdentity const &rlid,
|
||
|
Secured<HCardContext> &rhscardctx)
|
||
|
{
|
||
|
// TO DO: Support Entrust
|
||
|
if (m_fGuiEnabled)
|
||
|
rhscardctx->Login(rlid, InteractiveLoginTask(Window()));
|
||
|
else
|
||
|
rhscardctx->Login(rlid, LoginTask());
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CryptContext::OkDeletingCredentials() const
|
||
|
{
|
||
|
if (GuiEnabled())
|
||
|
{
|
||
|
UINT uiResponse = PromptUser(Window(),
|
||
|
IDS_DELETE_CREDENTIALS,
|
||
|
MB_OKCANCEL | MB_ICONWARNING);
|
||
|
|
||
|
switch (uiResponse)
|
||
|
{
|
||
|
case IDCANCEL:
|
||
|
throw scu::OsException(ERROR_CANCELLED);
|
||
|
break;
|
||
|
|
||
|
case IDOK:
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
throw scu::OsException(ERROR_INTERNAL_ERROR);
|
||
|
break;
|
||
|
};
|
||
|
}
|
||
|
else
|
||
|
throw scu::OsException(NTE_EXISTS);
|
||
|
}
|
||
|
|
||
|
// Access
|
||
|
CKeyContext *
|
||
|
CryptContext::LookupChecked(HCRYPTKEY hKey,
|
||
|
DWORD const dwKeyType)
|
||
|
{
|
||
|
CKeyContext *pKeyCtx = LookupKey(hKey);
|
||
|
|
||
|
if (dwKeyType != pKeyCtx->TypeOfKey())
|
||
|
throw scu::OsException(ERROR_INVALID_PARAMETER);
|
||
|
|
||
|
return pKeyCtx;
|
||
|
}
|
||
|
|
||
|
// Open to an existing container specified by the container
|
||
|
// specification rcspec. If container name is empty, then open the
|
||
|
// default container.
|
||
|
void
|
||
|
CryptContext::OpenExistingContainer(CSpec const &rcspec)
|
||
|
{
|
||
|
if (rcspec.CardId().empty())
|
||
|
{
|
||
|
if (!m_fEphemeralContainer)
|
||
|
{
|
||
|
CardFinder cardfinder(DefaultDialogMode(GuiEnabled()), Window());
|
||
|
Secured<HCardContext> hscardctx(cardfinder.Find(rcspec));
|
||
|
CContainer hcntr(hscardctx->Card()->DefaultContainer());
|
||
|
|
||
|
if (hcntr)
|
||
|
m_hacntr =
|
||
|
HAdaptiveContainer(AdaptiveContainerKey(hscardctx,
|
||
|
hcntr->Name()));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
AContainerFinder cntrfinder(DefaultDialogMode(GuiEnabled()), Window());
|
||
|
|
||
|
m_hacntr = cntrfinder.Find(rcspec);
|
||
|
}
|
||
|
|
||
|
if (!m_hacntr && (!rcspec.CardId().empty() || !m_fEphemeralContainer))
|
||
|
throw scu::OsException(NTE_BAD_KEYSET);
|
||
|
}
|
||
|
|
||
|
// Predicates
|
||
|
// Static Variables
|