📄 nagra2.c
字号:
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){ const int l1=l?l:wordsize; const int dl=l1<<3; cycles=0; switch(f) { case SETSIZE: wordsize=l; cycles=475-6; break; case IMPORT_J: cycles=890-6; // fall through case IMPORT_A: case IMPORT_B: case IMPORT_C: case IMPORT_D: if(!cycles) cycles=771+160*l1-6+(l==0?4:0); last=f-IMPORT_J; // fall through case IMPORT_LAST: if(!cycles) cycles=656+160*l-6; // Even for 'J' cycles is dependent on 'l' regs[last]->GetLE(data,last>0?dl:8); break; case EXPORT_J: cycles=897-6; // fall through case EXPORT_A: case EXPORT_B: case EXPORT_C: case EXPORT_D: if(!cycles) cycles=778+160*l1-6+(l==0?4:0); last=f-EXPORT_J; // fall through case EXPORT_LAST: if(!cycles) cycles=668+160*l-6; // Even for 'J' cycles is dependent on 'l' regs[last]->PutLE(data,last>0?dl:8); break; case SWAP_A: case SWAP_B: case SWAP_C: case SWAP_D: cycles=776+248*l1-6; last=f-SWAP_A+1; x.GetLE(data,dl); regs[last]->PutLE(data,dl); BN_copy(*regs[last],x); break; case CLEAR_A: case CLEAR_B: case CLEAR_C: case CLEAR_D: cycles=467+5*l1-6; last=f-CLEAR_A+1; BN_zero(*regs[last]); break; case COPY_A_B: last=2; BN_copy(B,A); cycles=467+5*l1-6; break; case COPY_B_A: last=1; BN_copy(A,B); cycles=467+5*l1-6; break; case COPY_A_C: last=3; BN_copy(C,A); cycles=467+5*l1-6; break; case COPY_C_A: last=1; BN_copy(A,C); cycles=467+5*l1-6; break; case COPY_C_D: last=4; BN_copy(D,C); cycles=467+5*l1-6; break; case COPY_D_C: last=3; BN_copy(C,D); cycles=467+5*l1-6; break; 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 ------------------------------------------------------------------cN2Prov::cN2Prov(int Id, int Flags){ keyValid=false; id=Id|0x100; flags=Flags; seedSize=5;}void cN2Prov::PrintCaps(int c){ 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":"");}void cN2Prov::ExpandInput(unsigned char *hw){ hw[0]^=(0xDE +(0xDE<<1)) & 0xFF; hw[1]^=(hw[0]+(0xDE<<1)) & 0xFF; for(int i=2; i<128; i++) hw[i]^=hw[i-2]+hw[i-1]; IdeaKS ks; idea.SetEncKey((unsigned char *)"NagraVision S.A.",&ks); unsigned char buf[8]; memset(buf,0,8); for(int i=0; i<128; i+=8) { xxor(buf,8,buf,&hw[i]); idea.Encrypt(buf,8,buf,&ks,0); xxor(buf,8,buf,&hw[i]); memcpy(&hw[i],buf,8); }}bool cN2Prov::MECM(unsigned char in15, int algo, const unsigned char *ed, unsigned char *cw){ 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]; DynamicHD(hd,ed); 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; memcpy(&hw[128],hw,64); RotateBytes(&hw[64],128); SHA1(&hw[64],128,buf); RotateBytes(buf,20); memcpy(seed,hd,seedSize); memcpy(cwkey,buf,8); keyValid=true; } memcpy(&buf[8],buf,8); IdeaKS ks; idea.SetEncKey(buf,&ks); memcpy(&buf[0],&cw[8],6); memcpy(&buf[6],&cw[0],6); idea.Encrypt(&buf[4],8,&buf[4],&ks,0); idea.Encrypt(buf,8,buf,&ks,0); memcpy(&cw[ 0],&buf[6],3); memcpy(&cw[ 4],&buf[9],3); memcpy(&cw[ 8],&buf[0],3); memcpy(&cw[12],&buf[3],3); for(int i=0; i<16; i+=4) cw[i+3]=cw[i]+cw[i+1]+cw[i+2]; return true;}void cN2Prov::SwapCW(unsigned char *cw){ if(NeedsCwSwap()) { unsigned char tt[8]; memcpy(&tt[0],&cw[0],8); memcpy(&cw[0],&cw[8],8); memcpy(&cw[8],&tt[0],8); }}// -- cN2Providers -------------------------------------------------------------cN2ProvLink *cN2Providers::first=0;void cN2Providers::Register(cN2ProvLink *plink){ PRINTF(L_CORE_DYN,"n2providers: registering prov %04X with flags %d",plink->id,plink->flags); plink->next=first; first=plink;}cN2Prov *cN2Providers::GetProv(int Id, int Flags){ cN2ProvLink *pl=first; while(pl) { if(pl->CanHandle(Id) && pl->HasFlags(Flags)) return pl->Create(); pl=pl->next; } return 0;}// -- cN2ProvLink --------------------------------------------------------------cN2ProvLink::cN2ProvLink(int Id, int Flags){ id=Id; flags=Flags; cN2Providers::Register(this);}// -- cNagra2 ------------------------------------------------------------------class cNagra2 : public cNagra {private: bool Signature(const unsigned char *vkey, const unsigned char *sig, const unsigned char *msg, int len);protected: cIDEA idea; // virtual void CreatePQ(const unsigned char *key, BIGNUM *p, BIGNUM *q); bool DecryptECM(const unsigned char *in, unsigned char *out, const unsigned char *key, int len, const unsigned char *vkey, BIGNUM *m); bool DecryptEMM(const unsigned char *in, unsigned char *out, const unsigned char *key, int len, const unsigned char *vkey, BIGNUM *m); };void cNagra2::CreatePQ(const unsigned char *key, BIGNUM *p, BIGNUM *q){ // Calculate P and Q from PK IdeaKS ks; idea.SetEncKey(key,&ks); // expand IDEA-G key unsigned char idata[96]; for(int i=11; i>=0; 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; idata[47] |= 1; BN_bin2bn(idata,48,p); BN_add_word(p,(key[21] << 5 ) | ((key[22] & 0xf0) >> 3)); // Calculate Q idata[48] |= 0x80; idata[95] |= 1; BN_bin2bn(idata+48,48,q); BN_add_word(q,(key[22] &0xf << 9 ) | (key[23]<<1));}bool cNagra2::Signature(const unsigned char *vkey, const unsigned char *sig, const unsigned char *msg, int len){ unsigned char buff[16]; memcpy(buff,vkey,sizeof(buff)); for(int i=0; i<len; i+=8) { IdeaKS ks; idea.SetEncKey(buff,&ks); memcpy(buff,buff+8,8); idea.Encrypt(msg+i,8,buff+8,&ks,0); xxor(&buff[8],8,&buff[8],msg+i); } buff[8]&=0x7F; return (memcmp(sig,buff+8,8)==0);}bool cNagra2::DecryptECM(const unsigned char *in, unsigned char *out, const unsigned char *key, int len, const unsigned char *vkey, BIGNUM *m){ int sign=in[0] & 0x80; if(rsa.RSA(out,in+1,64,pubExp,m)<=0) { PRINTF(L_SYS_CRYPTO,"first RSA failed (ECM)"); return false; } out[63]|=sign; // sign adjustment if(len>64) memcpy(out+64,in+65,len-64); if(in[0]&0x04) { unsigned char tmp[8]; DES_key_schedule ks1, ks2; RotateBytes(tmp,&key[0],8); DES_key_sched((DES_cblock *)tmp,&ks1); RotateBytes(tmp,&key[8],8); DES_key_sched((DES_cblock *)tmp,&ks2); memset(tmp,0,sizeof(tmp)); for(int i=7; i>=0; i--) RotateBytes(out+8*i,8); DES_ede2_cbc_encrypt(out,out,len,&ks1,&ks2,(DES_cblock *)tmp,DES_DECRYPT); for(int i=7; i>=0; i--) RotateBytes(out+8*i,8); } else idea.Decrypt(out,len,key,0); RotateBytes(out,64); if(rsa.RSA(out,out,64,pubExp,m,false)<=0) { PRINTF(L_SYS_CRYPTO,"second RSA failed (ECM)"); return false; } if(vkey && !Signature(vkey,out,out+8,len-8)) { PRINTF(L_SYS_CRYPTO,"signature failed (ECM)"); return false; } return true;}bool cNagra2::DecryptEMM(const unsigned char *in, unsigned char *out, const unsigned char *key, int len, const unsigned char *vkey, BIGNUM *m)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -