X-Git-Url: http://git.osdn.net/view?p=rec10%2Frec10-git.git;a=blobdiff_plain;f=b25-remote%2FBCasCard.cpp;fp=b25-remote%2FBCasCard.cpp;h=7d8387f7c256f46d8a3b5722729e4a67d8377a8a;hp=0000000000000000000000000000000000000000;hb=7868a1563cc62577db56b634e7505107559dbc62;hpb=0dcd333e60b7f6e7314cf7dd9f842cc5591ea0f5 diff --git a/b25-remote/BCasCard.cpp b/b25-remote/BCasCard.cpp new file mode 100755 index 0000000..7d8387f --- /dev/null +++ b/b25-remote/BCasCard.cpp @@ -0,0 +1,361 @@ +// BcasCard.cpp: CBcasCard ƒNƒ‰ƒX‚̃Cƒ“ƒvƒŠƒƒ“ƒe[ƒVƒ‡ƒ“ +// +////////////////////////////////////////////////////////////////////// + +#include "W2L.h" +#include "BCasCard.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + + +//#pragma comment(lib, "WinScard.lib") + + +using std::auto_ptr; + + +CBcasCard::CBcasCard() + : m_hBcasCard(NULL) + , m_bIsEstablish(false) + , m_dwLastError(BCEC_NOERROR) +{ + // “à•”ó‘ԏ‰Šú‰» + memset(&m_BcasCardInfo, 0, sizeof(m_BcasCardInfo)); + memset(&m_EcmStatus, 0, sizeof(m_EcmStatus)); + + // ƒŠƒ\[ƒXƒ}ƒl[ƒWƒƒƒRƒ“ƒeƒLƒXƒgŠm—§ + if(::SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &m_ScardContext) != SCARD_S_SUCCESS){ + m_dwLastError = BCEC_NOTESTABLISHED; + } + else{ + m_bIsEstablish = true; + + // ƒJ[ƒhƒŠ[ƒ_—ñ‹“ + EnumCardReader(); + } +} + +CBcasCard::~CBcasCard() +{ + CloseCard(); + + // ƒŠƒ\[ƒXƒ}ƒl[ƒWƒƒƒRƒ“ƒeƒLƒXƒg‚ÌŠJ•ú + if(m_bIsEstablish)::SCardReleaseContext(m_ScardContext); +} + +const DWORD CBcasCard::GetCardReaderNum(void) const +{ + // ƒJ[ƒhƒŠ[ƒ_[”‚ð•Ô‚· + return m_CardReaderArray.size(); +} + +LPCTSTR CBcasCard::GetCardReaderName(const DWORD dwIndex) const +{ + // ƒJ[ƒhƒŠ[ƒ_[–¼‚ð•Ô‚· + return (dwIndex < GetCardReaderNum())? m_CardReaderArray[dwIndex].c_str() : NULL; +} + +const bool CBcasCard::OpenCard(LPCTSTR lpszReader) +{ + // ƒŠƒ\[ƒXƒ}ƒl[ƒWƒƒƒRƒ“ƒeƒLƒXƒg‚ÌŠm—§ + if(!m_bIsEstablish){ + m_dwLastError = BCEC_NOTESTABLISHED; + return false; + } + + // ˆê’UƒNƒ[ƒY‚·‚é + CloseCard(); + + + if(lpszReader){ + // Žw’肳‚ꂽƒJ[ƒhƒŠ[ƒ_‚ɑ΂µ‚ăI[ƒvƒ“‚ðŽŽ‚Ý‚é + DWORD dwActiveProtocol = SCARD_PROTOCOL_UNDEFINED; + + if(::SCardConnect(m_ScardContext, lpszReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &m_hBcasCard, &dwActiveProtocol) != SCARD_S_SUCCESS){ + m_dwLastError = BCEC_CARDOPENERROR; + return false; + } + + if(dwActiveProtocol != SCARD_PROTOCOL_T1){ + CloseCard(); + m_dwLastError = BCEC_CARDOPENERROR; + return false; + } + } + else{ + // ‘S‚ẴJ[ƒhƒŠ[ƒ_‚ɑ΂µ‚ăI[ƒvƒ“‚ðŽŽ‚Ý‚é + DWORD dwIndex = 0UL; + + while(GetCardReaderName(dwIndex)){ + if(OpenCard(GetCardReaderName(dwIndex++)))return true; + } + + return false; + } + + // ƒJ[ƒh‰Šú‰» + if(!InitialSetting())return false; + + m_dwLastError = BCEC_NOERROR; + + return true; +} + +void CBcasCard::CloseCard(void) +{ + // ƒJ[ƒh‚ðƒNƒ[ƒY‚·‚é + if(m_hBcasCard){ + ::SCardDisconnect(m_hBcasCard, SCARD_LEAVE_CARD); + m_hBcasCard = NULL; + } +} + +const DWORD CBcasCard::GetLastError(void) const +{ + // ÅŒã‚É”­¶‚µ‚½ƒGƒ‰[‚ð•Ô‚· + return m_dwLastError; +} + +const bool CBcasCard::EnumCardReader(void) +{ + // ƒJ[ƒhƒŠ[ƒ_‚ð—ñ‹“‚·‚é + DWORD dwBuffSize = 0UL; + + switch(::SCardListReaders(m_ScardContext, NULL, NULL, &dwBuffSize)){ + case SCARD_E_NO_READERS_AVAILABLE : + // ƒJ[ƒhƒŠ[ƒ_‚ªŒ©‚‚©‚ç‚È‚¢ + m_dwLastError = BCEC_NOCARDREADERS; + return false; + + case SCARD_S_SUCCESS : + // ƒoƒbƒtƒ@ƒTƒCƒYŽæ“¾¬Œ÷ + break; + + default: + // ƒGƒ‰[ + m_dwLastError = BCEC_INTERNALERROR; + return false; + } + + // ƒoƒbƒtƒ@Šm•Û + auto_ptr szReaders(new TCHAR[dwBuffSize]); + + switch(::SCardListReaders(m_ScardContext, NULL, szReaders.get(), &dwBuffSize)){ + case SCARD_E_NO_READERS_AVAILABLE : + // ƒJ[ƒhƒŠ[ƒ_‚ªŒ©‚‚©‚ç‚È‚¢ + m_dwLastError = BCEC_NOCARDREADERS; + return false; + + case SCARD_S_SUCCESS : { + // ƒJ[ƒhƒŠ[ƒ_–¼•Û‘¶ + LPTSTR lpszCurReader = szReaders.get(); + m_CardReaderArray.clear(); + + while(*lpszCurReader){ + m_CardReaderArray.push_back(lpszCurReader); + lpszCurReader += m_CardReaderArray.back().length() + 1UL; + } + + break; + } + + default: + // ƒGƒ‰[ + m_dwLastError = BCEC_INTERNALERROR; + return false; + } + + m_dwLastError = BCEC_NOERROR; + + return true; +} + +const bool CBcasCard::TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData, const DWORD dwMaxRecv, DWORD *pdwRecvSize) +{ + DWORD dwRecvSize = dwMaxRecv; + + // ƒf[ƒ^‘—ŽóM + DWORD dwReturn = ::SCardTransmit(m_hBcasCard, SCARD_PCI_T1, pSendData, dwSendSize, NULL, pRecvData, &dwRecvSize); + + // ŽóMƒTƒCƒYŠi”[ + if(pdwRecvSize)*pdwRecvSize = dwRecvSize; + + return (dwReturn == SCARD_S_SUCCESS)? true : false; +} + +const bool CBcasCard::InitialSetting(void) +{ + static const BYTE InitSettingCmd[] = {0x90U, 0x30U, 0x00U, 0x00U, 0x00U}; + + // uInitial Setting Conditions Commandv‚ðˆ—‚·‚é + if(!m_hBcasCard){ + m_dwLastError = BCEC_CARDNOTOPEN; + return false; + } + + // ƒoƒbƒtƒ@€”õ + DWORD dwRecvSize = 0UL; + BYTE RecvData[1024]; + memset(RecvData, 0, sizeof(RecvData)); + + // ƒRƒ}ƒ“ƒh‘—M + if(!TransmitCommand(InitSettingCmd, sizeof(InitSettingCmd), RecvData, sizeof(RecvData), &dwRecvSize)){ + m_dwLastError = BCEC_TRANSMITERROR; + return false; + } + + if(dwRecvSize < 57UL){ + m_dwLastError = BCEC_TRANSMITERROR; + return false; + } + + // ƒŒƒXƒ|ƒ“ƒX‰ðÍ + memcpy(m_BcasCardInfo.BcasCardID, &RecvData[8], 6UL); // +8 Card ID + memcpy(m_BcasCardInfo.SystemKey, &RecvData[16], 32UL); // +16 Descrambling system key + memcpy(m_BcasCardInfo.InitialCbc, &RecvData[48], 8UL); // +48 Descrambler CBC initial value + + // ECMƒXƒe[ƒ^ƒX‰Šú‰» + memset(&m_EcmStatus, 0, sizeof(m_EcmStatus)); + + return true; +} + +const BYTE * CBcasCard::GetBcasCardID(void) +{ + // Card ID ‚ð•Ô‚· + if(!m_hBcasCard){ + m_dwLastError = BCEC_CARDNOTOPEN; + return NULL; + } + + m_dwLastError = BCEC_NOERROR; + + return m_BcasCardInfo.BcasCardID; +} + +const BYTE * CBcasCard::GetInitialCbc(void) +{ + // Descrambler CBC Initial Value ‚ð•Ô‚· + if(!m_hBcasCard){ + m_dwLastError = BCEC_CARDNOTOPEN; + return NULL; + } + + m_dwLastError = BCEC_NOERROR; + + return m_BcasCardInfo.InitialCbc; +} + +const BYTE * CBcasCard::GetSystemKey(void) +{ + // Descrambling System Key ‚ð•Ô‚· + if(!m_hBcasCard){ + m_dwLastError = BCEC_CARDNOTOPEN; + return NULL; + } + + m_dwLastError = BCEC_NOERROR; + + return m_BcasCardInfo.SystemKey; +} + +const BYTE * CBcasCard::GetKsFromEcm(const BYTE *pEcmData, const DWORD dwEcmSize) +{ + static const BYTE EcmReceiveCmd[] = {0x90U, 0x34U, 0x00U, 0x00U}; + + // uECM Receive Commandv‚ðˆ—‚·‚é + if(!m_hBcasCard){ + m_dwLastError = BCEC_CARDNOTOPEN; + return NULL; + } + + // ECMƒTƒCƒY‚ðƒ`ƒFƒbƒN + if(!pEcmData || (dwEcmSize < 30UL) || (dwEcmSize > 256UL)){ + m_dwLastError = BCEC_BADARGUMENT; + return NULL; + } + + // ƒLƒƒƒbƒVƒ…‚ðƒ`ƒFƒbƒN‚·‚é + if(!StoreEcmData(pEcmData, dwEcmSize)){ + // ECM‚ª“¯ˆê‚̏ꍇ‚̓LƒƒƒbƒVƒ…Ï‚ÝKs‚ð•Ô‚· + m_dwLastError = BCEC_NOERROR; + return m_EcmStatus.KsData; + } + + // ƒoƒbƒtƒ@€”õ + DWORD dwRecvSize = 0UL; + BYTE SendData[1024]; + BYTE RecvData[1024]; + memset(RecvData, 0, sizeof(RecvData)); + + // ƒRƒ}ƒ“ƒh\’z + memcpy(SendData, EcmReceiveCmd, sizeof(EcmReceiveCmd)); // CLA, INS, P1, P2 + SendData[sizeof(EcmReceiveCmd)] = (BYTE)dwEcmSize; // COMMAND DATA LENGTH + memcpy(&SendData[sizeof(EcmReceiveCmd) + 1], pEcmData, dwEcmSize); // ECM + SendData[sizeof(EcmReceiveCmd) + dwEcmSize + 1] = 0x00U; // RESPONSE DATA LENGTH + + // ƒRƒ}ƒ“ƒh‘—M + if(!TransmitCommand(SendData, sizeof(EcmReceiveCmd) + dwEcmSize + 2UL, RecvData, sizeof(RecvData), &dwRecvSize)){ + memset(&m_EcmStatus, 0, sizeof(m_EcmStatus)); + m_dwLastError = BCEC_TRANSMITERROR; + return NULL; + } + + // ƒTƒCƒYƒ`ƒFƒbƒN + if(dwRecvSize != 25UL){ + memset(&m_EcmStatus, 0, sizeof(m_EcmStatus)); + m_dwLastError = BCEC_TRANSMITERROR; + return NULL; + } + + // ƒŒƒXƒ|ƒ“ƒX‰ðÍ + memcpy(m_EcmStatus.KsData, &RecvData[6], sizeof(m_EcmStatus.KsData)); + + // ƒŠƒ^[ƒ“ƒR[ƒh‰ðÍ + switch(((WORD)RecvData[4] << 8) | (WORD)RecvData[5]){ + // Purchased: Viewing + case 0x0200U : // Payment-deferred PPV + case 0x0400U : // Prepaid PPV + case 0x0800U : // Tier + m_dwLastError = BCEC_NOERROR; + return m_EcmStatus.KsData; + + // ã‹LˆÈŠO(Ž‹’®•s‰Â) + default : + m_dwLastError = BCEC_ECMREFUSED; + return NULL; + } +} + +const bool CBcasCard::StoreEcmData(const BYTE *pEcmData, const DWORD dwEcmSize) +{ + bool bUpdate = false; + + // ECMƒf[ƒ^”äŠr + if(m_EcmStatus.dwLastEcmSize != dwEcmSize){ + // ƒTƒCƒY‚ª•Ï‰»‚µ‚½ + bUpdate = true; + } + else{ + // ƒTƒCƒY‚ª“¯‚¶ê‡‚̓f[ƒ^‚ðƒ`ƒFƒbƒN‚·‚é + for(DWORD dwPos = 0UL ; dwPos < dwEcmSize ; dwPos++){ + if(pEcmData[dwPos] != m_EcmStatus.LastEcmData[dwPos]){ + // ƒf[ƒ^‚ª•sˆê’v + bUpdate = true; + break; + } + } + } + + // ECMƒf[ƒ^‚ð•Û‘¶‚·‚é + if(bUpdate){ + m_EcmStatus.dwLastEcmSize = dwEcmSize; + memcpy(m_EcmStatus.LastEcmData, pEcmData, dwEcmSize); + } + + return bUpdate; +}