📄 crdspec_card.cpp
字号:
// {
// if(memcmp(&oriPin[6],pin,pinSize) != 0)
// {
// goto pinfail;
// }
// CloseHandle(hFile);
// return true;
// }
//pinfail:
// /*SetFilePointer(hFile,4,NULL,FILE_BEGIN);
// fp.WriteData(hFile,data,1,&size);*/
// oriPin[4]--;
// fp.DelFile(szFileName);
// CloseHandle(hFile);
// hFile = fp.NewFile(szFileName);
// fp.WriteData(hFile,oriPin,size,&size);
// CloseHandle(hFile);
// return false;
}
bool CCard::Authenticate()
{
int count;
bool fRet = false;
if (m_pbyPIN)
{
fRet = CheckPIN(WfSC_CSP_KP_USER, m_pbyPIN, m_byPINSize);
if(fRet)
return true;
else
{
memset(m_pbyPIN,0,m_byPINSize);
delete m_pbyPIN;
m_pbyPIN = NULL;
m_byPINSize = 0;
}
}
if(!LoadGuiLib())
return false;
count = 0;
do
{
BYTE* pbyUserPIN;
BYTE byUserPINLen;
assert(m_byPINSize == 0);
if(!m_lpfnGetPin(
(m_dwFlags&CRYPT_SILENT) == CRYPT_SILENT,
WfSC_CSP_KP_USER,
&pbyUserPIN,
&byUserPINLen))
return false;
assert(pbyUserPIN);
assert(!IsBadReadPtr(pbyUserPIN, byUserPINLen));
//Authenticate with the card.
fRet = CheckPIN(WfSC_CSP_KP_USER, pbyUserPIN, byUserPINLen);
if(!fRet && PINRETRY_OVER == GetLastError())
{
break;
}
memset(pbyUserPIN, 0, byUserPINLen);
m_lpfnFreeData(pbyUserPIN);
}while(!fRet && ++count < 3 );
return fRet;
}
/*
CCard::GenerateCardMutex
Purpose:
Generates a mutex object based on the reader name.
Calls into the GUI dll for help getting the reader name if
the mutex hasn't already been generated.
Params:
None.
Returns:
bool : Whether or not it successfully generated the mutex.
*/
bool CCard::GenerateCardMutex()
{
//If it's already been generated, we don't need to do anything.
if(m_hMutex)
return true;
WCHAR szMutexName[2*MAX_BUFFER];
HRESULT hr;
hr = StringCchPrintf(szMutexName,sizeof(szMutexName)/sizeof(WCHAR), WfSC_MUTEX_NAME,m_pszReaderName);
if (FAILED(hr))
{
return false;
}
m_hMutex = CreateMutex(NULL, false, szMutexName);
return NULL != m_hMutex;
}
bool CCard::AttachToCard()
{
return true;
}
/*
CCard::ReleaseCard
Purpose:
Effectively SCardDisconnects from the card and releases the context
Params:
None.
Returns:
void
*/
void CCard::ReleaseCard()
{
}
bool CCard::LoadGuiLib()
{
//If we're already done, just say so
if(m_hGUILib && m_lpfnGetPin && m_lpfnNewCard)
return true;
//Attempt to load the DLL
m_hGUILib = LoadLibrary(WfSC_GUI_LIB_NAME);
if(!m_hGUILib)
return false;
m_lpfnGetPin = (GETPIN)GetProcAddress(m_hGUILib, WfSC_GETPIN_PROC_NAME);
//m_lpfnWaitForCardInsertion = (WAITFORCARDINSERTION)GetProcAddress(m_hGUILib, WfSC_WAITFORCARDINSERTION_PROC_NAME);
m_lpfnNewCard = (NEWCARD)GetProcAddress(m_hGUILib, WfSC_NEWCARD_PROC_NAME);
m_lpfnFreeData = (FREEDATA)GetProcAddress(m_hGUILib, WfSC_FREEDATA_PROC_NAME);
if(!m_lpfnGetPin || !m_lpfnNewCard || !m_lpfnFreeData)
{
UnloadGuiLib();
return false;
}
return true;
}
void CCard::UnloadGuiLib()
{
if(!m_hGUILib)
return;
FreeLibrary(m_hGUILib);
m_hGUILib = NULL;
m_lpfnGetPin = NULL;
//m_lpfnWaitForCardInsertion = NULL;
m_lpfnNewCard = NULL;
m_lpfnFreeData = NULL;
}
bool CCard::SetUserPin(BYTE* pbyUserPin, BYTE byLength)
{
if(byLength > m_byPINSize)
{
//We need a bigger buffer
BYTE* pbyReplacementBuffer = new BYTE[byLength];
if(!pbyReplacementBuffer)
return false;
if (m_pbyPIN)
delete [] m_pbyPIN;
m_pbyPIN = pbyReplacementBuffer;
}
memcpy(m_pbyPIN, pbyUserPin, byLength);
m_byPINSize = byLength;
return true;
}
/*
CContainer::Create
Purpose:
Create a container
Params:
LPWSTR pszName: pszName
Returns:
CContainer* : NULL if it fails OR if a container with that
name already exists. A ptr to a CContainer
otherwise.
*/
CContainer* CCard::CreateContainer(LPWSTR pszName)
{
assert(!IsBadReadPtr(pszName, 1));
//Check for bogus params
if(!pszName)
return NULL;
//We shouldn't create one if there already is one...
CContainer* pContainer = GetContainer(pszName);
if(pContainer)
return NULL;
//We need to create the container
char szContainerName[MAX_BUFFER];
wcstombs(szContainerName, pszName, MAX_BUFFER - sizeof(CONTINFO));
szContainerName[MAX_BUFFER - sizeof(CONTINFO) - 1] = '\0';
int iContainerNameLen = strlen(szContainerName);
//Lock the card
if(!Lock())
return false;
//Find a unique serial number on the card
int iCurr;
int iMax = -1;
int iCookie = START;
WCHAR szFile[MAX_BUFFER];
CContainer* pCont = NextContainer(iCookie);
while(pCont)
{
iCurr = pCont->GetSerNum();
if(iCurr > iMax)
iMax = iCurr;
pCont = NextContainer(iCookie);
}
++iMax;
//Generate file name
wsprintf(szFile, TEXT("%s/%4.4X"),WfSC_DIR_CONT, iMax);
BOOL lResult;
//Create the file
HANDLE hFile = NULL;
DWORD byActuallyWritten = 0;
CONTINFO ciEmptyContainerData = {WfSC_CONT_VER_NUM,
0}; // num entries
memcpy(szContainerName+iContainerNameLen+1, &ciEmptyContainerData, sizeof(CONTINFO));
hFile = fp.NewFile(szFile);
lResult = fp.WriteData(hFile,(LPBYTE)szContainerName,iContainerNameLen+1+sizeof(CONTINFO),&byActuallyWritten);
if(lResult == 0 || byActuallyWritten != iContainerNameLen + 1 + sizeof(CONTINFO))
{
CloseHandle(hFile);
hFile = NULL;
fp.DelFile(szFile);
goto cleanup;
}
//Instantiate the container object
pContainer = new CContainer();
//Add it to our list.
if(!pContainer)
goto cleanup;
m_htContainers.AddToTable(pContainer);
if(!pContainer->Initialize(this, iMax, (BYTE *)szContainerName, byActuallyWritten))
{
m_htContainers.RemoveFromTable(pContainer);
delete pContainer;
pContainer = NULL;
}
cleanup:
if(fp.IsValid(hFile))
CloseHandle(hFile);
Unlock();
return pContainer;
}
/*
CCard::GetContainer
Purpose:
Finds a container associated with a card.
Params:
LPWSTR pszName: Name of the container to find
Returns:
CContainer* : A ptr to an object representing that container.
*/
CContainer* CCard::GetContainer(LPWSTR pszName)
{
//Check for bogus params
if(!pszName)
return NULL;
int iCookie = START;
m_htContainers.Lock();
CContainer * pCnt;
//Search for the container with that name
do
{
pCnt = (CContainer*)m_htContainers.GetNext(iCookie);
} while(pCnt && wcscmp(pCnt->GetName(), pszName) != 0);
m_htContainers.Unlock();
return pCnt;
}
/*
CCard::StoreKey
Purpose:
Stores a public/private key pair on the card.
Params:
CContainer* pCurrentContainer: a ptr to the container to add the key to.
ALG_ID algid: Must be either AT_SIGNATURE or AT_EXCHANGE
BYTE* pbyPrivateKey: The private key bytes.
DWORD dwPrivateKeySize: The size of the private key in bytes
BYTE* pbyPublicKey: The public key
DWORD dwPublicKeySize: The size of the public key in bytes
Returns:
true if the operation succeeds, false otherwise
*/
bool CCard::StoreKey(CContainer* pContainer, ALG_ID algid, BYTE* pbyPrivateKey, DWORD dwPrivateKeySize, BYTE* pbyPublicKey, DWORD dwPublicKeySize)
{
HANDLE hKeyFile = NULL;
HANDLE hContainerFile = NULL;
DWORD byActuallyWritten = 0;
//Lock the card
if(!Lock())
return false;
if(!Authenticate())
{
Unlock();
return false;
}
//Write the file to the card
int iKeyID = pContainer->GetNextKeyNum();
DWORD wIndex = 0;
DWORD wKeyDataLength;
BOOL lResult = TRUE;
//Get the path
WCHAR szPrivKeyPath[MAX_BUFFER];
WCHAR szPubKeyPath[MAX_BUFFER];
WCHAR szContainerPath[MAX_BUFFER];
wsprintf(szPrivKeyPath, TEXT("%s/%4.4X%4.4X.key"), WfSC_DIR_CSP, pContainer->GetSerNum(), iKeyID);
wsprintf(szPubKeyPath, TEXT("%s/%4.4X%4.4X.crt"), WfSC_DIR_CSP, pContainer->GetSerNum(), iKeyID);
wsprintf(szContainerPath, TEXT("%s/%4.4X"), WfSC_DIR_CONT, pContainer->GetSerNum());
//Check to see if we already have a key of this type
CCard::KEYINFO kiFile;
if(pContainer->GetKeyInfoOfKey(algid, &kiFile))
goto err;
//Open the private key file
hKeyFile = fp.NewFile(szPrivKeyPath);
if(!fp.IsValid(hKeyFile))
goto err;
wKeyDataLength = dwPrivateKeySize;
//Write the data
for(wIndex = 0; wIndex < wKeyDataLength && lResult; wIndex += MAX_CARD_BUFFER)
{
DWORD byBytesToWrite = wKeyDataLength - wIndex > MAX_CARD_BUFFER ? MAX_CARD_BUFFER : wKeyDataLength - wIndex;
//write private key to file
lResult = fp.WriteData(hKeyFile,&pbyPrivateKey[wIndex],byBytesToWrite,&byActuallyWritten);
}
memset(pbyPrivateKey, 0, wKeyDataLength);
delete [] pbyPrivateKey;
pbyPrivateKey = NULL;
if(!lResult)
goto err;
CloseHandle(hKeyFile);
hKeyFile = NULL;
//Write the public key to the .crt file.
hKeyFile = fp.NewFile(szPubKeyPath);
if(!fp.IsValid(hKeyFile))
goto err;
//Write the data
for(wIndex = 0; wIndex < dwPublicKeySize && lResult; wIndex += MAX_CARD_BUFFER)
{
DWORD byBytesToWrite = dwPublicKeySize - wIndex > MAX_CARD_BUFFER ? MAX_CARD_BUFFER : dwPublicKeySize - wIndex;
lResult = fp.WriteData(hKeyFile,&pbyPublicKey[wIndex],byBytesToWrite,&byActuallyWritten);
}
if(!lResult)
goto err;
//Close the file
//hScwCloseFile(m_hProxy, hKeyFile);
CloseHandle(hKeyFile);
hKeyFile = NULL;
//Update the container file
CONTINFO cInfo;
KEYINFO kiInfo, *pkiInfo;
kiInfo.wFileID = iKeyID;
kiInfo.wAlgID = ALG_RSA;
kiInfo.wOpID = (algid == AT_SIGNATURE) ? OP_SIGN : OP_EXCHANGE;
kiInfo.wKeyBits = (WORD)((RSAPUBKEY*)(pbyPublicKey + sizeof(PUBLICKEYSTRUC)))->bitlen;
//lResult = hScwCreateFile(m_hProxy, szContainerPath, NULL, &hContainerFile);
//TODO fp.GetFile or NewFile
hContainerFile = fp.GetFile(szContainerPath);
if(!fp.IsValid(hContainerFile))
goto err;
// skip the name
DWORD filePointer;
filePointer = SetFilePointer(hContainerFile, wcslen(pContainer->GetName())+1, NULL,FILE_BEGIN);
if(filePointer == 0xFFFFFFFF)
goto err;
// append the new key info
pkiInfo = pContainer->NewKey(&kiInfo);
// update the key count
cInfo.byVersion = WfSC_CONT_VER_NUM;
cInfo.byNumKeys = pContainer->GetNumKeys();
//lResult = hScwWriteFile(m_hProxy, hContainerFile, (BYTE *)&cInfo, SIZE_OF_CONTINFO, &byActuallyWritten);
lResult = fp.WriteData(hContainerFile,(LPBYTE)&cInfo,SIZE_OF_CONTINFO,&byActuallyWritten);
// update the key list
if (lResult && byActuallyWritten == SIZE_OF_CONTINFO)
lResult=fp.WriteData( hContainerFile, (LPBYTE)pkiInfo, SIZE_OF_KEYINFO*cInfo.byNumKeys, &byActuallyWritten);
if(!lResult || SIZE_OF_KEYINFO*cInfo.byNumKeys != byActuallyWritten)
goto err;
//hScwCloseFile(m_hProxy, hContainerFile);
CloseHandle(hContainerFile);
Unlock();
return true;
err:
if (pbyPrivateKey)
{
RtlSecureZeroMemory(pbyPrivateKey, wKeyDataLength);
delete [] pbyPrivateKey;
}
if(fp.IsValid(hKeyFile))
CloseHandle(hKeyFile);
if(fp.IsValid(hContainerFile))
CloseHandle(hContainerFile);
fp.DelFile(szPrivKeyPath);
fp.DelFile(szPubKeyPath);
Unlock();
return false;
}
/*
CCard::SignHash
Purpose:
Sign the data with the specified key
Params:
CContainer* pContainer: The container which contains the signing key
ALG_ID algidKey: the ALG_ID of the key to use for the signing
LPBYTE pbyHash: Pointer to the data to sign (typically a hash)
DWORD dwHashLen: Length of the data to sign (must be < dwModulus)
LPBYTE pbySignature: Buffer for the signature
LPDWORD pdwSigLen: The length of the signature
Returns:
_
*/
bool CCard::SignHash(CContainer* pContainer, ALG_ID algidKey, LPBYTE pbyHash, DWORD dwHashLen, LPBYTE pbySignature, LPDWORD pdwSigLen)
{
assert(!IsBadReadPtr(pContainer, sizeof(CContainer)));
assert(!IsBadReadPtr(pdwSigLen, sizeof(DWORD)));
assert(!IsBadWritePtr(pdwSigLen, sizeof(DWORD)));
printf("Key spec:%d\n",algidKey);
if(!pContainer)
{
SetLastError(NTE_NO_KEY);
return false;
}
if(!pdwSigLen)
{
SetLastError(NTE_FAIL);
return false;
}
if(!Lock())
return false;
bool bRet = false;
DWORD dwModulusLength;
BYTE * pbyEncoded = NULL;
WCHAR szFileName[sizeof(WfSC_DIR_CSP) + 14];
//Find the key with the specified algid.
KEYINFO kiSignKeyProperties;
if(!pContainer->GetKeyInfoOfKey(algidKey, &kiSignKeyProperties))
{
SetLastError(NTE_NO_KEY);
goto cleanup;
}
dwModulusLength = kiSignKeyProperties.wKeyBits/8;
assert(dwModulusLength < 0xFF); //Crypto can only handle 0xFF bytes
//The signature will be the same length as the key
if(!pbySignature || dwModulusLength > *pdwSigLen)
{
*pdwSigLen = dwModulusLength;
bRet = true;
if (pbySignature)
{
bRet = false;
SetLastError(ERROR_MORE_DATA);
}
goto cleanup;
}
if (!Authenticate())
{
SetLastError(NTE_PERM);
goto cleanup;
}
if(dwHashLen + 3 //size of minimum PKCS#1 wrapping
> dwModulusLength)
{
SetLastError(NTE_BAD_HASH);
goto cleanup;
}
*pdwSigLen = dwModulusLength;
wsprintf(szFileName, TEXT("%s/%4.4X%4.4X"), WfSC_DIR_CSP, pContainer->GetSerNum(), kiSignKeyProperties.wFileID);
//执行签名
if(!fp.DoSign(szFileName,pbyHash,dwHashLen,pbySignature,pdwSigLen))
{
SetLastError(NTE_FAIL);
goto cleanup;
}
DWORD i,j;
BYTE tempc;
for(j =*pdwSigLen-1,i=0;i<j;i++,j--)
{
tempc = pbySignature[i];
pbySignature[i] = pbySignature[j];
pbySignature[j] = tempc;
}
bRet = true;
cleanup:
if(pbyEncoded)
delete[] pbyEncoded;
Unlock();
return bRet;
}
/*
CCard::DoDecrypt
Purpose:
Decrypts the data with the specified key
Params:
IN WCHAR * pszKeyFile: The name of the key file on the card
IN BYTE * pbyData: The data to decrypt
IN WORD wDataLen: The length of the data to decrypt
OUT BYTE * pbyOutputData: The output buffer
OUT WORD *pwOutputLen: The length of the output buffer
int iKeyLen: The length of the modulus (basically the number of bytes we can decrypt at at time)
Returns:
_
*/
bool CCard::DoDecrypt(IN WCHAR * pszKeyFile, IN BYTE * pbyData, IN DWORD wDataLen, OUT BYTE * pbyOutputData, OUT DWORD *pwOutputLen, int iKeyLen)
{
DWORD i,j;
BYTE tempc;
for(j =wDataLen-1,i=0;i<j;i++,j--)
{
tempc = pbyData[i];
pbyData[i] = pbyData[j];
pbyData[j] = tempc;
}
return fp.Decrypt(pszKeyFile,pbyData,wDataLen,pbyOutputData,pwOutputLen);
}
/*
CContainer::DoCrypto
Purpose:
Performs the crypto operation of the specified type
Params:
BYTE byCryptoType: The type of crypto operation (see ScwCryptInitialize() in the WfSC API)
IN WCHAR * pszKeyFile: The path to the key
IN BYTE * pbyInput: The data to perform the operation on
IN BYTE byInputLen: The amount of input data
OUT BYTE * pbyOutput: The output buffer
OUT BYTE *pbyOutputLen: The length of the output buffer
Returns:
true if it succeds, false otherwise.
*/
bool CCard::DoCrypto(BYTE byCryptoType, IN WCHAR * pszKeyFile, IN BYTE * pbyInput, IN BYTE byInputLen, OUT BYTE * pbyOutput, OUT BYTE *pbyOutputLen)
{
/*LPBYTE keyContents = new BYTE[byInputLen+1];
HANDLE file = fp.GetFile(pszKeyFile);
DWORD actualSize;
fp.ReadData(file,keyContents,byInputLen,actualSize);
CloseHandle(file);
HKEY priKey;
CryptImportKey(*/
//TODO
return true;
}
BYTE* CCard::GetEncodedData(LPBYTE pbyHash, DWORD dwHashLen,DWORD dwModulusLen)
{
BYTE* pbyEncoded = new BYTE[dwModulusLen];
if(!pbyEncoded)
return false;
PKCS1_Encode_D_To_EB_01(pbyEncoded, pbyHash, dwHashLen, dwModulusLen);
return pbyEncoded;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -