⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 crdspec_card.cpp

📁 基于SD卡的软实现CSP程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//	{
//		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 + -