OSDN Git Service

add b25-remote
[rec10/rec10-git.git] / b25-remote / BCasCard.cpp
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
2 //\r
3 //////////////////////////////////////////////////////////////////////\r
4 \r
5 #include "W2L.h"\r
6 #include "BCasCard.h"\r
7 \r
8 #ifdef _DEBUG\r
9 #undef THIS_FILE\r
10 static char THIS_FILE[]=__FILE__;\r
11 #define new DEBUG_NEW\r
12 #endif\r
13 \r
14 \r
15 //#pragma comment(lib, "WinScard.lib")\r
16 \r
17 \r
18 using std::auto_ptr;\r
19 \r
20 \r
21 CBcasCard::CBcasCard()\r
22         : m_hBcasCard(NULL)\r
23         , m_bIsEstablish(false)\r
24         , m_dwLastError(BCEC_NOERROR)\r
25 {\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
29 \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
33                 }\r
34         else{\r
35                 m_bIsEstablish = true;\r
36                 \r
37                 // \83J\81[\83h\83\8a\81[\83_\97ñ\8b\93\r
38                 EnumCardReader();\r
39                 }\r
40 }\r
41 \r
42 CBcasCard::~CBcasCard()\r
43 {\r
44         CloseCard();\r
45 \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
48 }\r
49 \r
50 const DWORD CBcasCard::GetCardReaderNum(void) const\r
51 {\r
52         // \83J\81[\83h\83\8a\81[\83_\81[\90\94\82ð\95Ô\82·\r
53         return m_CardReaderArray.size();\r
54 }\r
55 \r
56 LPCTSTR CBcasCard::GetCardReaderName(const DWORD dwIndex) const\r
57 {\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
60 }\r
61 \r
62 const bool CBcasCard::OpenCard(LPCTSTR lpszReader)\r
63 {\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
67                 return false;\r
68                 }\r
69         \r
70         // \88ê\92U\83N\83\8d\81[\83Y\82·\82é\r
71         CloseCard();\r
72 \r
73 \r
74         if(lpszReader){\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
77                 \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
80                         return false;\r
81                         }\r
82 \r
83                 if(dwActiveProtocol != SCARD_PROTOCOL_T1){\r
84                         CloseCard();\r
85                         m_dwLastError = BCEC_CARDOPENERROR;\r
86                         return false;\r
87                         }\r
88                 }\r
89         else{\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
92         \r
93                 while(GetCardReaderName(dwIndex)){\r
94                         if(OpenCard(GetCardReaderName(dwIndex++)))return true;                  \r
95                         }\r
96                 \r
97                 return false;\r
98                 }\r
99 \r
100         // \83J\81[\83h\8f\89\8aú\89»\r
101         if(!InitialSetting())return false;\r
102 \r
103         m_dwLastError = BCEC_NOERROR;\r
104 \r
105         return true;\r
106 }\r
107 \r
108 void CBcasCard::CloseCard(void)\r
109 {\r
110         // \83J\81[\83h\82ð\83N\83\8d\81[\83Y\82·\82é\r
111         if(m_hBcasCard){\r
112                 ::SCardDisconnect(m_hBcasCard, SCARD_LEAVE_CARD);\r
113                 m_hBcasCard = NULL;\r
114                 }\r
115 }\r
116 \r
117 const DWORD CBcasCard::GetLastError(void) const\r
118 {\r
119         // \8dÅ\8cã\82É\94­\90\82µ\82½\83G\83\89\81[\82ð\95Ô\82·\r
120         return m_dwLastError;\r
121 }\r
122 \r
123 const bool CBcasCard::EnumCardReader(void)\r
124 {\r
125         // \83J\81[\83h\83\8a\81[\83_\82ð\97ñ\8b\93\82·\82é\r
126         DWORD dwBuffSize = 0UL;\r
127         \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
132                         return false;\r
133 \r
134                 case SCARD_S_SUCCESS :\r
135                         // \83o\83b\83t\83@\83T\83C\83Y\8eæ\93¾\90¬\8c÷\r
136                         break;\r
137                 \r
138                 default:\r
139                         // \83G\83\89\81[\r
140                         m_dwLastError = BCEC_INTERNALERROR;             \r
141                         return false;\r
142                 }\r
143 \r
144         // \83o\83b\83t\83@\8am\95Û\r
145         auto_ptr<TCHAR> szReaders(new TCHAR[dwBuffSize]);\r
146 \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
151                         return false;\r
152 \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
157                         \r
158                         while(*lpszCurReader){\r
159                                 m_CardReaderArray.push_back(lpszCurReader);\r
160                                 lpszCurReader += m_CardReaderArray.back().length() + 1UL;\r
161                                 }\r
162                         \r
163                         break;\r
164                         }\r
165                 \r
166                 default:\r
167                         // \83G\83\89\81[\r
168                         m_dwLastError = BCEC_INTERNALERROR;             \r
169                         return false;\r
170                 }\r
171 \r
172         m_dwLastError = BCEC_NOERROR;\r
173 \r
174         return true;\r
175 }\r
176 \r
177 const bool CBcasCard::TransmitCommand(const BYTE *pSendData, const DWORD dwSendSize, BYTE *pRecvData, const DWORD dwMaxRecv, DWORD *pdwRecvSize)\r
178 {\r
179         DWORD dwRecvSize = dwMaxRecv;\r
180 \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
183         \r
184         // \8eó\90M\83T\83C\83Y\8ai\94[\r
185         if(pdwRecvSize)*pdwRecvSize = dwRecvSize;\r
186 \r
187         return (dwReturn == SCARD_S_SUCCESS)? true : false;\r
188 }\r
189 \r
190 const bool CBcasCard::InitialSetting(void)\r
191 {\r
192         static const BYTE InitSettingCmd[] = {0x90U, 0x30U, 0x00U, 0x00U, 0x00U};\r
193 \r
194         // \81uInitial Setting Conditions Command\81v\82ð\8f\88\97\9d\82·\82é\r
195         if(!m_hBcasCard){\r
196                 m_dwLastError = BCEC_CARDNOTOPEN;\r
197                 return false;\r
198                 }\r
199 \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
204         \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
208                 return false;\r
209                 }\r
210 \r
211         if(dwRecvSize < 57UL){\r
212                 m_dwLastError = BCEC_TRANSMITERROR;\r
213                 return false;           \r
214                 }\r
215 \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
220 \r
221         // ECM\83X\83e\81[\83^\83X\8f\89\8aú\89»\r
222         memset(&m_EcmStatus, 0, sizeof(m_EcmStatus));\r
223 \r
224         return true;\r
225 }\r
226 \r
227 const BYTE * CBcasCard::GetBcasCardID(void)\r
228 {\r
229         // Card ID \82ð\95Ô\82·\r
230         if(!m_hBcasCard){\r
231                 m_dwLastError = BCEC_CARDNOTOPEN;\r
232                 return NULL;\r
233                 }\r
234         \r
235         m_dwLastError = BCEC_NOERROR;\r
236         \r
237         return m_BcasCardInfo.BcasCardID;\r
238 }\r
239 \r
240 const BYTE * CBcasCard::GetInitialCbc(void)\r
241 {\r
242         // Descrambler CBC Initial Value \82ð\95Ô\82·\r
243         if(!m_hBcasCard){\r
244                 m_dwLastError = BCEC_CARDNOTOPEN;\r
245                 return NULL;\r
246                 }\r
247         \r
248         m_dwLastError = BCEC_NOERROR;\r
249         \r
250         return m_BcasCardInfo.InitialCbc;\r
251 }\r
252 \r
253 const BYTE * CBcasCard::GetSystemKey(void)\r
254 {\r
255         // Descrambling System Key \82ð\95Ô\82·\r
256         if(!m_hBcasCard){\r
257                 m_dwLastError = BCEC_CARDNOTOPEN;\r
258                 return NULL;\r
259                 }\r
260         \r
261         m_dwLastError = BCEC_NOERROR;\r
262         \r
263         return m_BcasCardInfo.SystemKey;\r
264 }\r
265 \r
266 const BYTE * CBcasCard::GetKsFromEcm(const BYTE *pEcmData, const DWORD dwEcmSize)\r
267 {\r
268         static const BYTE EcmReceiveCmd[] = {0x90U, 0x34U, 0x00U, 0x00U};\r
269 \r
270         // \81uECM Receive Command\81v\82ð\8f\88\97\9d\82·\82é\r
271         if(!m_hBcasCard){\r
272                 m_dwLastError = BCEC_CARDNOTOPEN;\r
273                 return NULL;\r
274                 }\r
275 \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
279                 return NULL;\r
280                 }\r
281 \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
287                 }\r
288 \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
294 \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
300 \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
305                 return NULL;\r
306                 }\r
307 \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
312                 return NULL;\r
313                 }       \r
314         \r
315         // \83\8c\83X\83|\83\93\83X\89ð\90Í\r
316         memcpy(m_EcmStatus.KsData, &RecvData[6], sizeof(m_EcmStatus.KsData));\r
317 \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
326                 \r
327                 // \8fã\8bL\88È\8aO(\8e\8b\92®\95s\89Â)\r
328                 default :\r
329                         m_dwLastError = BCEC_ECMREFUSED;\r
330                         return NULL;\r
331                 }\r
332 }\r
333 \r
334 const bool CBcasCard::StoreEcmData(const BYTE *pEcmData, const DWORD dwEcmSize)\r
335 {\r
336         bool bUpdate = false;\r
337         \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
341                 bUpdate = true;\r
342                 }\r
343         else{\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
348                                 bUpdate = true;\r
349                                 break;\r
350                                 }                       \r
351                         }\r
352                 }\r
353 \r
354         // ECM\83f\81[\83^\82ð\95Û\91\82·\82é\r
355         if(bUpdate){\r
356                 m_EcmStatus.dwLastEcmSize = dwEcmSize;\r
357                 memcpy(m_EcmStatus.LastEcmData, pEcmData, dwEcmSize);\r
358                 }\r
359 \r
360         return bUpdate;\r
361 }\r