From ccf74f5b6365a792c6be0315ef364d9b7927f9f6 Mon Sep 17 00:00:00 2001 From: leslie Date: Thu, 27 Dec 2007 22:01:45 +0100 Subject: [PATCH] release 0.8.6 --- HISTORY | 16 + README | 18 +- cam.c | 4 +- crypto-bn.h | 1 + crypto.c | 4 +- data.c | 27 +- data.h | 1 + filter.c | 15 +- log.h | 8 +- misc.h | 4 + parse.c | 4 +- po/de_DE.po | 17 +- po/fi_FI.po | 19 +- po/fr_FR.po | 17 +- po/hu_HU.po | 17 +- po/it_IT.po | 17 +- po/nl_NL.po | 17 +- po/pl_PL.po | 17 +- po/ru_RU.po | 17 +- po/sc.pot | 17 +- po/sv_SE.po | 17 +- sc.c | 48 +- smartcard.c | 4 +- system-common.c | 2 +- system.c | 55 +- systems/cardclient/camd.c | 10 +- systems/cryptoworks/cryptoworks.c | 4 +- systems/irdeto/irdeto.c | 2 +- systems/nagra/cpu.c | 112 ++- systems/nagra/cpu.h | 8 +- systems/nagra/nagra.c | 4 - systems/nagra/nagra1.c | 57 +- systems/nagra/nagra2-0101.c | 1016 +++++++++++++++++++++-- systems/nagra/nagra2-0501.c | 17 +- systems/nagra/nagra2-4101.c | 89 +- systems/nagra/nagra2-map57.c | 677 --------------- systems/nagra/nagra2.c | 364 +++++--- systems/sc-irdeto/sc-irdeto.c | 2 +- systems/sc-videoguard2/sc-videoguard2.c | 2 +- systems/seca/seca.c | 7 +- systems/viaccess/st20.c | 18 +- systems/viaccess/tps.c | 23 +- testing/Makefile | 1 + testing/compat.c | 4 +- testing/testECM.c | 14 +- testing/testN2Emu.c | 9 +- version.h | 4 +- 47 files changed, 1801 insertions(+), 1026 deletions(-) delete mode 100644 systems/nagra/nagra2-map57.c diff --git a/HISTORY b/HISTORY index 126ee56..f41595d 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,22 @@ VDR Plugin 'sc' Revision History -------------------------------- +21.12.2007: Version 0.8.6 +- Added Nagra2 0501 dyn. AU execution fix. +- Added Nagra2 4101 map58 AU (though already outdated). Using unified ECC code + for map57 & map58. +- Added instruction cycle counter to Nagra ST7/19 cpu emulation. +- Added support for recent Nagra2 0101/0901 ECM (including map4e/22/3e cycle + calculation, timer/CRC hardware simulation, DES map, EEPROM updates, dynamic + ECM code, auxserver V2 call). +- Added Nagra2 config option to drop EMM-S packets. +- Added Nagra1 UK reg05 fix (i.e. moved it from N2 to N1). +- Added TPS AU fix. +- Added SVDR commands to inject keys and to configure logging to file. +- Removed some gcc'isims (case ranges, named variadic macros, variable length + arrays). +- Updated finnish translations. + 10.11.2007: Version 0.8.5 - Added new Nagra2 0501 AU sheme. - Added Nagra2 NA 'temporarily' fixes. diff --git a/README b/README index 90ad096..c1c78b6 100644 --- a/README +++ b/README @@ -214,7 +214,7 @@ right. The plugin searches for these files in the "nagra" subdirectory. For Nagra2 AU some providers need binary Rom and Eeprom files. The files have to be named "ROMxxx.bin" and "EEPyy_xxx.bin", where xxx is the ROM version (e.g. -102) and yy is the upper part of the provider ID (e.g. 08 for BEV). The files +102) and yy is the upper part of the provider ID (e.g. 09 for BEV). The files must contain the joined contents of all Rom/Eeprom pages. The plugin searches for these files in the "nagra" subdirectory. @@ -332,14 +332,21 @@ SVDR interface The plugin implements a SVDR interface. Supported commands are: RELOAD - reload all configuration files (only if the softcam isn't active at the + Reload all configuration files (only if the softcam isn't active at the moment). Return codes: 550 - Softcam active, can't reload files. 901 - Reloading files not entirely successfull. Most of the time this will leave you with an unusable softcam. 900 - Reload successfull. - LOG [on|off] module.option[,module.option][,...] + KEY string + Parse the given string and add the key to the key database (as if it was + received from EMM stream). + Return codes: 501 - Syntax error. + 900 - Key added. + 901 - Invalid key format or key already known. + + LOG module.option[,module.option][,...] Enables or disables all given message classes. Return codes: 501 - Syntax error or unknown message class. 900 - Options set and saved. @@ -350,3 +357,8 @@ The plugin implements a SVDR interface. Supported commands are: message classes. Return codes: 901 - No message classes available. 900 - Message class status (multi line reply). + + LOGFILE [filename] + Enables or disables logging to file and optionaly sets the filename.", + Return codes: 501 - Syntax error. + 900 - Logfile option set and saved. diff --git a/cam.c b/cam.c index 63195be..fbe81db 100644 --- a/cam.c +++ b/cam.c @@ -602,7 +602,7 @@ bool cEcmData::Parse(const char *buf) SetName(Name); const char *line=buf+num; if(nu>0 && *line++==':') { - unsigned char dat[nu]; + unsigned char *dat=AUTOMEM(nu); if(GetHex(line,dat,nu,true)==nu) AddData(dat,nu); } return true; @@ -614,7 +614,7 @@ bool cEcmData::Save(FILE *f) { fprintf(f,"%d:%x:%x:%s:%x/%x:%x:%x/%x",prgId,source,transponder,name,caId,emmCaId,provId,ecm_pid,ecm_table); if(data) { - char str[dataLen*2+2]; + char *str=AUTOARRAY(char,dataLen*2+2); fprintf(f,":%d:%s\n",dataLen,HexStr(str,data,dataLen)); } else diff --git a/crypto-bn.h b/crypto-bn.h index 14ce54d..0168d94 100644 --- a/crypto-bn.h +++ b/crypto-bn.h @@ -36,6 +36,7 @@ public: cBN(void) { BN_init(&big); } ~cBN() { BN_free(&big); } operator BIGNUM* () { return &big; } + BIGNUM *operator->() { return &big; } bool Get(const unsigned char *in, int n); bool GetLE(const unsigned char *in, int n); int Put(unsigned char *out, int n) const; diff --git a/crypto.c b/crypto.c index ed1e12a..c1e64cc 100644 --- a/crypto.c +++ b/crypto.c @@ -58,7 +58,7 @@ int cBN::Put(unsigned char *out, int n) const { int s=BN_num_bytes(&big); if(s>n) { - unsigned char buff[s]; + unsigned char *buff=AUTOMEM(s); BN_bn2bin(&big,buff); memcpy(out,buff+s-n,n); } @@ -73,7 +73,7 @@ int cBN::Put(unsigned char *out, int n) const bool cBN::GetLE(const unsigned char *in, int n) { - unsigned char tmp[n]; + unsigned char *tmp=AUTOMEM(n); RotateBytes(tmp,in,n); return BN_bin2bn(tmp,n,&big)!=0; } diff --git a/data.c b/data.c index 8973686..332ec0b 100644 --- a/data.c +++ b/data.c @@ -763,6 +763,21 @@ void cPlainKeys::ExternalUpdate(void) } } +bool cPlainKeys::NewKeyParse(const char *line) +{ + cPlainKey *nk=NewFromType(toupper(line[0])); + if(nk && nk->Parse(line)) { + cPlainKey *k=0; + while((k=FindKeyNoTrig(nk->type,nk->id,nk->keynr,-1,k))) + if(k->Cmp(nk)) break; + if(!k) { + AddNewKey(nk,2,true); + return true; + } + } + return false; +} + void cPlainKeys::Action(void) { last.Set(EXT_AU_MIN); @@ -774,17 +789,7 @@ void cPlainKeys::Action(void) while(fgets(buff,sizeof(buff),pipe)) { char *line=skipspace(stripspace(buff)); if(line[0]==0 || line[0]==';' || line[0]=='#') continue; - cPlainKey *nk=NewFromType(toupper(line[0])); - if(nk && nk->Parse(line)) { - cPlainKey *k=0; - while((k=FindKeyNoTrig(nk->type,nk->id,nk->keynr,-1,k))) - if(k->Cmp(nk)) break; - if(!k) { - AddNewKey(nk,2,true); - nk=0; - } - } - delete nk; + NewKeyParse(line); } } pipe.Close(); diff --git a/data.h b/data.h index 02ca51d..2650064 100644 --- a/data.h +++ b/data.h @@ -263,6 +263,7 @@ public: cPlainKey *FindKey(int Type, int Id, int Keynr, int Size, cPlainKey *key=0); cPlainKey *FindKeyNoTrig(int Type, int Id, int Keynr, int Size, cPlainKey *key=0); bool NewKey(int Type, int Id, int Keynr, void *Key, int Keylen); + bool NewKeyParse(const char *line); void HouseKeeping(void); }; diff --git a/filter.c b/filter.c index e8a8f9f..9f92029 100644 --- a/filter.c +++ b/filter.c @@ -222,19 +222,23 @@ void cAction::Priority(int Pri) void cAction::Action(void) { if(pri>0) SetPriority(pri); + struct pollfd *pfd=0; while(Running()) { - int num=filters.Count(); - if(num<=0) { + if(filters.Count()<=0) { cCondWait::SleepMs(100); } else { // first build pfd data Lock(); + delete pfd; pfd=new struct pollfd[filters.Count()]; + if(!pfd) { + PRINTF(L_GEN_ERROR,"action %s: pollfd: out of memory",id); + break; + } + int num=0; cPidFilter *filter; - struct pollfd pfd[num]; - num=0; - memset(pfd,0,sizeof(pfd)); for(filter=filters.First(); filter; filter=filters.Next(filter)) { + memset(&pfd[num],0,sizeof(struct pollfd)); pfd[num].fd=filter->fd; pfd[num].events=POLLIN; num++; @@ -289,4 +293,5 @@ void cAction::Action(void) Unlock(); } } + delete pfd; } diff --git a/log.h b/log.h index 7f4a4f6..38fa86b 100644 --- a/log.h +++ b/log.h @@ -38,11 +38,11 @@ #define ADD_MODULE(MOD,NAME) static bool __add_mod_ ## NAME = cLogging::AddModule(MOD,&NAME); -#define PRINTF(c,t...) cLogging::Printf((c),t) +#define PRINTF(c,...) cLogging::Printf((c),__VA_ARGS__) #define PUTS(c,t) cLogging::Puts((c),(t)) #define PUTLB(c,lb) cLogging::PutLB((c),(lb)) -#define HEXDUMP(c,d,n,t...) cLogging::Dump((c),(d),(n),t) -#define LDUMP(c,d,n,t...) cLogging::LineDump((c),(d),(n),t) +#define HEXDUMP(c,d,n,...) cLogging::Dump((c),(d),(n),__VA_ARGS__) +#define LDUMP(c,d,n,...) cLogging::LineDump((c),(d),(n),__VA_ARGS__) #define LOG(c) cLogging::Enabled((c)) // backward compatibility @@ -50,7 +50,7 @@ #define LBSTART(c) do { int __c=(c); if(LOG(__c)) { cLogLineBuff __llb(__c) #define LBSTARTF(c) do { int __c=(c); { cLogLineBuff __llb(__c) -#define LBPUT(t...) __llb.Printf(t) +#define LBPUT(...) __llb.Printf(__VA_ARGS__) #define LBFLUSH() __llb.Flush() #define LBEND( ) } } while(0) diff --git a/misc.h b/misc.h index d6404a1..f24f1ff 100644 --- a/misc.h +++ b/misc.h @@ -25,6 +25,10 @@ #define WORD(buffer,index,mask) (((buffer[(index)]<<8) + buffer[(index)+1]) & mask) #define SCT_LEN(sct) (3+(((sct)[1]&0x0f)<<8)+(sct)[2]) +// replacement for variable-sized arrays +#define AUTOARRAY(type,size) (type *)alloca(sizeof(type)*(size)) +#define AUTOMEM(size) (unsigned char *)alloca(size) + // ---------------------------------------------------------------- #define DEV_DVB_FRONTEND "frontend" diff --git a/parse.c b/parse.c index 856a674..429f144 100644 --- a/parse.c +++ b/parse.c @@ -406,7 +406,7 @@ int cProviderViaccess::Assemble(cAssembleData *ad) case 0x8E: if(sharedEmm) { - unsigned char tmp[len+sharedLen]; + unsigned char *tmp=AUTOMEM(len+sharedLen); unsigned char *ass=(unsigned char *)cParseViaccess::NanoStart(data); len-=(ass-data); if((data[6]&2)==0) { @@ -635,7 +635,7 @@ int cCardCryptoworks::Assemble(cAssembleData *ad) case 0x86: if(sharedEmm) { int alen=len-5 + sharedLen-12; - unsigned char tmp[alen]; + unsigned char *tmp=AUTOMEM(alen); memcpy(tmp,&data[5],len-5); memcpy(tmp+len-5,&sharedEmm[12],sharedLen-12); diff --git a/po/de_DE.po b/po/de_DE.po index cb87c27..6b231b9 100644 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-27 17:16+0200\n" +"POT-Creation-Date: 2007-12-19 18:49+0100\n" "PO-Revision-Date: 2007-08-27 12:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -160,6 +160,21 @@ msgstr "Cardclient: sofort verbinden" msgid "Nagra: min. ECM processing time" msgstr "Nagra: min. ECM Bearbeitungszeit" +msgid "Nagra2: drop EMM-S packets" +msgstr "Nagra2: EMM-S Pakete verwerfen" + +msgid "Nagra2: Enable AUXserver" +msgstr "Nagra2: AUXserver aktivieren" + +msgid "Nagra2: AUXserver hostname" +msgstr "Nagra2: AUXserver Hostname" + +msgid "Nagra2: AUXserver port" +msgstr "Nagra2: AUXserver Port" + +msgid "Nagra2: AUXserver password" +msgstr "Nagra2: AUXserver Passwort" + msgid "don't touch" msgstr "nicht ändern" diff --git a/po/fi_FI.po b/po/fi_FI.po index cfbfad2..2447c7d 100644 --- a/po/fi_FI.po +++ b/po/fi_FI.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-27 17:16+0200\n" +"POT-Creation-Date: 2007-12-19 18:52+0100\n" "PO-Revision-Date: 2007-08-27 12:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -116,7 +116,7 @@ msgid "Update keys (AU)" msgstr "Tilausten päivitys (AU)" msgid "Start AU on EPG scan" -msgstr "" +msgstr "Aloita AU EPG-päivityksessä" msgid "Concurrent FF streams" msgstr "Yhtäaikainen salauksenpurku (FF)" @@ -160,6 +160,21 @@ msgstr "Korttiasiakas: yhdist msgid "Nagra: min. ECM processing time" msgstr "Nagra: Min. ECM-prosessointiaika" +msgid "Nagra2: drop EMM-S packets" +msgstr "" + +msgid "Nagra2: Enable AUXserver" +msgstr "" + +msgid "Nagra2: AUXserver hostname" +msgstr "" + +msgid "Nagra2: AUXserver port" +msgstr "" + +msgid "Nagra2: AUXserver password" +msgstr "" + msgid "don't touch" msgstr "älä koske" diff --git a/po/fr_FR.po b/po/fr_FR.po index fb682c6..6fd88fe 100644 --- a/po/fr_FR.po +++ b/po/fr_FR.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-27 17:16+0200\n" +"POT-Creation-Date: 2007-12-19 18:52+0100\n" "PO-Revision-Date: 2007-08-27 12:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -160,6 +160,21 @@ msgstr "Cardclient: connecter immediatement" msgid "Nagra: min. ECM processing time" msgstr "Nagra: min. durée du processus ECM" +msgid "Nagra2: drop EMM-S packets" +msgstr "" + +msgid "Nagra2: Enable AUXserver" +msgstr "" + +msgid "Nagra2: AUXserver hostname" +msgstr "" + +msgid "Nagra2: AUXserver port" +msgstr "" + +msgid "Nagra2: AUXserver password" +msgstr "" + msgid "don't touch" msgstr "Ne pas modifier" diff --git a/po/hu_HU.po b/po/hu_HU.po index d608902..9744b77 100644 --- a/po/hu_HU.po +++ b/po/hu_HU.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.11\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-11-08 12:39+0100\n" +"POT-Creation-Date: 2007-12-19 18:52+0100\n" "PO-Revision-Date: 2007-11-01 16:45+0200\n" "Last-Translator: jv\n" "Language-Team: somebody\n" @@ -160,6 +160,21 @@ msgstr "Kliens: csatlakozzon azonnal" msgid "Nagra: min. ECM processing time" msgstr "Nagra: min. ECM feldolgozási idő" +msgid "Nagra2: drop EMM-S packets" +msgstr "" + +msgid "Nagra2: Enable AUXserver" +msgstr "" + +msgid "Nagra2: AUXserver hostname" +msgstr "" + +msgid "Nagra2: AUXserver port" +msgstr "" + +msgid "Nagra2: AUXserver password" +msgstr "" + msgid "don't touch" msgstr "ne bántsd" diff --git a/po/it_IT.po b/po/it_IT.po index dc64af7..273b6dc 100644 --- a/po/it_IT.po +++ b/po/it_IT.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-27 17:16+0200\n" +"POT-Creation-Date: 2007-12-19 18:52+0100\n" "PO-Revision-Date: 2007-08-27 12:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -160,6 +160,21 @@ msgstr "" msgid "Nagra: min. ECM processing time" msgstr "" +msgid "Nagra2: drop EMM-S packets" +msgstr "" + +msgid "Nagra2: Enable AUXserver" +msgstr "" + +msgid "Nagra2: AUXserver hostname" +msgstr "" + +msgid "Nagra2: AUXserver port" +msgstr "" + +msgid "Nagra2: AUXserver password" +msgstr "" + msgid "don't touch" msgstr "" diff --git a/po/nl_NL.po b/po/nl_NL.po index 143180b..5cc85db 100644 --- a/po/nl_NL.po +++ b/po/nl_NL.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-27 17:16+0200\n" +"POT-Creation-Date: 2007-12-19 18:52+0100\n" "PO-Revision-Date: 2007-08-27 12:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -160,6 +160,21 @@ msgstr "Cardclient: direct contact maken" msgid "Nagra: min. ECM processing time" msgstr "Nagra: min. ECM bewerkingstijd" +msgid "Nagra2: drop EMM-S packets" +msgstr "" + +msgid "Nagra2: Enable AUXserver" +msgstr "" + +msgid "Nagra2: AUXserver hostname" +msgstr "" + +msgid "Nagra2: AUXserver port" +msgstr "" + +msgid "Nagra2: AUXserver password" +msgstr "" + msgid "don't touch" msgstr "niet wijzigen" diff --git a/po/pl_PL.po b/po/pl_PL.po index 5e5e4d7..184cb32 100644 --- a/po/pl_PL.po +++ b/po/pl_PL.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-27 17:16+0200\n" +"POT-Creation-Date: 2007-12-19 18:52+0100\n" "PO-Revision-Date: 2007-08-27 12:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -160,6 +160,21 @@ msgstr "Klient karty: pod msgid "Nagra: min. ECM processing time" msgstr "Nagra: min. czas przetwarzania ECM" +msgid "Nagra2: drop EMM-S packets" +msgstr "" + +msgid "Nagra2: Enable AUXserver" +msgstr "" + +msgid "Nagra2: AUXserver hostname" +msgstr "" + +msgid "Nagra2: AUXserver port" +msgstr "" + +msgid "Nagra2: AUXserver password" +msgstr "" + msgid "don't touch" msgstr "nie dotykaj" diff --git a/po/ru_RU.po b/po/ru_RU.po index 785adc1..3dad903 100644 --- a/po/ru_RU.po +++ b/po/ru_RU.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-27 17:16+0200\n" +"POT-Creation-Date: 2007-12-19 18:52+0100\n" "PO-Revision-Date: 2007-09-17 23:03+0200\n" "Last-Translator: \n" "Language-Team: ru\n" @@ -161,6 +161,21 @@ msgstr "Cardclient: msgid "Nagra: min. ECM processing time" msgstr "Nagra: ÜØÝ. ÒàÕÜï ÞÑàÐÑÞâÚØ ECM" +msgid "Nagra2: drop EMM-S packets" +msgstr "" + +msgid "Nagra2: Enable AUXserver" +msgstr "" + +msgid "Nagra2: AUXserver hostname" +msgstr "" + +msgid "Nagra2: AUXserver port" +msgstr "" + +msgid "Nagra2: AUXserver password" +msgstr "" + msgid "don't touch" msgstr "ÝÕ Ø×ÜÕÝïâì" diff --git a/po/sc.pot b/po/sc.pot index 31df669..1fb168c 100644 --- a/po/sc.pot +++ b/po/sc.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-11-08 12:39+0100\n" +"POT-Creation-Date: 2007-12-19 18:52+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -162,6 +162,21 @@ msgstr "" msgid "Nagra: min. ECM processing time" msgstr "" +msgid "Nagra2: drop EMM-S packets" +msgstr "" + +msgid "Nagra2: Enable AUXserver" +msgstr "" + +msgid "Nagra2: AUXserver hostname" +msgstr "" + +msgid "Nagra2: AUXserver port" +msgstr "" + +msgid "Nagra2: AUXserver password" +msgstr "" + msgid "don't touch" msgstr "" diff --git a/po/sv_SE.po b/po/sv_SE.po index 1145838..04fcf04 100644 --- a/po/sv_SE.po +++ b/po/sv_SE.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: VDR 1.5.9\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2007-10-27 17:16+0200\n" +"POT-Creation-Date: 2007-12-19 18:52+0100\n" "PO-Revision-Date: 2007-08-27 12:45+0200\n" "Last-Translator: somebody\n" "Language-Team: somebody\n" @@ -160,6 +160,21 @@ msgstr "" msgid "Nagra: min. ECM processing time" msgstr "" +msgid "Nagra2: drop EMM-S packets" +msgstr "" + +msgid "Nagra2: Enable AUXserver" +msgstr "" + +msgid "Nagra2: AUXserver hostname" +msgstr "" + +msgid "Nagra2: AUXserver port" +msgstr "" + +msgid "Nagra2: AUXserver password" +msgstr "" + msgid "don't touch" msgstr "" diff --git a/sc.c b/sc.c index b76b687..a207da4 100644 --- a/sc.c +++ b/sc.c @@ -1369,10 +1369,14 @@ const char **cScPlugin::SVDRPHelpPages(void) static const char *HelpPages[] = { "RELOAD\n" " Reload all configuration files.", + "KEY \n", + " Add key to the key database (as if it was received from EMM stream).", "LOG [,...]\n" " Turn the given message class(es) on or off.", "LOGCFG\n" " Display available message classes and their status.", + "LOGFILE []\n" + " Enables/disables logging to file and optionaly sets the filename.", NULL }; return HelpPages; @@ -1394,9 +1398,22 @@ cString cScPlugin::SVDRPCommand(const char *Command, const char *Option, int &Re } } } + else if(!strcasecmp(Command,"KEY")) { + if(Option && *Option) { + if(keys.NewKeyParse(skipspace(Option))) + return "Key update successfull"; + else { + ReplyCode=901; + return "Key already known or invalid key format"; + } + } + else { ReplyCode=501; return "Missing args"; } + } else if(!strcasecmp(Command,"LOG")) { if(Option && *Option) { - char *opt=strdup(Option); + char tmp[1024]; + strn0cpy(tmp,Option,sizeof(tmp)); + char *opt=tmp; opt=skipspace(opt); bool mode; if(!strncasecmp(opt,"ON ",3)) { mode=true; opt+=3; } @@ -1436,6 +1453,35 @@ cString cScPlugin::SVDRPCommand(const char *Command, const char *Option, int &Re if(lb.Length()>0) return lb.Line(); ReplyCode=901; return "No config available"; } + else if(!strcasecmp(Command,"LOGFILE")){ + if(Option && *Option) { + char tmp[1024]; + strn0cpy(tmp,Option,sizeof(tmp)); + char *opt=tmp; + opt=skipspace(opt); + bool mode; + if(!strncasecmp(opt,"ON",2)) { mode=true; opt+=2; } + else if(!strncasecmp(opt,"OFF",3)) { mode=false; opt+=3; } + else { ReplyCode=501; return "Bad mode, valid: on off"; } + cLineBuff lb(256); + if(mode) { + logcfg.logFile=true; + if(*opt==' ' || *opt=='\t') { + opt=stripspace(skipspace(opt)); + strn0cpy(logcfg.logFilename,opt,sizeof(logcfg.logFilename)); + } + lb.Printf("logging to file enabled, file %s",logcfg.logFilename); + } + else { + logcfg.logFile=false; + lb.Printf("logging to file disabled"); + } + ScSetup.Store(true); + Setup.Save(); + return lb.Line(); + } + else { ReplyCode=501; return "Missing args"; } + } return NULL; } diff --git a/smartcard.c b/smartcard.c index 5391daa..50d43a3 100644 --- a/smartcard.c +++ b/smartcard.c @@ -961,7 +961,7 @@ int cSmartCard::Read(unsigned char *data, int len, int to) int cSmartCard::Write(const unsigned char *data, int len) { - unsigned char tmp[len]; + unsigned char *tmp=AUTOMEM(len); if(atr->convention==SM_INDIRECT) { memcpy(tmp,data,len); Invert(tmp,len); @@ -969,7 +969,7 @@ int cSmartCard::Write(const unsigned char *data, int len) } int r=ser->Write(data,len); if(r>0) { - unsigned char buff[r]; + unsigned char *buff=AUTOMEM(r); int rr=ser->Read(buff,r,cfg->serTO); if(rr<0) r=rr; } diff --git a/system-common.c b/system-common.c index 3011bcc..eec12fe 100644 --- a/system-common.c +++ b/system-common.c @@ -121,7 +121,7 @@ void cBNKey::Get(void *mem) cString cBNKey::Print(void) { - unsigned char mem[keylen]; + unsigned char *mem=AUTOMEM(keylen); if(rotate) key->PutLE(mem,keylen); else key->Put(mem,keylen); char *str=(char *)malloc(keylen*2+2); if(str) HexStr(str,mem,keylen); diff --git a/system.c b/system.c index 32e9325..8b77b91 100644 --- a/system.c +++ b/system.c @@ -525,20 +525,20 @@ int cMsgCache::Get(const unsigned char *msg, int len, unsigned char *store) } else { id=(s-&caches[0])+1; - switch(s->mode) { - case GOOD: - if(store && storeSize>0) - memcpy(store,&stores[(id-1)*storeSize],storeSize); - PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as GOOD (%d)",getpid(),this,id); - return 0; - case FAIL1...FAIL2: - PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as FAIL%d (%d)",getpid(),this,s->mode,id); - s->mode|=QUEUED; - return id; - case FAILN: - default: - PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as FAILN (%d)",getpid(),this,id); - return -1; + if(s->mode==GOOD) { + if(store && storeSize>0) + memcpy(store,&stores[(id-1)*storeSize],storeSize); + PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as GOOD (%d)",getpid(),this,id); + return 0; + } + else if(s->mode>=FAIL1 && s->mode<=FAIL2) { + PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as FAIL%d (%d)",getpid(),this,s->mode,id); + s->mode|=QUEUED; + return id; + } + else { + PRINTF(L_CORE_MSGCACHE,"%d/%p: msg is cached as FAILN (%d)",getpid(),this,id); + return -1; } } } @@ -559,23 +559,18 @@ int cMsgCache::Cache(int id, bool result, const unsigned char *store) return 0; } else { - switch(s->mode&MASK) { - case GOOD: - s->mode=FREE; - // fall through - case FREE: - case FAIL1...FAIL2: - s->mode=(s->mode&MASK)+1; - if(s->modemode); - break; - } - // fall through - case FAILN: - s->mode=FAILN; - LBPUT("(FAILN)"); - break; + int m=s->mode&MASK; + if(m==GOOD) + m=s->mode=FREE; + if(m==FREE || (m>=FAIL1 && m<=FAIL2)) { + s->mode=(s->mode&MASK)+1; + if(s->modemode); + else + m=s->mode=FAILN; } + if(m==FAILN) + LBPUT("(FAILN)"); return s->mode; } LBEND(); diff --git a/systems/cardclient/camd.c b/systems/cardclient/camd.c index 212f786..7d5c096 100644 --- a/systems/cardclient/camd.c +++ b/systems/cardclient/camd.c @@ -100,13 +100,13 @@ bool cCardClientCommon::ParseKeyConfig(const char *config, int *num) bool cCardClientCommon::SendMsg(cNetSocket *so, const unsigned char *data, int len) { - unsigned char buff2[minMsgLen]; + unsigned char *buff2=AUTOMEM(minMsgLen); if(len0) { data=buff; len=l; } return cCardClient::SendMsg(so,data,len); @@ -177,7 +177,7 @@ bool cCardClientCommon::ProcessEMM(int caSys, const unsigned char *source) const int length=SCT_LEN(source); int id=msEMM.Get(source,length,0); if(id>0) { - unsigned char buff[length+32]; + unsigned char *buff=AUTOMEM(length+32); buff[0]=0x03; buff[1]=(caSys>>8); buff[2]=(caSys&0xFF); @@ -201,7 +201,7 @@ bool cCardClientCommon::ProcessECM(const cEcmInfo *ecm, const unsigned char *sou while(exclusive) sleepCond.Wait(*this); if((so.Connected() || Login()) && (!emmProcessing || CanHandle(ecm->caId))) { const int length=SCT_LEN(source); - unsigned char buff[length+32]; + unsigned char *buff=AUTOMEM(length+32); int n; while((n=RecvMsg(&so,buff,16,0))>0) HandleEMMRequest(buff,n); buff[0]=0x02; @@ -467,7 +467,7 @@ bool cCardClientCamd35::SendBlock(struct CmdBlock *cb, int datalen) cb->udp_header.len=datalen; cb->udp_header.crc=bswap_32(crc32_le(0,&cb->data[0],datalen)); datalen+=CBSIZE(cb); - unsigned char buff[datalen+UCSIZE(cb)+16]; + unsigned char *buff=AUTOMEM(datalen+UCSIZE(cb)+16); *((unsigned int *)buff)=ucrc; HEXDUMP(L_CC_CAMDEXTR,cb,datalen+UCSIZE(cb),"send:"); const int l=Encrypt((unsigned char *)cb+UCSIZE(cb),datalen,buff+UCSIZE(cb)); diff --git a/systems/cryptoworks/cryptoworks.c b/systems/cryptoworks/cryptoworks.c index c807d33..c68ca63 100644 --- a/systems/cryptoworks/cryptoworks.c +++ b/systems/cryptoworks/cryptoworks.c @@ -281,7 +281,7 @@ void cCryptoworks::DecryptDES(unsigned char *data, unsigned char algo, const uns bool cCryptoworks::DecryptRSA(unsigned char *data, int len, unsigned char algo, const unsigned char *key22, BIGNUM *mod) { - unsigned char buf[64], mask[len]; + unsigned char buf[64], *mask=AUTOMEM(len); LDUMP(L_SYS_VERBOSE,data+len,8,"rsa in:"); memcpy(buf,data+len,8); @@ -379,7 +379,7 @@ bool cPlainKeyCryptoworks::Parse(const char *line) keylen=IsBNKey() ? PLAINLEN_CW_R : PLAINLEN_CW_D; } if(ok) { - unsigned char skey[keylen]; + unsigned char *skey=AUTOMEM(keylen); if(GetHex(line,skey,keylen)) { SetBinKey(skey,keylen); return true; diff --git a/systems/irdeto/irdeto.c b/systems/irdeto/irdeto.c index 98dc7f8..9f18073 100644 --- a/systems/irdeto/irdeto.c +++ b/systems/irdeto/irdeto.c @@ -428,6 +428,7 @@ void cSystemIrd::ProcessEMM(int pid, int caid, unsigned char *buffer) if((numKeys>0 && (id[0]!=lastKey || numKeys>1)) || mk) { memcpy(savebuf,buffer,n); // save the buffer cIrdCardInfo *ci=Icards.First(); + unsigned char *chkkey=AUTOMEM(max(sizeof(ci->PMK),sizeof(ci->HMK))); while(ci) { ci->hexBase=cParseIrdeto::AddrBase(buffer); if((numKeys>0 && (ci->cProviderIrdeto::MatchEMM(buffer) || CheckNull(ci->provId,sizeof(ci->provId)) )) || @@ -439,7 +440,6 @@ void cSystemIrd::ProcessEMM(int pid, int caid, unsigned char *buffer) lastKey=id[i]; SessionKeyCrypt(pk[i],ci->PMK,date); } - unsigned char chkkey[max(sizeof(ci->PMK),sizeof(ci->HMK))]; int keylen; if(mk) { memcpy(chkkey,ci->HMK,sizeof(ci->HMK)); // key is modified in decryptIrd() diff --git a/systems/nagra/cpu.c b/systems/nagra/cpu.c index b283b00..054920e 100644 --- a/systems/nagra/cpu.c +++ b/systems/nagra/cpu.c @@ -25,8 +25,8 @@ #include "cpu.h" #include "log-nagra.h" -#define LOGLBPUT(t...) loglb->Printf(t) -#define CCLOGLBPUT(t...) do { if(doDisAsm) loglb->Printf(t); } while(0) +#define LOGLBPUT(...) loglb->Printf(__VA_ARGS__) +#define CCLOGLBPUT(...) do { if(doDisAsm) loglb->Printf(__VA_ARGS__); } while(0) // -- cMapMem ------------------------------------------------------------------ @@ -79,7 +79,7 @@ cMapRom::~cMapRom() bool cMapRom::IsFine(void) { - return (addr!=0); + return addr!=0 && size>0; } unsigned char cMapRom::Get(unsigned short ea) @@ -146,6 +146,7 @@ c6805::c6805(void) { hasReadHandler=hasWriteHandler=false; ClearBreakpoints(); InitMapper(); + ResetCycles(); memset(stats,0,sizeof(stats)); loglb=new cLineBuff(128); } @@ -180,7 +181,7 @@ bool c6805::AddMapper(cMap *map, unsigned short start, int size, unsigned char s } else PRINTF(L_SYS_EMU,"6805: too many mappers"); } - else PRINTF(L_SYS_EMU,"6805: mapper not ready"); + else PRINTF(L_SYS_EMU,"6805: mapper not ready (start=%02x:%04x size=%04x)",seg,start,size); delete map; return false; } @@ -270,6 +271,11 @@ void c6805::PopCr(void) cr=pop(); } +void c6805::Push(unsigned char c) +{ + push(c); +} + void c6805::AddBreakpoint(unsigned short addr) { if(numBp0) { + clockcycles+=num; + TimerHandler(num); + } +} + +void c6805::ResetCycles(void) +{ + clockcycles=0; +} + static const char * const ops[] = { // 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f /* 0x00 */ "BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR","BRSET","BRCLR", @@ -333,6 +352,26 @@ static const char opFlags[] = { /* 0xf0 */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x05, 0x06, }; +static const unsigned char clock_cycles[] = { +// 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f +/* 0x00 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, +/* 0x10 */ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0, 0, 0, 0, 0, 0, +/* 0x20 */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, +/* 0x30 */ 5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 4, 5, 5, +/* 0x40 */ 3, 0, 11, 3, 3, 0, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, +/* 0x50 */ 3, 0, 0, 3, 3, 0, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, +/* 0x60 */ 6, 0, 0, 6, 6, 0, 6, 6, 6, 6, 6, 0, 6, 5, 6, 6, +/* 0x70 */ 5, 0, 0, 5, 5, 0, 5, 5, 5, 5, 5, 0, 5, 4, 5, 5, +/* 0x80 */ 9, 6, 0, 10, 4, 4, 4, 0, 3, 3, 3, 0, 0, 0, 2, 2, +/* 0x90 */ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, +/* 0xa0 */ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 0, 6, 2, 0, +/* 0xb0 */ 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 2, 5, 3, 4, +/* 0xc0 */ 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 3, 6, 4, 5, +/* 0xd0 */ 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 4, 7, 5, 6, +/* 0xe0 */ 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 3, 6, 4, 5, +/* 0xf0 */ 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 2, 5, 3, 4, + }; + char * c6805::PADDR(unsigned char s, unsigned short ea) { snprintf(addrBuff,sizeof(addrBuff),((ea&0x8000) && s>0)?"%2$x:%1$04x":"%04x",ea,s); @@ -368,7 +407,7 @@ int c6805::Run(int max_count) count++; if(!LOG(L_SYS_DISASM) && LOG(L_SYS_DISASM80)) { - bool flag=(pc>=0x80 && pc<0xE0); + bool flag=(pc>=0x80 && pc<0x200); if(doDisAsm && !flag) PRINTF(disAsmLogClass,"[...]"); doDisAsm=flag; } @@ -389,47 +428,72 @@ int c6805::Run(int max_count) bool paged=false, vbra=false; unsigned char ins=Get(pc++); char xs='X', xi='X'; + int cycles=0; // check pre-bytes switch(ins) { case 0x31: // use SP indexed or indirect paged mode (ST19) + cycles+=2; ins=Get(pc++); switch(ins) { - case 0x22 ... 0x27: vbra=true; PRINTF(L_SYS_EMU,"WARN: V-flag not yet calculated"); break; + case 0x22: case 0x23: case 0x24: case 0x25: + case 0x26: case 0x27: + vbra=true; PRINTF(L_SYS_EMU,"WARN: V-flag not yet calculated"); break; case 0x75: case 0x8D: - case 0xC0 ... 0xCB: - case 0xCE ... 0xCF: - case 0xD0 ... 0xDB: - case 0xDE ... 0xDF: paged=true; indirect=true; break; - case 0xE0 ... 0xEB: - case 0xEE ... 0xEF: idx=sp; xi='S'; break; + case 0xC0: case 0xC1: case 0xC2: case 0xC3: + case 0xC4: case 0xC5: case 0xC6: case 0xC7: + case 0xC8: case 0xC9: case 0xCA: case 0xCB: + case 0xCE: case 0xCF: + case 0xD0: case 0xD1: case 0xD2: case 0xD3: + case 0xD4: case 0xD5: case 0xD6: case 0xD7: + case 0xD8: case 0xD9: case 0xDA: case 0xDB: + case 0xDE: case 0xDF: + paged=true; indirect=true; break; + case 0xE0: case 0xE1: case 0xE2: case 0xE3: + case 0xE4: case 0xE5: case 0xE6: case 0xE7: + case 0xE8: case 0xE9: case 0xEA: case 0xEB: + case 0xEE: case 0xEF: + idx=sp; xi='S'; break; } break; case 0x32: // use indirect SP indexed or indirect paged Y indexed mode (ST19) + cycles+=2; ins=Get(pc++); switch(ins) { - case 0x22 ... 0x27: vbra=true; PRINTF(L_SYS_EMU,"WARN: V-flag not yet calculated"); indirect=true; break; + case 0x22: case 0x23: case 0x24: case 0x25: + case 0x26: case 0x27: + vbra=true; PRINTF(L_SYS_EMU,"WARN: V-flag not yet calculated"); indirect=true; break; case 0xC3: - case 0xCE ... 0xCF: - case 0xD0 ... 0xDB: - case 0xDE ... 0xDF: paged=true; indirect=true; ex=&y; idx=*ex; xs='Y'; xi='Y'; break; - case 0xE0 ... 0xEB: - case 0xEE ... 0xEF: indirect=true; idx=sp; xi='S'; break; + case 0xCE: case 0xCF: + case 0xD0: case 0xD1: case 0xD2: case 0xD3: + case 0xD4: case 0xD5: case 0xD6: case 0xD7: + case 0xD8: case 0xD9: case 0xDA: case 0xDB: + case 0xDE: case 0xDF: + paged=true; indirect=true; ex=&y; idx=*ex; xs='Y'; xi='Y'; break; + case 0xE0: case 0xE1: case 0xE2: case 0xE3: + case 0xE4: case 0xE5: case 0xE6: case 0xE7: + case 0xE8: case 0xE9: case 0xEA: case 0xEB: + case 0xEE: case 0xEF: + indirect=true; idx=sp; xi='S'; break; } break; case 0x91: // use Y register with indirect addr mode (ST7) + cycles++; indirect=true; // fall through case 0x90: // use Y register (ST7) + cycles++; ex=&y; idx=*ex; xs='Y'; xi='Y'; ins=Get(pc++); break; case 0x92: // use indirect addr mode (ST7) + cycles+=2; indirect=true; ins=Get(pc++); break; } + AddCycles(cycles+clock_cycles[ins]); if(doDisAsm) { char str[8]; @@ -759,7 +823,11 @@ int c6805::Run(int max_count) case 0x6E: case 0x7E: op=(op<<4)|(op>>4); tst(op); break; - case 0x00 ... 0x0F: // BRSET BRCLR + //case 0x00 ... 0x0F: // BRSET BRCLR + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0A: case 0x0B: + case 0x0C: case 0x0D: case 0x0E: case 0x0F: { int bit=(ins&0x0F)>>1; CCLOGLBPUT(",#%x,",bit); @@ -767,7 +835,11 @@ int c6805::Run(int max_count) branch((ins&0x01) ? !cc.c:cc.c); break; } - case 0x10 ... 0x1F: // BSET BCLR + //case 0x10 ... 0x1F: // BSET BCLR + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1A: case 0x1B: + case 0x1C: case 0x1D: case 0x1E: case 0x1F: { int bit=(ins&0x0F)>>1; CCLOGLBPUT(",#%x",bit); diff --git a/systems/nagra/cpu.h b/systems/nagra/cpu.h index 9cf7852..f8fedaa 100644 --- a/systems/nagra/cpu.h +++ b/systems/nagra/cpu.h @@ -88,7 +88,7 @@ public: // ---------------------------------------------------------------- -#define MAX_BREAKPOINTS 4 +#define MAX_BREAKPOINTS 24 #define MAX_MAPPER 8 #define MAX_PAGES 4 #define PAGE_SIZE 32*1024 @@ -107,6 +107,7 @@ private: int nextMapper; int pageMap[256]; bool indirect; + unsigned int clockcycles; // void InitMapper(void); void ClearMapper(void); @@ -144,9 +145,14 @@ protected: unsigned short GetPc(void) const { return pc; } void PopPc(void); void PopCr(void); + void Push(unsigned char c); + void ResetCycles(void); + void AddCycles(unsigned int num); + unsigned int Cycles(void) { return clockcycles; } virtual void Stepper(void)=0; virtual void WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op) {} virtual void ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op) {} + virtual void TimerHandler(unsigned int num) {} private: unsigned int stats[256]; char addrBuff[32]; diff --git a/systems/nagra/nagra.c b/systems/nagra/nagra.c index 185e67e..392a837 100644 --- a/systems/nagra/nagra.c +++ b/systems/nagra/nagra.c @@ -35,8 +35,6 @@ ADD_MODULE(L_SYS,lm_sys) int minEcmTime=400; // ms -#ifndef TESTER - // -- cPlainKeyNagra ----------------------------------------------------------- #define PLAINLEN_NAGRA_H 8 @@ -197,8 +195,6 @@ cString cPlainKeyNagra::PrintKeyNr(void) return nr; } -#endif // TESTER - // -- cNagra ------------------------------------------------------------------- cNagra::cNagra(void) diff --git a/systems/nagra/nagra1.c b/systems/nagra/nagra1.c index b50b764..a2c4e0a 100644 --- a/systems/nagra/nagra1.c +++ b/systems/nagra/nagra1.c @@ -186,22 +186,50 @@ bool cEmu::MathMapHandler(void) // -- cEmuRom3Core ------------------------------------------------------------- class cEmuRom3Core : public cEmu { +private: + bool special05; protected: virtual void Stepper(void); + virtual void WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op); + virtual void ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op); bool CoreInitSetup(void); bool DoMaps(bool hasExt); +public: + cEmuRom3Core(void); }; -void cEmuRom3Core::Stepper(void) +cEmuRom3Core::cEmuRom3Core(void) { - int rnd=random(); - unsigned char mem4=Get(0x04); - if(!bitset(mem4,2)) { - Set(0x06,(rnd&0xff00)>>8); - Set(0x07,rnd&0xff); + special05=false; +} + +void cEmuRom3Core::WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op) +{ + if(ea==0x05) special05=(op&0x40)!=0; +} + +void cEmuRom3Core::ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op) +{ + if(special05) { + special05=false; // prevent loop + unsigned short start=Get(0x30C0); + unsigned short end=Get(0x30C1); + if(((ea>>8)>=start) && ((ea>>8)<=end)) op=0x00; // dataspace + else op=0x01; // codespace + special05=true; } + else + switch(ea) { + case 0x06: + case 0x07: + if(!(Get(0x04)&4)) op=random()&0xFF; + break; + } } +void cEmuRom3Core::Stepper(void) +{} + bool cEmuRom3Core::CoreInitSetup(void) { ForceSet(0x0001,1<<3,true); @@ -403,7 +431,9 @@ bool cEmuRom10::MathMapHandler(void) } return true; - case 0x0e ... 0x10: + case 0x0e: + case 0x0F: + case 0x10: { const unsigned short addr=(Get(0x4d)<<8)|Get(0x4e); unsigned char tmp[64]; @@ -705,7 +735,7 @@ bool cSystemNagra::ProcessECM(const cEcmInfo *ecm, unsigned char *data) pk->Get(sessionKey); const int desLen=(ecmLen-9) & ~7; // datalen - signature - ks byte - unsigned char decrypted[desLen]; + unsigned char *decrypted=AUTOMEM(desLen); for(int i=(desLen/8)-1; decrypt && i>=0; i--) { const int off=i*8; Decrypt(data+11+off,sessionKey,decrypted+off); @@ -769,7 +799,7 @@ bool cSystemNagra::ProcessECM(const cEcmInfo *ecm, unsigned char *data) hasVerifyKey=true; } else if(doLog) PRINTF(L_SYS_KEY,"missing %04x V TYP%d key (non-fatal)",mecmProvId,keyType); - unsigned char decrMecmData[mecmRSALen]; + unsigned char *decrMecmData=AUTOMEM(mecmRSALen); if(!DecryptECM(&mecmData[4],decrMecmData,hasVerifyKey?verifyKey:0,mecmRSALen,e1,n1,n2)) return false; @@ -870,7 +900,14 @@ void cSystemNagra::ProcessEMM(int pid, int caid, unsigned char *buffer) switch(emmdata[i]) { // Check filter type case 0x00: // One card i+=7; break; - case 0x01 ... 0x20: // Group of cards + case 0x01: case 0x02: case 0x03: case 0x04: // Group of cards + case 0x05: case 0x06: case 0x07: case 0x08: + case 0x09: case 0x0A: case 0x0B: case 0x0C: + case 0x0D: case 0x0E: case 0x0F: case 0x10: + case 0x11: case 0x12: case 0x13: case 0x14: + case 0x15: case 0x16: case 0x17: case 0x18: + case 0x19: case 0x1A: case 0x1B: case 0x1C: + case 0x1D: case 0x1E: case 0x1F: case 0x20: i+=emmdata[i]+0x7; break; case 0x3e: i+=6; break; diff --git a/systems/nagra/nagra2-0101.c b/systems/nagra/nagra2-0101.c index bb3065e..8369d8b 100644 --- a/systems/nagra/nagra2-0101.c +++ b/systems/nagra/nagra2-0101.c @@ -19,9 +19,11 @@ // -- cAuxSrv ------------------------------------------------------------------ -/* -#define HAS_AUXSRV +//#define HAS_AUXSRV +#ifdef HAS_AUXSRV +#define AUX_PROTOCOL_VERSION 2 +static int auxEnabled=0; static int auxPort=7777; static char auxAddr[80]="localhost"; static char auxPassword[250]="auxserver"; @@ -33,7 +35,7 @@ private: bool Login(void); public: cAuxSrv(void); - bool Map(int map, unsigned char *data, int len, int outlen); + int Map(int map, unsigned char *data, int len, int outlen); }; cAuxSrv::cAuxSrv(void) @@ -52,16 +54,23 @@ bool cAuxSrv::Login() buff[3]=l; memcpy(&buff[4],auxPassword,l); buff[4+l]=0xFF; - if(so.Write(buff,l+5)==l+5) return true; + if(so.Write(buff,l+5)==l+5 && + so.Read(buff,sizeof(buff))>=9 && + buff[0]==0x7A && buff[1]==0xA7 && buff[2]==0x00 && buff[3]==0x04 && buff[8]==0xff && + ((buff[4]<<8)|buff[5])==AUX_PROTOCOL_VERSION) return true; PRINTF(L_SYS_MAP,"auxsrv: login write failed"); } so.Disconnect(); return false; } -bool cAuxSrv::Map(int map, unsigned char *data, int len, int outlen) +int cAuxSrv::Map(int map, unsigned char *data, int len, int outlen) { - if(len>500 || outlen>500) return false; + if(!auxEnabled) { + PRINTF(L_SYS_MAP,"auxsrv: AUXserver is disabled!"); + return -1; + } + if(len>500 || outlen>500) return -1; cMutexLock lock(this); if(!so.Connected() && !Login()) return false; PRINTF(L_SYS_MAP,"auxsrv: calling map%02x",map); @@ -77,15 +86,16 @@ bool cAuxSrv::Map(int map, unsigned char *data, int len, int outlen) if((len=so.Read(buff,sizeof(buff)))>0) { if(buff[0]==0x7A && buff[1]==0xA7) { if(buff[4]==0x00) { + int cycles=(buff[5]<<16)|(buff[6]<<8)|buff[7]; int l=buff[2]*256+buff[3]; - if(len>=l+5 && l==outlen+1) { + if(len>=l+5 && l==outlen+4) { if(buff[l+4]==0xFF) { - memcpy(data,buff+5,outlen); - return true; + memcpy(data,buff+8,outlen); + return cycles; } else PRINTF(L_SYS_MAP,"auxsrv: bad footer in map%02x response",map); } - else PRINTF(L_SYS_MAP,"auxsrv: bad length in map%02x response (got=%d want=%d)",map,l-1,outlen); + else PRINTF(L_SYS_MAP,"auxsrv: bad length in map%02x response (got=%d,%d want=%d,%d)",map,l-4,len,outlen,l+8); } else PRINTF(L_SYS_MAP,"auxsrv: map%02x not successfull (unsupported?)",map); } @@ -95,22 +105,29 @@ bool cAuxSrv::Map(int map, unsigned char *data, int len, int outlen) } else PRINTF(L_SYS_MAP,"auxsrv: map%02x write failed",map); so.Disconnect(); - return false; + return -1; } -*/ +#endif //HAS_AUXSRV // -- cMap0101 ---------------------------------------------------------------- -#include "nagra2-map57.c" - class cMap0101 : public cMapCore { private: static const unsigned char primes[]; - unsigned char residues[53]; -// cAuxSrv aux; - cN2Map57 map57; + static const unsigned short coef22[][32]; + static const unsigned short msbtbl3e[]; + unsigned int cycles; +#ifdef HAS_AUXSRV + cAuxSrv aux; +#endif + // + void GenCRC16Table(void); + void MakePrime(BIGNUM *n, unsigned char *residues); protected: + unsigned short crc16table[256]; + // void DoMap(int f, unsigned char *data=0, int l=0); + unsigned int MapCycles() { return cycles; } public: cMap0101(void); }; @@ -122,43 +139,416 @@ const unsigned char cMap0101::primes[] = { 0xE5,0xE9,0xEF,0xF1,0xFB }; +const unsigned short cMap0101::coef22[256][32] = { + {0,1,1,0,1,0,1,1,0,11,10,11,10,10,11,10,11,21,22,22,21,22,21,22,22,32,33,32,33,33,32,33}, + {3,1,0,1,1,0,1,0,1,10,11,11,10,11,10,11,11,21,22,21,22,22,21,22,21,33,33,33,33,32,33,33}, + {5,1,0,1,1,0,1,0,1,10,11,11,10,11,10,11,11,21,22,21,22,22,21,22,21,33,33,33,33,32,33,33}, + {7,1,1,1,0,1,1,1,1,10,11,10,11,11,10,11,10,22,22,22,22,21,22,22,22,33,32,33,33,33,33,32}, + {9,1,1,1,0,1,1,1,1,10,11,10,11,11,10,11,10,22,22,22,22,21,22,22,22,33,32,33,33,33,33,32}, + {12,0,1,1,1,1,0,1,1,11,11,11,11,10,11,11,11,22,21,22,22,22,22,21,22,33,33,33,34,33,33,33}, + {14,0,1,1,1,1,0,1,1,11,11,11,11,10,11,11,11,22,21,22,22,22,22,21,22,33,33,33,34,33,33,33}, + {16,1,1,2,1,1,1,1,2,11,10,11,11,11,11,10,11,22,22,22,23,22,22,22,22,34,33,33,33,33,34,33}, + {0,1,1,2,1,1,1,1,2,11,10,11,11,11,11,10,11,22,22,22,23,22,22,22,22,34,33,33,33,33,34,33}, + {3,1,1,1,1,2,1,1,1,11,11,11,12,11,11,11,11,23,22,22,22,22,23,22,22,33,33,34,33,34,33,33}, + {5,1,1,1,1,2,1,1,1,11,11,11,12,11,11,11,11,23,22,22,22,22,23,22,22,33,33,34,33,34,33,33}, + {7,1,2,1,2,1,1,2,1,12,11,11,11,11,12,11,11,22,22,23,22,23,22,22,23,33,34,33,33,34,33,34}, + {9,1,2,1,2,1,1,2,1,12,11,11,11,11,12,11,11,22,22,23,22,23,22,22,23,33,34,33,33,34,33,34}, + {12,2,1,1,2,1,2,1,1,11,11,12,11,12,11,11,12,22,23,22,22,23,22,23,22,34,34,33,34,33,34,34}, + {14,2,1,1,2,1,2,1,1,11,11,12,11,12,11,11,12,22,23,22,22,23,22,23,22,34,34,33,34,33,34,34}, + {16,2,1,2,1,2,2,1,2,11,12,11,11,12,11,12,11,23,23,22,23,22,23,23,22,34,33,34,34,33,34,33}, + {0,2,1,2,1,2,2,1,2,11,12,11,11,12,11,12,11,23,23,22,23,22,23,23,22,34,33,34,34,33,34,33}, + {3,1,2,2,1,2,1,2,2,12,12,11,12,11,12,12,11,23,22,23,23,22,23,22,23,34,34,34,33,34,34,34}, + {5,1,2,2,1,2,1,2,2,12,12,11,12,11,12,12,11,23,22,23,23,22,23,22,23,34,34,34,33,34,34,34}, + {7,2,2,1,2,2,2,2,1,12,11,12,12,11,12,11,12,23,23,23,22,23,23,23,23,33,34,34,34,34,33,34}, + {9,2,2,1,2,2,2,2,1,12,11,12,12,11,12,11,12,23,23,23,22,23,23,23,23,33,34,34,34,34,33,34}, + {12,2,2,2,2,1,2,2,2,12,12,12,11,12,12,12,12,22,23,23,23,23,22,23,23,34,34,35,34,34,34,34}, + {14,2,2,2,2,1,2,2,2,12,12,12,11,12,12,12,12,22,23,23,23,23,22,23,23,34,34,35,34,34,34,34}, + {16,2,3,2,2,2,2,3,2,11,12,12,12,12,11,12,12,23,23,24,23,23,23,23,24,34,34,34,34,35,34,34}, + {0,2,3,2,2,2,2,3,2,11,12,12,12,12,11,12,12,23,23,24,23,23,23,23,24,34,34,34,34,35,34,34}, + {3,2,2,2,3,2,2,2,2,12,12,13,12,12,12,12,13,23,23,23,23,24,23,23,23,34,35,34,35,34,34,35}, + {5,2,2,2,3,2,2,2,2,12,12,13,12,12,12,12,13,23,23,23,23,24,23,23,23,34,35,34,35,34,34,35}, + {7,3,2,3,2,2,3,2,3,12,12,12,12,13,12,12,12,23,24,23,24,23,23,24,23,35,34,34,35,34,35,34}, + {9,3,2,3,2,2,3,2,3,12,12,12,12,13,12,12,12,23,24,23,24,23,23,24,23,35,34,34,35,34,35,34}, + {12,2,2,3,2,3,2,2,3,12,13,12,13,12,12,13,12,24,23,23,24,23,24,23,23,35,34,35,34,35,35,34}, + {14,2,2,3,2,3,2,2,3,12,13,12,13,12,12,13,12,24,23,23,24,23,24,23,23,35,34,35,34,35,35,34}, + {16,2,3,2,3,3,2,3,2,13,12,12,13,12,13,12,12,24,23,24,23,24,24,23,24,34,35,35,34,35,34,35}, + {0,2,3,2,3,3,2,3,2,13,12,12,13,12,13,12,12,24,23,24,23,24,24,23,24,34,35,35,34,35,34,35}, + {3,3,3,2,3,2,3,3,2,13,12,13,12,13,13,12,13,23,24,24,23,24,23,24,24,35,35,34,35,35,35,35}, + {5,3,3,2,3,2,3,3,2,13,12,13,12,13,13,12,13,23,24,24,23,24,23,24,24,35,35,34,35,35,35,35}, + {7,3,2,3,3,3,3,2,3,12,13,13,12,13,12,13,13,24,24,23,24,24,24,24,23,35,35,35,35,34,35,35}, + {9,3,2,3,3,3,3,2,3,12,13,13,12,13,12,13,13,24,24,23,24,24,24,24,23,35,35,35,35,34,35,35}, + {12,3,3,3,2,3,3,3,3,13,13,12,13,13,13,13,12,24,24,24,24,23,24,24,24,35,36,35,35,35,35,36}, + {14,3,3,3,2,3,3,3,3,13,13,12,13,13,13,13,12,24,24,24,24,23,24,24,24,35,36,35,35,35,35,36}, + {16,4,3,3,3,3,4,3,3,13,13,13,13,12,13,13,13,24,25,24,24,24,24,25,24,35,35,35,36,35,35,35}, + {0,4,3,3,3,3,4,3,3,13,13,13,13,12,13,13,13,24,25,24,24,24,24,25,24,35,35,35,36,35,35,35}, + {3,3,3,4,3,3,3,3,4,13,14,13,13,13,13,14,13,24,24,24,25,24,24,24,24,36,35,36,35,35,36,35}, + {5,3,3,4,3,3,3,3,4,13,14,13,13,13,13,14,13,24,24,24,25,24,24,24,24,36,35,36,35,35,36,35}, + {7,3,4,3,3,4,3,4,3,13,13,13,14,13,13,13,13,25,24,25,24,24,25,24,25,35,35,36,35,36,35,35}, + {9,3,4,3,3,4,3,4,3,13,13,13,14,13,13,13,13,25,24,25,24,24,25,24,25,35,35,36,35,36,35,35}, + {12,3,4,3,4,3,3,4,3,14,13,14,13,13,14,13,14,24,24,25,24,25,24,24,25,35,36,35,36,36,35,36}, + {14,3,4,3,4,3,3,4,3,14,13,14,13,13,14,13,14,24,24,25,24,25,24,24,25,35,36,35,36,36,35,36}, + {16,4,3,4,4,3,4,3,4,13,13,14,13,14,13,13,14,24,25,24,25,25,24,25,24,36,36,35,36,35,36,36}, + {0,4,3,4,4,3,4,3,4,13,13,14,13,14,13,13,14,24,25,24,25,25,24,25,24,36,36,35,36,35,36,36}, + {3,4,3,4,3,4,4,3,4,13,14,13,14,14,13,14,13,25,25,24,25,24,25,25,24,36,35,36,36,36,36,35}, + {5,4,3,4,3,4,4,3,4,13,14,13,14,14,13,14,13,25,25,24,25,24,25,25,24,36,35,36,36,36,36,35}, + {7,3,4,4,4,4,3,4,4,14,14,13,14,13,14,14,13,25,24,25,25,25,25,24,25,36,36,36,35,36,36,36}, + {9,3,4,4,4,4,3,4,4,14,14,13,14,13,14,14,13,25,24,25,25,25,25,24,25,36,36,36,35,36,36,36}, + {12,4,4,3,4,4,4,4,3,14,13,14,14,14,14,13,14,25,25,25,24,25,25,25,25,37,36,36,36,36,37,36}, + {14,4,4,3,4,4,4,4,3,14,13,14,14,14,14,13,14,25,25,25,24,25,25,25,25,37,36,36,36,36,37,36}, + {16,4,4,4,4,5,4,4,4,14,14,14,13,14,14,14,14,26,25,25,25,25,26,25,25,36,36,37,36,36,36,36}, + {0,4,4,4,4,5,4,4,4,14,14,14,13,14,14,14,14,26,25,25,25,25,26,25,25,36,36,37,36,36,36,36}, + {3,4,5,4,4,4,4,5,4,15,14,14,14,14,15,14,14,25,25,26,25,25,25,25,26,36,37,36,36,37,36,37}, + {5,4,5,4,4,4,4,5,4,15,14,14,14,14,15,14,14,25,25,26,25,25,25,25,37,36,37,36,36,37,36,37}, + {7,5,4,4,5,4,5,4,4,14,14,15,14,14,14,14,15,25,26,25,25,26,25,26,36,36,37,36,37,36,36,37}, + {9,5,4,4,5,4,5,4,4,14,14,15,14,14,14,14,26,25,26,25,25,26,25,26,36,36,37,36,37,36,36,37}, + {12,5,4,5,4,4,5,4,5,14,15,14,14,15,14,15,25,25,26,25,26,25,25,26,36,37,36,37,37,36,37,36}, + {14,5,4,5,4,4,5,4,15,14,15,14,14,15,14,15,25,25,26,25,26,25,25,26,36,37,36,37,37,36,37,36}, + {16,4,5,5,4,5,4,5,14,14,15,14,15,14,14,15,25,26,25,26,26,25,26,25,37,37,36,37,36,37,37,36}, + {40,4,5,5,4,5,4,5,14,14,15,14,15,14,14,15,25,26,25,26,26,25,26,25,37,37,36,37,36,37,37,36}, + {44,4,5,4,5,5,4,5,14,15,14,15,15,14,15,14,26,26,25,26,25,26,26,25,37,36,37,37,37,37,36,37}, + {44,4,5,4,5,5,4,5,14,15,14,15,15,14,15,14,26,26,25,26,25,26,26,25,37,36,37,37,37,37,36,37}, + {47,5,5,5,5,4,5,5,15,15,14,15,14,15,15,14,26,25,26,26,26,26,25,26,37,37,37,36,37,37,37,37}, + {47,5,5,5,5,4,5,5,15,15,14,15,14,15,15,14,26,25,26,26,26,26,25,26,37,37,37,36,37,37,37,37}, + {52,5,4,5,5,5,5,4,15,14,15,15,15,15,14,15,26,26,26,25,26,26,26,26,38,37,37,37,37,38,37,37}, + {52,5,4,5,5,5,5,4,15,14,15,15,15,15,14,15,26,26,26,25,26,26,26,26,38,37,37,37,37,38,37,37}, + {56,5,5,5,6,5,5,5,15,15,15,14,15,15,15,15,27,26,26,26,26,27,26,26,37,37,38,37,37,37,37,38}, + {56,5,5,5,6,5,5,5,15,15,15,14,15,15,15,15,27,26,26,26,26,27,26,26,37,37,38,37,37,37,37,38}, + {60,6,5,5,5,5,6,5,16,15,15,15,15,16,15,15,26,26,27,26,26,26,26,27,37,38,37,37,38,37,38,37}, + {60,6,5,5,5,5,6,5,16,15,15,15,15,16,15,15,26,26,27,26,26,26,26,27,37,38,37,37,38,37,38,37}, + {65,5,5,6,5,6,5,5,15,15,16,15,15,15,15,16,26,27,26,26,27,26,27,26,37,38,37,38,37,37,38,37}, + {65,5,5,6,5,6,5,5,15,15,16,15,15,15,15,16,26,27,26,26,27,26,27,26,37,38,37,38,37,37,38,37}, + {69,5,6,5,5,6,5,6,15,16,15,15,16,15,16,15,26,27,26,27,26,26,27,26,38,37,38,38,37,38,37,38}, + {69,5,6,5,5,6,5,6,15,16,15,15,16,15,16,15,26,27,26,27,26,26,27,26,38,37,38,38,37,38,37,38}, + {72,6,6,5,6,5,6,6,15,16,15,16,15,15,16,15,27,26,27,27,26,27,26,27,38,37,38,37,38,38,37,38}, + {72,6,6,5,6,5,6,6,15,16,15,16,15,15,16,15,27,26,27,27,26,27,26,27,38,37,38,37,38,38,37,38}, + {76,6,5,6,6,5,6,5,16,15,16,16,15,16,15,16,27,26,27,26,27,27,26,27,37,38,38,38,38,37,38,38}, + {76,6,5,6,6,5,6,5,16,15,16,16,15,16,15,16,27,26,27,26,27,27,26,27,37,38,38,38,38,37,38,38}, + {81,6,6,6,5,6,6,6,16,15,16,15,16,16,15,16,26,27,27,27,27,26,27,27,38,38,37,38,38,38,38,37}, + {81,6,6,6,5,6,6,6,16,15,16,15,16,16,15,16,26,27,27,27,27,26,27,27,38,38,37,38,38,38,38,37}, + {85,5,6,6,6,6,5,6,15,16,16,16,16,15,16,16,27,27,26,27,27,27,27,26,38,38,38,38,39,38,38,38}, + {85,5,6,6,6,6,5,6,15,16,16,16,16,15,16,16,27,27,26,27,27,27,27,26,38,38,38,38,39,38,38,38}, + {89,6,6,7,6,6,6,6,16,16,15,16,16,16,16,15,27,27,27,27,28,27,27,27,38,39,38,38,38,38,39,38}, + {89,6,6,7,6,6,6,6,16,16,15,16,16,16,16,15,27,27,27,27,28,27,27,27,38,39,38,38,38,38,39,38}, + {94,6,6,6,6,7,6,6,16,16,16,16,17,16,16,16,27,28,27,27,27,27,28,27,39,38,38,39,38,39,38,38}, + {94,6,6,6,6,7,6,6,16,16,16,16,17,16,16,16,27,28,27,27,27,27,28,27,39,38,38,39,38,39,38,38}, + {97,6,7,6,7,6,6,7,16,17,16,16,16,16,17,16,28,27,27,28,27,28,27,27,39,38,39,38,38,39,38,39}, + {97,6,7,6,7,6,6,7,16,17,16,16,16,16,17,16,28,27,27,28,27,28,27,27,39,38,39,38,38,39,38,39}, + {101,7,6,6,7,6,7,6,17,16,16,17,16,17,16,16,28,27,28,27,27,28,27,28,38,39,39,38,39,38,39,39}, + {101,7,6,6,7,6,7,6,17,16,16,17,16,17,16,16,28,27,28,27,27,28,27,28,38,39,39,38,39,38,39,39}, + {106,7,6,7,6,7,7,6,17,16,17,16,16,17,16,17,27,28,28,27,28,27,28,28,38,39,38,39,39,38,39,38}, + {106,7,6,7,6,7,7,6,17,16,17,16,16,17,16,17,27,28,28,27,28,27,28,28,38,39,38,39,39,38,39,38}, + {110,6,7,7,6,7,6,7,16,17,17,16,17,16,17,17,27,28,27,28,28,27,28,27,39,39,39,39,38,39,39,39}, + {110,6,7,7,6,7,6,7,16,17,17,16,17,16,17,17,27,28,27,28,28,27,28,27,39,39,39,39,38,39,39,39}, + {114,7,7,6,7,7,7,7,16,17,16,17,17,16,17,16,28,28,28,28,27,28,28,28,39,38,39,39,39,39,38,39}, + {114,7,7,6,7,7,7,7,16,17,16,17,17,16,17,16,28,28,28,28,27,28,28,28,39,38,39,39,39,39,38,39}, + {117,7,7,7,7,6,7,7,17,17,17,17,16,17,17,17,28,27,28,28,28,28,27,28,39,39,39,40,39,39,39,39}, + {117,7,7,7,7,6,7,7,17,17,17,17,16,17,17,17,28,27,28,28,28,28,27,28,39,39,39,40,39,39,39,39}, + {122,7,8,7,7,7,7,8,17,16,17,17,17,17,16,17,28,28,28,29,28,28,28,28,40,39,39,39,39,40,39,39}, + {122,7,8,7,7,7,7,8,17,16,17,17,17,17,16,17,28,28,28,29,28,28,28,28,40,39,39,39,39,40,39,39}, + {126,7,7,7,8,7,7,7,17,17,17,18,17,17,17,17,29,28,28,28,28,29,28,28,39,39,40,39,40,39,39,40}, + {126,7,7,7,8,7,7,7,17,17,17,18,17,17,17,17,29,28,28,28,28,29,28,28,39,39,40,39,40,39,39,40}, + {130,8,7,8,7,7,8,7,18,17,17,17,17,18,17,17,28,28,29,28,29,28,28,29,39,40,39,39,40,39,40,39}, + {130,8,7,8,7,7,8,7,18,17,17,17,17,18,17,17,28,28,29,28,29,28,28,29,39,40,39,39,40,39,40,39}, + {135,7,7,8,7,8,7,7,17,17,18,17,18,17,17,18,28,29,28,28,29,28,29,28,40,40,39,40,39,40,40,39}, + {135,7,7,8,7,8,7,7,17,17,18,17,18,17,17,18,28,29,28,28,29,28,29,28,40,40,39,40,39,40,40,39}, + {139,7,8,7,8,8,7,8,17,18,17,17,18,17,18,17,29,29,28,29,28,29,29,28,40,39,40,40,39,40,39,40}, + {139,7,8,7,8,8,7,8,17,18,17,17,18,17,18,17,29,29,28,29,28,29,29,28,40,39,40,40,39,40,39,40}, + {142,8,8,7,8,7,8,8,18,18,17,18,17,18,18,17,29,28,29,29,28,29,28,29,40,40,40,39,40,40,40,40}, + {142,8,8,7,8,7,8,8,18,18,17,18,17,18,18,17,29,28,29,29,28,29,28,29,40,40,40,39,40,40,40,40}, + {147,8,7,8,8,8,8,7,18,17,18,18,17,18,17,18,29,29,29,28,29,29,29,29,39,40,40,40,40,39,40,40}, + {147,8,7,8,8,8,8,7,18,17,18,18,17,18,17,18,29,29,29,28,29,29,29,29,39,40,40,40,40,39,40,40}, + {151,8,8,8,7,8,8,8,18,18,18,17,18,18,18,18,28,29,29,29,29,28,29,29,40,40,41,40,40,40,40,41}, + {151,8,8,8,7,8,8,8,18,18,18,17,18,18,18,18,28,29,29,29,29,28,29,29,40,40,41,40,40,40,40,41}, + {155,9,8,8,8,8,9,8,17,18,18,18,18,17,18,18,29,29,30,29,29,29,29,30,40,40,40,40,41,40,40,40}, + {155,9,8,8,8,8,9,8,17,18,18,18,18,17,18,18,29,29,30,29,29,29,29,30,40,40,40,40,41,40,40,40}, + {159,8,8,9,8,8,8,8,18,18,19,18,18,18,18,19,29,29,29,29,30,29,29,29,40,41,40,41,40,40,41,40}, + {159,8,8,9,8,8,8,8,18,18,19,18,18,18,18,19,29,29,29,29,30,29,29,29,40,41,40,41,40,40,41,40}, + {164,8,9,8,8,9,8,9,18,18,18,18,19,18,18,18,29,30,29,30,29,29,30,29,41,40,40,41,40,41,40,40}, + {164,8,9,8,8,9,8,9,18,18,18,18,19,18,18,18,29,30,29,30,29,29,30,29,41,40,40,41,40,41,40,40}, + {167,8,9,8,9,8,8,9,18,19,18,19,18,18,19,18,30,29,29,30,29,30,29,29,41,40,41,40,41,41,40,41}, + {167,8,9,8,9,8,8,9,18,19,18,19,18,18,19,18,30,29,29,30,29,30,29,29,41,40,41,40,41,41,40,41}, + {171,9,8,9,9,8,9,8,19,18,18,19,18,19,18,18,30,29,30,29,30,30,29,30,40,41,41,40,41,40,41,41}, + {171,9,8,9,9,8,9,8,19,18,18,19,18,19,18,18,30,29,30,29,30,30,29,30,40,41,41,40,41,40,41,41}, + {176,9,8,9,8,9,9,8,19,18,19,18,19,19,18,19,29,30,30,29,30,29,30,30,41,41,40,41,41,41,41,40}, + {176,9,8,9,8,9,9,8,19,18,19,18,19,19,18,19,29,30,30,29,30,29,30,30,41,41,40,41,41,41,41,40}, + {180,8,9,9,9,9,8,9,18,19,19,18,19,18,19,19,30,30,29,30,30,30,30,29,41,41,41,41,40,41,41,41}, + {180,8,9,9,9,9,8,9,18,19,19,18,19,18,19,19,30,30,29,30,30,30,30,29,41,41,41,41,40,41,41,41}, + {184,9,9,8,9,9,9,9,19,19,18,19,19,19,19,18,30,30,30,30,29,30,30,30,41,42,41,41,41,41,42,41}, + {184,9,9,8,9,9,9,9,19,19,18,19,19,19,19,18,30,30,30,30,29,30,30,30,41,42,41,41,41,41,42,41}, + {189,9,9,9,9,10,9,9,19,19,19,19,18,19,19,19,30,31,30,30,30,30,31,30,41,41,41,42,41,41,41,41}, + {189,9,9,9,9,10,9,9,19,19,19,19,18,19,19,19,30,31,30,30,30,30,31,30,41,41,41,42,41,41,41,41}, + {192,9,10,9,9,9,9,10,19,20,19,19,19,19,20,19,30,30,30,31,30,30,30,30,42,41,42,41,41,42,41,42}, + {192,9,10,9,9,9,9,10,19,20,19,19,19,19,20,19,30,30,30,31,30,30,30,30,42,41,42,41,41,42,41,42}, + {196,10,9,9,10,9,10,9,19,19,19,20,19,19,19,19,31,30,31,30,30,31,30,31,41,41,42,41,42,41,41,42}, + {196,10,9,9,10,9,10,9,19,19,19,20,19,19,19,19,31,30,31,30,30,31,30,31,41,41,42,41,42,41,41,42}, + {200,10,9,10,9,9,10,9,20,19,20,19,19,20,19,20,30,30,31,30,31,30,30,31,41,42,41,42,42,41,42,41}, + {200,10,9,10,9,9,10,9,20,19,20,19,19,20,19,20,30,30,31,30,31,30,30,31,41,42,41,42,42,41,42,41}, + {205,9,10,10,9,10,9,10,19,19,20,19,20,19,19,20,30,31,30,31,31,30,31,30,42,42,41,42,41,42,42,41}, + {205,9,10,10,9,10,9,10,19,19,20,19,20,19,19,20,30,31,30,31,31,30,31,30,42,42,41,42,41,42,42,41}, + {209,9,10,9,10,10,9,10,19,20,19,20,20,19,20,19,31,31,30,31,30,31,31,30,42,41,42,42,42,42,41,42}, + {209,9,10,9,10,10,9,10,19,20,19,20,20,19,20,19,31,31,30,31,30,31,31,30,42,41,42,42,42,42,41,42}, + {212,10,10,10,10,9,10,10,20,20,19,20,19,20,20,19,31,30,31,31,31,31,30,31,42,42,42,41,42,42,42,42}, + {212,10,10,10,10,9,10,10,20,20,19,20,19,20,20,19,31,30,31,31,31,31,30,31,42,42,42,41,42,42,42,42}, + {217,10,9,10,10,10,10,9,20,19,20,20,20,20,19,20,31,31,31,30,31,31,31,31,43,42,42,42,42,43,42,42}, + {217,10,9,10,10,10,10,9,20,19,20,20,20,20,19,20,31,31,31,30,31,31,31,31,43,42,42,42,42,43,42,42}, + {221,10,10,10,11,10,10,10,20,20,20,19,20,20,20,20,32,31,31,31,31,32,31,31,42,42,43,42,42,42,42,43}, + {221,10,10,10,11,10,10,10,20,20,20,19,20,20,20,20,32,31,31,31,31,32,31,31,42,42,43,42,42,42,42,43}, + {225,11,10,10,10,10,11,10,21,20,20,20,20,21,20,20,31,31,32,31,31,31,31,32,42,43,42,42,43,42,43,42}, + {225,11,10,10,10,10,11,10,21,20,20,20,20,21,20,20,31,31,32,31,31,31,31,32,42,43,42,42,43,42,43,42}, + {230,10,10,11,10,11,10,10,20,20,21,20,20,20,20,21,31,32,31,31,32,31,32,31,42,43,42,43,42,42,43,42}, + {230,10,10,11,10,11,10,10,20,20,21,20,20,20,20,21,31,32,31,31,32,31,32,31,42,43,42,43,42,42,43,42}, + {234,10,11,10,10,11,10,11,20,21,20,20,21,20,21,20,31,32,31,32,31,31,32,31,43,42,43,43,42,43,42,43}, + {234,10,11,10,10,11,10,11,20,21,20,20,21,20,21,20,31,32,31,32,31,31,32,31,43,42,43,43,42,43,42,43}, + {237,11,11,10,11,10,11,11,20,21,20,21,20,20,21,20,32,31,32,32,31,32,31,32,43,42,43,42,43,43,42,43}, + {237,11,11,10,11,10,11,11,20,21,20,21,20,20,21,20,32,31,32,32,31,32,31,32,43,42,43,42,43,43,42,43}, + {241,11,10,11,11,10,11,10,21,20,21,21,20,21,20,21,32,31,32,31,32,32,31,32,42,43,43,43,43,42,43,43}, + {241,11,10,11,11,10,11,10,21,20,21,21,20,21,20,21,32,31,32,31,32,32,31,32,42,43,43,43,43,42,43,43}, + {246,11,11,11,10,11,11,11,21,20,21,20,21,21,20,21,31,32,32,32,32,31,32,32,43,43,42,43,43,43,43,42}, + {246,11,11,11,10,11,11,11,21,20,21,20,21,21,20,21,31,32,32,32,32,31,32,32,43,43,42,43,43,43,43,42}, + {250,10,11,11,11,11,10,11,20,21,21,21,21,20,21,21,32,32,31,32,32,32,32,31,43,43,43,43,44,43,43,43}, + {250,10,11,11,11,11,10,11,20,21,21,21,21,20,21,21,32,32,31,32,32,32,32,31,43,43,43,43,44,43,43,43}, + {254,11,11,12,11,11,11,11,21,21,20,21,21,21,21,20,32,32,32,32,33,32,32,32,43,44,43,43,43,43,44,43}, + {254,11,11,12,11,11,11,11,21,21,20,21,21,21,21,20,32,32,32,32,33,32,32,32,43,44,43,43,43,43,44,43}, + {259,11,11,11,11,12,11,11,21,21,21,21,22,21,21,21,32,33,32,32,32,32,33,32,44,43,43,44,43,44,43,43}, + {259,11,11,11,11,12,11,11,21,21,21,21,22,21,21,21,32,33,32,32,32,32,33,32,44,43,43,44,43,44,43,43}, + {262,11,12,11,12,11,11,12,21,22,21,21,21,21,22,21,33,32,32,33,32,33,32,32,44,43,44,43,43,44,43,44}, + {262,11,12,11,12,11,11,12,21,22,21,21,21,21,22,21,33,32,32,33,32,33,32,32,44,43,44,43,43,44,43,44}, + {266,12,11,11,12,11,12,11,22,21,21,22,21,22,21,21,33,32,33,32,32,33,32,33,43,44,44,43,44,43,44,44}, + {266,12,11,11,12,11,12,11,22,21,21,22,21,22,21,21,33,32,33,32,32,33,32,33,43,44,44,43,44,43,44,44}, + {271,12,11,12,11,12,12,11,22,21,22,21,21,22,21,22,32,33,33,32,33,32,33,33,43,44,43,44,44,43,44,43}, + {271,12,11,12,11,12,12,11,22,21,22,21,21,22,21,22,32,33,33,32,33,32,33,33,43,44,43,44,44,43,44,43}, + {275,11,12,12,11,12,11,12,21,22,22,21,22,21,22,22,32,33,32,33,33,32,33,32,44,44,44,44,43,44,44,44}, + {275,11,12,12,11,12,11,12,21,22,22,21,22,21,22,22,32,33,32,33,33,32,33,32,44,44,44,44,43,44,44,44}, + {279,12,12,11,12,12,12,12,21,22,21,22,22,21,22,21,33,33,33,33,32,33,33,33,44,43,44,44,44,44,43,44}, + {279,12,12,11,12,12,12,12,21,22,21,22,22,21,22,21,33,33,33,33,32,33,33,33,44,43,44,44,44,44,43,44}, + {282,12,12,12,12,11,12,12,22,22,22,22,21,22,22,22,33,32,33,33,33,33,32,33,44,44,44,45,44,44,44,44}, + {282,12,12,12,12,11,12,12,22,22,22,22,21,22,22,22,33,32,33,33,33,33,32,33,44,44,44,45,44,44,44,44}, + {287,12,13,12,12,12,12,13,22,21,22,22,22,22,21,22,33,33,33,34,33,33,33,33,45,44,44,44,44,45,44,44}, + {287,12,13,12,12,12,12,13,22,21,22,22,22,22,21,22,33,33,33,34,33,33,33,33,45,44,44,44,44,45,44,44}, + {291,12,12,12,13,12,12,12,22,22,22,23,22,22,22,22,34,33,33,33,33,34,33,33,44,44,45,44,45,44,44,45}, + {291,12,12,12,13,12,12,12,22,22,22,23,22,22,22,22,34,33,33,33,33,34,33,33,44,44,45,44,45,44,44,45}, + {295,13,12,13,12,12,13,12,23,22,22,22,22,23,22,22,33,33,34,33,34,33,33,34,44,45,44,44,45,44,45,44}, + {295,13,12,13,12,12,13,12,23,22,22,22,22,23,22,22,33,33,34,33,34,33,33,34,44,45,44,44,45,44,45,44}, + {300,12,12,13,12,13,12,12,22,22,23,22,23,22,22,23,33,34,33,33,34,33,34,33,45,45,44,45,44,45,45,44}, + {300,12,12,13,12,13,12,12,22,22,23,22,23,22,22,23,33,34,33,33,34,33,34,33,45,45,44,45,44,45,45,44}, + {304,12,13,12,13,13,12,13,22,23,22,22,23,22,23,22,34,34,33,34,33,34,34,33,45,44,45,45,44,45,44,45}, + {304,12,13,12,13,13,12,13,22,23,22,22,23,22,23,22,34,34,33,34,33,34,34,33,45,44,45,45,44,45,44,45}, + {307,13,13,12,13,12,13,13,23,23,22,23,22,23,23,22,34,33,34,34,33,34,33,34,45,45,45,44,45,45,45,45}, + {307,13,13,12,13,12,13,13,23,23,22,23,22,23,23,22,34,33,34,34,33,34,33,34,45,45,45,44,45,45,45,45}, + {312,13,12,13,13,13,13,12,23,22,23,23,22,23,22,23,34,34,34,33,34,34,34,34,44,45,45,45,45,44,45,45}, + {312,13,12,13,13,13,13,12,23,22,23,23,22,23,22,23,34,34,34,33,34,34,34,34,44,45,45,45,45,44,45,45}, + {316,13,13,13,12,13,13,13,23,23,23,22,23,23,23,23,33,34,34,34,34,33,34,34,45,45,46,45,45,45,45,46}, + {316,13,13,13,12,13,13,13,23,23,23,22,23,23,23,23,33,34,34,34,34,33,34,34,45,45,46,45,45,45,45,46}, + {320,14,13,13,13,13,14,13,22,23,23,23,23,22,23,23,34,34,35,34,34,34,34,35,45,45,45,45,46,45,45,45}, + {320,14,13,13,13,13,14,13,22,23,23,23,23,22,23,23,34,34,35,34,34,34,34,35,45,45,45,45,46,45,45,45}, + {324,13,13,14,13,13,13,13,23,23,24,23,23,23,23,24,34,34,34,34,35,34,34,34,45,46,45,46,45,45,46,45}, + {324,13,13,14,13,13,13,13,23,23,24,23,23,23,23,24,34,34,34,34,35,34,34,34,45,46,45,46,45,45,46,45}, + {329,13,14,13,13,14,13,14,23,23,23,23,24,23,23,23,34,35,34,35,34,34,35,34,46,45,45,46,45,46,45,45}, + {329,13,14,13,13,14,13,14,23,23,23,23,24,23,23,23,34,35,34,35,34,34,35,34,46,45,45,46,45,46,45,45}, + {332,13,14,13,14,13,13,14,23,24,23,24,23,23,24,23,35,34,34,35,34,35,34,34,46,45,46,45,46,46,45,46}, + {332,13,14,13,14,13,13,14,23,24,23,24,23,23,24,23,35,34,34,35,34,35,34,34,46,45,46,45,46,46,45,46}, + {336,14,13,14,14,13,14,13,24,23,23,24,23,24,23,23,35,34,35,34,35,35,34,35,45,46,46,45,46,45,46,46}, + {336,14,13,14,14,13,14,13,24,23,23,24,23,24,23,23,35,34,35,34,35,35,34,35,45,46,46,45,46,45,46,46}, + {341,14,13,14,13,14,14,13,24,23,24,23,24,24,23,24,34,35,35,34,35,34,35,35,46,46,45,46,46,46,46,45}, + {341,14,13,14,13,14,14,13,24,23,24,23,24,24,23,24,34,35,35,34,35,34,35,35,46,46,45,46,46,46,46,45}, + {345,13,14,14,14,14,13,14,23,24,24,23,24,23,24,24,35,35,34,35,35,35,35,34,46,46,46,46,45,46,46,46}, + {345,13,14,14,14,14,13,14,23,24,24,23,24,23,24,24,35,35,34,35,35,35,35,34,46,46,46,46,45,46,46,46}, + {349,14,14,13,14,14,14,14,24,24,23,24,24,24,24,23,35,35,35,35,34,35,35,35,46,47,46,46,46,46,47,46}, + {349,14,14,13,14,14,14,14,24,24,23,24,24,24,24,23,35,35,35,35,34,35,35,35,46,47,46,46,46,46,47,46}, + {354,14,14,14,14,15,14,14,24,24,24,24,23,24,24,24,35,36,35,35,35,35,36,35,46,46,46,47,46,46,46,46}, + {354,14,14,14,14,15,14,14,24,24,24,24,23,24,24,24,35,36,35,35,35,35,36,35,46,46,46,47,46,46,46,46}, + {357,14,15,14,14,14,14,15,24,25,24,24,24,24,25,24,35,35,35,36,35,35,35,35,47,46,47,46,46,47,46,47}, + {357,14,15,14,14,14,14,15,24,25,24,24,24,24,25,24,35,35,35,36,35,35,35,35,47,46,47,46,46,47,46,47}, + {361,15,14,14,15,14,15,14,24,24,24,25,24,24,24,24,36,35,36,35,35,36,35,36,46,46,47,46,47,46,46,47}, + {361,15,14,14,15,14,15,14,24,24,24,25,24,24,24,24,36,35,36,35,35,36,35,36,46,46,47,46,47,46,46,47}, + {365,15,14,15,14,14,15,14,25,24,25,24,24,25,24,25,35,35,36,35,36,35,35,36,46,47,46,47,47,46,47,46}, + {365,15,14,15,14,14,15,14,25,24,25,24,24,25,24,25,35,35,36,35,36,35,35,36,46,47,46,47,47,46,47,46}, + {370,14,15,15,14,15,14,15,24,24,25,24,25,24,24,25,35,36,35,36,36,35,36,35,47,47,46,47,46,47,47,46}, + {370,14,15,15,14,15,14,15,24,24,25,24,25,24,24,25,35,36,35,36,36,35,36,35,47,47,46,47,46,47,47,46}, + {374,14,15,14,15,15,14,15,24,25,24,25,25,24,25,24,36,36,35,36,35,36,36,35,47,46,47,47,47,47,46,47}, + {374,14,15,14,15,15,14,15,24,25,24,25,25,24,25,24,36,36,35,36,35,36,36,35,47,46,47,47,47,47,46,47}, + {377,15,15,15,15,14,15,15,25,25,24,25,24,25,25,24,36,35,36,36,36,36,35,36,47,47,47,46,47,47,47,47}, + {377,15,15,15,15,14,15,15,25,25,24,25,24,25,25,24,36,35,36,36,36,36,35,36,47,47,47,46,47,47,47,47}, + {382,15,14,15,15,15,15,14,25,24,25,25,25,25,24,25,36,36,36,35,36,36,36,36,48,47,47,47,47,48,47,47}, + {382,15,14,15,15,15,15,14,25,24,25,25,25,25,24,25,36,36,36,35,36,36,36,36,48,47,47,47,47,48,47,47}, + {386,15,15,15,16,15,15,15,25,25,25,24,25,25,25,25,37,36,36,36,36,37,36,36,47,47,48,47,47,47,47,48}, + {386,15,15,15,16,15,15,15,25,25,25,24,25,25,25,25,37,36,36,36,36,37,36,36,47,47,48,47,47,47,47,48}, + {390,16,15,15,15,15,16,15,26,25,25,25,25,26,25,25,36,36,37,36,36,36,36,37,47,48,47,47,48,47,48,47}, + {390,16,15,15,15,15,16,15,26,25,25,25,25,26,25,25,36,36,37,36,36,36,36,37,47,48,47,47,48,47,48,47}, + {395,15,15,16,15,16,15,15,25,25,26,25,25,25,25,26,36,37,36,36,37,36,37,36,47,48,47,48,47,47,48,47}, + {395,15,15,16,15,16,15,15,25,25,26,25,25,25,25,26,36,37,36,36,37,36,37,36,47,48,47,48,47,47,48,47}, + {399,15,16,15,15,16,15,16,25,26,25,25,26,25,26,25,36,37,36,37,36,36,37,36,48,47,48,48,47,48,47,48}, + {399,15,16,15,15,16,15,16,25,26,25,25,26,25,26,25,36,37,36,37,36,36,37,36,48,47,48,48,47,48,47,48}, + {402,16,16,15,16,15,16,16,25,26,25,26,25,25,26,25,37,36,37,37,36,37,36,37,48,47,48,47,48,48,47,48}, + {402,16,16,15,16,15,16,16,25,26,25,26,25,25,26,25,37,36,37,37,36,37,36,37,48,47,48,47,48,48,47,48}, + {406,16,15,16,16,15,16,15,26,25,26,26,25,26,25,26,37,36,37,36,37,37,36,37,47,48,48,48,48,47,48,48}, + {406,16,15,16,16,15,16,15,26,25,26,26,25,26,25,26,37,36,37,36,37,37,36,37,47,48,48,48,48,47,48,48}, + {411,16,16,16,15,16,16,16,26,25,26,25,26,26,25,26,36,37,37,37,37,36,37,37,48,48,47,48,48,48,48,47}, + {411,16,16,16,15,16,16,16,26,25,26,25,26,26,25,26,36,37,37,37,37,36,37,37,48,48,47,48,48,48,48,47}, + {415,15,16,16,16,16,15,16,25,26,26,26,26,25,26,26,37,37,36,37,37,37,37,36,48,48,48,48,49,48,48,48}, + {415,15,16,16,16,16,15,16,25,26,26,26,26,25,26,26,37,37,36,37,37,37,37,36,48,48,48,48,49,48,48,48}, + {419,16,16,17,16,16,16,16,26,26,25,26,26,26,26,25,37,37,37,37,38,37,37,37,48,49,48,48,48,48,49,48}, + {419,16,16,17,16,16,16,16,26,26,25,26,26,26,26,25,37,37,37,37,38,37,37,37,48,49,48,48,48,48,49,48}, + {424,16,16,16,16,17,16,16,26,26,26,26,27,26,26,26,37,38,37,37,37,37,38,37,49,48,48,49,48,49,48,48}, + {424,16,16,16,16,17,16,16,26,26,26,26,27,26,26,26,37,38,37,37,37,37,38,37,49,48,48,49,48,49,48,48}, + {427,16,17,16,17,16,16,17,26,27,26,26,26,26,27,26,38,37,37,38,37,38,37,37,49,48,49,48,48,49,48,49}, + {427,16,17,16,17,16,16,17,26,27,26,26,26,26,27,26,38,37,37,38,37,38,37,37,49,48,49,48,48,49,48,49}, + {431,17,16,16,17,16,17,16,27,26,26,27,26,27,26,26,38,37,38,37,37,38,37,38,48,49,49,48,49,48,49,49}, + {431,17,16,16,17,16,17,16,27,26,26,27,26,27,26,26,38,37,38,37,37,38,37,38,48,49,49,48,49,48,49,49}, + {436,17,16,17,16,17,17,16,27,26,27,26,26,27,26,27,37,38,38,37,38,37,38,38,48,49,48,49,49,48,49,48}, + }; + +const unsigned short cMap0101::msbtbl3e[] = { +// 0 1 2 3 4 5 6 7 8 9 a b c d e f +/*0*/ 0, 88, 148, 236, 224, 312, 312, 400, 302, 390, 390, 476, 390, 476, 476, 566, +/*1*/ 378, 466, 466, 554, 466, 554, 554, 642, 466, 554, 554, 642, 554, 642, 642, 730, +/*2*/ 448, 536, 536, 624, 536, 624, 624, 712, 536, 624, 624, 712, 624, 712, 712, 796, +/*3*/ 536, 624, 624, 712, 624, 712, 712, 796, 624, 712, 712, 796, 712, 796, 796, 884, +/*4*/ 524, 612, 612, 700, 612, 700, 700, 790, 612, 700, 700, 790, 700, 790, 790, 878, +/*5*/ 612, 700, 700, 790, 700, 790, 790, 878, 700, 790, 790, 878, 790, 878, 878, 966, +/*6*/ 612, 700, 700, 790, 700, 790, 790, 878, 700, 790, 790, 878, 790, 878, 878, 966, +/*7*/ 700, 790, 790, 878, 790, 878, 878, 966, 790, 878, 878, 966, 878, 966, 966,1054, +/*8*/ 602, 690, 690, 778, 690, 778, 778, 862, 690, 778, 778, 862, 778, 862, 862, 950, +/*9*/ 690, 778, 778, 862, 778, 862, 862, 950, 778, 862, 862, 950, 862, 950, 950,1038, +/*a*/ 690, 778, 778, 862, 778, 862, 862, 950, 778, 862, 862, 950, 862, 950, 950,1038, +/*b*/ 778, 862, 862, 950, 862, 950, 950,1038, 862, 950, 950,1038, 950,1038,1038,1126, +/*c*/ 690, 778, 778, 862, 778, 862, 862, 950, 778, 862, 862, 950, 862, 950, 950,1038, +/*d*/ 778, 862, 862, 950, 862, 950, 950,1038, 862, 950, 950,1038, 950,1038,1038,1126, +/*e*/ 778, 862, 862, 950, 862, 950, 950,1038, 862, 950, 950,1038, 950,1038,1038,1126, +/*f*/ 862, 950, 950,1038, 950,1038,1038,1126, 950,1038,1038,1126,1038,1126,1126,1214 + }; + cMap0101::cMap0101(void) { + GenCRC16Table(); +} + +void cMap0101::GenCRC16Table(void) +{ + unsigned char hi[256]; + for(int i=0; i<256; ++i) { + unsigned short c = i; + for(int j=0; j<8; ++j) c = (c>>1) ^ ((c&1) ? 0x8408 : 0); // ccitt poly + crc16table[0xff-i] = c & 0xff; + hi[i] = c>>8; + } + for(int i=0; i<32; ++i) + for(int j=0; j<8; ++j) + crc16table[i*8+j] |= hi[(0x87+(i*8)-j)&0xff]<<8; +} + +void cMap0101::MakePrime(BIGNUM *n, unsigned char *residues) +{ + bool isPrime; + cycles+=1290; + do { + cycles+=1465; + BN_add_word(n,2); + isPrime=true; + for(int i=0; i<53; i++) { + residues[i]+=2; + unsigned char num=residues[i]; + unsigned char denom=primes[i]; + if(num>denom) { + unsigned char r=0; + while(denom>=r) { cycles+=1; r=(r<<1)|((num&0x80)>>7); num<<=1; } + } + residues[i]%=primes[i]; + if(residues[i]==0) { cycles+=13; isPrime=false; } + } + } while(!isPrime); } void cMap0101::DoMap(int f, unsigned char *data, int l) { PRINTF(L_SYS_MAP,"0101: calling function %02X",f); + cycles=0; switch(f) { + case 0x22: + { + int shift=((-l)&0xFF00)>>8, exp=(-l)&0x1F; + BN_zero(B); + BN_set_bit(B,wordsize<<6); + BN_sub(B,B,D); + BN_set_word(I,exp*2); + BN_mod_exp(B,B,I,D,ctx); + BN_mod_lshift(B,B,shift,D,ctx); + if(exp) cycles=559 + 2112*exp + 16*((shift+1)>>1) + 4*coef22[shift][exp] - 6; + else cycles=931 + 4*coef22[shift][0] - 6; + break; + } case 0x3b: - MakeJ(); - BN_zero(R); - BN_set_bit(R,132); // or 66*wordsize ? - BN_mod(H,R,D,ctx); - for(int i=0; i<4; i++) MonMul(H,H,H); - MonMul(B,A,H); + MonInit(132); // or 66*wordsize ? + MonMul(B,A,B); + break; + case 0x3e: + { + I.GetLE(data,(l?l:wordsize)<<3); + BN_mod_exp(B,A,I,D,ctx); + BN_one(A); + int end=(BN_num_bits(I)-1)/8; + cycles=3848 + end*650 + msbtbl3e[data[end]] - 13; + for(int i=end*8; --i>=0;) if(BN_is_bit_set(I,i)) cycles+=88; break; + } case 0x4d: - for(int i=0; i<53; i++) residues[i]=BN_mod_word(A,primes[i]); + if(-0x018000==l) + //for(int i=64; i<(wordsize<<6); i++) BN_clear_bit(B,i); + BN_mask_bits(B,64); + else { + BN_set_bit(B,(wordsize<<6)-1); + if(-0x028000==l) BN_set_bit(B,(wordsize<<6)-2); + } + BN_set_bit(B,0); + for(int i=0; i<53; i++) data[i]=BN_mod_word(B,primes[i]); break; case 0x4e: + MakePrime(B,data); + break; + case 0x57: { - bool isPrime; - do { - BN_add_word(A,2); - isPrime=true; - for(int i=0; i<53; i++) { - residues[i]+=2; - residues[i]%=primes[i]; - if(residues[i]==0) isPrime=false; + cBN a, b, x, y, scalar; + D.GetLE(data+0x60,16); + x.GetLE(data+0x00,16); + y.GetLE(data+0x30,16); + b.GetLE(data+0x10,16); + a.GetLE(data+0x70,16); + scalar.GetLE(data+0x50,16); + int scalarbits=BN_num_bits(scalar); + if(scalarbits>=2 && !BN_is_zero(x) && !BN_is_zero(y) && !BN_is_zero(b)) { + CurveInit(a); + ToProjective(0,x,y); + BN_copy(Qx,Px); + BN_copy(Qy,Py); + for(int i=scalarbits-2; i>=0; i--) { + DoubleP(0); + if(BN_is_bit_set(scalar,i)) { + BN_copy(A,Pz); + if(BN_is_zero(Pz)) { + BN_copy(Px,Qx); + BN_copy(Py,Qy); + BN_copy(Pz,Qz); + AddP(1); + } + else { + BN_mask_bits(Px,32); + BN_lshift(b,Qz,32); + BN_add(Px,Px,b); + BN_mask_bits(Px,128); + AddP(0); + } + } } - } while(!isPrime); + ToAffine(); + } + memset(data+0x20,0,64); + Px.PutLE(&data[0x20],16); + unsigned char tmp[16]; + Qz.PutLE(tmp,16); + memcpy(&data[0x30],&tmp[0x0C],4); + Py.PutLE(&data[0x40],16); break; } - case 0x57: - map57.Map57(data); - //aux.Map(0x57,data,l,l); - break; default: if(!cMapCore::DoMap(f,data,l)) PRINTF(L_SYS_MAP,"0101: unsupported call %02x",f); @@ -166,36 +556,191 @@ void cMap0101::DoMap(int f, unsigned char *data, int l) } } +// -- cN2Timer ----------------------------------------------------------------- + +enum { tmCONTINUOUS=0x01, tmRUNNING=0x02, tmLATCHED=0x04 }; + +class cN2Timer { +private: + int ctrl, divisor, cycles, remainder; + unsigned int latch; +public: + cN2Timer(void); + void AddCycles(int count); + unsigned int GetCycles(void) { return (unsigned int)cycles; } + void SetLatch(int val); + void Stop(void); + void Start(int mode, int div); + bool Running(void) { return ctrl&tmRUNNING; } + }; + +cN2Timer::cN2Timer(void) +{ + cycles=0; ctrl=0; divisor=1; remainder=-1; latch=0xFF; +} + +void cN2Timer::AddCycles(int count) +{ + remainder+=count; + if(remainder>=divisor) { + cycles-=remainder/divisor; + remainder%=divisor; + } + if(ctrl&tmCONTINUOUS) { + while(cycles<0) cycles+=latch+1; + } + else if(cycles<0 || (cycles==0 && remainder>=4)) { + cycles=0; + Stop(); + } +} + +void cN2Timer::SetLatch(int val) +{ + val&=0xFF; if(val==0) val=0x100; + latch=val; cycles=val; remainder=0; + ctrl|=tmLATCHED; +} + +void cN2Timer::Start(int mode, int div) +{ + ctrl=(ctrl&~tmCONTINUOUS) | (mode&tmCONTINUOUS) | tmRUNNING; + divisor=div; + if(!(ctrl&tmLATCHED)) cycles=(unsigned int)(cycles-1)&0xFF; + remainder=-1; + if(!mode && cycles==0) ctrl&=~tmRUNNING; +} + +void cN2Timer::Stop(void) +{ + ctrl&=~(tmRUNNING|tmLATCHED); +} + // -- cN2Prov0101 ---------------------------------------------------------------- +#define MAX_TIMERS 3 +#define TIMER_NUM(x) (((x)>>2)&3) // timer order doesn't match HW order + class cN2Prov0101 : public cN2Prov, public cN2Emu, private cMap0101 { private: - bool special05; + int desSize; + DES_key_schedule desks1, desks2; + unsigned char desblock[8]; + IdeaKS ks; + // memory mapped HW + enum { + HW_IO=0x00, HW_SECURITY, + HW_TIMER0_DATA=0x08, HW_TIMER0_LATCH, HW_TIMER0_CONTROL, + HW_CRC_CONTROL=0x0e, HW_CRC_DATA, + HW_TIMER1_DATA=0x10, HW_TIMER1_LATCH, HW_TIMER1_CONTROL, + HW_TIMER2_DATA=0x14, HW_TIMER2_LATCH, HW_TIMER2_CONTROL + }; + cN2Timer timer[MAX_TIMERS]; + enum { CRCCALC_DELAY=9, CRC_BUSY=1, CRC_DISABLED=2 }; + unsigned short CRCvalue; + unsigned char CRCpos; + unsigned int CRCstarttime; + // + void AddRomCallbacks(void); + bool RomCallbacks(void); + bool ProcessMap(int f); + bool ProcessDESMap(int f); protected: - int hwCount; + int mecmAddr[2]; + int mecmKeyId; // - virtual bool Algo(int algo, const unsigned char *hd, unsigned char *hw); + virtual bool Algo(int algo, unsigned char *hd, const unsigned char *ed, unsigned char *hw); + virtual bool RomInit(void); virtual void Stepper(void); virtual void WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op); virtual void ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op); + virtual void TimerHandler(unsigned int num); public: cN2Prov0101(int Id, int Flags); + virtual bool PostProcAU(int id, unsigned char *data); virtual int ProcessBx(unsigned char *data, int len, int pos); + virtual int ProcessEx(unsigned char *data, int len, int pos); }; -static cN2ProvLinkReg staticPL0101; +static cN2ProvLinkReg staticPL0101; cN2Prov0101::cN2Prov0101(int Id, int Flags) :cN2Prov(Id,Flags) { hasWriteHandler=hasReadHandler=true; - special05=false; - hwCount=4; + mecmAddr[0]=0x91d7; mecmAddr[1]=0x92d7; mecmKeyId=0x106; + seedSize=10; + + desSize=16; + CRCvalue=0; CRCpos=0; CRCstarttime=0; } -bool cN2Prov0101::Algo(int algo, const unsigned char *hd, unsigned char *hw) +bool cN2Prov0101::Algo(int algo, unsigned char *hd, const unsigned char *ed, unsigned char *hw) { + if(algo!=0x40 && algo!=0x60) { + PRINTF(L_SYS_ECM,"%04X: unknown MECM algo %02x",id,algo); + return false; + } + if(!Init(id,102)) { + PRINTF(L_SYS_ECM,"%04X: failed to initialize ROM",id); + return false; + } + + unsigned char keyNr=(algo>>5)&0x01; + unsigned char mecmCode[256]; + GetMem(mecmAddr[keyNr],mecmCode,256,0x80); + cPlainKey *pk; + unsigned char ideaKey[16]; + if(!(pk=keys.FindKey('N',mecmKeyId,keyNr,sizeof(ideaKey)))) { + PRINTF(L_SYS_KEY,"missing %04x %02x MECM key",mecmKeyId,keyNr); + return false; + } + pk->Get(ideaKey); + idea.SetEncKey(ideaKey,&ks); + for(int i=0x100-8; i>=8; i-=8) { + idea.Encrypt(mecmCode+i,8,mecmCode+i,&ks,0); + xxor(mecmCode+i,8,mecmCode+i,mecmCode+i-8); + } + idea.Encrypt(mecmCode,8,mecmCode,&ks,0); + HEXDUMP(L_SYS_RAWECM,mecmCode,sizeof(mecmCode),"decrypted MECM code"); + // check signature + unsigned char data[256]; + memcpy(data,mecmCode,sizeof(data)); + RotateBytes(data,sizeof(data)); + SHA1(data,sizeof(data)-8,data); + RotateBytes(data,20); + if(memcmp(data,mecmCode,8)) { + PRINTF(L_SYS_ECM,"%04X: MECM %02x decrypt signature failed",id,keyNr); + return false; + } + + // dynamic expand + hd[5]=ed[5]; + hd[6]=(ed[7]&0xEF) | ((ed[6]&0x40)>>2); + hd[7]=ed[8]; + hd[8]=(ed[9]&0x7F) | ((ed[6]&0x20)<<2); + hd[9]=ed[6]&0x80; + memcpy(hw,hd,seedSize); + ExpandInput(hw); + + SetSp(0x0FFF,0x0EF8); + ClearBreakpoints(); + SetMem(0x0100,mecmCode+8,0x100-8); + SetMem(0x0ba2,hw,0x80); + AddBreakpoint(0x0000); + AddRomCallbacks(); + SetPc(0x0100); + while(!Run(10000)) { + if(GetPc()==0x0000) { + GetMem(0x0ba2,hw,0x80); + return true; + } + else if(!RomCallbacks()) return false; + } + +/* if(algo==0x40) { + const int hwCount=2; memcpy(hw,hd,hwCount+1); ExpandInput(hw); hw[0x18]|=1; hw[0x40]|=1; @@ -216,8 +761,6 @@ bool cN2Prov0101::Algo(int algo, const unsigned char *hd, unsigned char *hw) return true; } else if(algo==0x60) { // map 4D/4E/57 - memcpy(hw,hd,5); - ExpandInput(hw); hw[127]|=0x80; hw[0]|=0x01; DoMap(SETSIZE,0,16); DoMap(IMPORT_A,hw); @@ -228,81 +771,376 @@ bool cN2Prov0101::Algo(int algo, const unsigned char *hd, unsigned char *hw) DoMap(IMPORT_A,hw); DoMap(0x4e); DoMap(EXPORT_A,hw); - DoMap(0x57,hw,128); + DoMap(0x57,hw); return true; } PRINTF(L_SYS_ECM,"%04X: unknown MECM algo %02x",id,algo); +*/ + return false; +} + +bool cN2Prov0101::PostProcAU(int id, unsigned char *data) +{ + if(data[1]&0x5f) return false; + return true; +} + +bool cN2Prov0101::RomInit(void) +{ + SetPc(0x4000); + SetSp(0x0FFF,0x0FE0); + ClearBreakpoints(); + AddBreakpoint(0x537d); + AddBreakpoint(0x8992); + AddBreakpoint(0xA822); + while(!Run(5000)) { + switch(GetPc()) { + case 0x537d: + PRINTF(L_SYS_EMU,"%04x: ROM init successfull",id); + return true; + default: + PRINTF(L_SYS_EMU,"%04x: ROM init failed: unexpected breakpoint",id); + break; + } + } return false; } +bool cN2Prov0101::ProcessMap(int f) +{ + unsigned short addr; + int size=wordsize<<3; + unsigned char tmp[256]; + + switch(f) { + case SETSIZE: // set map size + DoMap(f,0,Get(0x48)); + if((wordsize<<3)>256) { + PRINTF(L_SYS_EMU,"%04x: MAP word size too large: %d",id,wordsize); + return false; + } + break; + case IMPORT_J: //Import Ram at [44:45] to Map Registers A-E, E is 0x03 the rest in sequence + case IMPORT_A: + case IMPORT_B: + case IMPORT_C: + case IMPORT_D: + case IMPORT_LAST: + addr=HILO(0x44); + GetMem(addr,tmp,size,0); DoMap(f,tmp); + break; + case EXPORT_J: //Export Registers A-E with 44:45: 0x09 is E + case EXPORT_A: + case EXPORT_B: + case EXPORT_C: + case EXPORT_D: + case EXPORT_LAST: + addr=HILO(0x44); + DoMap(f,tmp); SetMem(addr,tmp,size,0); + break; + case SWAP_A: //Swap Registers A-D with 44:45 + case SWAP_B: + case SWAP_C: + case SWAP_D: + addr=HILO(0x44); + GetMem(addr,tmp,size,0); DoMap(f,tmp); SetMem(addr,tmp,size,0); + break; + case CLEAR_A: + case CLEAR_B: + case CLEAR_C: + case CLEAR_D: + case COPY_A_B: + case COPY_B_A: + case COPY_A_C: + case COPY_C_A: + case COPY_C_D: + case COPY_D_C: + DoMap(f); break; + case 0x22: + DoMap(f,tmp,-((Get(0x48)<<16)|(Get(0x49)<<8)|Get(0x4a))); + AddCycles(MapCycles()); + break; + case 0x3e: + GetMem(HILO(0x44),tmp,size,0); + DoMap(f,tmp,Get(0x48)); + AddCycles(MapCycles()); + break; + case 0x4d: + DoMap(f,tmp,-((Get(0x48)<<16)|(Get(0x49)<<8)|Get(0x4a))); + SetMem(0x400,tmp,53,0); + break; + case 0x4e: + GetMem(0x400,tmp,53,0); + DoMap(f,tmp); + SetMem(0x400,tmp,53,0); + AddCycles(MapCycles()); + break; + default: + PRINTF(L_SYS_EMU,"%04x: map call %02x not emulated",id,f); + return false; + } + return true; +} + +bool cN2Prov0101::ProcessDESMap(int f) +{ + unsigned char data[16]; + switch(f) { + case 0x05: // 3DES encrypt + DES_ecb2_encrypt(DES_CAST(desblock),DES_CAST(desblock),&desks1,&desks2,DES_ENCRYPT); + break; + case 0x06: // 3DES decrypt + DES_ecb2_encrypt(DES_CAST(desblock),DES_CAST(desblock),&desks1,&desks2,DES_DECRYPT); + break; + case 0x0b: // load DES data block from memory + GetMem(HILO(0x25),desblock,8,Get(0x24)); + break; + case 0x0c: // store DES data block to memory + SetMem(HILO(0x2b),desblock,8,Get(0x2a)); + break; + case 0x0e: // get DES key1 and key2 + GetMem(HILO(0x25),data,8,Get(0x24)); + DES_key_sched(DES_CAST(data),&desks1); + GetMem(HILO(0x28),data,8,Get(0x27)); + DES_key_sched(DES_CAST(data),&desks2); + break; + case 0x0f: // set DES size + desSize=Get(0x2d); + if(desSize!=0x10 && desSize!=0x18) { + PRINTF(L_SYS_EMU,"%04x: invalid DES key size %02x",id,desSize); + return false; + } + break; + default: + PRINTF(L_SYS_EMU,"%04x: DES map call %02x not emulated",id,f); + return false; + } + return true; +} + +bool cN2Prov0101::RomCallbacks(void) +{ + unsigned int ea=GetPc(); + if(ea&0x8000) ea|=(cr<<16); + switch(ea) { + case 0x3840: //MAP Handler + case 0x00A822: + if(!ProcessMap(a)) return false; + break; + case 0x3844: //DES Handler + if(!ProcessDESMap(a)) return false; + break; + case 0x5F23: //Erase_RAM_and_Hang + case 0x5F27: //Erase_RAM_and_Hang_Lp + case 0x5F5E: //BrainDead + PRINTF(L_SYS_EMU,"%04x: emu hung at %04x",id,ea); + return false; + case 0x70A6: //Write_Row_EEP_RC2_Len_A_To_RC1 + { + unsigned short rc1=HILO(0x47); + unsigned short rc2=HILO(0x4a); + for(int i=0; i>8); + Set(0x4b,rc2&0xff); + break; + } + case 0x7BFE: //Write_Row_EEPROM_A_from_X_to_RC1 + { + unsigned short rc1=HILO(0x47); + unsigned short rc2=c6805::x; + for(int i=0; i=0x8000) PopCr(); + PopPc(); + return true; +} + +void cN2Prov0101::AddRomCallbacks(void) +{ + AddBreakpoint(0xA822); // map handler + AddBreakpoint(0x3840); + AddBreakpoint(0x3844); + AddBreakpoint(0xA23C); //IDEA + AddBreakpoint(0xA2E9); + AddBreakpoint(0x70A6); + AddBreakpoint(0x7BFE); + AddBreakpoint(0x7CFF); + AddBreakpoint(0x5F23); + AddBreakpoint(0x5F27); + AddBreakpoint(0x5F5E); +} + int cN2Prov0101::ProcessBx(unsigned char *data, int len, int pos) { if(Init(id,102)) { SetMem(0x80,data,len); SetPc(0x80+pos); - SetSp(0x0FFF,0x0FF0); + SetSp(0x0FFF,0x0EF8); ClearBreakpoints(); - ForceSet(0x0001,0x0f,true); // fix xor 80 - AddBreakpoint(0x0000); AddBreakpoint(0x9569); - AddBreakpoint(0xA822); // map handler + AddBreakpoint(0x0000); + AddRomCallbacks(); while(!Run(1000)) { if(GetPc()==0x9569) { GetMem(0x80,data,len); return max((int)a,6); } - if(GetPc()==0x0000) - break; - if(GetPc()==0xA822) { - int size=wordsize<<3; - unsigned char tmp[size]; - unsigned short addr=(Get(0x44)<<8)+Get(0x45); - switch(a) { - case 0x02: - DoMap(a,0,Get(0x48)); break; - case IMPORT_J ... IMPORT_LAST: - GetMem(addr,tmp,size,0); DoMap(a,tmp); break; - case EXPORT_J ... EXPORT_LAST: - DoMap(a,tmp); SetMem(addr,tmp,size,0); break; - case SWAP_A ... SWAP_D: - GetMem(addr,tmp,size,0); DoMap(a,tmp); SetMem(addr,tmp,size,0); break; - case CLEAR_A ... CLEAR_D: - case COPY_A_B ... COPY_D_C: - DoMap(a); break; - default: - PRINTF(L_SYS_EMM,"%04X: unrecognized map call %02x",id,a); - return -1; - } - PopCr(); PopPc(); + else if(GetPc()==0x0000) break; + else if(!RomCallbacks()) break; + } + } + return -1; +} + +int cN2Prov0101::ProcessEx(unsigned char *data, int len, int pos) +{ + if(Init(id,102)) { + SetMem(0x80,data,len); + SetPc(0x9591); + SetSp(0x0FFF,0x0EF8); + Push(0x99); //push the bug-table return onto the stack + Push(0x95); + Push(0x00); + Set(0x00,0x62,0x26); + Set(0x00,0x63,0x02); + Set(0x00,0x03d3,len-0x12); + ClearBreakpoints(); + AddBreakpoint(0x9569); + AddBreakpoint(0x9599); + AddRomCallbacks(); + while(!Run(10000)) { + if(GetPc()==0x9569) { + GetMem(0x80,data,len); + return max((int)a,6); } + else if(GetPc()==0x9599) break; + else if(!RomCallbacks()) break; } } return -1; } +void cN2Prov0101::TimerHandler(unsigned int num) +{ + for(int i=0; i 0 ) : you can only + // stop it (i.e. op and 2 = 0). + if(timer[num].Running()) { + op=(Get(ea)&~tmRUNNING) | (op&tmRUNNING); + if(!(op&tmRUNNING)) timer[num].Stop(); + } + else if(op&tmRUNNING) { + unsigned int div; + if((op&0xc0)==0x40) div=1 << (2 *(1 + ((op & 0x38) >> 3))); + else div=4; // This is wrong, but we haven't figured the right value out yet + timer[num].Start(op,div); + } + break; } - else if(ea==0x0a || ea==0x12 || ea==0x16) { - unsigned char old=Get(ea); - if(old&2) op=(old&~0x02) | (op&0x02); + case HW_TIMER0_LATCH: + case HW_TIMER1_LATCH: + case HW_TIMER2_LATCH: + { + int num=TIMER_NUM(ea); + if(!timer[num].Running()) timer[num].SetLatch(op); + break; } + case HW_CRC_CONTROL: + // $0e is to program the CRC unit. $0f is the data to CRC + // assumes: + // bit 1 disables/enables CRCing + if(!(op&CRC_DISABLED)) { + // disable -> reset CRC + CRCvalue=0; CRCpos=0; + CRCstarttime=Cycles()-CRCCALC_DELAY; + } + break; + case HW_CRC_DATA: + if(!(Get(HW_CRC_CONTROL)&CRC_DISABLED)) { + if(Cycles()-CRCstarttime>=CRCCALC_DELAY) { + // accept new data if not busy + CRCvalue=(CRCvalue>>8)^crc16table[(CRCvalue^op)&0xff]; + CRCpos=0; + CRCstarttime=Cycles(); + } + } + break; } } void cN2Prov0101::ReadHandler(unsigned char seg, unsigned short ea, unsigned char &op) { - if(special05) { - special05=false; // prevent loop - unsigned short start=Get(0x00,0x30C0); - unsigned short end=Get(0x00,0x30C1); - if(((ea>>8)>=start) && ((ea>>8)<=end)) op=0x00; // dataspace - else op=0x01; // codespace - special05=true; + switch(ea) { + case HW_SECURITY: + if(cr==0) op=0x0F; break; + case HW_TIMER0_CONTROL: + case HW_TIMER1_CONTROL: + case HW_TIMER2_CONTROL: + { + int num=TIMER_NUM(ea); + op=timer[num].Running() ? op|tmRUNNING : op&~tmRUNNING; + break; + } + case HW_TIMER0_DATA: + case HW_TIMER1_DATA: + case HW_TIMER2_DATA: + { + int num=TIMER_NUM(ea); + op=timer[num].GetCycles(); + break; + } + case HW_CRC_CONTROL: + if(!(op&CRC_DISABLED)) { + //CRC takes 10 cycles to generate + if(Cycles()-CRCstarttime>=CRCCALC_DELAY) op&=~CRC_BUSY; // not busy + else op|=CRC_BUSY; // busy + } + else op&=~CRC_BUSY; // clear busy bit + break; + case HW_CRC_DATA: + op=CRCvalue>>((CRCpos&1)<<3); + CRCpos=!CRCpos; + break; } } @@ -348,10 +1186,10 @@ public: cN2Prov0901(int Id, int Flags); }; -static cN2ProvLinkReg staticPL0901; +static cN2ProvLinkReg staticPL0901; cN2Prov0901::cN2Prov0901(int Id, int Flags) :cN2Prov0101(Id,Flags) { - hwCount=4; + mecmAddr[0]=0x91f5; mecmAddr[1]=0x92f5; mecmKeyId=0x907; } diff --git a/systems/nagra/nagra2-0501.c b/systems/nagra/nagra2-0501.c index 5c0f4bf..6821da1 100644 --- a/systems/nagra/nagra2-0501.c +++ b/systems/nagra/nagra2-0501.c @@ -39,16 +39,12 @@ void cMap0501::DoMap(int f, unsigned char *data, int l) switch(f) { case 0x37: l=(l?l:wordsize)<<3; - H.GetLE(data,l); - MonMul(B,H,A); + B.GetLE(data,l); + MonMul(B,B,A); break; case 0x3a: - MakeJ(); - BN_zero(R); - BN_set_bit(R,68*wordsize); - BN_mod(H,R,D,ctx); - for(int i=0; i<4; i++) MonMul(H,H,H); - MonMul(B,A,H); + MonInit(); + MonMul(B,A,B); MonMul(B,A,B); break; default: @@ -62,7 +58,7 @@ void cMap0501::DoMap(int f, unsigned char *data, int l) class cN2Prov0501 : public cN2Prov, private cMap0501, public cN2Emu { protected: - virtual bool Algo(int algo, const unsigned char *hd, unsigned char *hw); + virtual bool Algo(int algo, unsigned char *hd, const unsigned char *ed, unsigned char *hw); virtual bool NeedsCwSwap(void) { return true; } public: cN2Prov0501(int Id, int Flags); @@ -76,7 +72,7 @@ cN2Prov0501::cN2Prov0501(int Id, int Flags) ,cMap0501(Id) {} -bool cN2Prov0501::Algo(int algo, const unsigned char *hd, unsigned char *hw) +bool cN2Prov0501::Algo(int algo, unsigned char *hd, const unsigned char *ed, unsigned char *hw) { if(algo==0x60) { hw[0]=hd[0]; @@ -113,6 +109,7 @@ int cN2Prov0501::ProcessBx(unsigned char *data, int len, int pos) SetSp(0x0FFF,0x0FE0); Set(0x0001,0xFF); Set(0x000E,0xFF); + Set(0x0000,0x04); ClearBreakpoints(); AddBreakpoint(0x821f); while(!Run(5000)) { diff --git a/systems/nagra/nagra2-4101.c b/systems/nagra/nagra2-4101.c index d2d8187..7366ccb 100644 --- a/systems/nagra/nagra2-4101.c +++ b/systems/nagra/nagra2-4101.c @@ -17,9 +17,70 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */ +// -- cMap4101 ----------------------------------------------------------------- + +class cMap4101 : public cMapCore { +private: + int mId; +protected: + void DoMap(int f, unsigned char *data=0, int l=0); +public: + cMap4101(int Id); + }; + +cMap4101::cMap4101(int Id) +{ + mId=Id|0x100; +} + +void cMap4101::DoMap(int f, unsigned char *data, int l) +{ + PRINTF(L_SYS_MAP,"%04x: calling function %02X",mId,f); + switch(f) { + case 0x58: + { + cBN a, b, x, y, scalar; + D.GetLE(data+0x00,16); + x.GetLE(data+0x10,16); + y.GetLE(data+0x20,16); + b.GetLE(data+0x30,16); + a.GetLE(data+0x40,16); + scalar.GetLE(data+0x50,16); + int scalarbits=BN_num_bits(scalar); + if(scalarbits>=2 && !BN_is_zero(x) && !BN_is_zero(y) && !BN_is_zero(b)) { + CurveInit(a); + ToProjective(0,x,y); + BN_copy(Qx,Px); + BN_copy(Qy,Py); + for(int i=scalarbits-2; i>=0; i--) { + DoubleP(0); + if(BN_is_bit_set(scalar,i)) AddP(0); + } + ToAffine(); + } + memset(data,0,64); + Px.PutLE(&data[0],16); + Py.PutLE(&data[32],16); + break; + } + case 0x44: + sctx.h4=UINT32_LE(data); + sctx.h3=UINT32_LE(data+4); + sctx.h2=UINT32_LE(data+8); + sctx.h1=UINT32_LE(data+12); + sctx.h0=UINT32_LE(data+16); + cMapCore::DoMap(0x44,data); + break; + default: + if(!cMapCore::DoMap(f,data,l)) + PRINTF(L_SYS_MAP,"%04x: unsupported call %02x",mId,f); + break; + } +} + // -- cN2Prov4101 ---------------------------------------------------------------- -class cN2Prov4101 : public cN2Prov, public cN2Emu { +class cN2Prov4101 : public cN2Prov, public cMap4101, public cN2Emu { protected: virtual void WriteHandler(unsigned char seg, unsigned short ea, unsigned char &op); public: @@ -32,6 +93,7 @@ static cN2ProvLinkReg staticPL4101 cN2Prov4101::cN2Prov4101(int Id, int Flags) :cN2Prov(Id,Flags) +,cMap4101(Id) { hasWriteHandler=true; } @@ -64,6 +126,7 @@ int cN2Prov4101::ProcessBx(unsigned char *data, int len, int pos) ClearBreakpoints(); AddBreakpoint(0xACDD); AddBreakpoint(0x9BDD); + AddBreakpoint(0x7EC5); while(!Run(5000)) { switch(GetPc()) { case 0xACDD: @@ -71,6 +134,30 @@ int cN2Prov4101::ProcessBx(unsigned char *data, int len, int pos) case 0x9BDD: GetMem(0x80,data,len); return a; + case 0x7EC5: + { + PopPc(); + unsigned short args=GetPc(); + int clen=Get(args+4); + unsigned short ptr=(Get(args)<<8)+Get(args+1); + if(clen+pos-1>len) return -1; // sanity + GetMem(ptr,&data[pos-1],clen); + ptr=(Get(args+2)<<8)+Get(args+3)-0x0CED+0x00B4-0x0080; // wild hack + if(ptr<7 || ptr+8>len || data[ptr-1]!=0x10 || data[ptr-7]!=0x42) // sanity + return -1; + unsigned char tmp[96]; + memcpy(&tmp[0],&data[ptr],8); + ptr=(((data[ptr]&0x3F)|0x40)<<8)+(data[ptr+1]&0x7F); + GetMem(ptr,&tmp[8],sizeof(tmp)-8); + DoMap(0x02,0,2); + DoMap(0x58,tmp); + DoMap(0x43); + DoMap(0x44,tmp); + SetMem(0x0440,tmp,20); + SetMem(0x80,data,len); + SetPc(0x80+pos); + break; + } } } } diff --git a/systems/nagra/nagra2-map57.c b/systems/nagra/nagra2-map57.c deleted file mode 100644 index a1408a9..0000000 --- a/systems/nagra/nagra2-map57.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * Softcam plugin to VDR (C++) - * - * This code is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * Or, point your browser to http://www.gnu.org/copyleft/gpl.html - */ - -// -- cN2Map57 ---------------------------------------------------------------- - -class cN2Map57 { -private: - void mod_add(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4); - void bn_cmplx1(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4, BIGNUM *arg5); - void bn_cmplx1a(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4, BIGNUM *arg5); - void mod_sub(void); - void bn_func1(BIGNUM *arg0); - void bn_func2(int arg0); - void bn_func3(int arg0); - void bn_cmplx7(void); - void bn_cmplx2(BIGNUM *var1, BIGNUM *var2, BIGNUM *var3, BIGNUM *var4, BIGNUM *var5, BIGNUM *var6); - BIGNUM *bn_glb0, *bn_glb1, *bn_glb3, *bn_glb5, *bn_glb6, *bn_glb7; - BIGNUM *bn_glb_a, *bn_glb_b, *bn_glb_c, *bn_glb_d, *bn_glb_e, *bn_glb_f, *bn_glb_g; - BIGNUM *bn_glb_h, *bn_glb_i, *bn_glb_j, *bn_glb_k, *bn_glb_l, *bn_glb_m; - BIGNUM *glb2pow128, *mask128, *glb2pow64, *mask64; - BN_CTX *t1; -public: - void Map57(unsigned char *data); - }; - -void cN2Map57::mod_add(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4) -{ - BN_add(arg1, arg2, arg3); - if(BN_cmp(arg1, arg4) >= 0) { - BN_sub(arg1, arg1, arg4); - } - BN_mask_bits(arg1, 128); -} - -void cN2Map57::bn_cmplx1(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4, BIGNUM *arg5) -{ - int j; - BIGNUM *var44, *var64, *var84, *vara4; - var44 = BN_new(); - var64 = BN_new(); - var84 = BN_new(); - vara4 = BN_new(); - BN_copy(var44, arg2); - BN_copy(var64, arg3); - BN_clear(vara4); - for(j=0; j<2; j++) { - BN_copy(var84, var64); - BN_mask_bits(var84, 64); - BN_rshift(var64, var64, 64); - BN_mul(var84, var84, var44, t1); - BN_add(vara4, vara4, var84); - BN_copy(var84, vara4); - BN_mask_bits(var84, 128); - BN_mul(var84, vara4, arg4, t1); - BN_mask_bits(var84, 64); - BN_mul(var84, var84, arg5, t1); - BN_add(vara4, vara4, var84); - BN_rshift(vara4, vara4, 64); - if(BN_cmp(vara4, arg5) >= 0) { - BN_sub(vara4, vara4, arg5); - } - BN_mask_bits(vara4, 128); - } - BN_copy(arg1, vara4); - BN_free(var44); - BN_free(var64); - BN_free(var84); - BN_free(vara4); -} - -void cN2Map57::bn_cmplx1a(BIGNUM *arg1, BIGNUM *arg2, BIGNUM *arg3, BIGNUM *arg4, BIGNUM *arg5) -{ - int j; - BIGNUM *var44, *var64, *var84, *vara4; - var44 = BN_new(); - var64 = BN_new(); - var84 = BN_new(); - vara4 = BN_new(); - BN_copy(var44, arg2); - BN_copy(var64, arg3); - BN_clear(vara4); - for(j=0; j<2; j++) { - BN_copy(var84, var64); - BN_mask_bits(var84, 64); - BN_rshift(var64, var64, 64); - BN_mul(var84, var84, var44, t1); - BN_add(vara4, vara4, var84); - BN_copy(var84, vara4); - BN_mask_bits(var84, 128); - BN_mul(var84, vara4, arg4, t1); - BN_mask_bits(var84, 64); - BN_mul(var84, var84, arg5, t1); - BN_add(vara4, vara4, var84); - BN_rshift(vara4, vara4, 64); - if(j==0 && BN_cmp(vara4, arg5) >= 0) { - BN_sub(vara4, vara4, arg5); - } - BN_mask_bits(vara4, 128); - } - BN_copy(arg1, vara4); - BN_free(var44); - BN_free(var64); - BN_free(var84); - BN_free(vara4); -} - -//uses 3, 1, glb2pow128 -//sets 1, 0 (unused) -void cN2Map57::mod_sub() -{ - BN_copy(bn_glb0, bn_glb3); - BN_mod_sub(bn_glb1, bn_glb3, bn_glb1, glb2pow128, t1); - BN_mask_bits(bn_glb1, 128); -} - -//uses 1, 3, 6 -//sets 1, 0 (unused), 7(unused) -void cN2Map57::bn_func1(BIGNUM *arg0) -{ - BIGNUM *var30 = BN_new(); - BIGNUM *var50 = BN_new(); - BN_copy(var30,arg0); - BN_mask_bits(var30, 8); - unsigned int x = BN_get_word(var30); - BN_copy(var30,arg0); - if( x != 0) { - BN_clear(var50); - BN_set_word(var50, 2); - BN_sub(var30, var30, var50); - } else { - BN_clear(var50); - BN_set_word(var50, 0xfe); - BN_add(var30, var30, var50); - } - BN_copy(bn_glb7, bn_glb1); - if(BN_is_zero(arg0)) { - BN_clear(bn_glb7); - BN_set_word(bn_glb7, 1); - BN_clear(bn_glb0); - - mod_add(bn_glb1, bn_glb7, bn_glb0, bn_glb3); - BN_free(var30); - BN_free(var50); - return; - } else { - int msb = BN_num_bits(var30) -1; - while (msb > 0) { - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3); - msb--; - if(BN_is_bit_set(var30, msb)) { - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3); - } - } - BN_clear(bn_glb7); - BN_set_word(bn_glb7, 1); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3); - BN_clear(bn_glb0); - } - BN_free(var30); - BN_free(var50); -} - -//uses 3, 6, a, b, c, l, glb2pow128 -//sets 0, 1, 5, 7, a, b, c, f, g -void cN2Map57::bn_func2(int arg0) -{ - BN_copy(bn_glb1, bn_glb_b); - - mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3); - BN_copy(bn_glb7, bn_glb1); - BN_copy(bn_glb5, bn_glb_c); - BN_mask_bits(bn_glb1, 128); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - BN_copy(bn_glb_g, bn_glb1); - BN_copy(bn_glb1, bn_glb7); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3); - BN_copy(bn_glb7, bn_glb_a); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3); - mod_sub(); - BN_copy(bn_glb_f, bn_glb1); - BN_copy(bn_glb1, bn_glb7); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3); - BN_copy(bn_glb7, bn_glb1); - - mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3); - - mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3); - BN_copy(bn_glb7, bn_glb1); - BN_copy(bn_glb1, bn_glb_c); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3); - BN_copy(bn_glb5, bn_glb_l); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - - mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3); - BN_copy(bn_glb7, bn_glb1); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3); - BN_copy(bn_glb0, bn_glb_f); - - mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3); - mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3); - if(arg0 == 0) { - BN_copy(bn_glb_a, bn_glb1); - } else { - BN_copy(bn_glb_f, bn_glb1); - } - - mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3); - BN_copy(bn_glb7, bn_glb1); - BN_copy(bn_glb1, bn_glb_b); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3); - - mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3); - - mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3); - - mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3); - mod_sub(); - if(arg0 == 0) { - BN_copy(bn_glb_b, bn_glb1); - BN_copy(bn_glb_c, bn_glb_g); - } else { - BN_copy(bn_glb_f, bn_glb1); - BN_copy(bn_glb_f, bn_glb_g); - } -} - -//uses 3, 6, a, b, c, d, e, k -//sets 0, 1, 5, 7, a, b, c, f, g, h, i, j -void cN2Map57::bn_func3(int arg0) -{ - BN_copy(bn_glb1, bn_glb_c); - BN_copy(bn_glb7, bn_glb1); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3); - - bn_cmplx1(bn_glb0, bn_glb1, bn_glb7, bn_glb6, bn_glb3); - BN_copy(bn_glb_f, bn_glb0); - BN_copy(bn_glb5, bn_glb_d); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - BN_copy(bn_glb7, bn_glb1); - mod_sub(); - BN_copy(bn_glb0, bn_glb_a); - - mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3); - BN_copy(bn_glb_g, bn_glb1); - BN_copy(bn_glb5, bn_glb_c); - - bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - if(arg0 == 0) { - BN_copy(bn_glb_c, bn_glb0); - } else { - BN_copy(bn_glb_g, bn_glb0); - } - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3); - BN_copy(bn_glb_h, bn_glb1); - BN_copy(bn_glb0, bn_glb_a); - - mod_add(bn_glb0, bn_glb0, bn_glb7, bn_glb3); - BN_copy(bn_glb7, bn_glb0); - - //NOTE: don't 'mod' bn_glb1, but DO 'mod' glb_i - bn_cmplx1(bn_glb7, bn_glb1, bn_glb7, bn_glb6, bn_glb3); - bn_cmplx1a(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3); - BN_copy(bn_glb_i, bn_glb7); - BN_copy(bn_glb1, bn_glb_e); - BN_copy(bn_glb5, bn_glb_f); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - BN_copy(bn_glb_f, bn_glb1); - mod_sub(); - BN_copy(bn_glb0, bn_glb_b); - - mod_add(bn_glb1, bn_glb0, bn_glb1, bn_glb3); - BN_copy(bn_glb_j, bn_glb1); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3); - BN_copy(bn_glb0, bn_glb1); - BN_copy(bn_glb1, bn_glb7); - BN_copy(bn_glb7, bn_glb0); - mod_sub(); - - mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3); - if(arg0 == 0) { - BN_copy(bn_glb_a, bn_glb1); - } else { - BN_copy(bn_glb_f, bn_glb1); - } - - mod_add(bn_glb1, bn_glb1, bn_glb1, bn_glb3); - mod_sub(); - BN_copy(bn_glb7, bn_glb_i); - - mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3); - BN_copy(bn_glb5, bn_glb_j); - - bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - BN_copy(bn_glb1, bn_glb_f); - BN_copy(bn_glb_f, bn_glb0); - BN_copy(bn_glb7, bn_glb_b); - - mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3); - BN_copy(bn_glb7, bn_glb1); - BN_copy(bn_glb1, bn_glb_g); - BN_copy(bn_glb5, bn_glb_h); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3); - mod_sub(); - BN_copy(bn_glb7, bn_glb_f); - - mod_add(bn_glb1, bn_glb1, bn_glb7, bn_glb3); - BN_copy(bn_glb5, bn_glb_k); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - if(arg0 == 0) { - BN_copy(bn_glb_b, bn_glb1); - } else { - BN_copy(bn_glb_f, bn_glb1); - } -} - -//uses c, d, e, m -//sets 0, a, b, c -void cN2Map57::bn_cmplx7() -{ - BIGNUM *var1; - var1 = BN_new(); - BN_copy(bn_glb0, bn_glb_c); - if(BN_is_zero(bn_glb_c)) { - BN_copy(bn_glb_a, bn_glb_d); - BN_copy(bn_glb_b, bn_glb_e); - BN_copy(bn_glb_c, bn_glb_m); - bn_func3(1); - } else { - BN_clear(var1); - BN_set_word(var1, 0xFFFFFFFF); - BN_mask_bits(bn_glb_a, 32); - BN_lshift(var1, bn_glb_m, 0x20); - BN_add(bn_glb_a, bn_glb_a, var1); - BN_mask_bits(bn_glb_a, 128); - bn_func3(0); - } - BN_free(var1); -} - -void cN2Map57::bn_cmplx2(BIGNUM *var1, BIGNUM *var2, BIGNUM *var3, BIGNUM *var4, BIGNUM *var5, BIGNUM *var6) -{ - BIGNUM *var48; - int len = BN_num_bits(var6); - int i; - if(len < 2) - return; - - if(BN_is_zero(var2) && BN_is_zero(var3) && BN_is_zero(var4)) - return; - var48 = BN_new(); - BN_copy(bn_glb3, var1); - - BN_copy(bn_glb6, bn_glb3); - BN_set_bit(bn_glb6, 0); - BN_sub(bn_glb6, glb2pow128, bn_glb6); - BN_mod_inverse(bn_glb6, bn_glb6, glb2pow64, t1); - BN_clear(bn_glb0); - // - if(! BN_is_zero(bn_glb3)) { - BN_clear(bn_glb1); - BN_set_word(bn_glb1, 2); - BN_clear(bn_glb_k); - BN_set_word(bn_glb_k, 0x88); - BN_mod_exp(bn_glb1, bn_glb1, bn_glb_k, bn_glb3, t1); - } - // - for(i=0; i < 4; i++) { - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3); - } - // - BN_clear(bn_glb7); - BN_set_word(bn_glb7, 1); - BN_add(bn_glb0, bn_glb3, bn_glb7); - BN_copy(bn_glb_k, bn_glb0); - BN_rshift(bn_glb_k, bn_glb_k, 1); - BN_copy(bn_glb7, bn_glb1); - BN_copy(bn_glb5, bn_glb_k); - BN_mask_bits(bn_glb5, 128); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - BN_copy(bn_glb_k, bn_glb1); - - BN_copy(bn_glb1, var5); - BN_mask_bits(bn_glb1, 128); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3); - BN_copy(bn_glb_l, bn_glb1); - BN_copy(bn_glb1, bn_glb7); - BN_clear(bn_glb5); - BN_set_word(bn_glb5, 1); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - BN_copy(bn_glb_c, bn_glb1); - BN_copy(bn_glb_m, bn_glb1); - BN_copy(bn_glb1, bn_glb7); - - BN_copy(bn_glb5, var2); - BN_mask_bits(bn_glb5, 128); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - BN_copy(bn_glb_a, bn_glb1); - BN_copy(bn_glb1, bn_glb7); - - BN_copy(bn_glb5, var3); - BN_mask_bits(bn_glb5, 128); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - BN_copy(bn_glb_b, bn_glb1); - BN_copy(bn_glb_d, bn_glb_a); - BN_copy(bn_glb_e, bn_glb_b); - - int x = len -1; - while(x > 0) { - x--; - bn_func2(0); - if(BN_is_bit_set(var6, x)) { - bn_cmplx7(); - } - } - - BN_copy(bn_glb1, bn_glb_c); - BN_mask_bits(bn_glb1, 128); - BN_copy(bn_glb7, bn_glb1); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb1, bn_glb6, bn_glb3); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3); - BN_clear(bn_glb7); - BN_set_word(bn_glb7, 1); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb7, bn_glb6, bn_glb3); - BN_copy(bn_glb0, bn_glb1); - BN_clear(bn_glb7); - BN_set_word(bn_glb7, 1); - BN_copy(bn_glb1, bn_glb0); - BN_clear(bn_glb0); - bn_func1(var1); - BN_copy(bn_glb5, bn_glb_b); - BN_mask_bits(bn_glb5, 128); - - bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - - BN_copy(bn_glb7, bn_glb0); - BN_copy(bn_glb5, bn_glb_c); - BN_mask_bits(bn_glb5, 128); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - - BN_copy(bn_glb5, bn_glb_a); - BN_mask_bits(bn_glb5, 128); - - bn_cmplx1(bn_glb1, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - - BN_clear(bn_glb5); - BN_set_word(bn_glb5, 1); - - bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - BN_copy(bn_glb_a, bn_glb0); - BN_copy(bn_glb1, bn_glb7); - - BN_clear(bn_glb5); - BN_set_word(bn_glb5, 1); - - bn_cmplx1(bn_glb0, bn_glb1, bn_glb5, bn_glb6, bn_glb3); - BN_copy(bn_glb_b, bn_glb0); - BN_free(var48); -} - -void cN2Map57::Map57(unsigned char *data) -{ - BIGNUM *var38, *var58, *var78, *var98, *varb8, *vard8; - BN_CTX *t; - unsigned char tmpdata[256]; - unsigned char res[256]; - - t = BN_CTX_new(); - t1 = BN_CTX_new(); - BN_CTX_init(t); - - glb2pow128 = BN_new(); - BN_clear(glb2pow128); - BN_set_bit(glb2pow128, 128); - mask128 = BN_new(); - BN_hex2bn(&mask128, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); - - glb2pow64 = BN_new(); - BN_clear(glb2pow64); - BN_set_bit(glb2pow64, 64); - mask64 = BN_new(); - BN_hex2bn(&mask64, "FFFFFFFFFFFFFFFF"); - - bn_glb0=BN_new(); BN_clear(bn_glb0); - bn_glb1=BN_new(); BN_clear(bn_glb1); - bn_glb3=BN_new(); BN_clear(bn_glb3); - bn_glb5=BN_new(); BN_clear(bn_glb5); - bn_glb6=BN_new(); BN_clear(bn_glb6); - bn_glb7=BN_new(); BN_clear(bn_glb7); - - bn_glb_a=BN_new(); BN_clear(bn_glb_a); - bn_glb_b=BN_new(); BN_clear(bn_glb_b); - bn_glb_c=BN_new(); BN_clear(bn_glb_c); - bn_glb_d=BN_new(); BN_clear(bn_glb_d); - bn_glb_e=BN_new(); BN_clear(bn_glb_e); - bn_glb_f=BN_new(); BN_clear(bn_glb_f); - bn_glb_g=BN_new(); BN_clear(bn_glb_g); - bn_glb_h=BN_new(); BN_clear(bn_glb_h); - bn_glb_i=BN_new(); BN_clear(bn_glb_i); - bn_glb_j=BN_new(); BN_clear(bn_glb_j); - bn_glb_k=BN_new(); BN_clear(bn_glb_k); - bn_glb_l=BN_new(); BN_clear(bn_glb_l); - bn_glb_m=BN_new(); BN_clear(bn_glb_m); - - var38=BN_new(); BN_clear(var38); - var58=BN_new(); BN_clear(var58); - var78=BN_new(); BN_clear(var78); - var98=BN_new(); BN_clear(var98); - varb8=BN_new(); BN_clear(varb8); - vard8=BN_new(); BN_clear(vard8); - - memcpy(tmpdata, data, 0x80); - RotateBytes(tmpdata, 0x80); - BN_bin2bn(tmpdata, 16, var78); - BN_bin2bn(tmpdata+0x10, 16, varb8); - BN_bin2bn(tmpdata+0x20, 16, var98); - BN_bin2bn(tmpdata+0x40, 16, vard8); - BN_bin2bn(tmpdata+0x60, 16, var38); - BN_bin2bn(tmpdata+0x70, 16, var58); - - bn_cmplx2(varb8, var58, vard8, var38, var78, var98); - - memset(res, 0, 0x80); - unsigned int *dest = (unsigned int *)res, *src = (unsigned int *)data; - *dest++ = src[0x03]; - *dest++ = src[0x02]; - *dest++ = src[0x01]; - *dest++ = src[0x00]; - *dest++ = src[0x07]; - *dest++ = src[0x06]; - *dest++ = src[0x05]; - *dest++ = src[0x04]; - - memset(tmpdata, 0, 0x20); - int len = BN_bn2bin(bn_glb_a, tmpdata); - if(len) { - RotateBytes(tmpdata, len); - } - src = (unsigned int *)tmpdata; - *dest++ = src[0x03]; - *dest++ = src[0x02]; - *dest++ = src[0x01]; - *dest++ = src[0x00]; - - memset(tmpdata, 0, 0x20); - len = BN_bn2bin(bn_glb_m, tmpdata); - if(len) { - RotateBytes(tmpdata, len); - } - *dest = src[0x03]; - dest+=4; - - memset(tmpdata, 0, 0x20); - len = BN_bn2bin(bn_glb_b, tmpdata); - if(len) { - RotateBytes(tmpdata, len); - } - *dest++ = src[0x03]; - *dest++ = src[0x02]; - *dest++ = src[0x01]; - *dest++ = src[0x00]; - - dest+=4; - src = (unsigned int *)(data+0x60); - *dest++ = src[0x03]; - *dest++ = src[0x02]; - *dest++ = src[0x01]; - *dest++ = src[0x00]; - *dest++ = src[0x07]; - *dest++ = src[0x06]; - *dest++ = src[0x05]; - *dest++ = src[0x04]; - - *(unsigned int *)(data + (8<<2))= *(unsigned int *)(res + (11<<2)); - *(unsigned int *)(data + (9<<2))= *(unsigned int *)(res + (10<<2)); - *(unsigned int *)(data + (10<<2))= *(unsigned int *)(res + (9<<2)); - *(unsigned int *)(data + (11<<2))= *(unsigned int *)(res + (8<<2)); - *(unsigned int *)(data + (12<<2))= *(unsigned int *)(res + (12<<2)); - *(unsigned int *)(data + (13<<2))= *(unsigned int *)(res + (13<<2)); - *(unsigned int *)(data + (14<<2))= *(unsigned int *)(res + (14<<2)); - *(unsigned int *)(data + (15<<2))= *(unsigned int *)(res + (15<<2)); - *(unsigned int *)(data + (16<<2))= *(unsigned int *)(res + (19<<2)); - *(unsigned int *)(data + (17<<2))= *(unsigned int *)(res + (18<<2)); - *(unsigned int *)(data + (18<<2))= *(unsigned int *)(res + (17<<2)); - *(unsigned int *)(data + (19<<2))= *(unsigned int *)(res + (16<<2)); - *(unsigned int *)(data + (20<<2))= *(unsigned int *)(res + (20<<2)); - *(unsigned int *)(data + (21<<2))= *(unsigned int *)(res + (21<<2)); - *(unsigned int *)(data + (22<<2))= *(unsigned int *)(res + (22<<2)); - *(unsigned int *)(data + (23<<2))= *(unsigned int *)(res + (23<<2)); - - BN_free(glb2pow128); - BN_free(mask128); - BN_free(glb2pow64); - BN_free(mask64); - - BN_free(bn_glb0); - BN_free(bn_glb1); - BN_free(bn_glb3); - BN_free(bn_glb5); - BN_free(bn_glb6); - BN_free(bn_glb7); - - BN_free(bn_glb_a); - BN_free(bn_glb_b); - BN_free(bn_glb_c); - BN_free(bn_glb_d); - BN_free(bn_glb_e); - BN_free(bn_glb_f); - BN_free(bn_glb_g); - BN_free(bn_glb_h); - BN_free(bn_glb_i); - BN_free(bn_glb_j); - BN_free(bn_glb_k); - BN_free(bn_glb_l); - BN_free(bn_glb_m); - - BN_free(var38); - BN_free(var58); - BN_free(var78); - BN_free(var98); - BN_free(varb8); - BN_free(vard8); - - BN_CTX_free(t); - BN_CTX_free(t1); -} diff --git a/systems/nagra/nagra2.c b/systems/nagra/nagra2.c index 63f5386..d2bda22 100644 --- a/systems/nagra/nagra2.c +++ b/systems/nagra/nagra2.c @@ -46,6 +46,7 @@ private: bool initDone; protected: bool Init(int id, int romv); + virtual bool RomInit(void) { return true; } virtual void Stepper(void) {} public: cN2Emu(void); @@ -74,14 +75,14 @@ bool cN2Emu::Init(int id, int romv) snprintf(buff,sizeof(buff),"EEP%02X_%d.bin",(id>>8)&0xFF|0x01,romv); // Eeprom00 0x00:0x3000-0x37ff OTP 0x80 - if(!AddMapper(new cMapRom(0x3000,buff,0x0000),0x3000,0x0800,0x00)) return false; - //XXX if(!AddMapper(new cMapEeprom(0x3000,buff,128,0x0000),0x3000,0x0800,0x00)) return false; + //XXX if(!AddMapper(new cMapRom(0x3000,buff,0x0000),0x3000,0x0800,0x00)) return false; + if(!AddMapper(new cMapEeprom(0x3000,buff,128,0x0000),0x3000,0x0800,0x00)) return false; // Eeprom80 0x80:0x8000-0xbfff - if(!AddMapper(new cMapRom(0x8000,buff,0x0800),0x8000,0x4000,0x80)) return false; - //XXX if(!AddMapper(new cMapEeprom(0x8000,buff, 0,0x0800),0x8000,0x4000,0x80)) return false; - initDone=true; + //XXX if(!AddMapper(new cMapRom(0x8000,buff,0x0800),0x8000,0x4000,0x80)) return false; + if(!AddMapper(new cMapEeprom(0x8000,buff, 0,0x0800),0x8000,0x4000,0x80)) return false; + initDone=RomInit(); } - return true; + return initDone; } // -- cMapCore ----------------------------------------------------------------- @@ -116,17 +117,32 @@ bool cN2Emu::Init(int id, int romv) class cMapCore { private: - cBN x, y, s, j; - SHA_CTX sctx; + int last; + cBN *regs[5]; + cBN x, y, s; protected: - cBN A, B, C, D, J; - cBN H, R; + int wordsize; + cBN A, B, C, D, J, I; + cBN Px, Py, Pz,Qx, Qy, Qz; // 0x00,0x20,0x40,0x60,0x80,0x180 + cBN sA0, sC0, sE0, s100, s120, s140, s160; cBNctx ctx; - int wordsize, last; - cBN *regs[5]; + SHA_CTX sctx; + // stateless + void MakeJ0(BIGNUM *j, BIGNUM *d); + void ModAdd(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *d); + void ModSub(BIGNUM *r, BIGNUM *d, BIGNUM *b); + void MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b, BIGNUM *c, BIGNUM *d, BIGNUM *j); + // statefull + void MonInit(int bits=0); + void MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b) { MonMul(o,a,b,C,D,J); } + void MonExpNeg(void); + // ECC + void DoubleP(int temp); + void AddP(int temp); + void ToProjective(int set, BIGNUM *x, BIGNUM *y); + void ToAffine(void); + void CurveInit(BIGNUM *a); // - void MakeJ(void); - void MonMul(BIGNUM *o, BIGNUM *i1, BIGNUM *i2); bool DoMap(int f, unsigned char *data=0, int l=0); public: cMapCore(void); @@ -138,60 +154,215 @@ cMapCore::cMapCore(void) regs[0]=&J; regs[1]=&A; regs[2]=&B; regs[3]=&C; regs[4]=&D; } -void cMapCore::MakeJ(void) +void cMapCore::ModAdd(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *d) +{ + BN_add(r,a,b); + if(BN_cmp(r,d)>=0) BN_sub(r,r,d); + BN_mask_bits(r,wordsize<<6); +} + +void cMapCore::ModSub(BIGNUM *r, BIGNUM *d, BIGNUM *b) +{ + cBN p; + BN_set_bit(p,wordsize<<6); + BN_mod_sub(r,d,b,p,ctx); + BN_mask_bits(r,wordsize<<6); +} + +void cMapCore::MakeJ0(BIGNUM *j, BIGNUM *d) { #if OPENSSL_VERSION_NUMBER < 0x0090700fL #error BN_mod_inverse is probably buggy in your openssl version #endif BN_zero(x); - BN_sub(J,x,D); - BN_set_bit(J,0); + BN_sub(j,x,d); + BN_set_bit(j,0); BN_set_bit(x,64); - BN_mod_inverse(J,J,x,ctx); + BN_mod_inverse(j,j,x,ctx); } -void cMapCore::MonMul(BIGNUM *o, BIGNUM *i1, BIGNUM *i2) +void cMapCore::MonMul(BIGNUM *o, BIGNUM *a, BIGNUM *b, BIGNUM *c, BIGNUM *d, BIGNUM *j) { - int words=(BN_num_bytes(i1)+7)>>3; + int words=(BN_num_bytes(d)+7)>>3; BN_zero(s); - for(int i=0; i-1; i--) { + MonMul(B,B,B); + if(BN_is_bit_set(e,i)) MonMul(B,A,B); + } + BN_set_word(A,1); + MonMul(B,A,B); +} + +void cMapCore::DoubleP(int temp) +{ + ModAdd(B,Py,Py,D); + MonMul(sC0,Pz,B); + MonMul(B,B,B); + MonMul(B,Px,B); + ModSub(sA0,D,B); + MonMul(B,Px,Px); + BN_copy(A,B); + ModAdd(B,B,B,D); + ModAdd(A,B,A,D); + MonMul(B,Pz,Pz); + MonMul(B,B,B); + MonMul(B,s160,B); + ModAdd(B,B,A,D); + BN_copy(A,B); + MonMul(B,B,B); + BN_copy(C,sA0); + ModAdd(B,C,B,D); + ModAdd(B,C,B,D); + if(temp==0) BN_copy(Px,B); else BN_copy(sA0,B); + ModAdd(B,C,B,D); + MonMul(B,A,B); + BN_copy(A,B); + MonMul(B,Py,Py); + ModAdd(B,B,B,D); + MonMul(B,B,B); + ModAdd(B,B,B,D); + ModAdd(B,B,A,D); + ModSub(B,D,B); + if(temp==0) { BN_copy(Py,B); BN_copy(Pz,sC0); } + else BN_copy(sA0,sC0); +} + +void cMapCore::AddP(int temp) +{ + MonMul(B,Pz,Pz); + MonMul(sA0,Pz,B); + MonMul(B,Qx,B); + BN_copy(A,B); + ModSub(B,D,B); + ModAdd(B,Px,B,D); + BN_copy(sC0,B); + MonMul(I,Pz,B); + if(temp==0) BN_copy(Pz,I); else BN_copy(sA0,I); + MonMul(B,B,B); + BN_copy(sE0,B); + ModAdd(A,Px,A,D); + MonMul(A,A,B); + BN_copy(s100,A); + MonMul(B,sA0,Qy); + BN_copy(sA0,B); + ModSub(B,D,B); + ModAdd(B,Py,B,D); + BN_copy(s120,B); + MonMul(B,B,B); + BN_swap(A,B); + ModSub(B,D,B); + ModAdd(B,A,B,D); + if(temp==0) BN_copy(Px,B); else BN_copy(sA0,B); + ModAdd(B,B,B,D); + ModSub(B,D,B); + ModAdd(B,B,s100,D); + ModAdd(A,sA0,Py,D); + MonMul(sA0,s120,B); + MonMul(B,sE0,sC0); + MonMul(B,A,B); + ModSub(B,D,B); + ModAdd(B,B,sA0,D); + MonMul(B,s140,B); + if(temp==0) BN_copy(Py,B); else BN_copy(sA0,B); +} + +void cMapCore::ToProjective(int set, BIGNUM *x, BIGNUM *y) +{ + if(set==0) { + BN_set_word(I,1); MonMul(Pz,I,B); + BN_copy(Qz,Pz); + MonMul(Px,x,B); + MonMul(Py,y,B); + } + else { + MonMul(Qx,x,B); + MonMul(Qy,y,B); + } +} + +void cMapCore::ToAffine(void) +{ + BN_set_word(I,1); + MonMul(B,Pz,Pz); MonMul(B,Pz,B); MonMul(B,I,B); + MonExpNeg(); + BN_set_word(I,1); + MonMul(A,Py,B); MonMul(Py,I,A); + MonMul(B,Pz,B); MonMul(B,Px,B); MonMul(Px,I,B); +} + +void cMapCore::CurveInit(BIGNUM *a) +{ + BN_zero(Px); BN_zero(Py); BN_zero(Pz); BN_zero(Qx); BN_zero(Qy); BN_zero(Qz); + BN_zero(sA0); BN_zero(sC0); BN_zero(sE0); BN_zero(s100); + BN_zero(s120); BN_zero(s140); BN_zero(s160); + MonInit(); + BN_copy(A,B); + BN_copy(I,D); + BN_add_word(I,1); + BN_rshift(I,I,1); + MonMul(s140,I,B); + MonMul(s160,B,a); +} + bool cMapCore::DoMap(int f, unsigned char *data, int l) { int dl=(l?l:wordsize)<<3; @@ -283,25 +454,27 @@ bool cMapCore::DoMap(int f, unsigned char *data, int l) #define N2FLAG_MECM 1 #define N2FLAG_Bx 2 #define N2FLAG_POSTAU 4 +#define N2FLAG_Ex 8 #define N2FLAG_INV 128 class cN2Prov { private: - unsigned seed[5], cwkey[8]; + unsigned char seed[32], cwkey[8]; bool keyValid; - cIDEA idea; protected: - int id, flags; + int id, flags, seedSize; + cIDEA idea; // - virtual bool Algo(int algo, const unsigned char *hd, unsigned char *hw) { return false; } + virtual bool Algo(int algo, unsigned char *hd, const unsigned char *ed, unsigned char *hw) { return false; } virtual bool NeedsCwSwap(void) { return false; } void ExpandInput(unsigned char *hw); public: cN2Prov(int Id, int Flags); virtual ~cN2Prov() {} - bool MECM(unsigned char in15, int algo, unsigned char *cws); + bool MECM(unsigned char in15, int algo, const unsigned char *ed, unsigned char *cw); void SwapCW(unsigned char *cw); virtual int ProcessBx(unsigned char *data, int len, int pos) { return -1; } + virtual int ProcessEx(unsigned char *data, int len, int pos) { return -1; } virtual bool PostProcAU(int id, unsigned char *data) { return true; } bool CanHandle(int Id) { return MATCH_ID(Id,id); } bool HasFlags(int Flags) { return (flags&Flags)==Flags; } @@ -310,14 +483,15 @@ public: cN2Prov::cN2Prov(int Id, int Flags) { - keyValid=false; id=Id|0x100; flags=Flags; + keyValid=false; id=Id|0x100; flags=Flags; seedSize=5; } void cN2Prov::PrintCaps(int c) { - PRINTF(c,"provider %04x capabilities%s%s%s%s",id, + PRINTF(c,"provider %04x capabilities%s%s%s%s%s",id, HasFlags(N2FLAG_MECM) ?" MECM":"", HasFlags(N2FLAG_Bx) ?" Bx":"", + HasFlags(N2FLAG_Ex) ?" Ex":"", HasFlags(N2FLAG_POSTAU) ?" POSTPROCAU":"", HasFlags(N2FLAG_INV) ?" INVCW":""); } @@ -339,27 +513,27 @@ void cN2Prov::ExpandInput(unsigned char *hw) } } -bool cN2Prov::MECM(unsigned char in15, int algo, unsigned char *cw) +bool cN2Prov::MECM(unsigned char in15, int algo, const unsigned char *ed, unsigned char *cw) { - unsigned char hd[5], hw[128+64], buf[20]; + unsigned char hd[32], hw[128+64], buf[20]; hd[0]=in15&0x7F; hd[1]=cw[14]; hd[2]=cw[15]; hd[3]=cw[6]; hd[4]=cw[7]; - if(keyValid && !memcmp(seed,hd,5)) { // key cached + if(keyValid && !memcmp(seed,hd,seedSize)) { // key cached memcpy(buf,cwkey,8); } else { // key not cached memset(hw,0,sizeof(hw)); - if(!Algo(algo,hd,hw)) return false; + if(!Algo(algo,hd,ed,hw)) return false; memcpy(&hw[128],hw,64); RotateBytes(&hw[64],128); SHA1(&hw[64],128,buf); RotateBytes(buf,20); - memcpy(seed,hd,5); + memcpy(seed,hd,seedSize); memcpy(cwkey,buf,8); keyValid=true; } @@ -578,6 +752,8 @@ bool cNagra2::DecryptEMM(const unsigned char *in, unsigned char *out, const unsi // -- cSystemNagra2 ------------------------------------------------------------ +static int dropEMMs=1; + class cSystemNagra2 : public cSystem, protected cNagra2 { private: int lastEcmId, lastEmmId; @@ -606,6 +782,8 @@ bool cSystemNagra2::ProcessECM(const cEcmInfo *ecm, unsigned char *data) { #define NA_SOURCE_START 0x8267 // cSource::FromString("S61.5W"); #define NA_SOURCE_END 0x85c8 // cSource::FromString("S148W"); + unsigned char odata[15]; + memcpy(odata,data,sizeof(odata)); if(ecm->source>=NA_SOURCE_START && ecm->source<=NA_SOURCE_END) { if(ecm->caId==0x1234) data[5]=0x09; // NA rev 248 morph else data[5]=0x01; // I _HATE_ this provider @@ -679,7 +857,13 @@ bool cSystemNagra2::ProcessECM(const cEcmInfo *ecm, unsigned char *data) break; case 0x00: i+=2; break; - case 0x30 ... 0x36: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: case 0xB0: i+=buff[i+1]+2; break; @@ -696,7 +880,7 @@ bool cSystemNagra2::ProcessECM(const cEcmInfo *ecm, unsigned char *data) if(l!=3) return false; if(mecmAlgo>0) { if(ecmP && ecmP->HasFlags(N2FLAG_MECM)) { - if(!ecmP->MECM(buff[15],mecmAlgo,cw)) return false; + if(!ecmP->MECM(buff[15],mecmAlgo,odata,cw)) return false; } else { PRINTF(L_SYS_ECM,"MECM for provider %04x not supported",id); return false; } } @@ -713,6 +897,7 @@ void cSystemNagra2::ProcessEMM(int pid, int caid, unsigned char *buffer) int cmdLen=buffer[9]-5; int id=buffer[10]*256+buffer[11]; + if(buffer[0]==0x83 && dropEMMs) return; // skip EMM-S if disabled if(cmdLen<96 || SCT_LEN(buffer)HasFlags(N2FLAG_Bx)) { @@ -841,7 +1029,24 @@ void cSystemNagra2::ProcessEMM(int pid, int caid, unsigned char *buffer) case 0xAE: i+=11;break; case 0x12: i+=emmdata[i+1]+2; break; // create tier case 0x20: i+=19; break; // modify tier - case 0xE3: i+=emmdata[i+4]+5; break; // Eeprom update + case 0x9F: i+=6; break; + case 0xE3: // Eeprom update + { + int ex=emmdata[i]&15; + if(!emmP || !emmP->HasFlags(N2FLAG_Ex)) { + i+=emmdata[i+4]+5; + PRINTF(L_SYS_EMM,"E%X for provider %04x not supported",ex,id); + break; + } + int r; + if((r=emmP->ProcessEx(emmdata,cmdLen,i+1))>0) + i+=r; + else { + PRINTF(L_SYS_EMM,"E%X executing failed for %04x",ex,id); + i=cmdLen; + } + break; + } case 0xE1: case 0xE2: case 0x00: i=cmdLen; break; // end of processing @@ -859,52 +1064,6 @@ void cSystemNagra2::ProcessEMM(int pid, int caid, unsigned char *buffer) // -- cSystemLinkNagra2 -------------------------------------------------------- -static const tI18nPhrase Phrases2[] = { - { "Nagra2: AUXserver hostname", - "Nagra2: AUXserver Hostname", - "", - "", - "", - "", - "", - "", - "Nagra2: AUX-palvelimen osoite", - "", - "", - "", - "", - }, - { "Nagra2: AUXserver port", - "Nagra2: AUXserver Port", - "", - "", - "", - "", - "", - "", - "Nagra2: AUX-palvelimen portti", - "", - "", - "", - "", - }, - { "Nagra2: AUXserver password", - "Nagra2: AUXserver Passwort", - "", - "", - "", - "", - "", - "", - "Nagra2: AUX-palvelimen salasana", - "", - "", - "", - "", - }, - { NULL } - }; - class cSystemLinkNagra2 : public cSystemLink { public: cSystemLinkNagra2(void); @@ -917,13 +1076,14 @@ static cSystemLinkNagra2 staticInitN2; cSystemLinkNagra2::cSystemLinkNagra2(void) :cSystemLink(SYSTEM_NAME,SYSTEM_PRI) { + opts=new cOpts(SYSTEM_NAME,5); + opts->Add(new cOptBool("DropEMMS",trNOOP("Nagra2: drop EMM-S packets"),&dropEMMs)); #ifdef HAS_AUXSRV static const char allowed_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz-."; - opts=new cOpts(SYSTEM_NAME,3); - opts->Add(new cOptStr("AuxServerAddr","Nagra2: AUXserver hostname",auxAddr,sizeof(auxAddr),allowed_chars)); - opts->Add(new cOptInt("AuxServerPort","Nagra2: AUXserver port",&auxPort,0,65535)); - opts->Add(new cOptStr("AuxServerPass","Nagra2: AUXserver password",auxPassword,sizeof(auxPassword),allowed_chars)); - Feature.AddPhrases(Phrases2); + opts->Add(new cOptBool("AuxServerEnable",trNOOP("Nagra2: Enable AUXserver"),&auxEnabled)); + opts->Add(new cOptStr("AuxServerAddr",trNOOP("Nagra2: AUXserver hostname"),auxAddr,sizeof(auxAddr),allowed_chars)); + opts->Add(new cOptInt("AuxServerPort",trNOOP("Nagra2: AUXserver port"),&auxPort,0,65535)); + opts->Add(new cOptStr("AuxServerPass",trNOOP("Nagra2: AUXserver password"),auxPassword,sizeof(auxPassword),allowed_chars)); #endif Feature.NeedsKeyFile(); } diff --git a/systems/sc-irdeto/sc-irdeto.c b/systems/sc-irdeto/sc-irdeto.c index ecb1659..2a316f5 100644 --- a/systems/sc-irdeto/sc-irdeto.c +++ b/systems/sc-irdeto/sc-irdeto.c @@ -50,7 +50,7 @@ ADD_MODULE(L_SC,lm_sc) static void BN_complement(const unsigned char *data, int len, BIGNUM *bn) { - unsigned char buff[len]; + unsigned char *buff=AUTOMEM(len); for(int i=len-1; i>=0; i--) buff[i]=~data[i]; BN_bin2bn(buff,len,bn); BN_add_word(bn,1); diff --git a/systems/sc-videoguard2/sc-videoguard2.c b/systems/sc-videoguard2/sc-videoguard2.c index 1528b75..f36639d 100644 --- a/systems/sc-videoguard2/sc-videoguard2.c +++ b/systems/sc-videoguard2/sc-videoguard2.c @@ -413,7 +413,7 @@ struct CmdTab { unsigned char size; unsigned char Nentries; unsigned char dummy; - CmdTabEntry e[0]; + CmdTabEntry e[1]; }; class CmdTable { diff --git a/systems/seca/seca.c b/systems/seca/seca.c index 8376da2..3a0fa0c 100644 --- a/systems/seca/seca.c +++ b/systems/seca/seca.c @@ -124,7 +124,7 @@ bool cPlainKeySeca::Parse(const char *line) break; } if(ok) { - unsigned char skey[keylen]; + unsigned char *skey=AUTOMEM(keylen); len=GetHex(line,skey,keylen,false); if(IsBNKey()) { if(C2(keynr)=='E' && len==PLAINLEN_SECA_E) { @@ -1225,8 +1225,8 @@ bool cSystemSeca::ProcessECM(const cEcmInfo *ecmD, unsigned char *data) bool key8=!(cParseSeca::SysMode(data)&0x10); cPlainKey *pk=0; cKeySnoop ks(this,'S',ecmD->provId,keyNr&0x0F); + unsigned char *buff=AUTOMEM(msgLen); while((pk=keys.FindKey('S',ecmD->provId,keyNr&0x0F,key8?8:16,pk))) { - unsigned char buff[msgLen]; memcpy(buff,ecm,sizeof(buff)); // if decoding fails we need the original data unsigned char PK[16], signature[20]; @@ -1551,6 +1551,7 @@ void cSystemSeca::ProcessEMM(int pid, int caid, unsigned char *buffer) } } + unsigned char *buff=AUTOMEM(msgLen); for(cSecaCardInfo *ci=Scards.First(); ci; ci=Scards.Next(ci)) { if(ci->MatchEMM(buffer) || (CheckNull(ci->sa,sizeof(ci->sa)) && ci->MatchID(buffer))) { unsigned char MK[16]; @@ -1563,7 +1564,7 @@ void cSystemSeca::ProcessEMM(int pid, int caid, unsigned char *buffer) memcpy(&MK[8],ci->key,8); } - unsigned char buff[msgLen], signature[20]; + unsigned char signature[20]; memcpy(buff,emm,sizeof(buff)); // if decoding fails we need the original de-sse'd data if(!SE) { diff --git a/systems/viaccess/st20.c b/systems/viaccess/st20.c index c619dcc..8cc3253 100644 --- a/systems/viaccess/st20.c +++ b/systems/viaccess/st20.c @@ -148,22 +148,22 @@ void cST20::SetReg(int reg, unsigned int val) unsigned char *cST20::Addr(unsigned int off) { - switch(off) { - case FLASHS ... FLASHE: + if(off>=FLASHS && off<=FLASHE) { #ifndef SAVE_DEBUG - return &flash[off-FLASHS]; + return &flash[off-FLASHS]; #else - off-=FLASHS; if(off=RAMS && off<=RAME) { #ifndef SAVE_DEBUG - return &ram[off-RAMS]; + return &ram[off-RAMS]; #else - off-=RAMS; if(off=IRAMS && off<=IRAME) + return &iram[off-IRAMS]; #ifndef SAVE_DEBUG invalid=ERRORVAL; return (unsigned char *)&invalid; #else diff --git a/systems/viaccess/tps.c b/systems/viaccess/tps.c index 8bc8d01..9203b73 100644 --- a/systems/viaccess/tps.c +++ b/systems/viaccess/tps.c @@ -74,7 +74,7 @@ void cRC6::SetKey(const unsigned char *Key, int len) key[0]=RC6_P32; for(int v=1; vRC6_MAX ? len : RC6_MAX) ; v>0; v--) { a=key[i]=rol(key[i]+a+b,3); @@ -440,7 +440,13 @@ bool cOpenTVModule::DoDecompress(unsigned char *out_ptr, const unsigned char *in int off=0, len=0; unsigned char cmd=BYTE(); in_ptr++; switch(cmd>>4) { - case 0x0 ... 0x6: + case 0x0: + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: off=((cmd&0xF)<<8)+BYTE(); in_ptr++; len=((cmd>>4)&0x7)+3; break; @@ -461,14 +467,19 @@ bool cOpenTVModule::DoDecompress(unsigned char *out_ptr, const unsigned char *in } break; } - case 0x8 ... 0xB: + case 0x8: + case 0x9: + case 0xA: + case 0xB: if(cmd&0x20) NIBBLE(off); else off=0; off=(off<<1)|(cmd&0x1F); len=2; break; case 0xC: off=cmd&0x0F; len=3; break; - case 0xD ... 0xF: + case 0xD: + case 0xE: + case 0xF: NIBBLE(off); off|=cmd&0x0F; len=((cmd>>4)&0x3)+2; break; @@ -717,6 +728,9 @@ bool cTpsKeys::ProcessAu(const cOpenTVModule *mod) for(int j=2; j < 0xC; j++) if(!memcmp(&d[addr+j],scan1,sizeof(scan1))) { cb1=addr; break; } } + else if(cb1 && !cb2) cb2=addr; + else if(cb1 && cb2 && !cb3) cb3=addr; +/* else if((d[addr]&0xF0)==0x60 && (d[addr+1]&0xF0)==0xB0) { int vajw = (int)(((~(d[addr]&0x0F))<<4)|(d[addr+1]&0x0F)); unsigned char hits=0; @@ -733,6 +747,7 @@ bool cTpsKeys::ProcessAu(const cOpenTVModule *mod) else if(cb3==0) cb3=addr; } } +*/ } } } diff --git a/testing/Makefile b/testing/Makefile index 209f8e7..fc03ea2 100644 --- a/testing/Makefile +++ b/testing/Makefile @@ -64,3 +64,4 @@ clean: @-rm -f *.o core* *~ @-rm -f testECM testEMM testN1Emu testN2Emu @-rm -f filterhelper + @-rm -f dump.txt diff --git a/testing/compat.c b/testing/compat.c index 87b486f..bd9c397 100644 --- a/testing/compat.c +++ b/testing/compat.c @@ -80,7 +80,9 @@ int ReadRaw(const char *name, unsigned char *buff, int maxlen) int len=0; while(len int main(int argc, char *argv[]) { - if(argc<5) { - printf("usage: %s \n",argv[0]); + if(argc<6) { + printf("usage: %s \n",argv[0]); return 1; } DllsLoad(argv[1]); InitAll(argv[2]); LogAll(); + cLogging::SetModuleOption(LCLASS(7,0x20<<2),false); // Nagra L_SYS_DISASM + cLogging::SetModuleOption(LCLASS(7,0x20<<4),false); // Nagra L_SYS_CPUSTATS unsigned char ecm[4096]; - ReadRaw(argv[5],ecm,sizeof(ecm)); + ReadRaw(argv[6],ecm,sizeof(ecm)); int caid=strtol(argv[3],0,0); int provid=strtol(argv[4],0,0); printf("using caid %04x provid %04x\n",caid,provid); cEcmInfo ecmD("dummy",0x123,caid,provid); + ecmD.SetSource(10,cSource::FromString(argv[5]),120); cSystem *sys=0; int lastPri=0; while((sys=cSystems::FindBySysId(caid,false,lastPri))) { lastPri=sys->Pri(); printf("processing with module '%s'\n",sys->Name()); bool res=sys->ProcessECM(&ecmD,ecm); + if(res) { + printf("resulting CW: "); + SDump(sys->CW(),16); + } delete sys; if(res) break; } diff --git a/testing/testN2Emu.c b/testing/testN2Emu.c index 4c0ef89..3d36e62 100644 --- a/testing/testN2Emu.c +++ b/testing/testN2Emu.c @@ -96,11 +96,7 @@ bool Ecm(unsigned char *buff, int cmdLen, int id) unsigned char cw[16]; cN2Prov *ecmP=cN2Providers::GetProv(id,N2FLAG_NONE); - if(ecmP) printf("provider %04x capabilities%s%s%s%s\n",id, - ecmP->HasFlags(N2FLAG_MECM) ?" MECM":"", - ecmP->HasFlags(N2FLAG_Bx) ?" Bx":"", - ecmP->HasFlags(N2FLAG_POSTAU) ?" POSTPROCAU":"", - ecmP->HasFlags(N2FLAG_INV) ?" INVCW":""); + if(ecmP) ecmP->PrintCaps(L_SYS_ECM); int l=0, mecmAlgo=0; for(int i=16; i0) { if(ecmP && ecmP->HasFlags(N2FLAG_MECM)) { - if(!ecmP->MECM(buff[15],mecmAlgo,cw)) return false; +static unsigned char odata[15] = { 0x80,0x30,0x47,0x07,0x45,0xec,0xc1,0xee,0xc5,0x53,0x91,0x2f,0x70,0x34,0x34 }; + if(!ecmP->MECM(buff[15],mecmAlgo,odata,cw)) return false; } else { printf("MECM for provider %04x not supported\n",id); return false; } } diff --git a/version.h b/version.h index 6aab704..61f45b7 100644 --- a/version.h +++ b/version.h @@ -21,8 +21,8 @@ #define ___VERSION_H // all release versions must end with 0xFF !! -#define SCVERSNUM 0x000805FF -#define SCVERSION "0.8.5" +#define SCVERSNUM 0x000806FF +#define SCVERSION "0.8.6" extern const char *ScVersion; -- 2.39.5