1 // BcasCard.cpp: CBcasCard
\83N
\83\89\83X
\82Ì
\83C
\83\93\83v
\83\8a\83\81\83\93\83e
\81[
\83V
\83\87\83\93\r
3 //////////////////////////////////////////////////////////////////////
\r
6 #include "BCasCard.h"
\r
10 static char THIS_FILE[]=__FILE__;
\r
11 #define new DEBUG_NEW
\r
15 //#pragma comment(lib, "WinScard.lib")
\r
18 using std::auto_ptr;
\r
21 CBcasCard::CBcasCard()
\r
23 , m_bIsEstablish(false)
\r
24 , m_dwLastError(BCEC_NOERROR)
\r
26 //
\93à
\95\94\8fó
\91Ô
\8f\89\8aú
\89»
\r
27 memset(&m_BcasCardInfo, 0, sizeof(m_BcasCardInfo));
\r
28 memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));
\r
30 //
\83\8a\83\
\81[
\83X
\83}
\83l
\81[
\83W
\83\83\83R
\83\93\83e
\83L
\83X
\83g
\8am
\97§
\r
31 if(::SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &m_ScardContext) != SCARD_S_SUCCESS){
\r
32 m_dwLastError = BCEC_NOTESTABLISHED;
\r
35 m_bIsEstablish = true;
\r
37 //
\83J
\81[
\83h
\83\8a\81[
\83_
\97ñ
\8b\93\r
42 CBcasCard::~CBcasCard()
\r
46 //
\83\8a\83\
\81[
\83X
\83}
\83l
\81[
\83W
\83\83\83R
\83\93\83e
\83L
\83X
\83g
\82Ì
\8aJ
\95ú
\r
47 if(m_bIsEstablish)::SCardReleaseContext(m_ScardContext);
\r
50 const DWORD CBcasCard::GetCardReaderNum(void) const
\r
52 //
\83J
\81[
\83h
\83\8a\81[
\83_
\81[
\90\94\82ð
\95Ô
\82·
\r
53 return m_CardReaderArray.size();
\r
56 LPCTSTR CBcasCard::GetCardReaderName(const DWORD dwIndex) const
\r
58 //
\83J
\81[
\83h
\83\8a\81[
\83_
\81[
\96¼
\82ð
\95Ô
\82·
\r
59 return (dwIndex < GetCardReaderNum())? m_CardReaderArray[dwIndex].c_str() : NULL;
\r
62 const bool CBcasCard::OpenCard(LPCTSTR lpszReader)
\r
64 //
\83\8a\83\
\81[
\83X
\83}
\83l
\81[
\83W
\83\83\83R
\83\93\83e
\83L
\83X
\83g
\82Ì
\8am
\97§
\r
65 if(!m_bIsEstablish){
\r
66 m_dwLastError = BCEC_NOTESTABLISHED;
\r
70 //
\88ê
\92U
\83N
\83\8d\81[
\83Y
\82·
\82é
\r
75 //
\8ew
\92è
\82³
\82ê
\82½
\83J
\81[
\83h
\83\8a\81[
\83_
\82É
\91Î
\82µ
\82Ä
\83I
\81[
\83v
\83\93\82ð
\8e\8e\82Ý
\82é
\r
76 DWORD dwActiveProtocol = SCARD_PROTOCOL_UNDEFINED;
\r
78 if(::SCardConnect(m_ScardContext, lpszReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &m_hBcasCard, &dwActiveProtocol) != SCARD_S_SUCCESS){
\r
79 m_dwLastError = BCEC_CARDOPENERROR;
\r
83 if(dwActiveProtocol != SCARD_PROTOCOL_T1){
\r
85 m_dwLastError = BCEC_CARDOPENERROR;
\r
90 //
\91S
\82Ä
\82Ì
\83J
\81[
\83h
\83\8a\81[
\83_
\82É
\91Î
\82µ
\82Ä
\83I
\81[
\83v
\83\93\82ð
\8e\8e\82Ý
\82é
\r
91 DWORD dwIndex = 0UL;
\r
93 while(GetCardReaderName(dwIndex)){
\r
94 if(OpenCard(GetCardReaderName(dwIndex++)))return true;
\r
100 //
\83J
\81[
\83h
\8f\89\8aú
\89»
\r
101 if(!InitialSetting())return false;
\r
103 m_dwLastError = BCEC_NOERROR;
\r
108 void CBcasCard::CloseCard(void)
\r
110 //
\83J
\81[
\83h
\82ð
\83N
\83\8d\81[
\83Y
\82·
\82é
\r
112 ::SCardDisconnect(m_hBcasCard, SCARD_LEAVE_CARD);
\r
113 m_hBcasCard = NULL;
\r
117 const DWORD CBcasCard::GetLastError(void) const
\r
119 //
\8dÅ
\8cã
\82É
\94
\90¶
\82µ
\82½
\83G
\83\89\81[
\82ð
\95Ô
\82·
\r
120 return m_dwLastError;
\r
123 const bool CBcasCard::EnumCardReader(void)
\r
125 //
\83J
\81[
\83h
\83\8a\81[
\83_
\82ð
\97ñ
\8b\93\82·
\82é
\r
126 DWORD dwBuffSize = 0UL;
\r
128 switch(::SCardListReaders(m_ScardContext, NULL, NULL, &dwBuffSize)){
\r
129 case SCARD_E_NO_READERS_AVAILABLE :
\r
130 //
\83J
\81[
\83h
\83\8a\81[
\83_
\82ª
\8c©
\82Â
\82©
\82ç
\82È
\82¢
\r
131 m_dwLastError = BCEC_NOCARDREADERS;
\r
134 case SCARD_S_SUCCESS :
\r
135 //
\83o
\83b
\83t
\83@
\83T
\83C
\83Y
\8eæ
\93¾
\90¬
\8c÷
\r
140 m_dwLastError = BCEC_INTERNALERROR;
\r
144 //
\83o
\83b
\83t
\83@
\8am
\95Û
\r
145 auto_ptr<TCHAR> szReaders(new TCHAR[dwBuffSize]);
\r
147 switch(::SCardListReaders(m_ScardContext, NULL, szReaders.get(), &dwBuffSize)){
\r
148 case SCARD_E_NO_READERS_AVAILABLE :
\r
149 //
\83J
\81[
\83h
\83\8a\81[
\83_
\82ª
\8c©
\82Â
\82©
\82ç
\82È
\82¢
\r
150 m_dwLastError = BCEC_NOCARDREADERS;
\r
153 case SCARD_S_SUCCESS : {
\r
154 //
\83J
\81[
\83h
\83\8a\81[
\83_
\96¼
\95Û
\91¶
\r
155 LPTSTR lpszCurReader = szReaders.get();
\r
156 m_CardReaderArray.clear();
\r
158 while(*lpszCurReader){
\r
159 m_CardReaderArray.push_back(lpszCurReader);
\r
160 lpszCurReader += m_CardReaderArray.back().length() + 1UL;
\r
168 m_dwLastError = BCEC_INTERNALERROR;
\r
172 m_dwLastError = BCEC_NOERROR;
\r
177 const bool CBcasCard::TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData, const DWORD dwMaxRecv, DWORD *pdwRecvSize)
\r
179 DWORD dwRecvSize = dwMaxRecv;
\r
181 //
\83f
\81[
\83^
\91\97\8eó
\90M
\r
182 DWORD dwReturn = ::SCardTransmit(m_hBcasCard, SCARD_PCI_T1, pSendData, dwSendSize, NULL, pRecvData, &dwRecvSize);
\r
184 //
\8eó
\90M
\83T
\83C
\83Y
\8ai
\94[
\r
185 if(pdwRecvSize)*pdwRecvSize = dwRecvSize;
\r
187 return (dwReturn == SCARD_S_SUCCESS)? true : false;
\r
190 const bool CBcasCard::InitialSetting(void)
\r
192 static const BYTE InitSettingCmd[] = {0x90U, 0x30U, 0x00U, 0x00U, 0x00U};
\r
194 //
\81uInitial Setting Conditions Command
\81v
\82ð
\8f\88\97\9d\82·
\82é
\r
196 m_dwLastError = BCEC_CARDNOTOPEN;
\r
200 //
\83o
\83b
\83t
\83@
\8f\80\94õ
\r
201 DWORD dwRecvSize = 0UL;
\r
202 BYTE RecvData[1024];
\r
203 memset(RecvData, 0, sizeof(RecvData));
\r
205 //
\83R
\83}
\83\93\83h
\91\97\90M
\r
206 if(!TransmitCommand(InitSettingCmd, sizeof(InitSettingCmd), RecvData, sizeof(RecvData), &dwRecvSize)){
\r
207 m_dwLastError = BCEC_TRANSMITERROR;
\r
211 if(dwRecvSize < 57UL){
\r
212 m_dwLastError = BCEC_TRANSMITERROR;
\r
216 //
\83\8c\83X
\83|
\83\93\83X
\89ð
\90Í
\r
217 memcpy(m_BcasCardInfo.BcasCardID, &RecvData[8], 6UL); // +8 Card ID
\r
218 memcpy(m_BcasCardInfo.SystemKey, &RecvData[16], 32UL); // +16 Descrambling system key
\r
219 memcpy(m_BcasCardInfo.InitialCbc, &RecvData[48], 8UL); // +48 Descrambler CBC initial value
\r
221 // ECM
\83X
\83e
\81[
\83^
\83X
\8f\89\8aú
\89»
\r
222 memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));
\r
227 const BYTE * CBcasCard::GetBcasCardID(void)
\r
229 // Card ID
\82ð
\95Ô
\82·
\r
231 m_dwLastError = BCEC_CARDNOTOPEN;
\r
235 m_dwLastError = BCEC_NOERROR;
\r
237 return m_BcasCardInfo.BcasCardID;
\r
240 const BYTE * CBcasCard::GetInitialCbc(void)
\r
242 // Descrambler CBC Initial Value
\82ð
\95Ô
\82·
\r
244 m_dwLastError = BCEC_CARDNOTOPEN;
\r
248 m_dwLastError = BCEC_NOERROR;
\r
250 return m_BcasCardInfo.InitialCbc;
\r
253 const BYTE * CBcasCard::GetSystemKey(void)
\r
255 // Descrambling System Key
\82ð
\95Ô
\82·
\r
257 m_dwLastError = BCEC_CARDNOTOPEN;
\r
261 m_dwLastError = BCEC_NOERROR;
\r
263 return m_BcasCardInfo.SystemKey;
\r
266 const BYTE * CBcasCard::GetKsFromEcm(const BYTE *pEcmData, const DWORD dwEcmSize)
\r
268 static const BYTE EcmReceiveCmd[] = {0x90U, 0x34U, 0x00U, 0x00U};
\r
270 //
\81uECM Receive Command
\81v
\82ð
\8f\88\97\9d\82·
\82é
\r
272 m_dwLastError = BCEC_CARDNOTOPEN;
\r
276 // ECM
\83T
\83C
\83Y
\82ð
\83`
\83F
\83b
\83N
\r
277 if(!pEcmData || (dwEcmSize < 30UL) || (dwEcmSize > 256UL)){
\r
278 m_dwLastError = BCEC_BADARGUMENT;
\r
282 //
\83L
\83\83\83b
\83V
\83\85\82ð
\83`
\83F
\83b
\83N
\82·
\82é
\r
283 if(!StoreEcmData(pEcmData, dwEcmSize)){
\r
284 // ECM
\82ª
\93¯
\88ê
\82Ì
\8fê
\8d\87\82Í
\83L
\83\83\83b
\83V
\83\85\8dÏ
\82ÝKs
\82ð
\95Ô
\82·
\r
285 m_dwLastError = BCEC_NOERROR;
\r
286 return m_EcmStatus.KsData;
\r
289 //
\83o
\83b
\83t
\83@
\8f\80\94õ
\r
290 DWORD dwRecvSize = 0UL;
\r
291 BYTE SendData[1024];
\r
292 BYTE RecvData[1024];
\r
293 memset(RecvData, 0, sizeof(RecvData));
\r
295 //
\83R
\83}
\83\93\83h
\8d\
\92z
\r
296 memcpy(SendData, EcmReceiveCmd, sizeof(EcmReceiveCmd)); // CLA, INS, P1, P2
\r
297 SendData[sizeof(EcmReceiveCmd)] = (BYTE)dwEcmSize; // COMMAND DATA LENGTH
\r
298 memcpy(&SendData[sizeof(EcmReceiveCmd) + 1], pEcmData, dwEcmSize); // ECM
\r
299 SendData[sizeof(EcmReceiveCmd) + dwEcmSize + 1] = 0x00U; // RESPONSE DATA LENGTH
\r
301 //
\83R
\83}
\83\93\83h
\91\97\90M
\r
302 if(!TransmitCommand(SendData, sizeof(EcmReceiveCmd) + dwEcmSize + 2UL, RecvData, sizeof(RecvData), &dwRecvSize)){
\r
303 memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));
\r
304 m_dwLastError = BCEC_TRANSMITERROR;
\r
308 //
\83T
\83C
\83Y
\83`
\83F
\83b
\83N
\r
309 if(dwRecvSize != 25UL){
\r
310 memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));
\r
311 m_dwLastError = BCEC_TRANSMITERROR;
\r
315 //
\83\8c\83X
\83|
\83\93\83X
\89ð
\90Í
\r
316 memcpy(m_EcmStatus.KsData, &RecvData[6], sizeof(m_EcmStatus.KsData));
\r
318 //
\83\8a\83^
\81[
\83\93\83R
\81[
\83h
\89ð
\90Í
\r
319 switch(((WORD)RecvData[4] << 8) | (WORD)RecvData[5]){
\r
320 // Purchased: Viewing
\r
321 case 0x0200U : // Payment-deferred PPV
\r
322 case 0x0400U : // Prepaid PPV
\r
323 case 0x0800U : // Tier
\r
324 m_dwLastError = BCEC_NOERROR;
\r
325 return m_EcmStatus.KsData;
\r
327 //
\8fã
\8bL
\88È
\8aO(
\8e\8b\92®
\95s
\89Â)
\r
329 m_dwLastError = BCEC_ECMREFUSED;
\r
334 const bool CBcasCard::StoreEcmData(const BYTE *pEcmData, const DWORD dwEcmSize)
\r
336 bool bUpdate = false;
\r
338 // ECM
\83f
\81[
\83^
\94ä
\8ar
\r
339 if(m_EcmStatus.dwLastEcmSize != dwEcmSize){
\r
340 //
\83T
\83C
\83Y
\82ª
\95Ï
\89»
\82µ
\82½
\r
344 //
\83T
\83C
\83Y
\82ª
\93¯
\82¶
\8fê
\8d\87\82Í
\83f
\81[
\83^
\82ð
\83`
\83F
\83b
\83N
\82·
\82é
\r
345 for(DWORD dwPos = 0UL ; dwPos < dwEcmSize ; dwPos++){
\r
346 if(pEcmData[dwPos] != m_EcmStatus.LastEcmData[dwPos]){
\r
347 //
\83f
\81[
\83^
\82ª
\95s
\88ê
\92v
\r
354 // ECM
\83f
\81[
\83^
\82ð
\95Û
\91¶
\82·
\82é
\r
356 m_EcmStatus.dwLastEcmSize = dwEcmSize;
\r
357 memcpy(m_EcmStatus.LastEcmData, pEcmData, dwEcmSize);
\r