DeCSSInputPin.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
00019  *
00020  */
00021 
00022 #include "stdafx.h"
00023 #include <atlbase.h>
00024 #include <streams.h>
00025 #include <dvdmedia.h>
00026 #include <ks.h>
00027 #include <ksmedia.h>
00028 #include "DeCSSInputPin.h"
00029 #include "..\DSUtil\DSUtil.h"
00030 #include "CSSauth.h"
00031 #include "CSSscramble.h"
00032 
00033 #include <initguid.h>
00034 #include "..\..\include\moreuuids.h"
00035 
00036 //
00037 // CDeCSSInputPin
00038 //
00039 
00040 CDeCSSInputPin::CDeCSSInputPin(TCHAR* pObjectName, CTransformFilter* pFilter, HRESULT* phr, LPWSTR pName)
00041         : CTransformInputPin(pObjectName, pFilter, phr, pName)
00042 {
00043         m_varient = -1;
00044         memset(m_Challenge, 0, sizeof(m_Challenge));
00045         memset(m_KeyCheck, 0, sizeof(m_KeyCheck));
00046         memset(m_DiscKey, 0, sizeof(m_DiscKey));
00047         memset(m_TitleKey, 0, sizeof(m_TitleKey));
00048 }
00049 
00050 STDMETHODIMP CDeCSSInputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00051 {
00052     CheckPointer(ppv, E_POINTER);
00053 
00054         return
00055                 QI(IKsPropertySet)
00056                  __super::NonDelegatingQueryInterface(riid, ppv);
00057 }
00058 
00059 // IMemInputPin
00060 
00061 STDMETHODIMP CDeCSSInputPin::Receive(IMediaSample* pSample)
00062 {
00063         long len = pSample->GetActualDataLength();
00064         
00065         BYTE* p = NULL;
00066         if(SUCCEEDED(pSample->GetPointer(&p)) && len > 0)
00067         {
00068                 BYTE* base = p;
00069 
00070                 if(m_mt.majortype == MEDIATYPE_DVD_ENCRYPTED_PACK && len == 2048 && (p[0x14]&0x30))
00071                 {
00072                         CSSdescramble(p, m_TitleKey);
00073                         p[0x14] &= ~0x30;
00074 
00075                         if(CComQIPtr<IMediaSample2> pMS2 = pSample)
00076                         {
00077                                 AM_SAMPLE2_PROPERTIES props;
00078                                 memset(&props, 0, sizeof(props));
00079                                 if(SUCCEEDED(pMS2->GetProperties(sizeof(props), (BYTE*)&props))
00080                                 && (props.dwTypeSpecificFlags & AM_UseNewCSSKey))
00081                                 {
00082                                         props.dwTypeSpecificFlags &= ~AM_UseNewCSSKey;
00083                                         pMS2->SetProperties(sizeof(props), (BYTE*)&props);
00084                                 }
00085                         }
00086                 }
00087         }
00088 
00089         HRESULT hr = Transform(pSample);
00090 
00091         return hr == S_OK ? __super::Receive(pSample) :
00092                 hr == S_FALSE ? S_OK : hr;
00093 }
00094 
00095 void CDeCSSInputPin::StripPacket(BYTE*& p, long& len)
00096 {
00097         GUID majortype = m_mt.majortype;
00098 
00099         if(majortype == MEDIATYPE_MPEG2_PACK || majortype == MEDIATYPE_DVD_ENCRYPTED_PACK)
00100         if(len > 0 && *(DWORD*)p == 0xba010000) // MEDIATYPE_*_PACK
00101         {
00102                 len -= 14; p += 14;
00103                 if(int stuffing = (p[-1]&7)) {len -= stuffing; p += stuffing;}
00104                 majortype = MEDIATYPE_MPEG2_PES;
00105         }
00106 
00107         if(majortype == MEDIATYPE_MPEG2_PES)
00108         if(len > 0 && *(DWORD*)p == 0xbb010000)
00109         {
00110                 len -= 4; p += 4;
00111                 int hdrlen = ((p[0]<<8)|p[1]) + 2;
00112                 len -= hdrlen; p += hdrlen;
00113         }
00114 
00115         if(majortype == MEDIATYPE_MPEG2_PES)
00116         if(len > 0 
00117         && ((*(DWORD*)p&0xf0ffffff) == 0xe0010000 
00118         || (*(DWORD*)p&0xe0ffffff) == 0xc0010000
00119         || (*(DWORD*)p&0xbdffffff) == 0xbd010000)) // PES
00120         {
00121                 bool ps1 = (*(DWORD*)p&0xbdffffff) == 0xbd010000;
00122 
00123                 len -= 4; p += 4;
00124                 int expected = ((p[0]<<8)|p[1]);
00125                 len -= 2; p += 2;
00126                 BYTE* p0 = p;
00127 
00128                 for(int i = 0; i < 16 && *p == 0xff; i++, len--, p++);
00129 
00130                 if((*p&0xc0) == 0x80) // mpeg2
00131                 {
00132                         len -= 2; p += 2;
00133                         len -= *p+1; p += *p+1;
00134                 }
00135                 else // mpeg1
00136                 {
00137                         if((*p&0xc0) == 0x40) 
00138                         {
00139                                 len -= 2; p += 2;
00140                         }
00141 
00142                         if((*p&0x30) == 0x30 || (*p&0x30) == 0x20)
00143                         {
00144                                 bool pts = !!(*p&0x20), dts = !!(*p&0x10);
00145                                 if(pts) len -= 5; p += 5;
00146                                 if(dts) {ASSERT((*p&0xf0) == 0x10); len -= 5; p += 5;}
00147                         }
00148                         else
00149                         {
00150                                 len--; p++;
00151                         }
00152                 }
00153 
00154                 if(ps1)
00155                 {
00156                         len--; p++;
00157                         if(m_mt.subtype == MEDIASUBTYPE_DVD_LPCM_AUDIO) {len -= 6; p += 6;}
00158                         else if(m_mt.subtype == MEDIASUBTYPE_DOLBY_AC3 || m_mt.subtype == MEDIASUBTYPE_WAVE_DOLBY_AC3 
00159                                 || m_mt.subtype == MEDIASUBTYPE_DTS || m_mt.subtype == MEDIASUBTYPE_WAVE_DTS) {len -= 3; p += 3;}
00160                 }
00161 
00162                 if(expected > 0)
00163                 {
00164                         expected -= (p - p0);
00165                         len = min(expected, len);
00166                 }
00167         }
00168 
00169         if(len < 0) {ASSERT(0); len = 0;}
00170 }
00171 
00172 // IKsPropertySet
00173 
00174 STDMETHODIMP CDeCSSInputPin::Set(REFGUID PropSet, ULONG Id, LPVOID pInstanceData, ULONG InstanceLength, LPVOID pPropertyData, ULONG DataLength)
00175 {
00176         if(PropSet != AM_KSPROPSETID_CopyProt)
00177                 return E_NOTIMPL;
00178 
00179         switch(Id)
00180         {
00181         case AM_PROPERTY_COPY_MACROVISION:
00182                 break;
00183         case AM_PROPERTY_DVDCOPY_CHLG_KEY: // 3. auth: receive drive nonce word, also store and encrypt the buskey made up of the two nonce words
00184                 {
00185                         AM_DVDCOPY_CHLGKEY* pChlgKey = (AM_DVDCOPY_CHLGKEY*)pPropertyData;
00186                         for(int i = 0; i < 10; i++)
00187                                 m_Challenge[i] = pChlgKey->ChlgKey[9-i];
00188 
00189                         CSSkey2(m_varient, m_Challenge, &m_Key[5]);
00190 
00191                         CSSbuskey(m_varient, m_Key, m_KeyCheck);
00192                 }
00193                 break;
00194         case AM_PROPERTY_DVDCOPY_DISC_KEY: // 5. receive the disckey
00195                 {
00196                         AM_DVDCOPY_DISCKEY* pDiscKey = (AM_DVDCOPY_DISCKEY*)pPropertyData; // pDiscKey->DiscKey holds the disckey encrypted with itself and the 408 disckeys encrypted with the playerkeys
00197 
00198                         bool fSuccess = false;
00199 
00200                         for(int j = 0; j < g_nPlayerKeys; j++)
00201                         {
00202                                 for(int k = 1; k < 409; k++)
00203                                 {
00204                                         BYTE DiscKey[6];
00205                                         for(int i = 0; i < 5; i++)
00206                                                 DiscKey[i] = pDiscKey->DiscKey[k*5+i] ^ m_KeyCheck[4-i];
00207                                         DiscKey[5] = 0;
00208 
00209                                         CSSdisckey(DiscKey, g_PlayerKeys[j]);
00210 
00211                                         BYTE Hash[6];
00212                                         for(int i = 0; i < 5; i++)
00213                                                 Hash[i] = pDiscKey->DiscKey[i] ^ m_KeyCheck[4-i];
00214                                         Hash[5] = 0;
00215 
00216                                         CSSdisckey(Hash, DiscKey);
00217 
00218                                         if(!memcmp(Hash, DiscKey, 6))
00219                                         {
00220                                                 memcpy(m_DiscKey, DiscKey, 6);
00221                                                 j = g_nPlayerKeys;
00222                                                 fSuccess = true;
00223                                                 break;
00224                                         }
00225                                 }
00226                         }
00227 
00228                         if(!fSuccess)
00229                                 return E_FAIL;
00230                 }
00231                 break;
00232         case AM_PROPERTY_DVDCOPY_DVD_KEY1: // 2. auth: receive our drive-encrypted nonce word and decrypt it for verification
00233                 {
00234                         AM_DVDCOPY_BUSKEY* pKey1 = (AM_DVDCOPY_BUSKEY*)pPropertyData;
00235                         for(int i = 0; i < 5; i++)
00236                                 m_Key[i] =  pKey1->BusKey[4-i];
00237 
00238                         m_varient = -1;
00239 
00240                         for(int i = 31; i >= 0; i--)
00241                         {
00242                                 CSSkey1(i, m_Challenge, m_KeyCheck);
00243 
00244                                 if(memcmp(m_KeyCheck, &m_Key[0], 5) == 0)
00245                                         m_varient = i;
00246                         }
00247                 }
00248                 break;
00249         case AM_PROPERTY_DVDCOPY_REGION:
00250                 break;
00251         case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
00252                 break;
00253         case AM_PROPERTY_DVDCOPY_TITLE_KEY: // 6. receive the title key and decrypt it with the disc key
00254                 {
00255                         AM_DVDCOPY_TITLEKEY* pTitleKey = (AM_DVDCOPY_TITLEKEY*)pPropertyData;
00256                         for(int i = 0; i < 5; i++)
00257                                 m_TitleKey[i] = pTitleKey->TitleKey[i] ^ m_KeyCheck[4-i];
00258                         m_TitleKey[5] = 0;
00259                         CSStitlekey(m_TitleKey, m_DiscKey);
00260                 }
00261                 break;
00262         default:
00263                 return E_PROP_ID_UNSUPPORTED;
00264         }
00265 
00266         return S_OK;
00267 }
00268 
00269 STDMETHODIMP CDeCSSInputPin::Get(REFGUID PropSet, ULONG Id, LPVOID pInstanceData, ULONG InstanceLength, LPVOID pPropertyData, ULONG DataLength, ULONG* pBytesReturned)
00270 {
00271         if(PropSet != AM_KSPROPSETID_CopyProt)
00272                 return E_NOTIMPL;
00273 
00274         switch(Id)
00275         {
00276         case AM_PROPERTY_DVDCOPY_CHLG_KEY: // 1. auth: send our nonce word
00277                 {
00278                         AM_DVDCOPY_CHLGKEY* pChlgKey = (AM_DVDCOPY_CHLGKEY*)pPropertyData;
00279                         for(int i = 0; i < 10; i++)
00280                                 pChlgKey->ChlgKey[i] = 9 - (m_Challenge[i] = i);
00281                         *pBytesReturned = sizeof(AM_DVDCOPY_CHLGKEY);
00282                 }
00283                 break;
00284         case AM_PROPERTY_DVDCOPY_DEC_KEY2: // 4. auth: send back the encrypted drive nonce word to finish the authentication
00285                 {
00286                         AM_DVDCOPY_BUSKEY* pKey2 = (AM_DVDCOPY_BUSKEY*)pPropertyData;
00287                         for(int i = 0; i < 5; i++)
00288                                 pKey2->BusKey[4-i] = m_Key[5+i];
00289                         *pBytesReturned = sizeof(AM_DVDCOPY_BUSKEY);
00290                 }
00291                 break;
00292         case AM_PROPERTY_DVDCOPY_REGION:
00293                 {
00294                         DVD_REGION* pRegion = (DVD_REGION*)pPropertyData;
00295                         pRegion->RegionData = 0;
00296                         pRegion->SystemRegion = 0;
00297                         *pBytesReturned = sizeof(DVD_REGION);
00298                 }
00299                 break;
00300         case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
00301                 {
00302                         AM_DVDCOPY_SET_COPY_STATE* pState = (AM_DVDCOPY_SET_COPY_STATE*)pPropertyData;
00303                         pState->DVDCopyState = AM_DVDCOPYSTATE_AUTHENTICATION_REQUIRED;
00304                         *pBytesReturned = sizeof(AM_DVDCOPY_SET_COPY_STATE);
00305                 }
00306                 break;
00307         default:
00308                 return E_PROP_ID_UNSUPPORTED;
00309         }
00310 
00311         return S_OK;
00312 }
00313 
00314 STDMETHODIMP CDeCSSInputPin::QuerySupported(REFGUID PropSet, ULONG Id, ULONG* pTypeSupport)
00315 {
00316         if(PropSet != AM_KSPROPSETID_CopyProt)
00317                 return E_NOTIMPL;
00318 
00319         switch(Id)
00320         {
00321         case AM_PROPERTY_COPY_MACROVISION:
00322                 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
00323                 break;
00324         case AM_PROPERTY_DVDCOPY_CHLG_KEY:
00325                 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
00326                 break;
00327         case AM_PROPERTY_DVDCOPY_DEC_KEY2:
00328                 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
00329                 break;
00330         case AM_PROPERTY_DVDCOPY_DISC_KEY:
00331                 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
00332                 break;
00333         case AM_PROPERTY_DVDCOPY_DVD_KEY1:
00334                 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
00335                 break;
00336         case AM_PROPERTY_DVDCOPY_REGION:
00337                 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
00338                 break;
00339         case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
00340                 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
00341                 break;
00342         case AM_PROPERTY_DVDCOPY_TITLE_KEY:
00343                 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
00344                 break;
00345         default:
00346                 return E_PROP_ID_UNSUPPORTED;
00347         }
00348 
00349         return S_OK;
00350 }

Generated on Tue Dec 13 14:47:06 2005 for guliverkli by  doxygen 1.4.5