rendered paste body--- sc/PLUGINS/src/sc-src/systems/nagra/nagra1.c (revision 103)+++ sc/PLUGINS/src/sc-src/systems/nagra/nagra1.c (working copy)@@ -27,6 +27,7 @@ #include "system.h" #include "misc.h" #include "opts.h"+#include "helper.h" #include "debug.h" #include "nagra.h"@@ -512,7 +513,7 @@ for(int j=0; j<rounds; j++) { unsigned char cr[8]; Crypt(block+j*8,hash,cr);- for(int i=0; i<8; i++) hash[i]=cr[i]^block[j*8+i];+ xxor(hash,8,cr,&block[j*8]); } return (0==memcmp(hash,sig,8)); }--- sc/PLUGINS/src/sc-src/systems/nagra/nagra2-0501.c (revision 103)+++ sc/PLUGINS/src/sc-src/systems/nagra/nagra2-0501.c (working copy)@@ -17,13 +17,82 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */ -// -- cN2Prov0501 ----------------------------------------------------------------+// -- cMap0501 ----------------------------------------------------------------- -class cN2Prov0501 : public cN2Prov {+class cMap0501 : public cMapCore {+private: protected:+ void DoMap(int f, unsigned char *data=0, int l=0);+public:+ cMap0501(void);+ };++cMap0501::cMap0501(void)+{+}++void cMap0501::DoMap(int f, unsigned char *data, int l)+{+ PRINTF(L_SYS_MAP,"0501: calling function %02X",f);+ switch(f) {+ case 0x37:+ l=(l?l:wordsize)<<3;+ H.GetLE(data,l);+ MonMul(B,H,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);+ MonMul(B,A,B);+ break;+ default:+ if(!cMapCore::DoMap(f,data,l))+ PRINTF(L_SYS_MAP,"0501: unsupported call %02x",f);+ break;+ }+}++// -- cN2Prov0501 --------------------------------------------------------------++class cN2Prov0501 : public cN2Prov, private cMap0501 {+protected:+ virtual bool Algo(int algo, const unsigned char *hd, unsigned char *hw); virtual bool NeedsCwSwap(void) { return true; } public: cN2Prov0501(int Id, int Flags):cN2Prov(Id,Flags) {} }; -static cN2ProvLinkReg<cN2Prov0501,0x0501,N2FLAG_INV> staticPL0501;+static cN2ProvLinkReg<cN2Prov0501,0x0501,N2FLAG_MECM|N2FLAG_INV> staticPL0501;++bool cN2Prov0501::Algo(int algo, const unsigned char *hd, unsigned char *hw)+{+ if(algo==0x60) {+ hw[0]=hd[0];+ hw[1]=hd[1];+ hw[2]=hd[2]&0xF8;+ ExpandInput(hw);+ hw[63]|=0x80;+ hw[95]=hw[127]=hw[95]&0x7F;+ SetWordSize(4);+ ImportReg(IMPORT_J,hw+0x18);+ ImportReg(IMPORT_D,hw+0x20);+ ImportReg(IMPORT_A,hw+0x60);+ DoMap(0x37,hw+0x40);+ ExportReg(EXPORT_C,hw);+ DoMap(0x3a);+ ExportReg(EXPORT_C,hw+0x20);+ DoMap(0x43);+ DoMap(0x44,hw);+ hw[0]&=7;+ ExportReg(EXPORT_B,hw+3);+ memset(hw+3+0x20,0,128-(3+0x20));+ return true;+ }++ PRINTF(L_SYS_ECM,"0501: unknown MECM algo %02x",algo);+ return false;+}--- sc/PLUGINS/src/sc-src/systems/nagra/nagra2.c (revision 103)+++ sc/PLUGINS/src/sc-src/systems/nagra/nagra2.c (working copy)@@ -88,6 +88,155 @@ return true; } +// -- cMapCore -----------------------------------------------------------------++#define SETSIZE 0x02+#define IMPORT_J 0x03+#define IMPORT_A 0x04+#define IMPORT_B 0x05+#define IMPORT_C 0x06+#define IMPORT_D 0x07+#define EXPORT_A 0x0A+#define EXPORT_B 0x0B+#define EXPORT_C 0x0C+#define EXPORT_D 0x0D++class cMapCore {+private:+ cBN x, y, s, j;+ SHA_CTX sctx;+protected:+ cBN A, B, C, D, J;+ cBN H, R;+ cBNctx ctx;+ int wordsize;+ //+ void ImportReg(unsigned char reg, const unsigned char *data, int l=0);+ void ExportReg(unsigned char reg, unsigned char *data, int l=0, bool BE=false);+ void SetWordSize(int l) { wordsize=l; }+ 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);+ };++cMapCore::cMapCore(void)+{+ wordsize=4;+}++void cMapCore::ImportReg(unsigned char reg, const unsigned char *in, int l)+{+ l=(l?l:wordsize)<<3;+ switch(reg) {+ case IMPORT_J: J.GetLE(in,8); break;+ case IMPORT_A: A.GetLE(in,l); break;+ case IMPORT_B: B.GetLE(in,l); break;+ case IMPORT_C: C.GetLE(in,l); break;+ case IMPORT_D: D.GetLE(in,l); break;+ default: PRINTF(L_GEN_DEBUG,"internal: nagramap import register not supported"); return;+ }+}++void cMapCore::ExportReg(unsigned char reg, unsigned char *out, int l, bool BE)+{+ l=(l?l:wordsize)<<3;+ cBN *ptr;+ switch(reg) {+ case EXPORT_A: ptr=&A; break;+ case EXPORT_B: ptr=&B; break;+ case EXPORT_C: ptr=&C; break;+ case EXPORT_D: ptr=&D; break;+ default: PRINTF(L_GEN_DEBUG,"internal: nagramap export register not supported"); return;+ }+ if(!BE) ptr->PutLE(out,l);+ else ptr->Put(out,l);+}++void cMapCore::MakeJ(void)+{+#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_set_bit(x,64);+ BN_mod_inverse(J,J,x,ctx);+}++void cMapCore::MonMul(BIGNUM *o, BIGNUM *i1, BIGNUM *i2)+{+ int words=(BN_num_bytes(i1)+7)>>3;+ BN_zero(s);+ for(int i=0; i<words; i++) { + BN_rshift(x,i1,i<<6);+ BN_mask_bits(x,64);+ BN_mul(x,x,i2,ctx);+ BN_add(s,s,x);++ BN_copy(x,s);+ BN_mask_bits(x,64);+ BN_mul(x,x,J,ctx);+ if(i==(words-1)) {+ BN_lshift(y,x,64);+ BN_add(y,y,x);+ // Low+ BN_rshift(C,y,2);+ BN_add(C,C,s);+ BN_rshift(C,C,52);+ BN_mask_bits(C,12);+ }++ BN_mask_bits(x,64);+ BN_mul(x,x,D,ctx);+ BN_add(s,s,x);+ if(i==(words-1)) {+ // High+ BN_lshift(y,s,12);+ BN_add(C,C,y);+ BN_mask_bits(C,wordsize<<6);+ }++ BN_rshift(s,s,64);+ if(BN_cmp(s,D)==1) {+ BN_copy(x,s);+ BN_sub(s,x,D);+ }+ }+ BN_copy(o,s);+}++bool cMapCore::DoMap(int f, unsigned char *data, int l)+{+ switch(f) {+ case 0x43: // init SHA1+ SHA1_Init(&sctx);+ break;+ case 0x44: // add 64 bytes to SHA1 buffer+ RotateBytes(data,64);+ SHA1_Update(&sctx,data,64);+ BYTE4_LE(data ,sctx.h4);+ BYTE4_LE(data+4 ,sctx.h3);+ BYTE4_LE(data+8 ,sctx.h2);+ BYTE4_LE(data+12,sctx.h1);+ BYTE4_LE(data+16,sctx.h0);+ break;+ case 0x45: // add wordsize bytes to SHA1 buffer and finalize SHA result+ if(wordsize) {+ if(wordsize>1) RotateBytes(data,wordsize);+ SHA1_Update(&sctx,data,wordsize);+ }+ memset(data,0,64);+ SHA1_Final(data+64,&sctx);+ break;+ default:+ return false;+ }+ return true;+}+ // -- cN2Prov ------------------------------------------------------------------ class cN2Prov {@@ -274,12 +423,12 @@ // expand IDEA-G key unsigned char idata[96]; for(int i=11; i>=0; i--) {- const int off=i*8;- memcpy(&idata[off],&key[13],8);- idata[off]^=i;- idea.Decrypt(&idata[off],8,&ks,0);- for(int j=7; j>=0; j--) idata[off+j] ^= key[13+j];- idata[off]^=i;+ unsigned char *d=&idata[i*8];+ memcpy(d,&key[13],8);+ *d^=i;+ idea.Decrypt(d,8,&ks,0);+ xxor(d,8,d,&key[13]);+ *d^=i; } // Calculate P idata[0] |= 0x80;@@ -302,7 +451,7 @@ idea.SetEncKey(buff,&ks); memcpy(buff,buff+8,8); idea.Encrypt(msg+i,8,buff+8,&ks,0);- for(int j=7; j>=0; j--) buff[j+8]^=msg[i+j];+ xxor(&buff[8],8,&buff[8],msg+i); } buff[8]&=0x7F; return (memcmp(sig,buff+8,8)==0);@@ -467,7 +616,7 @@ break; case 0x00: i+=2; break;- case 0x13 ... 0x15:+ case 0x13 ... 0x17: i+=4; break; case 0x30 ... 0x36: case 0xB0:@@ -592,11 +741,12 @@ i+=emmdata[i+1]+2+4; break; case 0xA6:- i+=emmdata[i+1]+1;+ i+=15;+ break;+ case 0xAE:+ i+=11; break;- case 0x13:- case 0x14:- case 0x15:+ case 0x13 ... 0x17: // Date i+=4; break; case 0xB0: // Update with ROM101 CPU code