www.pudn.com > SmartCardSrc.zip > ACOS1.cpp


//------------------------------------------------------------------------------ 
// 
// Copyright (c) 1999-2005  Matt Brunk   
// 
// This program is free software; you can redistribute it and/or modify 
// it under the terms of the GNU General Public License VERSION 2 as 
// published by the Free Software Foundation.  You are not allowed to 
// use any other version of the license; unless you got the explicit 
// permission from the author to do so. 
// 
// This program is distributed in the hope that it will be useful, 
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
// GNU General Public License for more details. 
// 
// You should have received a copy of the GNU General Public License 
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
// 
//------------------------------------------------------------------------------ 
#include "stdafx.h" 
#include "ACOS1.h" 
#include "sdes.h" 
 
unsigned char SUBMIT_CODE[]		= {0x80, 0x20, 0x07, 0x00, 0x08}; 
unsigned char SELECT_FILE[]		= {0x80, 0xA4, 0x00, 0x00, 0x02}; 
unsigned char START_SESSION[]	= {0x80, 0x84, 0x00, 0x00, 0x08}; 
 
static void EncryptBuffer(unsigned char *buf, size_t length); 
 
void CACOS1::SetStopBits(int num) 
{ 
	if ( num == 1 ) 
	{ 
		m_stopBits = CSerialPort::OneStopBit; 
	} 
	else 
	{ 
		m_stopBits = CSerialPort::TwoStopBits; 
	} 
} 
 
CACOS1::CACOS1() 
{ 
	m_iPort				= 1; 
	m_iBaud				= 9600; 
	m_stopBits			= CSerialPort::TwoStopBits; 
	m_pEdit				= NULL; 
	m_bEnableEncryption	= false; 
	m_bVerbose			= true; 
	::ZeroMemory(m_buf, sizeof m_buf); 
	::ZeroMemory(m_inBuf, sizeof m_inBuf); 
} 
 
CACOS1::~CACOS1() 
{ 
	try 
	{ 
		if ( m_port.IsOpen() ) 
		{ 
			m_port.Close(); 
		} 
	} 
	catch (...) 
	{ 
 
	} 
}	//lint !e1740: pointer member 'CACOS1::m_pEdit' not freed 
 
void CACOS1::EnableEncryption(bool bEnable) 
{ 
	m_bEnableEncryption = bEnable; 
} 
 
void CACOS1::SetVerbose(bool bEnable) 
{ 
	m_bVerbose = bEnable; 
} 
 
CString	CACOS1::GetLastErrorMsg() 
{ 
	return m_lastErrorMsg; 
} 
 
bool CACOS1::OpenPort() 
{ 
	bool success = true; 
	try 
	{ 
		m_port.Open 
		( 
			m_iPort, 
			m_iBaud, 
			CSerialPort::EvenParity, 
			8,  
			m_stopBits, 
			CSerialPort::NoFlowControl, 
			FALSE 
		); 
 
 
		m_port.SetMask(0); 
 
		COMMTIMEOUTS timeouts; 
 
		timeouts.ReadIntervalTimeout			= MAXDWORD; 
		timeouts.ReadTotalTimeoutMultiplier		= MAXDWORD; 
		timeouts.ReadTotalTimeoutConstant		= 200; 
		timeouts.WriteTotalTimeoutMultiplier	= 1; 
		timeouts.WriteTotalTimeoutConstant		= 1000; 
 
		m_port.SetTimeouts(timeouts); 
		m_port.Setup(8192, 1024); 
		Sleep(200); 
		m_port.Purge(PURGE_RXABORT | PURGE_RXCLEAR ); 
	} 
	catch (CSerialException* pEx)	//lint !e1752 catch parameter 1 is not a reference 
	{ 
		TRACE(_T("Handle Exception, Message:%s\n"), (LPCTSTR)pEx->SerialGetErrorMessage());	//lint !e506 Constant value Boolean 
		m_lastErrorMsg = pEx->SerialGetErrorMessage(); 
		pEx->Delete(); 
		success = false; 
	} 
	return success; 
} 
 
void CACOS1::ClosePort() 
{ 
	if ( m_port.IsOpen() ) 
	{ 
		m_port.Close(); 
	} 
} 
 
bool CACOS1::GetATR(unsigned char *outBuf, DWORD &nLength) 
{ 
	ASSERT(m_port.IsOpen()); 
 
	AppendText(_T("Resetting card ...")); 
 
	DWORD	inBufLength = nLength; 
	nLength = 0; 
 
	m_port.SetRTS(); 
	Sleep(50); 
	m_port.ClearRTS(); 
 
	unsigned char buf[128]; 
	DWORD dwRead = 0; 
	DWORD nn = 0; 
 
	do 
	{ 
		nn = m_port.Read(&buf[dwRead], 1); 
		dwRead += nn; 
	} while ((nn > 0) && (dwRead < inBufLength)); 
 
	CString atr; 
	CString ccc; 
 
	if ( dwRead > 0 ) 
	{ 
		//if ( m_bVerbose ) 
		{ 
			for ( DWORD ii = 0; ii < dwRead; ii++ ) 
			{ 
				outBuf[ii] = buf[ii]; 
				ccc.Format(_T("%02X "), buf[ii]); 
				atr += ccc; 
			} 
 
			atr += _T("\r\n"); 
			AppendText(atr); 
		} 
#if 0 
		else 
		{ 
			AppendText(_T("SUCCESS")); 
		} 
#endif 
	} 
	else 
	{ 
		AppendText(_T("ATR not received.")); 
	} 
 
	nLength = dwRead; 
 
	return dwRead > 0; 
} 
 
void CACOS1::AppendText(LPCTSTR Text) 
{ 
	if ( !m_pEdit ) 
	{ 
		return; 
	} 
 
	CString msg = Text; 
 
	msg += _T("\r\n"); 
 
	int Length = m_pEdit->GetWindowTextLength(); 
 
	m_pEdit->SetSel(Length, Length); 
	m_pEdit->ReplaceSel(msg); 
	m_pEdit->LineScroll( m_pEdit->GetLineCount() ); 
} 
 
static void EncryptBuffer(unsigned char *buf, size_t length) 
{ 
	for ( size_t ii = 0; ii < length; ii++ ) 
	{ 
		buf[ii] = SDES::Encrypt(buf[ii]); 
	} 
} 
bool CACOS1::SendCommand(unsigned char *cmd) 
{ 
	bool success = false; 
	CString ccc; 
 
	ASSERT(m_port.IsOpen()); 
 
	if ( SendData(cmd, 5) ) 
	{ 
		DWORD	nn; 
		DWORD	numRead = 0; 
 
		nn = m_port.Read(&m_buf[numRead], 1); 
		if ( nn == 1 ) 
		{ 
			numRead++; 
		} 
 
		if ( numRead == 1 ) 
		{ 
			if ( m_buf[0] == cmd[1] ) 
			{ 
				if ( m_bVerbose ) 
				{ 
					ccc.Format(_T("CORRECT procedure byte %02X == %02X"), m_buf[0], cmd[1]); 
					AppendText(ccc); 
				} 
				success = true; 
			} 
			else 
			{ 
				nn = m_port.Read(&m_buf[numRead], 1); 
				if ( nn == 1 ) 
				{ 
					numRead++; 
					ccc.Format(_T("error status = %02X %02X"), m_buf[0], m_buf[1]); 
					AppendText(ccc); 
				} 
			} 
		} 
		else 
		{ 
			ccc.Format(_T("SendCommand ERROR: numRead = %lu"), numRead); 
			AppendText(ccc); 
		} 
	} 
 
	return success; 
} 
 
bool CACOS1::SendData(unsigned char *data, DWORD dwLength) 
{ 
	ASSERT(m_port.IsOpen()); 
 
	DWORD	nn; 
	CString sss; 
	bool	success = true; 
 
	for ( size_t ii = 0; ii < dwLength; ii++ ) 
	{ 
		m_port.Write(&data[ii], 1); 
		nn = m_port.Read(&m_buf[0], 1); 
		if ( nn == 1 ) 
		{ 
			if ( m_buf[0] != data[ii] ) 
			{ 
				sss.Format(_T("Echo error -- mismatch %02X != %02X"), m_buf[0], data[ii]); 
				AppendText(sss); 
				success = false; 
			} 
			else if ( m_bVerbose ) 
			{ 
				sss.Format(_T("Echo SUCCESS -- %02X"), m_buf[0]); 
				AppendText(sss);	 
			} 
		} 
		else 
		{ 
			AppendText(_T("Echo error -- no echo..."));	 
			success = false; 
		} 
	} 
 
	return success; 
} 
 
bool CACOS1::GetData(unsigned char *data, DWORD &dwLength) 
{ 
	ASSERT(m_port.IsOpen()); 
	bool success = false; 
 
	dwLength = 0; 
 
	DWORD	dwRead = 0; 
	DWORD	nn; 
 
	do 
	{ 
		nn		= m_port.Read(&data[dwRead], 1); 
		dwRead += nn; 
	} while (nn > 0); 
 
	if ( (dwRead >= 3) ) 
	{ 
		U8 c1 = 0x90; 
		U8 c2 = 0x00; 
 
		if ( m_bEnableEncryption ) 
		{ 
			c1 = SDES::Encrypt(c1); 
			c2 = SDES::Encrypt(c2); 
		} 
 
		if ( (data[dwRead - 2] == c1) && (data[dwRead - 1] == c2) ) 
		{ 
			success  = true; 
			dwLength = dwRead - 2; 
		} 
	} 
 
	return success; 
} 
 
bool CACOS1::GetStatus() 
{ 
	ASSERT(m_port.IsOpen()); 
 
	bool	success = false; 
	DWORD	dwRead = 0; 
	DWORD	nn; 
 
	do 
	{ 
		nn = m_port.Read(&m_buf[dwRead], 1); 
		dwRead += nn; 
	} while (nn > 0); 
 
	if ( dwRead == 2 ) 
	{ 
		U8 c1 = 0x90; 
		U8 c2 = 0x00; 
 
		if ( m_bEnableEncryption ) 
		{ 
			c1 = SDES::Encrypt(c1); 
			c2 = SDES::Encrypt(c2); 
		} 
				 
		if ( (m_buf[0] == c1) && (m_buf[1] == c2) ) 
		{ 
			success = true; 
		} 
		else 
		{ 
			CString ccc; 
			ccc.Format(_T("Status: %02X %02X"), m_buf[0], m_buf[1]); 
			AppendText(ccc); 
		} 
	} 
 
	return success; 
} 
 
bool CACOS1::SubmitIC(unsigned char *ic) 
{ 
	ASSERT(m_port.IsOpen()); 
	bool success = false; 
	AppendText(_T("Sending submit code command ...")); 
 
	::CopyMemory(m_inBuf, SUBMIT_CODE, 5); 
 
	if ( m_bEnableEncryption ) 
	{ 
		EncryptBuffer(m_inBuf, 5); 
	} 
 
	if ( SendCommand(m_inBuf) ) 
	{ 
		::CopyMemory(m_inBuf, ic, 8); 
 
		if ( m_bEnableEncryption ) 
		{ 
			EncryptBuffer(m_inBuf, 8); 
		} 
 
		if ( SendData(m_inBuf, 8) ) 
		{ 
			if ( GetStatus() ) 
			{ 
				AppendText(_T("SUCCESS")); 
				success = true; 
			} 
			else 
			{ 
				AppendText(_T("GetStatus ERROR")); 
			} 
		} 
		else 
		{ 
			AppendText(_T("SendCommand ERROR")); 
		} 
	} 
	else 
	{ 
		AppendText(_T("SendData ERROR")); 
	} 
 
	return success; 
} 
 
bool CACOS1::SelectFile(unsigned char *file) 
{ 
	ASSERT(m_port.IsOpen()); 
	bool success = false; 
	AppendText(_T("Sending select file command ...")); 
 
	::CopyMemory(m_inBuf, SELECT_FILE, 5); 
 
	if ( m_bEnableEncryption ) 
	{ 
		EncryptBuffer(m_inBuf, 5); 
	} 
 
	if ( SendCommand(m_inBuf) ) 
	{ 
		::CopyMemory(m_inBuf, file, 2); 
 
		if ( m_bEnableEncryption ) 
		{ 
			EncryptBuffer(m_inBuf, 2); 
		} 
 
		if ( SendData(m_inBuf, 2) ) 
		{ 
			if ( GetStatus() ) 
			{ 
				AppendText(_T("SUCCESS")); 
				success = true; 
			} 
			else 
			{ 
				AppendText(_T("GetStatus ERROR")); 
			} 
		} 
	} 
 
	return success; 
} 
 
bool CACOS1::StartSession(unsigned char *key, DWORD &dwLength) 
{ 
	ASSERT(m_port.IsOpen()); 
	bool success = false; 
	AppendText(_T("Sending start session command ...")); 
 
	::CopyMemory(m_inBuf, START_SESSION, 5); 
 
	if ( m_bEnableEncryption ) 
	{ 
		EncryptBuffer(m_inBuf, 5); 
	} 
 
	if ( SendCommand(m_inBuf) ) 
	{ 
		if ( GetData(key, dwLength) ) 
		{ 
			AppendText(_T("SUCCESS")); 
			success = true; 
		} 
	} 
 
	return success; 
 
} 
 
bool CACOS1::ReadRecord(int recordNum, int numBytes, unsigned char *data, DWORD &dwLength) 
{ 
	ASSERT(m_port.IsOpen()); 
	unsigned char cmd[] = {0x80, 0xB2, 0x00, 0x00, 0x00}; 
	cmd[2] = (unsigned char)recordNum; 
	cmd[4] = (unsigned char)numBytes; 
 
	bool success = false; 
	AppendText(_T("Reading record ...")); 
 
	::CopyMemory(m_inBuf, cmd, 5); 
 
	if ( m_bEnableEncryption ) 
	{ 
		EncryptBuffer(m_inBuf, 5); 
	} 
 
	if ( SendCommand(m_inBuf) ) 
	{ 
		if ( GetData(data, dwLength) ) 
		{ 
			AppendText(_T("SUCCESS")); 
			success = true; 
		} 
	} 
 
	return success; 
} 
 
bool CACOS1::WriteRecord(int recordNum, unsigned char *data, int numBytes) 
{ 
	ASSERT(m_port.IsOpen()); 
	unsigned char cmd[] = {0x80, 0xD2, 0x00, 0x00, 0x00}; 
	cmd[2] = (unsigned char)recordNum; 
	cmd[4] = (unsigned char)numBytes; 
 
	bool success = false; 
	AppendText(_T("Writing record ...")); 
 
	::CopyMemory(m_inBuf, cmd, 5); 
 
	if ( m_bEnableEncryption ) 
	{ 
		EncryptBuffer(m_inBuf, 5); 
	} 
 
	if ( SendCommand(m_inBuf) ) 
	{ 
		::CopyMemory(m_inBuf, data, numBytes); 
 
		if ( m_bEnableEncryption ) 
		{ 
			EncryptBuffer(m_inBuf, numBytes); 
		} 
 
		if ( SendData(m_inBuf, numBytes) ) 
		{ 
			if ( GetStatus() ) 
			{ 
				AppendText(_T("SUCCESS")); 
				success = true; 
			} 
			else 
			{ 
				AppendText(_T("GetStatus ERROR")); 
			} 
		} 
	} 
 
	return success; 
 
} 
 
void CACOS1::DumpDCB() 
{ 
	ASSERT(m_port.IsOpen()); 
 
	DCB dcb; 
	m_port.GetState(dcb); 
 
	CString sss; 
 
	AppendText(_T("---- DCB---")); 
	sss.Format(_T("DCBlength         : %lu"), dcb.DCBlength); 
	AppendText(sss); 
	sss.Format(_T("BaudRate          : %lu"), dcb.BaudRate); 
	AppendText(sss); 
	sss.Format(_T("fBinary           : %lu"), dcb.fBinary); 
	AppendText(sss); 
	sss.Format(_T("fParity           : %lu"), dcb.fParity); 
	AppendText(sss); 
	sss.Format(_T("fOutxCtsFlow      : %lu"), dcb.fOutxCtsFlow); 
	AppendText(sss); 
	sss.Format(_T("fOutxDsrFlow      : %lu"), dcb.fOutxDsrFlow); 
	AppendText(sss); 
	sss.Format(_T("fDtrControl       : %lu"), dcb.fDtrControl); 
	AppendText(sss); 
	sss.Format(_T("fDsrSensitivity   : %lu"), dcb.fDsrSensitivity); 
	AppendText(sss); 
	sss.Format(_T("fTXContinueOnXoff : %lu"), dcb.fTXContinueOnXoff); 
	AppendText(sss); 
	sss.Format(_T("fOutX             : %lu"), dcb.fOutX); 
	AppendText(sss); 
	sss.Format(_T("fInX              : %lu"), dcb.fInX); 
	AppendText(sss); 
	sss.Format(_T("fErrorChar        : %lu"), dcb.fErrorChar); 
	AppendText(sss); 
	sss.Format(_T("fNull             : %lu"), dcb.fNull); 
	AppendText(sss); 
	sss.Format(_T("fRtsControl       : %lu"), dcb.fRtsControl); 
	AppendText(sss); 
	sss.Format(_T("fAbortOnError     : %lu"), dcb.fAbortOnError); 
	AppendText(sss); 
	sss.Format(_T("fDummy2           : %lu"), dcb.fDummy2); 
	AppendText(sss); 
	sss.Format(_T("wReserved         : %lu"), dcb.wReserved); 
	AppendText(sss); 
	sss.Format(_T("XonLim            : %lu"), dcb.XonLim); 
	AppendText(sss); 
	sss.Format(_T("XoffLim           : %lu"), dcb.XoffLim); 
	AppendText(sss); 
	sss.Format(_T("ByteSize          : %lu"), dcb.ByteSize); 
	AppendText(sss); 
	sss.Format(_T("Parity            : %lu"), dcb.Parity); 
	AppendText(sss); 
	sss.Format(_T("StopBits          : %lu"), dcb.StopBits); 
	AppendText(sss); 
	sss.Format(_T("XonChar           : %02X"), dcb.XonChar); 
	AppendText(sss); 
	sss.Format(_T("XoffChar          : %02X"), dcb.XoffChar); 
	AppendText(sss); 
	sss.Format(_T("ErrorChar         : %02X"), dcb.ErrorChar); 
	AppendText(sss); 
	sss.Format(_T("EofChar           : %02X"), dcb.EofChar); 
	AppendText(sss); 
	sss.Format(_T("EvtChar           : %02X"), dcb.EvtChar); 
	AppendText(sss); 
	sss.Format(_T("wReserved1        : %lu"), dcb.wReserved1); 
	AppendText(sss); 
}