📄 context.cpp
字号:
/*
Context.CPP
Each of these functions are effectively the export functions
only with the context parameter checked and is now
implied by the 'this' ptr.
call crdspec_card.cpp,crdspec_container.cpp to implement functions.
*/
#include "Context.h"
#include "CRDSPEC_Container.h"
#include "assert.h"
#include "PaddingHelp.h"
#include "csp.h"
#include <windows.h>
//Initialization of static member variable
CHandleTable CContext::m_sHT;
/*
CContext::CContext
Purpose:
Construct a context object (returned to the caller as a handle)
Params:
None.
Returns:
void
*/
CContext::CContext() : m_pCurrentContainer(NULL), m_dwFlags(0)
{
}
/*
CContext::Initialize
Purpose:
Initializes the context object
Params:
const WCHAR IN * const pszContainer: Container name
const DWORD IN dwFlags: Flags on the object
PVTableProvStruc IN pVTable: vtable
Returns:
TRUE if it succeeds, FALSE otherwise.
*/
BOOL CContext::Initialize(const WCHAR IN * const pszContainer,const DWORD IN dwFlags, PVTableProvStruc IN pVTable)
{
//We need a valid container name
assert(!IsBadReadPtr(pszContainer, 1));
m_dwFlags = dwFlags;
//Initialize our helper classes
if(!m_rsaProv.Initialize((dwFlags & CRYPT_SILENT) == CRYPT_SILENT))
return FALSE;
m_ppManager.Initialize(this);
//Add ourselves to the context hashtable so we can be found
//on subsequent lookups.
if(!m_sHT.AddToTable(this))
{
SetLastError(NTE_NO_MEMORY);
return FALSE;
}
//We don't support machine contexts
if((m_dwFlags & CRYPT_MACHINE_KEYSET) == CRYPT_MACHINE_KEYSET)
{
SetLastError(NTE_BAD_FLAGS);
return FALSE;
}
//Only initialize the card and build the container list if
//we're actually going to use it. We don't if we're doing
//a CRYPT_VERIFY_CONTEXT
if((m_dwFlags & CRYPT_VERIFYCONTEXT) == CRYPT_VERIFYCONTEXT)
return TRUE;
//TODO
//Parse the container name
WCHAR szReaderName[MAX_BUFFER];
szReaderName[0] = TEXT('\0');
WCHAR szContainerName[MAX_BUFFER];
szContainerName[0] = TEXT('\0');
//See if the format is \\reader\containername
if(wcsstr(pszContainer, TEXT("\\\\.\\")) == pszContainer)
{
const WCHAR* pContNameStart = wcsstr(pszContainer+4, TEXT("\\"));
//Check to make sure there is a container name. If there isn't, return.
if(!pContNameStart)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
//One past the \ before the container name.
++pContNameStart;
DWORD dwCharsOfReader = pContNameStart - pszContainer - 5;
if(dwCharsOfReader > MAX_BUFFER)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
wcsncpy(szContainerName, pContNameStart, MAX_BUFFER);
wcscpy(szReaderName, pszContainer + 2);
}
else
{
wcsncpy(szContainerName, pszContainer, MAX_BUFFER);
szReaderName[MAX_BUFFER - 1] = TEXT('\0');
}
//Make sure it's NULL terminated if it cut it off at MAX_BUFFER
szContainerName[MAX_BUFFER - 1] = TEXT('\0');
//Initialize the card
if(!m_crd.Initialize(szReaderName, dwFlags))
return FALSE;
//New keyset?
if((dwFlags & CRYPT_NEWKEYSET) == CRYPT_NEWKEYSET)
{
//Create the keyset on the card
m_pCurrentContainer = m_crd.CreateContainer(szContainerName);
if(!m_pCurrentContainer)
{
SetLastError(NTE_EXISTS);
return FALSE;
}
}
//Delete keyset?
else if((dwFlags&CRYPT_DELETEKEYSET) == CRYPT_DELETEKEYSET)
{
//Retrieve the container to be deleted
m_pCurrentContainer = m_crd.GetContainer(szContainerName);
//If it exists, delete it
if(m_pCurrentContainer)
{
m_pCurrentContainer->Delete();
delete m_pCurrentContainer;
}
else
{
SetLastError(NTE_BAD_KEYSET);
return FALSE;
}
}
//"Normal" usage of the CSP -- use a keyset.
else
{
m_pCurrentContainer = m_crd.GetContainer(szContainerName);
if(!m_pCurrentContainer)
{
SetLastError(NTE_BAD_KEYSET);
return FALSE;
}
}
//If we made it through all that, it worked.
return TRUE;
}
/*
CContext::~CContext
Purpose:
Destructor of a context object. Called when CryptReleaseContext is called.
Params:
None.
Returns:
void
*/
CContext::~CContext()
{
m_sHT.RemoveFromTable(this);
}
/*
CContext::VerifyContext
Purpose:
Determines if the context pointer passed in is actually a
valid ptr to a CContext object.
Params:
CContext* pSpeculativeContext: Ptr to the obj to be verified.
Returns:
bool : true if it is valid, false otherwise.
*/
bool CContext::VerifyContext(CContext* pSpeculativeContext)
{
//Ask the static context hashtable if the context is valid.
return m_sHT.VerifyExistance(pSpeculativeContext);
}
/*
CContext::GetProvParam
Purpose:
Effectively CPGetProvParam with the context parameter missing
The context that this method is being called on is the current
object.
Params:
DWORD dwParam: See MSDN
BYTE* pbData: See MSDN
DWORD* dwDataLen: See MSDN
DWORD dwFlags: See MSDN
Returns:
BOOL : See MSDN
*/
BOOL CContext::GetProvParam(DWORD dwParam, BYTE* pbData, DWORD* pdwDataLen, DWORD dwFlags)
{
//If we don't know how big the buffer is, fail.
if(!pdwDataLen)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
//if we don't get a buffer, set the amount of data to 0.
if(!pbData)
*pdwDataLen = 0;
switch(dwParam)
{
case PP_CONTAINER:
return m_ppManager.HandleContainer(pbData, pdwDataLen, dwFlags);
case PP_ENUMALGS:
return m_ppManager.HandleEnumAlgs(pbData, pdwDataLen, dwFlags);
case PP_ENUMALGS_EX:
return m_ppManager.HandleEnumAlgsEx(pbData, pdwDataLen, dwFlags);
case PP_ENUMCONTAINERS:
return m_ppManager.HandleEnumContainers(&m_crd, pbData, pdwDataLen, dwFlags);
case PP_IMPTYPE:
return m_ppManager.HandleImpType(pbData, pdwDataLen, dwFlags);
case PP_NAME:
return m_ppManager.HandleName(pbData, pdwDataLen, dwFlags);
case PP_VERSION:
return m_ppManager.HandleVersion(pbData, pdwDataLen, dwFlags);
case PP_SIG_KEYSIZE_INC:
return m_ppManager.HandleSigKeySizeInc(pbData, pdwDataLen, dwFlags);
case PP_KEYX_KEYSIZE_INC:
return m_ppManager.HandleKeyXKeySizeInc(pbData, pdwDataLen, dwFlags);
case PP_KEYSET_SEC_DESCR:
SetLastError(NTE_BAD_TYPE);
return FALSE;
case PP_UNIQUE_CONTAINER:
return m_ppManager.HandleUniqueContainer(pbData, pdwDataLen, dwFlags);
case PP_PROVTYPE:
return m_ppManager.HandleProvType(pbData, pdwDataLen, dwFlags);
default:
SetLastError(NTE_BAD_TYPE);
return FALSE;
}
}
/*
CContext::SetProvParam
Purpose:
Same as CPSetProvParam (See MSDN). Context parameter missing
as the context is the current object (this ptr). We don't
support this since it only applies to ACLs.
Params:
DWORD dwParam: See MSDN
BYTE* pbData: See MSDN
DWORD dwFlags: See MSDN
Returns:
BOOL : See MSDN
*/
BOOL CContext::SetProvParam(DWORD dwParam, BYTE* pbData, DWORD dwFlags)
{
SetLastError(NTE_BAD_TYPE);
return FALSE;
}
/*
CContext::CreateHash
Purpose:
Same as CP* (See MSDN). Context parameter missing
as the context is the current object (this ptr).
We pass this call along to the RSA base provider.
Params:
ALG_ID Algid: See MSDN
HCRYPTKEY hCryptKey: See MSDN
DWORD dwFlags: See MSDN
HCRYPTHASH* phHash: See MSDN
Returns:
BOOL : See MSDN
*/
BOOL CContext::CreateHash(ALG_ID Algid, HCRYPTKEY hCryptKey, DWORD dwFlags, HCRYPTHASH* phHash)
{
return CryptCreateHash(m_rsaProv,Algid, hCryptKey, dwFlags, phHash);
}
/*
CContext::DestroyHash
Purpose:
Same as CP* (See MSDN). Context parameter missing
as the context is the current object (this ptr).
We pass this call along to our RSA base provider.
Params:
HCRYPTHASH hHash: See MSDN
Returns:
BOOL : See MSDN
*/
BOOL CContext::DestroyHash(HCRYPTHASH hHash)
{
return CryptDestroyHash(hHash);
}
/*
CContext::GetHashParam
Purpose:
Same as CP* (See MSDN). Context parameter missing
as the context is the current object (this ptr).
Note we simply pass this through to our RSA base provider.
Params:
HCRYPTHASH hHash: See MSDN
DWORD dwParam: See MSDN
BYTE* pbData: See MSDN
DWORD*pdwDataLen: See MSDN
DWORD dwFlags: See MSDN
Returns:
BOOL : See MSDN
*/
BOOL CContext::GetHashParam(HCRYPTHASH hHash, DWORD dwParam, BYTE* pbData, DWORD*pdwDataLen, DWORD dwFlags)
{
return CryptGetHashParam(hHash, dwParam, pbData, pdwDataLen, dwFlags);
}
/*
CContext::HashData
Purpose:
Same as CP* (See MSDN). Context parameter missing
as the context is the current object (this ptr).
Note we simply pass this through to our RSA base provider.
Params:
HCRYPTHASH hHash: See MSDN
CONST BYTE* pbData: See MSDN
DWORD dwDatalen: See MSDN
DWORD dwFlags: See MSDN
Returns:
BOOL : See MSDN
*/
BOOL CContext::HashData(HCRYPTHASH hHash, CONST BYTE* pbData, DWORD dwDatalen, DWORD dwFlags)
{
return CryptHashData(hHash, pbData, dwDatalen, dwFlags);
}
/*
CContext::HashSessionKey
Purpose:
Same as CP* (See MSDN). Context parameter missing
as the context is the current object (this ptr).
Note we simply pass this through to our RSA base provider.
Params:
HCRYPTHASH hHash: See MSDN
HCRYPTKEY hKey: See MSDN
DWORD dwFlags: See MSDN
Returns:
BOOL : See MSDN
*/
BOOL CContext::HashSessionKey(HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags)
{
return CryptHashSessionKey(hHash, hKey, dwFlags);
}
/*
CContext::SetHashParam
Purpose:
Same as CP* (See MSDN). Context parameter missing
as the context is the current object (this ptr).
Note we simply pass this through to our RSA base provider.
Params:
HCRYPTHASH hHash: See MSDN
DWORD dwParam: See MSDN
BYTE*pbData: See MSDN
DWORD dwFlags: See MSDN
Returns:
BOOL : See MSDN
*/
BOOL CContext::SetHashParam(HCRYPTHASH hHash, DWORD dwParam, BYTE*pbData, DWORD dwFlags)
{
return CryptSetHashParam(hHash,dwParam,pbData,dwFlags);
}
/*
CContext::Encrypt
Purpose:
Same as CP* (See MSDN). Context parameter missing
as the context is the current object (this ptr).
Note we simply pass this through to our RSA base provider.
Params:
HCRYPTKEY hKey: See MSDN
HCRYPTHASH hHash: See MSDN
BOOL Final: See MSDN
DWORD dwFlags: See MSDN
BYTE* pbData: See MSDN
DWORD*pdwDataLen: See MSDN
DWORD dwBufLen: See MSDN
Returns:
BOOL : See MSDN
*/
BOOL CContext::Encrypt(HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE* pbData, DWORD*pdwDataLen, DWORD dwBufLen)
{
return CryptEncrypt(hKey, hHash, Final, dwFlags, pbData, pdwDataLen, dwBufLen);
}
/*
CContext::Decrypt
Purpose:
Same as CP* (See MSDN). Context parameter missing
as the context is the current object (this ptr).
Note we simply pass this through to our RSA base provider.
Params:
HCRYPTKEY hKey: See MSDN
HCRYPTHASH hHash: See MSDN
BOOL Final: See MSDN
DWORD dwFlags: See MSDN
BYTE*pbData: See MSDN
DWORD*pdwDataLen: See MSDN
Returns:
BOOL : See MSDN
*/
BOOL CContext::Decrypt(HCRYPTKEY hKey, HCRYPTHASH hHash, BOOL Final, DWORD dwFlags, BYTE*pbData, DWORD*pdwDataLen)
{
return CryptDecrypt(hKey, hHash, Final, dwFlags, pbData, pdwDataLen);
}
/*
CContext::SignHash
Purpose:
Same as CP* (See MSDN). Context parameter missing
as the context is the current object (this ptr).
This calls through to the card to ask it to sign the hash.
Params:
HCRYPTHASH hHash: See MSDN
DWORD dwKeySpec: See MSDN
LPCWSTR sDescription: See MSDN
DWORD dwFlags: See MSDN
BYTE*pbSignature: See MSDN
DWORD* pdwSigLen: See MSDN
Returns:
BOOL : See MSDN
*/
BOOL CContext::SignHash(HCRYPTHASH hHash, DWORD dwKeySpec, LPCWSTR sDescription, DWORD dwFlags, BYTE*pbSignature, DWORD* pdwSigLen)
{
//No keys are in a verify context
if((m_dwFlags&CRYPT_VERIFYCONTEXT) == CRYPT_VERIFYCONTEXT)
{
SetLastError(NTE_NO_KEY);
return FALSE;
}
ALG_ID algidHash;
DWORD dwBufferLen;
LPBYTE pbyHash = NULL;
DWORD dwHashLen;
const BYTE * pbyOID = NULL;
DWORD dwOIDLen = 0;
BOOL bRet = FALSE;
dwBufferLen = sizeof(algidHash);
if(!CryptGetHashParam(hHash, HP_ALGID, (LPBYTE)&algidHash, &dwBufferLen, 0))
return FALSE;
dwBufferLen = sizeof(dwHashLen);
if(!CryptGetHashParam(hHash, HP_HASHSIZE, (LPBYTE)&dwHashLen, &dwBufferLen, 0))
return FALSE;
//Prepend the appropriate OID to the hash.
//This means that identical hashes will result in different signatures.
switch(algidHash)
{
case CALG_SSL3_SHAMD5:
dwOIDLen = 0;
break;
case CALG_MD2:
pbyOID = &kbyoidMD2[0];
dwOIDLen = sizeof(kbyoidMD2);
break;
case CALG_MD4:
pbyOID = &kbyoidMD4[0];
dwOIDLen = sizeof(kbyoidMD4);
break;
case CALG_MD5:
pbyOID = &kbyoidMD5[0];
dwOIDLen = sizeof(kbyoidMD5);
break;
case CALG_SHA1:
pbyOID = &kbyoidSHA1[0];
dwOIDLen = sizeof(kbyoidSHA1);
break;
default:
SetLastError(NTE_BAD_ALGID);
return FALSE;
}
pbyHash = new BYTE[dwHashLen + dwOIDLen];
if(!pbyHash)
return FALSE;
if(pbyOID)
memcpy(pbyHash, pbyOID, dwOIDLen);
if(!CryptGetHashParam(hHash, HP_HASHVAL, pbyHash+dwOIDLen, &dwHashLen, 0))
goto cleanup;
if(!m_crd.SignHash(m_pCurrentContainer, dwKeySpec, pbyHash, dwHashLen+dwOIDLen, pbSignature, pdwSigLen))
goto cleanup;
bRet = TRUE;
cleanup:
if(pbyHash)
delete [] pbyHash;
return bRet;
}
/*
CContext::VerifySignature
Purpose:
Same as CP* (See MSDN). Context parameter missing
as the context is the current object (this ptr).
Note we simply pass this through to our RSA base provider.
Params:
HCRYPTHASH hHash: See MSDN
CONST BYTE* pbSignature: See MSDN
DWORD dwSigLen: See MSDN
HCRYPTKEY hPubKey: See MSDN
LPCWSTR sDescription: See MSDN
DWORD dwFlags: See MSDN
Returns:
BOOL : _
*/
BOOL CContext::VerifySignature(HCRYPTHASH hHash, CONST BYTE* pbSignature, DWORD dwSigLen, HCRYPTKEY hPubKey, LPCWSTR sDescription, DWORD dwFlags)
{
return CryptVerifySignature(hHash, pbSignature, dwSigLen, hPubKey, (reinterpret_cast<const WCHAR*>(sDescription)), dwFlags);
}
/*
CContext::DeriveKey
Purpose:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -