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); }