]> www.vanbest.org Git - sasc-ng.git/commitdiff
sc-viaccess: update ECM/EMM card handling (from oscam R127)
authorleslie <unknown>
Wed, 29 Jul 2009 07:43:00 +0000 (15:43 +0800)
committerleslie <unknown>
Wed, 29 Jul 2009 07:43:00 +0000 (15:43 +0800)
16 files changed:
crypto.c
crypto.h
examples/smartcard.conf.example
parse.c
parse.h
po/de_DE.po
po/fi_FI.po
po/fr_FR.po
po/hu_HU.po
po/it_IT.po
po/nl_NL.po
po/pl_PL.po
po/ru_RU.po
po/sv_SE.po
systems/sc-viaccess/sc-viaccess.c
systems/viaccess/viaccess.c

index a6c5bb4028a162dc9d26436b7e10dc180461604c..a19ce8b2ac4f893be707a89452a718529fe6bc7c 100644 (file)
--- a/crypto.c
+++ b/crypto.c
@@ -408,8 +408,11 @@ int cAES::Encrypt(const unsigned char *data, int len, unsigned char *crypt) cons
   return -1;
 }
 
-void cAES::Decrypt(unsigned char *data, int len) const
+bool cAES::Decrypt(unsigned char *data, int len) const
 {
-  if(active)
+  if(active) {
     for(int i=0; i<len; i+=16) AES_decrypt(data+i,data+i,(const AES_KEY *)&dkey);
+    return true;
+    }
+  return false;
 }
index ddc94943971d710d4a31d3f3ea7bebd1da6e84d7..8e056afdeec4eaf0fb2ffe298e8d2aeae8993156 100644 (file)
--- a/crypto.h
+++ b/crypto.h
@@ -92,7 +92,7 @@ private:
   AES_KEY dkey, ekey;
 protected:
   void SetKey(const unsigned char *key);
-  void Decrypt(unsigned char *data, int len) const ;
+  bool Decrypt(unsigned char *data, int len) const ;
   int Encrypt(const unsigned char *data, int len, unsigned char *crypt) const;
 public:
   cAES(void);
index c2fb4a2bd9bb90fb5d2b97f37d3082e55dbc0452..5418a1e3d7886b70adac5c6f93556d512bbf3474 100644 (file)
@@ -55,7 +55,18 @@ cryptoworks: UCPK 0102030405 001122334455667788990011223344556677889900112233445
 ; cryptoworks: PIN serial pin
 cryptoworks: PIN 0102030405 1234
 
+; Viaccess
 ;
+; serial - serial number (UA) identifying the card
+; pin    - pin number to disable parental rating (up to 16 digits)
+; aes    - AES key for postprocessing CW, 16 bytes = 32 chars
+;
+; viaccess: PIN serial pin
+viaccess: PIN 0102030405 1234
+;
+; viaccess: AES serial aes
+viaccess: AES 0102030405 00112233445566778899001122334455
+
 ; Irdeto/Betacrypt
 ;
 ; RSA certificate for camkey challenge
diff --git a/parse.c b/parse.c
index e4f3e152eee501d19f62d614cf8535604f7d8223..8d622e1f3b989ec26956e6f02887cd74e76729bb 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -454,7 +454,7 @@ bool cCardViaccess::MatchEMM(const unsigned char *data)
 
 // -- cParseViaccess -----------------------------------------------------------
 
-const unsigned char *cParseViaccess::NanoStart(const unsigned char *data)
+const unsigned char *cParseViaccess::PayloadStart(const unsigned char *data)
 {
   switch(data[0]) {
     case 0x88: return &data[8];
@@ -467,6 +467,16 @@ const unsigned char *cParseViaccess::NanoStart(const unsigned char *data)
   return 0;
 }
 
+const unsigned char *cParseViaccess::NanoStart(const unsigned char *data)
+{
+  const unsigned char *p=PayloadStart(data);
+  switch(data[0]) {
+    case 0x80:
+    case 0x81: if(p && p[0]==0xD2) return p+p[1]+2; // skip TPS
+    }
+  return p;
+}
+
 const unsigned char *cParseViaccess::CheckNano90(const unsigned char *data)
 {
   return CheckNano90FromNano(NanoStart(data));
@@ -474,7 +484,7 @@ const unsigned char *cParseViaccess::CheckNano90(const unsigned char *data)
 
 const unsigned char *cParseViaccess::CheckNano90FromNano(const unsigned char *data)
 {
-  if(data && data[0]==0x90 && data[1]==0x03) return data;
+  if(data && (data[0]==0x90 || data[0]==0x40) && data[1]==0x03) return data;
   return 0;
 }
 
diff --git a/parse.h b/parse.h
index 4d7cb1558d83b25abf5a2412f55bfbdae06f46f9..7263723172a347a935bcb2068d00f47a612d8162 100644 (file)
--- a/parse.h
+++ b/parse.h
@@ -214,6 +214,7 @@ public:
 
 class cParseViaccess {
 public:
+  static const unsigned char *PayloadStart(const unsigned char *data);
   static const unsigned char *NanoStart(const unsigned char *data);
   static const unsigned char *CheckNano90(const unsigned char *data);
   static const unsigned char *CheckNano90FromNano(const unsigned char *data);
index 3b9b8b6c17a55f4692c67ababc71efd766011f03..85ce8e2ff866f19b7b73a97672fdfa1f324d0562 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-12-22 18:52+0100\n"
+"POT-Creation-Date: 2009-07-27 03:33-0400\n"
 "PO-Revision-Date: 2007-08-27 12:45+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -226,6 +226,9 @@ msgstr "SC-Seca: EMM updates"
 msgid "SC-Seca: activate PPV"
 msgstr "SC-Seca: PPV aktivieren"
 
+msgid "SC-Viaccess: Parental lock"
+msgstr "SC-Viaccess: Altersbeschränkung"
+
 msgid "stream"
 msgstr "Datenstrom"
 
index 547cbbd35ef905407a4b25802323be5ca57e1419..425d6544a7f190bd6be081ebf320c5556d26552f 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-12-22 18:52+0100\n"
+"POT-Creation-Date: 2009-07-27 03:33-0400\n"
 "PO-Revision-Date: 2008-11-19 13:45+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -226,6 +226,9 @@ msgstr "SC-Seca: EMM-p
 msgid "SC-Seca: activate PPV"
 msgstr "SC-Seca: Aktivoi PPV"
 
+msgid "SC-Viaccess: Parental lock"
+msgstr ""
+
 msgid "stream"
 msgstr "lähete"
 
index cff06b21e2f7da3bf0d53c169721f605d2615e2d..0874ed82cab89a948e65cc42f898edf7bc9df66e 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-12-22 18:52+0100\n"
+"POT-Creation-Date: 2009-07-27 03:33-0400\n"
 "PO-Revision-Date: 2007-08-27 12:45+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -226,6 +226,9 @@ msgstr "SC-Seca: mise 
 msgid "SC-Seca: activate PPV"
 msgstr "SC-Seca: activer les PPV"
 
+msgid "SC-Viaccess: Parental lock"
+msgstr ""
+
 msgid "stream"
 msgstr ""
 
index dbe1b874658c88ed82177eeabbf2d92566457de6..cf2fa62470058b333f91c53a7d3087dd939002c3 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.11\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-12-22 18:52+0100\n"
+"POT-Creation-Date: 2009-07-27 03:33-0400\n"
 "PO-Revision-Date: 2009-05-17 11:09+0800\n"
 "Last-Translator: jv\n"
 "Language-Team: somebody\n"
@@ -226,6 +226,9 @@ msgstr "SC-Seca: EMM friss
 msgid "SC-Seca: activate PPV"
 msgstr "SC-Seca: aktiváld a PPV-t"
 
+msgid "SC-Viaccess: Parental lock"
+msgstr ""
+
 msgid "stream"
 msgstr ""
 
index fa68e4405f340b10f67454d971afd975b2762725..ce8f8c28aa72b47d0cb1b6ca2d3301e4f9adcb3a 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-12-22 18:52+0100\n"
+"POT-Creation-Date: 2009-07-27 03:33-0400\n"
 "PO-Revision-Date: 2008-11-19 12:23+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -226,6 +226,9 @@ msgstr "SC-Seca: aggiornamenti EMM"
 msgid "SC-Seca: activate PPV"
 msgstr "SC-Seca: attiva PPV"
 
+msgid "SC-Viaccess: Parental lock"
+msgstr ""
+
 msgid "stream"
 msgstr "flusso"
 
index cbfe41efbc9648feafaf9d5ea3052dd47c90706d..a8773caaaea21e18c66145ab516e48e42543c894 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-12-22 18:52+0100\n"
+"POT-Creation-Date: 2009-07-27 03:33-0400\n"
 "PO-Revision-Date: 2007-08-27 12:45+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -226,6 +226,9 @@ msgstr "SC-Seca: EMM updates"
 msgid "SC-Seca: activate PPV"
 msgstr "SC-Seca: activeer PPV"
 
+msgid "SC-Viaccess: Parental lock"
+msgstr ""
+
 msgid "stream"
 msgstr ""
 
index 3aa8d9ea12cc2b5368ae3840a9fde912858addff..5847d60761eb52aa63851439741d2f0999f34770 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-12-22 18:52+0100\n"
+"POT-Creation-Date: 2009-07-27 03:33-0400\n"
 "PO-Revision-Date: 2007-08-27 12:45+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -226,6 +226,9 @@ msgstr "SC-Seca: aktualizacje EMM"
 msgid "SC-Seca: activate PPV"
 msgstr "SC-Seca: aktywuj PPV"
 
+msgid "SC-Viaccess: Parental lock"
+msgstr ""
+
 msgid "stream"
 msgstr ""
 
index b9ca8e9d655d884b371646a8a3e7035c6cf6d6e2..bebdd3a80c20963acaed036d6fd6c6a4f1e1124a 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-12-22 18:52+0100\n"
+"POT-Creation-Date: 2009-07-27 03:33-0400\n"
 "PO-Revision-Date: 2009-05-14 19:33+0100\n"
 "Last-Translator: somebody\n"
 "Language-Team: ru\n"
@@ -227,6 +227,9 @@ msgstr "SC-Seca: 
 msgid "SC-Seca: activate PPV"
 msgstr "SC-Seca: ÐÚâØÒØàÞÒÐâì PPV"
 
+msgid "SC-Viaccess: Parental lock"
+msgstr ""
+
 msgid "stream"
 msgstr "ßÞâÞÚÐ"
 
index 75150986d375c3fcf184693dec26597ee43b531e..673b4b6bf63c39e5e94b80e3dc98d4e557ba69cc 100644 (file)
@@ -6,7 +6,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: VDR 1.5.9\n"
 "Report-Msgid-Bugs-To: <noone@nowhere.org>\n"
-"POT-Creation-Date: 2008-12-22 18:52+0100\n"
+"POT-Creation-Date: 2009-07-27 03:33-0400\n"
 "PO-Revision-Date: 2007-08-27 12:45+0200\n"
 "Last-Translator: somebody\n"
 "Language-Team: somebody\n"
@@ -226,6 +226,9 @@ msgstr ""
 msgid "SC-Seca: activate PPV"
 msgstr ""
 
+msgid "SC-Viaccess: Parental lock"
+msgstr ""
+
 msgid "stream"
 msgstr ""
 
index 7561462963edc4d10e6927b074ae9d5b2202b0bf..843539770c379616cec6edc6aff39bf1b93181ed 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "system-common.h"
 #include "smartcard.h"
+#include "crypto.h"
 #include "parse.h"
+#include "opts.h"
 #include "misc.h"
 #include "log-sc.h"
 #include "log-core.h"
@@ -51,6 +54,8 @@ static const struct LogModule lm_sc = {
   };
 ADD_MODULE(L_SC,lm_sc)
 
+static int disableParental=0;
+
 // -- cSystemScViaccess ------------------------------------------------------------------
 
 class cSystemScViaccess : public cSystemScCore { //, private cTPS {
@@ -89,6 +94,13 @@ static cSystemLinkScViaccess staticInit;
 cSystemLinkScViaccess::cSystemLinkScViaccess(void)
 :cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
 {
+  static const char *rat[] = {
+    trNOOP("don't touch"),
+    trNOOP("disable")
+    };
+
+  opts=new cOpts(SYSTEM_NAME,1);
+  opts->Add(new cOptSel("DisableParental",trNOOP("SC-Viaccess: Parental lock"),&disableParental,sizeof(rat)/sizeof(char *),rat));
   Feature.NeedsSmartCard();
 }
 
@@ -97,6 +109,83 @@ bool cSystemLinkScViaccess::CanHandle(unsigned short SysId)
   return smartcards.HaveCard(SC_ID) && SYSTEM_CAN_HANDLE(SysId);
 }
 
+// -- cSmartCardDataViaccess ---------------------------------------------------
+
+enum eDataType { dtPIN, dtAES };
+
+class cSmartCardDataViaccess : public cSmartCardData {
+private:
+  int IdLen(void) const { return 5; }
+public:
+  eDataType type;
+  unsigned char id[5], pin[8], aes[16];
+  //
+  cSmartCardDataViaccess(void);
+  cSmartCardDataViaccess(eDataType Type, unsigned char *Id);
+  virtual bool Parse(const char *line);
+  virtual bool Matches(cSmartCardData *param);
+  };
+
+cSmartCardDataViaccess::cSmartCardDataViaccess(void)
+:cSmartCardData(SC_ID)
+{
+  memset(id,0,sizeof(id));
+}
+
+cSmartCardDataViaccess::cSmartCardDataViaccess(eDataType Type, unsigned char *Id)
+:cSmartCardData(SC_ID)
+{
+  type=Type;
+  memset(id,0,sizeof(id));
+  memcpy(id,Id,IdLen());
+}
+
+bool cSmartCardDataViaccess::Matches(cSmartCardData *param)
+{
+  cSmartCardDataViaccess *cd=(cSmartCardDataViaccess *)param;
+  return cd->type==type && !memcmp(cd->id,id,IdLen());
+}
+
+bool cSmartCardDataViaccess::Parse(const char *line)
+{
+  line=skipspace(line);
+  if(!strncasecmp(line,"PIN",3))       { type=dtPIN; line+=3; }
+  else if(!strncasecmp(line,"AES",3))  { type=dtAES; line+=3; }
+  else {
+    PRINTF(L_CORE_LOAD,"smartcarddataviaccess: format error: datatype");
+    return false;
+    }
+  line=skipspace(line);
+  if(GetHex(line,id,IdLen())!=IdLen()) {
+    PRINTF(L_CORE_LOAD,"smartcarddataviaccess: format error: serial");
+    return false;
+    }
+  line=skipspace(line);
+  if(type==dtPIN) {
+    memset(pin,0,sizeof(pin));
+    int i, shift=4;
+    for(i=0; i<16; i++) {
+      if(!isdigit(*line)) {
+        PRINTF(L_CORE_LOAD,"smartcarddataviaccess: format error: pin");
+        return false;
+        }
+      pin[i]|=(*line++ - '0')<<shift;
+      shift^=4;
+      }
+    i=(i+1)/2; // num bytes
+    memmove(&pin[8-i],pin,i);
+//XXX
+LDUMP(L_CORE_LOAD,pin,sizeof(pin),"smartcarddataviaccess: pin ");
+    }
+  else {
+    if(GetHex(line,aes,16)!=16) {
+      PRINTF(L_CORE_LOAD,"smartcarddataviaccess: format error: aes");
+      return false;
+      }
+    }
+  return true;
+}
+
 // -- cProviderScViaccess ----------------------------------------------------------
 
 class cProviderScViaccess : public cProviderViaccess {
@@ -109,9 +198,9 @@ public:
 
 // -- cSmartCardViaccess -----------------------------------------------------------------
 
-class cSmartCardViaccess : public cSmartCard, public cIdSet {
+class cSmartCardViaccess : public cSmartCard, public cIdSet, private cAES {
 private:
-  unsigned char lastId[3];
+  unsigned char ua[5], sa0[4], lastId[3];
   //
   unsigned char GetSW1(void) { return sb[1]; }
   bool CheckKey(cProviderScViaccess *p, const unsigned char keynr);
@@ -181,15 +270,17 @@ bool cSmartCardViaccess::Init(void)
     PRINTF(L_SC_ERROR,"failed to read ua");
     return false;
     }
-  SetCard(new cCardViaccess(&buff[2]));
-  PRINTF(L_SC_INIT,"card UA: %llu",Bin2LongLong(&buff[2],5));
-  infoStr.Printf("Card v.%s UA %010llu\n",ver,Bin2LongLong(&buff[2],5));
+  memcpy(ua,&buff[2],sizeof(ua));
+  SetCard(new cCardViaccess(ua));
+  PRINTF(L_SC_INIT,"card UA: %llu",Bin2LongLong(ua,5));
+  infoStr.Printf("Card v.%s UA %010llu\n",ver,Bin2LongLong(ua,5));
 
   insa4[2]=0x00; // select issuer 0
   if(!IsoWrite(insa4,buff) || !Status()) {
     PRINTF(L_SC_ERROR,"failed to select issuer 0");
     return false;
     }
+  int issuer=0;
   do {
     insc0[4]=0x1a; // show provider properties
     if(!IsoRead(insc0,buff) || !Status()) {
@@ -208,6 +299,7 @@ bool cSmartCardViaccess::Init(void)
       PRINTF(L_SC_ERROR,"failed to read sa");
       return false;
       }
+    if(issuer==0) memcpy(sa0,&buff[2],sizeof(sa0));
     cProviderScViaccess *p=new cProviderScViaccess(&buff[0],&buff2[2]);
     if(p) {
       AddProv(p);
@@ -245,8 +337,30 @@ bool cSmartCardViaccess::Init(void)
       PRINTF(L_SC_ERROR,"failed to select next issuer");
       return false;
       }
+    issuer++;
     } while(GetSW1()==0x00);
   infoStr.Finish();
+
+  if(disableParental) {
+      static unsigned char ins24[] = { 0xca,0x24,0x02,0x00,0x09 };
+      static unsigned char pindt[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F };
+      cSmartCardDataViaccess cd(dtPIN,ua);
+      cSmartCardDataViaccess *entry=(cSmartCardDataViaccess *)smartcards.FindCardData(&cd);
+      if(entry) {
+        PRINTF(L_SC_INIT,"got PIN from smartcard.conf.");
+        memcpy(&pindt[0],entry->pin,8);
+        if(!IsoWrite(ins24,pindt) || !Status())
+          PRINTF(L_SC_ERROR,"failed to disable parental lock");
+        }
+      else PRINTF(L_SC_INIT,"no PIN available.");
+    }
+  cSmartCardDataViaccess cd(dtAES,ua);
+  cSmartCardDataViaccess *entry=(cSmartCardDataViaccess *)smartcards.FindCardData(&cd);
+  if(entry) {
+    PRINTF(L_SC_INIT,"got AES key from smartcard.conf.");
+    SetKey(entry->aes);
+    }
+
   return true;
 }
 
@@ -281,7 +395,19 @@ bool cSmartCardViaccess::Decode(const cEcmInfo *ecm, const unsigned char *data,
     if(CheckKey(p,keynr)) {
       if(!SetProvider(cParseViaccess::ProvIdPtr(data))) return false;
 
-      const unsigned char *start=cParseViaccess::NanoStart(data)+5;
+      const unsigned char *start=cParseViaccess::PayloadStart(data);
+      bool hasD2=false;
+      if(start[0]==0xD2) { // TPS alike, TNTSAT/TNTop
+        start+=start[1]+2;
+        hasD2=true;
+        }
+      start+=5;
+
+      const unsigned char *DE04=0;
+      if(start[0]==0xDE && start[1]==0x04) {
+        DE04=start;
+        start+=6;
+        }
       const unsigned char *ecm88Data=start;
       int ecm88Len=SCT_LEN(data)-(start-data);
       int ecmf8Len=0;
@@ -299,20 +425,36 @@ bool cSmartCardViaccess::Decode(const cEcmInfo *ecm, const unsigned char *data,
       ins88[2]=ecmf8Len?1:0;
       ins88[3]=keynr;
       ins88[4]=ecm88Len;
+      if(DE04) {
+        unsigned char *mem=AUTOMEM(ecm88Len+6);
+        memcpy(mem,DE04,6);
+        memcpy(mem+6,ecm88Data,ecm88Len);
+        ins88[4]+=6;
+        ecm88Data=mem;
+        }
       if(!IsoWrite(ins88,ecm88Data) || !Status()) return false; // request dcw
       unsigned char buff[MAX_LEN];
       if(!IsoRead(insc0,buff) || !Status()) return false; // read dcw
+      unsigned char cwbuff[16];
+      int cwmask=0;
       switch(buff[0]) {
         case 0xe8: // even
-          if(buff[1]==8) { memcpy(cw,buff+2,8); return true; }
+          if(buff[1]==8) { memcpy(cwbuff,buff+2,8); cwmask=1; }
           break;
         case 0xe9: // odd
-          if(buff[1]==8) { memcpy(cw+8,buff+2,8); return true; }
+          if(buff[1]==8) { memcpy(cwbuff+8,buff+2,8); cwmask=2; }
           break;
         case 0xea: // complete
-          if(buff[1]==16) { memcpy(cw,buff+2,16); return true; }
+          if(buff[1]==16) { memcpy(cwbuff,buff+2,16); cwmask=3; }
           break;
         }
+      if(cwmask) {
+        if(hasD2 && !Decrypt(cwbuff,16))
+          PRINTF(L_SC_ERROR,"no AES key for this card");
+        if(cwmask&1) memcpy(cw,cwbuff,8);
+        if(cwmask&2) memcpy(cw+8,cwbuff+8,8);
+        return true;
+        }
       }
     else PRINTF(L_SC_ERROR,"key not found on card");
     }
@@ -324,6 +466,8 @@ bool cSmartCardViaccess::Update(int pid, int caid, const unsigned char *data)
 {
   static unsigned char insf0[] = { 0xca,0xf0,0x00,0x00,0x00 };
   static unsigned char ins18[] = { 0xca,0x18,0x00,0x00,0x00 };
+  static unsigned char insf4[] = { 0xca,0xf4,0x00,0x00,0x00 };
+  static unsigned char ins1c[] = { 0xca,0x1c,0x01,0x00,0x00 };
 
   int updtype;
   cAssembleData ad(data);
@@ -332,21 +476,82 @@ bool cSmartCardViaccess::Update(int pid, int caid, const unsigned char *data)
       const unsigned char *start=cParseViaccess::NanoStart(data);
       int nanolen=SCT_LEN(data)-(start-data);
 
-      if(start && start[0]==0x90 && start[1]==0x03 && nanolen>=5 && SetProvider(&start[2])) {
-        insf0[3]=ins18[3]=cParseViaccess::KeyNrFromNano(start);
-        start+=5; nanolen-=5;
-
-        int n;
-        if(start[0]==0x9e && nanolen>=(n=start[1]+2)) {
-          insf0[4]=n;
-          if(!IsoWrite(insf0,start) || !Status()) continue;
-          start+=n; nanolen-=n;
+      if(start && nanolen>=5) {
+        const unsigned char *nano81=0, *nano91=0, *nano92=0, *nano9e=0, *nanof0=0;
+        unsigned char *nanos18=AUTOMEM(nanolen+10);
+        bool provOK=false;
+        int len18=0, keynr=0;
+        
+        while(nanolen>0) {
+          switch(start[0]) {
+            case 0x90:
+              if(SetProvider(&start[2])) {
+                provOK=true;
+                keynr=cParseViaccess::KeyNrFromNano(start);
+                }
+              break;
+            case 0x9E: // ADF
+              if(!nano91) { // not crypted
+                unsigned char custwp=sa0[3];
+                const unsigned char *afd=&start[2];
+                if(!(afd[31-custwp/8] & (1<<(custwp&7)))) { // not for this card
+                  provOK=false; nanolen=0; // skip, next assemble data
+                  break;
+                  }
+                }
+              nano9e=start;
+              break;
+            case 0x81: nano81=start; break;
+            case 0x91: nano91=start; break;
+            case 0x92: nano92=start; break;
+            case 0xF0: nanof0=start; break;
+            default:
+              {
+              int l=start[1]+2;
+              memcpy(nanos18+len18,start,l);
+              len18+=l;
+              }
+            }
+          int l=start[1]+2;
+          start+=l; nanolen-=l;
           }
 
-        if(nanolen>0) {
-          ins18[2]=updtype>0 ? updtype-1 : updtype;
-          ins18[4]=nanolen;
-          if(IsoWrite(ins18,start)) Status();
+        if(provOK && nanof0) {
+          unsigned char buff[MAX_LEN*2];
+          if(nano9e) {
+            int l9e=nano9e[1]+2;
+            if(!nano91) {
+              insf0[3]=keynr;
+              insf0[4]=l9e;
+              if(!IsoWrite(insf0,nano9e) || !Status()) continue;
+              }
+            else {
+              int l91=nano91[1]+2;
+              insf4[3]=keynr;
+              insf4[4]=l91+l9e;
+              memcpy(buff,nano91,l91);
+              memcpy(buff+l91,nano9e,l9e);
+              if(!IsoWrite(insf4,buff) || !Status()) continue;
+              }
+            }
+          if(!nano92) {
+            int lf0=nanof0[1]+2;
+            ins18[2]=updtype>0 ? updtype-1 : updtype;
+            ins18[3]=keynr;
+            ins18[4]=len18+lf0;
+            memcpy(buff,nanos18,len18);
+            memcpy(buff+len18,nanof0,lf0);
+            if(IsoWrite(ins18,buff)) Status();
+            }
+          else if(nano81) {
+            int l92=nano92[1]+2, l81=nano81[1]+2, lf0=nanof0[1]+2;
+            ins1c[3]=keynr;
+            ins1c[4]=l92+l81+lf0;
+            memcpy(buff,nano92,l92);
+            memcpy(buff+l92,nano81,l81);
+            memcpy(buff+l92+l81,nanof0,lf0);
+            if(IsoWrite(ins1c,buff)) Status();
+            }
           }
         }
       }
index 51782473d44acbe95a18a38cc60fe4be3ab256fc..dcb99522a8c9ff9e8212f325655f3151a6c1a5d9 100644 (file)
@@ -378,7 +378,7 @@ void cSystemViaccess::ParseCADescriptor(cSimpleList<cEcmInfo> *ecms, unsigned sh
 
 bool cSystemViaccess::ProcessECM(const cEcmInfo *ecm, unsigned char *data)
 {
-  unsigned char *nanos=(unsigned char *)cParseViaccess::NanoStart(data);
+  unsigned char *nanos=(unsigned char *)cParseViaccess::PayloadStart(data);
   int len=SCT_LEN(data)-(nanos-data);
 
   bool mayHaveTps=false;