📄 ffdecsa.c
字号:
XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*4+g],&r[roff+GROUP_PARALLELISM*0+g]); XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*3+g],&r[roff+GROUP_PARALLELISM*0+g]); XOREQ_BEST_BY(&r[roff+GROUP_PARALLELISM*2+g],&r[roff+GROUP_PARALLELISM*0+g]); }#endif }#define FASTTRASP2#ifndef FASTTRASP2 for(g=0;g<count;g++){ // Copy results int j; for(j=0;j<8;j++){ bd[8*g+j]=r[roff+GROUP_PARALLELISM*j+g]; } }#else trasp_8_N((unsigned char *)&r[roff],(unsigned char *)bd,count);#endif}//-----------------------------------EXTERNAL INTERFACE//-----get internal parallelismint get_internal_parallelism(void){ return GROUP_PARALLELISM;}//-----get suggested cluster sizeint get_suggested_cluster_size(void){ int r; r=GROUP_PARALLELISM+GROUP_PARALLELISM/10; if(r<GROUP_PARALLELISM+5) r=GROUP_PARALLELISM+5; return r;}//-----key structurevoid *get_key_struct(void){ struct csa_keys_t *keys=(struct csa_keys_t *)MALLOC(sizeof(struct csa_keys_t)); if(keys) { static const unsigned char pk[8] = { 0,0,0,0,0,0,0,0 }; set_control_words(keys,pk,pk); } return keys;}void free_key_struct(void *keys){ return FREE(keys);}//-----set control wordsstatic void schedule_key(struct csa_key_t *key, const unsigned char *pk){ // could be made faster, but is not run often int bi,by; int i,j;// key memcpy(key->ck,pk,8);// precalculations for stream key_schedule_stream(key->ck,key->iA,key->iB); for(by=0;by<8;by++){ for(bi=0;bi<8;bi++){ key->ck_g[by][bi]=(key->ck[by]&(1<<bi))?FF1():FF0(); } } for(by=0;by<8;by++){ for(bi=0;bi<4;bi++){ key->iA_g[by][bi]=(key->iA[by]&(1<<bi))?FF1():FF0(); key->iB_g[by][bi]=(key->iB[by]&(1<<bi))?FF1():FF0(); } }// precalculations for block key_schedule_block(key->ck,key->kk); for(i=0;i<56;i++){ for(j=0;j<BYTES_PER_BATCH;j++){ *(((unsigned char *)&key->kkmulti[i])+j)=key->kk[i]; } }}void set_control_words(void *keys, const unsigned char *ev, const unsigned char *od){ schedule_key(&((struct csa_keys_t *)keys)->even,ev); schedule_key(&((struct csa_keys_t *)keys)->odd,od);}void set_even_control_word(void *keys, const unsigned char *pk){ schedule_key(&((struct csa_keys_t *)keys)->even,pk);}void set_odd_control_word(void *keys, const unsigned char *pk){ schedule_key(&((struct csa_keys_t *)keys)->odd,pk);}//-----get control wordsvoid get_control_words(void *keys, unsigned char *even, unsigned char *odd){ memcpy(even,&((struct csa_keys_t *)keys)->even.ck,8); memcpy(odd,&((struct csa_keys_t *)keys)->odd.ck,8);}//----- decryptint decrypt_packets(void *keys, unsigned char **cluster){ // statistics, currently unused int stat_no_scramble=0; int stat_reserved=0; int stat_decrypted[2]={0,0}; int stat_decrypted_mini=0; unsigned char **clst; unsigned char **clst2; int grouped; int group_ev_od; int advanced; int can_advance; unsigned char *g_pkt[GROUP_PARALLELISM]; int g_len[GROUP_PARALLELISM]; int g_offset[GROUP_PARALLELISM]; int g_n[GROUP_PARALLELISM]; int g_residue[GROUP_PARALLELISM]; unsigned char *pkt; int xc0,ev_od,len,offset,n,residue; struct csa_key_t* k; int i,j,iter,g; int t23,tsmall; int alive[24];//icc craziness int pad1=0; //////////align! FIXME unsigned char *encp[GROUP_PARALLELISM]; unsigned char stream_in[GROUP_PARALLELISM*8]; unsigned char stream_out[GROUP_PARALLELISM*8]; MEMALIGN unsigned char ib[GROUP_PARALLELISM*8]; MEMALIGN unsigned char block_out[GROUP_PARALLELISM*8]; struct stream_regs regs;//icc craziness i=(int)&pad1;//////////align!!! FIXME // build a list of packets to be processed clst=cluster; grouped=0; advanced=0; can_advance=1; group_ev_od=-1; // silence incorrect compiler warning pkt=*clst; do{ // find a new packet if(grouped==GROUP_PARALLELISM){ // full break; } if(pkt==NULL){ // no more ranges break; } if(pkt>=*(clst+1)){ // out of this range, try next clst++;clst++; pkt=*clst; continue; } do{ // handle this packet xc0=pkt[3]&0xc0; DBG(fprintf(stderr," exam pkt=%p, xc0=%02x, can_adv=%i\n",pkt,xc0,can_advance)); if(xc0==0x00){ DBG(fprintf(stderr,"skip clear pkt %p (can_advance is %i)\n",pkt,can_advance)); advanced+=can_advance; stat_no_scramble++; break; } if(xc0==0x40){ DBG(fprintf(stderr,"skip reserved pkt %p (can_advance is %i)\n",pkt,can_advance)); advanced+=can_advance; stat_reserved++; break; } if(xc0==0x80||xc0==0xc0){ // encrypted ev_od=(xc0&0x40)>>6; // 0 even, 1 odd if(grouped==0) group_ev_od=ev_od; // this group will be all even (or odd) if(group_ev_od==ev_od){ // could be added to group pkt[3]&=0x3f; // consider it decrypted now if(pkt[3]&0x20){ // incomplete packet offset=4+pkt[4]+1; len=188-offset; n=len>>3; residue=len-(n<<3); if(n==0){ // decrypted==encrypted! DBG(fprintf(stderr,"DECRYPTED MINI! (can_advance is %i)\n",can_advance)); advanced+=can_advance; stat_decrypted_mini++; break; // this doesn't need more processing } }else{ len=184; offset=4; n=23; residue=0; } g_pkt[grouped]=pkt; g_len[grouped]=len; g_offset[grouped]=offset; g_n[grouped]=n; g_residue[grouped]=residue; DBG(fprintf(stderr,"%2i: eo=%i pkt=%p len=%03i n=%2i residue=%i\n",grouped,ev_od,pkt,len,n,residue)); grouped++; advanced+=can_advance; stat_decrypted[ev_od]++; } else{ can_advance=0; DBG(fprintf(stderr,"skip pkt %p and can_advance set to 0\n",pkt)); break; // skip and go on } } } while(0); if(can_advance){ // move range start forward *clst+=188; } // next packet, if there is one pkt+=188; } while(1); DBG(fprintf(stderr,"-- result: grouped %i pkts, advanced %i pkts\n",grouped,advanced)); // delete empty ranges and compact list clst2=cluster; for(clst=cluster;*clst!=NULL;clst+=2){ // if not empty if(*clst<*(clst+1)){ // it will remain *clst2=*clst; *(clst2+1)=*(clst+1); clst2+=2; } } *clst2=NULL; if(grouped==0){ // no processing needed return advanced; } // sort them, longest payload first // we expect many n=23 packets and a few n<23 DBG(fprintf(stderr,"PRESORTING\n")); for(i=0;i<grouped;i++){ DBG(fprintf(stderr,"%2i of %2i: pkt=%p len=%03i n=%2i residue=%i\n",i,grouped,g_pkt[i],g_len[i],g_n[i],g_residue[i])); } // grouped is always <= GROUP_PARALLELISM#define g_swap(a,b) \ pkt=g_pkt[a]; \ g_pkt[a]=g_pkt[b]; \ g_pkt[b]=pkt; \\ len=g_len[a]; \ g_len[a]=g_len[b]; \ g_len[b]=len; \\ offset=g_offset[a]; \ g_offset[a]=g_offset[b]; \ g_offset[b]=offset; \\ n=g_n[a]; \ g_n[a]=g_n[b]; \ g_n[b]=n; \\ residue=g_residue[a]; \ g_residue[a]=g_residue[b]; \ g_residue[b]=residue; // step 1: move n=23 packets before small packets t23=0; tsmall=grouped-1; for(;;){ for(;t23<grouped;t23++){ if(g_n[t23]!=23) break; }DBG(fprintf(stderr,"t23 after for =%i\n",t23)); for(;tsmall>=0;tsmall--){ if(g_n[tsmall]==23) break; }DBG(fprintf(stderr,"tsmall after for =%i\n",tsmall)); if(tsmall-t23<1) break; DBG(fprintf(stderr,"swap t23=%i,tsmall=%i\n",t23,tsmall)); g_swap(t23,tsmall); t23++; tsmall--;DBG(fprintf(stderr,"new t23=%i,tsmall=%i\n\n",t23,tsmall)); } DBG(fprintf(stderr,"packets with n=23, t23=%i grouped=%i\n",t23,grouped)); DBG(fprintf(stderr,"MIDSORTING\n")); for(i=0;i<grouped;i++){ DBG(fprintf(stderr,"%2i of %2i: pkt=%p len=%03i n=%2i residue=%i\n",i,grouped,g_pkt[i],g_len[i],g_n[i],g_residue[i])); } // step 2: sort small packets in decreasing order of n (bubble sort is enough) for(i=t23;i<grouped;i++){ for(j=i+1;j<grouped;j++){ if(g_n[j]>g_n[i]){ g_swap(i,j); } } } DBG(fprintf(stderr,"POSTSORTING\n")); for(i=0;i<grouped;i++){ DBG(fprintf(stderr,"%2i of %2i: pkt=%p len=%03i n=%2i residue=%i\n",i,grouped,g_pkt[i],g_len[i],g_n[i],g_residue[i])); } // we need to know how many packets need 23 iterations, how many 22... for(i=0;i<=23;i++){ alive[i]=0; } // count alive[23-1]=t23; for(i=t23;i<grouped;i++){ alive[g_n[i]-1]++; } // integrate for(i=22;i>=0;i--){ alive[i]+=alive[i+1]; } DBG(fprintf(stderr,"ALIVE\n")); for(i=0;i<=23;i++){ DBG(fprintf(stderr,"alive%2i=%i\n",i,alive[i])); } // choose key if(group_ev_od==0){ k=&((struct csa_keys_t *)keys)->even; } else{ k=&((struct csa_keys_t *)keys)->odd; } //INIT//#define INITIALIZE_UNUSED_INPUT#ifdef INITIALIZE_UNUSED_INPUT// unnecessary zeroing.// without this, we operate on uninitialized memory// when grouped<GROUP_PARALLELISM, but it's not a problem,// as final results will be discarded.// random data makes debugging sessions difficult. for(j=0;j<GROUP_PARALLELISM*8;j++) stream_in[j]=0;DBG(fprintf(stderr,"--- WARNING: you could gain speed by not initializing unused memory ---\n"));#elseDBG(fprintf(stderr,"--- WARNING: DEBUGGING IS MORE DIFFICULT WHEN PROCESSING RANDOM DATA CHANGING AT EVERY RUN! ---\n"));#endif for(g=0;g<grouped;g++){ encp[g]=g_pkt[g]; DBG(fprintf(stderr,"header[%i]=%p (%02x)\n",g,encp[g],*(encp[g]))); encp[g]+=g_offset[g]; // skip header FFTABLEIN(stream_in,g,encp[g]); }//dump_mem("stream_in",stream_in,GROUP_PARALLELISM*8,BYPG); // ITER 0DBG(fprintf(stderr,">>>>>ITER 0\n")); iter=0; stream_cypher_group_init(®s,k->iA_g,k->iB_g,stream_in); // fill first ib for(g=0;g<alive[iter];g++){ COPY_8_BY(ib+8*g,encp[g]); }DBG(dump_mem("IB ",ib,8*alive[iter],8)); // ITER 1..N-1 for (iter=1;iter<23&&alive[iter-1]>0;iter++){DBG(fprintf(stderr,">>>>>ITER %i\n",iter)); // alive and just dead packets: calc block block_decypher_group(k->kkmulti,ib,block_out,alive[iter-1]);DBG(dump_mem("BLO_ib ",block_out,8*alive[iter-1],8)); // all packets (dead too): calc stream stream_cypher_group_normal(®s,stream_out);//dump_mem("stream_out",stream_out,GROUP_PARALLELISM*8,BYPG); // alive packets: calc ib for(g=0;g<alive[iter];g++){ FFTABLEOUT(ib+8*g,stream_out,g);DBG(dump_mem("stream_out_ib ",ib+8*g,8,8));// XOREQ8BY gcc bug? 2x4 ok, 8 ko UPDATE: result ok but speed 1-2% slower (!!!???)#if 1 XOREQ_4_BY(ib+8*g,encp[g]+8); XOREQ_4_BY(ib+8*g+4,encp[g]+8+4);#else XOREQ_8_BY(ib+8*g,encp[g]+8);#endifDBG(dump_mem("after_stream_xor_ib ",ib+8*g,8,8)); } // alive packets: decrypt data for(g=0;g<alive[iter];g++){DBG(dump_mem("before_ib_decrypt_data ",encp[g],8,8)); XOR_8_BY(encp[g],ib+8*g,block_out+8*g);DBG(dump_mem("after_ib_decrypt_data ",encp[g],8,8)); } // just dead packets: write decrypted data for(g=alive[iter];g<alive[iter-1];g++){DBG(dump_mem("jd_before_ib_decrypt_data ",encp[g],8,8)); COPY_8_BY(encp[g],block_out+8*g);DBG(dump_mem("jd_after_ib_decrypt_data ",encp[g],8,8)); } // just dead packets: decrypt residue for(g=alive[iter];g<alive[iter-1];g++){DBG(dump_mem("jd_before_decrypt_residue ",encp[g]+8,g_residue[g],g_residue[g])); FFTABLEOUTXORNBY(g_residue[g],encp[g]+8,stream_out,g);DBG(dump_mem("jd_after_decrypt_residue ",encp[g]+8,g_residue[g],g_residue[g])); } // alive packets: pointers++ for(g=0;g<alive[iter];g++) encp[g]+=8; }; // ITER NDBG(fprintf(stderr,">>>>>ITER 23\n")); iter=23; // calc block block_decypher_group(k->kkmulti,ib,block_out,alive[iter-1]);DBG(dump_mem("23BLO_ib ",block_out,8*alive[iter-1],8)); // just dead packets: write decrypted data for(g=alive[iter];g<alive[iter-1];g++){DBG(dump_mem("23jd_before_ib_decrypt_data ",encp[g],8,8)); COPY_8_BY(encp[g],block_out+8*g);DBG(dump_mem("23jd_after_ib_decrypt_data ",encp[g],8,8)); } // no residue possible // so do nothing DBG(fprintf(stderr,"returning advanced=%i\n",advanced)); M_EMPTY(); // restore CPU multimedia state return advanced;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -