From 55c1e2964da0a022393ebcc8a6498bf0b90c90a3 Mon Sep 17 00:00:00 2001
From: leslie <unknown>
Date: Wed, 20 Aug 2008 20:22:17 +0800
Subject: [PATCH] irdeto: support for I2 key formats

---
 examples/SoftCam.Key     |  16 ++++++-
 systems/irdeto/irdeto.c  | 100 ++++++++++++++++++++++++++++++++++++++-
 systems/irdeto/irdeto.h  |  10 ++++
 systems/irdeto/irdeto1.c |   4 +-
 4 files changed, 125 insertions(+), 5 deletions(-)

diff --git a/examples/SoftCam.Key b/examples/SoftCam.Key
index 7038809..84d208a 100644
--- a/examples/SoftCam.Key
+++ b/examples/SoftCam.Key
@@ -1,11 +1,23 @@
 ;
 ; Irdeto/Betacrypt
 ;
-; I XX YY <16 characters>
+; I XX ZZ <16 characters>
 ;
 ; XX               - provider
-; YY               - key number
+; ZZ               - key number
+;
+; Irdeto 2
+;
+; I XXXX YY ZZ <32 characters>          ; opkey
+; I XXXX YY IV <32 characters>          ; IV (M2)
+; I XXXX YY ECM <32 characters>         ; ECM seed (M1)
+; I XXXX YY EMM <32 characters>         ; EMM seed (M0)
+; I XXXX YY MK0 <32 characters>         ; first PMK (M3)
+; I XXXX YY MK1 <32 characters>         ; second PMK (M4)
 ;
+; XXXX             - caid
+; YY               - provider
+; ZZ               - opkey number
 
 ;
 ; Seca
diff --git a/systems/irdeto/irdeto.c b/systems/irdeto/irdeto.c
index 855b4cf..e72d501 100644
--- a/systems/irdeto/irdeto.c
+++ b/systems/irdeto/irdeto.c
@@ -19,6 +19,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "system-common.h"
 
@@ -33,4 +34,101 @@ static const struct LogModule lm_sys = {
   };
 ADD_MODULE(L_SYS,lm_sys)
 
-static cPlainKeyTypeReg<cPlainKeyStd,'I',false> KeyReg;
+// -- cPlainKeyIrd -------------------------------------------------------------
+
+#define I1_KEYLEN 8
+#define I2_KEYLEN 16
+
+class cPlainKeyIrd : public cHexKey {
+private:
+  bool IsI2Key(void);
+protected:
+  virtual int IdSize(void);
+  virtual cString PrintKeyNr(void);
+public:
+  cPlainKeyIrd(bool Super);
+  virtual bool Parse(const char *line);
+  virtual bool SetKey(void *Key, int Keylen);
+  virtual bool SetBinKey(unsigned char *Mem, int Keylen);
+  };
+
+static cPlainKeyTypeReg<cPlainKeyIrd,'I'> KeyReg;
+
+cPlainKeyIrd::cPlainKeyIrd(bool Super)
+:cHexKey(Super)
+{}
+
+bool cPlainKeyIrd::SetKey(void *Key, int Keylen)
+{
+  if(!IsI2Key()) SetSupersede(false);
+  return cHexKey::SetKey(Key,Keylen);
+}
+
+bool cPlainKeyIrd::SetBinKey(unsigned char *Mem, int Keylen)
+{
+  if(!IsI2Key()) SetSupersede(false);
+  return cHexKey::SetBinKey(Mem,Keylen);
+}
+
+int cPlainKeyIrd::IdSize(void)
+{
+  return IsI2Key() ? 4 : 2;
+}
+
+bool cPlainKeyIrd::IsI2Key(void)
+{
+  return TYPE(keynr)!=TYPE_I1;
+}
+
+bool cPlainKeyIrd::Parse(const char *line)
+{
+  unsigned char sid[2], skey[I2_KEYLEN];
+  int klen;
+  if(GetChar(line,&type,1) && (klen=GetHex(line,sid,2,false))) {
+     type=toupper(type); id=Bin2Int(sid,klen);
+     line=skipspace(line);
+     bool ok=false;
+     if(klen==2) {
+       klen=I2_KEYLEN;
+       unsigned char prov;
+       if(GetHex(line,&prov,1)) {
+         line=skipspace(line);
+         int typ, id;
+         if(!strncasecmp(line,"IV",2)) {       typ=TYPE_IV; id=0; line+=2; ok=true; }
+         else if(!strncasecmp(line,"ECM",3)) { typ=TYPE_SEED; id=0; line+=3; ok=true; }
+         else if(!strncasecmp(line,"EMM",3)) { typ=TYPE_SEED; id=1; line+=3; ok=true; }
+         else if(!strncasecmp(line,"MK",2)) {  typ=TYPE_PMK; id=line[2]-'0'; line+=3; ok=true; }
+         else { typ=TYPE_OP; ok=GetHex(line,sid,1); id=sid[0]; }
+         keynr=KEYSET(prov,typ,id);
+         }
+       }
+     else {
+       klen=I1_KEYLEN;
+       ok=GetHex(line,sid,1);
+       keynr=KEYSET(0,TYPE_I1,sid[0]);
+       }
+     line=skipspace(line);
+     if(ok && GetHex(line,skey,klen)) {
+       SetBinKey(skey,klen);
+       return true;
+       }
+    }
+  return false;
+}
+
+cString cPlainKeyIrd::PrintKeyNr(void)
+{
+  char tmp[16];
+  if(IsI2Key()) {
+    snprintf(tmp,sizeof(tmp),"%02X ",PROV(keynr));
+    switch(TYPE(keynr)) {
+      case TYPE_OP:   snprintf(tmp+3,sizeof(tmp)-3,"%02X",ID(keynr)); break;
+      case TYPE_IV:   snprintf(tmp+3,sizeof(tmp)-3,"IV"); break;
+      case TYPE_SEED: snprintf(tmp+3,sizeof(tmp)-3,"%s",ID(keynr)?"EMM":"ECM"); break;
+      case TYPE_PMK:  snprintf(tmp+3,sizeof(tmp)-3,"MK%d",ID(keynr)); break;
+      }
+    }
+  else
+    snprintf(tmp,sizeof(tmp),"%02X",ID(keynr));
+  return tmp;
+}
diff --git a/systems/irdeto/irdeto.h b/systems/irdeto/irdeto.h
index af46efa..6c5709e 100644
--- a/systems/irdeto/irdeto.h
+++ b/systems/irdeto/irdeto.h
@@ -26,5 +26,15 @@
 #define SYSTEM_NAME          "Irdeto"
 #define SYSTEM_PRI           -10
 
+#define TYPE_I1   0
+#define TYPE_OP   1
+#define TYPE_IV   2
+#define TYPE_SEED 3
+#define TYPE_PMK  4
+
+#define PROV(keynr)         (((keynr)>>16)&0xFF)
+#define TYPE(keynr)         (((keynr)>> 8)&0xFF)
+#define ID(keynr)           (((keynr)   )&0xFF)
+#define KEYSET(prov,typ,id) ((((prov)&0xFF)<<16)|(((typ)&0xFF)<<8)|((id)&0xFF))
 
 #endif
diff --git a/systems/irdeto/irdeto1.c b/systems/irdeto/irdeto1.c
index 5e5d97b..c829316 100644
--- a/systems/irdeto/irdeto1.c
+++ b/systems/irdeto/irdeto1.c
@@ -260,10 +260,10 @@ bool cSystemIrd::ProcessECM(const cEcmInfo *ecm, unsigned char *source)
     return false;
     }
 
-  cKeySnoop ks(this,'I',source[2],keynr);
+  cKeySnoop ks(this,'I',source[2],KEYSET(0,TYPE_I1,keynr));
   cPlainKey *pk=0;
   unsigned char key[8];
-  while((pk=keys.FindKey('I',source[2],keynr,sizeof(key),pk))) {
+  while((pk=keys.FindKey('I',source[2],KEYSET(0,TYPE_I1,keynr),sizeof(key),pk))) {
     unsigned char save[16];
     memcpy(save,data,16); // save the encrypted data
     pk->Get(key);
-- 
2.39.5