📄 crdspec_container.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//
//
/*
CRDSPEC_Container.cpp
This source file contains card specific functionality for containers
for the WfSC (Windows for SmartCard) cards The interfaces here
should be abstract enough that the implementation can be changed
for other cards easily.
History:
jamesku - Created 2/19/2001
*/
#include "CRDSPEC_Container.h"
#include <windows.h>
#include "CRDSPEC_Card.h"
#include "cspconst.h"
#include "assert.h"
#include "PaddingHelp.h"
/*
CContainer::CContainer
Purpose:
Initializes the container
Params:
CCard* pCrd: The card with which this container is associated
int iSerNum: The ser# of this container
WCHAR* pszName: The name of this container
int iNumKeys: The number of keys in this container
int iKeyInfoStartLoc: The location of the start info for the first key in the file.
Returns:
void
*/
CContainer::CContainer() :
m_iNextKeyNum(0), m_iNumKeys(0), m_pKeyInfo(NULL),
m_iSerNum(0), m_pCard(NULL), m_pszName(NULL), m_hCAPI2Lib(NULL)
{
// Set to defaults of 0.
m_pCertFile[1] =0;
m_pCertFile[0] =0;
m_dwCertLen[1] =0;
m_dwCertLen[0] =0;
}
/*
CContainer::Initialize
Purpose:
Initializes the container object with data.
The container file looks like this:
NULL terminated ASCII string: Container Name
BYTE version: Always 1
BYTE num entries: number of key entries in the container
[num entries repeats of the following block]
WORD fileID: the id of the key (/CSP/contIDfileID.key)
WORD algID: AlgID of the key. See cspconst.h for possible values (ALG_*)
WORD operation id: What this key is permitted to do. See cspconst.h (OP_*)
WORD keybits: the strength of the key
[end repeating block]
More information about the structure of the data on the smart
card can be found in the WfSCCSP.doc.
Params:
CCard* pCrd: The card that this container is associated with
int iSerNum: The serial number of this container
PBYTE pbyFileContents: pointer to the container file contents
int cbFileSize: size in bytes of container file
Returns:
true if it succeeds, false otherwise
*/
bool CContainer::Initialize (CCard* pCrd, int iSerNum, PBYTE pbyFileContents, int cbFileSize)
{
WCHAR* pszUnicodeName = NULL;
BYTE* pbyNullLoc;
UNALIGNED CCard::CONTINFO * pciContainerInfo;
int iContainerNameLen;
CCard::KEYINFO * pkiCurrentKey;
WORD wNextKeyNum = 0;
//Verify the card obj is OK
assert(!IsBadReadPtr(pCrd, sizeof(CCard)));
pbyNullLoc = (BYTE*)memchr(pbyFileContents, 0, cbFileSize);
if(!pbyNullLoc) //invalid file -- no 0 terminated container name!
goto cleanup;
iContainerNameLen = pbyNullLoc - pbyFileContents;
m_pszName = new WCHAR[iContainerNameLen + 1];
if(!m_pszName)
goto cleanup;
//Get the container name
mbstowcs(m_pszName, (char*)pbyFileContents, iContainerNameLen+1);
//We should not have run past the end of our buffer!
if(iContainerNameLen + 1 + SIZE_OF_CONTINFO > cbFileSize)
goto cleanup;
pciContainerInfo = (CCard::CONTINFO *)(pbyFileContents+iContainerNameLen+1);
// check version
// check that there is space for the specified number of KEYINFO structs
if(WfSC_CONT_VER_NUM != pciContainerInfo->byVersion
|| (PBYTE)(pciContainerInfo + 1) + pciContainerInfo->byNumKeys * sizeof(CCard::KEYINFO) > pbyFileContents +cbFileSize )
goto cleanup;
m_iNumKeys = pciContainerInfo->byNumKeys;
m_pKeyInfo = NULL;
if (m_iNumKeys)
{
m_pKeyInfo = new CCard::KEYINFO[m_iNumKeys];
if (!m_pKeyInfo)
goto cleanup;
memcpy(m_pKeyInfo, pciContainerInfo+1, m_iNumKeys * sizeof(CCard::KEYINFO));
}
//Iterate through each key and find the next value for a key id
pkiCurrentKey = m_pKeyInfo;
while(pkiCurrentKey - m_pKeyInfo < m_iNumKeys)
{
if(pkiCurrentKey->wFileID >= wNextKeyNum)
wNextKeyNum = pkiCurrentKey->wFileID + 1;
pkiCurrentKey++;
}
//Verify that we're in the container list
//assert(pCrd->GetContainerList()->VerifyExistance(this));
m_iNextKeyNum = wNextKeyNum;
m_iSerNum = iSerNum;
m_pCard = pCrd;
return true;
cleanup:
return FALSE;
}
/*
CContainer::~CContainer
Purpose:
Destructs CContainer
Params:
void
Returns:
void
*/
CContainer::~CContainer()
{
if(m_pszName)
delete [] m_pszName;
if (m_pKeyInfo)
delete [] m_pKeyInfo;
// Clean up our cache.
if(m_pCertFile[0]) delete [] m_pCertFile[0];
if(m_pCertFile[1]) delete [] m_pCertFile[1];
}
/*
CContainer::Delete
Purpose:
Deletes this container off of the card.
Params:
None.
Returns:
bool : true if it succeeds, false otherwise.
*/
bool CContainer::Delete()
{
if(!m_pCard)
return false;
//Get the container list
CHandleTable* pHT = m_pCard->GetContainerList();
if(!pHT)
return false;
//Add it to the container list.
pHT->RemoveFromTable(this);
WCHAR szContSer[5];
wsprintf(szContSer, TEXT("%4.4X"), GetSerNum());
long lResult;
UINT iFileIndex;
WCHAR szPath[100];
UINT16 usCookie = 0;
//Access the card
if(!m_pCard->Lock())
return false;
//Authenticate with the card
if(!m_pCard->Authenticate())
{
m_pCard->Unlock();
return false;
}
lResult = NO_ERROR;
memcpy(szPath, WfSC_DIR_CSP, sizeof(WfSC_DIR_CSP));
iFileIndex = sizeof(WfSC_DIR_CSP)/sizeof(WCHAR);
//szPath[iFileIndex - 1] = L'/';
szPath[iFileIndex] = 0;
BOOL ret = fp.DeleteKeySet(szPath,iFileIndex,szContSer,WfSC_DIR_CONT);
m_pCard->Unlock();
return ret != 0;
}
/*
Decrypt
Purpose:
Decrypt some data using the private key
Params:
ALG_ID algid: the algorithm ID of the key
CONST BYTE* pbySource: The data to decrypt
CONST DWORD dwSourceLength: The length of that data
BYTE* pbyDestination: reference to a BYTE ptr for the buffer (freed using FreeBuffer())
DWORD & dwDecryptedDataLength: size of the data copied to the buffer
Returns:
true if it succeeds, false otherwise.
*/
bool CContainer::Decrypt(ALG_ID algid, BYTE* pbySource, DWORD wSourceLength, BYTE* pbyDestination, DWORD* pwDestinationLen)
{
if(!m_pCard->Lock())
return false;
bool bRet = false;
BYTE* pbyDecryptedData = NULL;
CCard::KEYINFO kiDecrypt;
WCHAR szKeyFile[sizeof(WfSC_DIR_CSP) + 14];
DWORD wModulusLength = 0;
DWORD wDecryptedDataLen = 0;
if(!GetKeyInfoOfKey(algid, &kiDecrypt))
{
SetLastError(NTE_NO_KEY);
goto cleanup;
}
if (!m_pCard->Authenticate())
{
SetLastError(NTE_PERM);
goto cleanup;
}
wModulusLength = kiDecrypt.wKeyBits/8;
pbyDecryptedData = new BYTE[wSourceLength];
if(!pbyDecryptedData)
goto cleanup;
//Decrypt the data
wDecryptedDataLen = wSourceLength;
//TODO
wsprintf(szKeyFile, TEXT("%s/%4.4X%4.4X"), WfSC_DIR_CSP, GetSerNum(), kiDecrypt.wFileID);
if(!m_pCard->DoDecrypt(szKeyFile, pbySource, wSourceLength, pbyDecryptedData, &wDecryptedDataLen, wModulusLength))
goto cleanup;
*pwDestinationLen = wDecryptedDataLen;
memcpy(pbyDestination,pbyDecryptedData,wDecryptedDataLen);
bRet = true;
cleanup:
if(pbyDecryptedData)
delete [] pbyDecryptedData;
m_pCard->Unlock();
return bRet;
}
// Take the cert file, and import the certs public key into our down stream Provider.
bool CContainer::GetPublicKeyFromCert(HCRYPTPROV hProv, ALG_ID algid, HCRYPTKEY* phKey,BYTE *pbyCertFile,DWORD cbCertLen)
{
bool ret=false;
PCCERT_CONTEXT pCertContextForImport=0;
ASSERT(algid == AT_SIGNATURE || algid == AT_KEYEXCHANGE);
if(!LoadCAPI2Lib()) goto cleanup;
pCertContextForImport = m_lpfnCreateCertificateContext(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
pbyCertFile,
cbCertLen);
if(!pCertContextForImport) goto cleanup;
// Remap Algid
if (AT_SIGNATURE == algid ) algid = CALG_RSA_SIGN;
else if ( AT_KEYEXCHANGE == algid ) algid = CALG_RSA_KEYX;
else (ASSERT(0));
// Reimport the key
if(!m_lpfnImportPublicKeyInfoEx(
hProv,
X509_ASN_ENCODING |PKCS_7_ASN_ENCODING,
&pCertContextForImport->pCertInfo->SubjectPublicKeyInfo,
algid,
0,
0,
phKey
))
{
goto cleanup;
}
ret = true;
cleanup:
if (pCertContextForImport) m_lpfnFreeCertificateContext(pCertContextForImport);
return ret;
}
/*
CContainer::GetPublicKey
Purpose:
Gets a handle to the public key by going to the card
and getting the .crt file associated with the key
Valid CRT files start with 0x30 which indicate that the file
is a full fledged certificate which we will need CAPI2 to decode
On the other hand, if the CRT file starts with PUBLICKEYBLOB
(ie. the first field of a PUBLICKEYSTRUC) then we know it's
just a plain public key.
Params:
HCRYPTPROV hProv: The provider into which to import the public key
ALG_ID algid: The algID of the key to fetch
HCRYPTKEY* phKey: out parameter for the handle to the key
Returns:
true if it succeeds, false otherwise
*/
bool CContainer::GetPublicKey(HCRYPTPROV hProv, ALG_ID algid, HCRYPTKEY* phKey)
{
assert(!IsBadWritePtr(phKey, sizeof(HCRYPTKEY)));
bool bRet = false;
bool bLocked = false;
BOOL lResult;
WCHAR szKeyPath[MAX_BUFFER];
BYTE* pbyPublicKey = NULL;
DWORD dwActualBytes;
DWORD offFileSize;
HANDLE hCrtFile = NULL;
CCard::KEYINFO kiPubKey;
DWORD len;
PBYTE p;
DWORD fileSize;
//Get the fileID of the key with the specified alg_id.
if(!GetKeyInfoOfKey(algid, &kiPubKey))
{
SetLastError(NTE_NO_KEY);
goto cleanup;
}
//check if we already cached the .crt file.
p = GetCachedCert(algid,&len);
if (p)
{
pbyPublicKey = new BYTE [len];
if (!pbyPublicKey) goto cleanup;
memcpy(pbyPublicKey,p,len );
ASSERT(len < 0xFFFF);
fileSize=len;
}
else
{
// We didn't cache the file, so get ready to read it from card.
if(!m_pCard->Lock()) goto cleanup;
bLocked = true;
//Now that we have a key with the specified operation code
//Let's go get the crt file that's associated with it
wsprintf(szKeyPath, TEXT("%s/%4.4X%4.4X.crt"),
WfSC_DIR_CSP, GetSerNum(), kiPubKey.wFileID);
//lResult = hScwCreateFile(m_pCard->GetProxyHandle(), szKeyPath, NULL, &hCrtFile);
//if(FAILED(lResult)) goto cleanup;
hCrtFile = fp.GetFile(szKeyPath);
if(!fp.IsValid(hCrtFile))
goto cleanup;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -