📄 smartcard.c
字号:
if(mem[3]==1) { nextSW[0]=0x94; nextSW[1]=0x02; dataLen=0; } else { dataLen=0x42; static const unsigned char resp[0x42] = { 0x83,0x01,0x88, 0x8c,0x03,0xA0,0x30,0x40, 0x8d,0x04,0x16,0xac,0x16,0xba, 0xd5,0x10,'D','u','m','m','y',0,0,0,0,0,0,0,0x12,0x34,0x56,0x67, 0x92,0x20,0x00 // ... }; memcpy(data,resp,sizeof(resp)); } break; case 0x80: dataLen=0x07; data[0]=0x80; data[1]=0x05; data[2]=0x5c; data[3]=0x0c; data[4]=0x00; data[5]=0xec; data[6]=0x0a; break; case 0xD1: dataLen=0x04; data[0]=0xd1; data[1]=0x02; data[2]=0x0d; data[3]=0x22; break; case 0x9F: dataLen=0x03; data[0]=0x9f; data[1]=0x01; data[2]=0x88; break; case 0x9E: { dataLen=0x42; static const unsigned char resp[0x42] = { 0x9E,0x40, 0x28,0xFE, /// ... }; memcpy(data,resp,sizeof(resp)); flag=true; break; } case 0xC0: case 0xD6: dataLen=0x12; data[0]=record; data[1]=0x10; memset(data+2,0,16); strcpy((char *)data+2,"Dum Issuer"); break; } break; case 0xa4b8: readcmd=true; if(mem[2]==0) { dataLen=0x0C; memset(data,0,0x0c); data[0]=0xDF; data[1]=0x0A; data[4]=0xDF; data[5]=0x88; } else { dataLen=0; nextSW[0]=0x94; nextSW[1]=0x02; } break; case 0xa44c: nextSW[0]=0x9f; nextSW[1]=flag ? 0x42 : 0x1c; break; case 0xa4c0: readcmd=true; if(mem[4]==0x1c) { data[0]=0xdb; data[1]=0x10; memset(&data[2],0x45,16); data[18]=0xdf; data[19]=0x08; data[20]=0x50; data[23]=0x80; } else if(mem[4]==0x11) { memset(data,0,0x11); data[0]=0xdf; data[1]=0x0f; data[6]=0x3f; data[7]=0x6a; } else if(mem[4]==0x42) { static const unsigned char resp[0x42] = { 0xdf,0x40, 0x6d,0xbb,0x81, // ... }; memcpy(data,resp,sizeof(resp)); } break; } if(readcmd) { if(dataLen>0) { PUSHB(mem[INS_IDX]); // ACK byte PUSH(data,dataLen); } PUSH(nextSW,2); cmdStart=true; } else { PUSHB(mem[INS_IDX]); // ACK byte } } else { dataLen-=len; if(dataLen<=0 && !cmdStart) { PUSH(nextSW,2); cmdStart=true; } }#elif defined(EMU_IRD) static const struct Resp { unsigned int cmd; unsigned char data[MAX_LEN]; } resp[] = {#ifdef EMU_IRD_384 { 0x01020203, {0x01,0x02,0x00,0x00,0x02,0x00,0x00,0x10,0x03,0x84,0x00,0x00,0x00,0x17,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x45,0x52} }, { 0x01020E02, {0x01,0x02,0x00,0x00,0x0e,0x02,0x00,0x40,0xa9,0x6d,0x73,0x97,0x9e,0xfc,0x9b,0x8e,0x5b,0x8c,0xfa,0xb2,0x0c,0xb2,0x57,0x0f,0xb2,0xf7,0x29,0x4e,0xa2,0xcb,0xbd,0x5b,0x52,0x74,0xb1,0x2a,0xb7,0xc5,0xd9,0x62,0x6d,0x37,0x6d,0x9d,0xa3,0xe9,0x61,0xbb,0x1b,0x2b,0x56,0xb7,0x86,0x0c,0xe6,0xb1,0x07,0x6f,0xe0,0xf8,0x8a,0xd3,0x05,0x83,0xf6,0x53,0x0e,0xd2,0x72,0xd5,0xc1,0x50} }, { 0x01020E03, {0x01,0x02,0x00,0x00,0x0e,0x03,0x00,0x40,0xb6,0xde,0xa8,0xce,0x86,0x1c,0x42,0x72,0xa8,0x16,0x4b,0xf9,0xce,0x33,0xb5,0x43,0xd0,0x50,0xe6,0xa7,0xf1,0xcb,0x55,0x25,0x97,0x13,0xee,0x62,0x98,0xe7,0x17,0x50,0xeb,0x3b,0x59,0x10,0x0a,0xb6,0x2e,0x93,0x61,0x71,0x3c,0xe6,0xe2,0x2c,0x1e,0x7d,0xbd,0x6a,0x49,0xbb,0x04,0x5b,0xdf,0x2f,0xb7,0xa7,0x93,0xe0,0x3d,0x40,0x4e,0xd1} },#else { 0x01020203, {0x01,0x02,0x00,0x00,0x02,0x00,0x00,0x10,0x03,0x83,0x00,0x00,0x00,0x17,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x45,0x52} }, { 0x01020E02, {0x01,0x02,0x00,0x00,0x0E,0x02,0x00,0x40,0x65,0xEF,0xD0,0xA7,0xF3,0x80,0x48,0x0E,0xC1,0x4B,0x41,0x6C,0xDB,0x68,0x47,0xE4,0x23,0xAD,0x96,0x12,0x07,0x58,0x58,0x29,0xE9,0x14,0x27,0x7F,0x7D,0xF8,0xC2,0x65,0x76,0x4D,0x75,0x04,0x7C,0x9B,0xAA,0x99,0x58,0xEA,0xE2,0x43,0xB5,0x03,0x05,0xD6,0x62,0x99,0xF5,0x18,0x16,0x4E,0xCF,0x49,0x11,0xBD,0xF3,0xEE,0xC3,0xCD,0x90,0x3B} }, { 0x01020E03, {0x01,0x02,0x00,0x00,0x0E,0x03,0x00,0x40,0x9B,0x06,0xB5,0x0A,0x98,0xC6,0x2E,0x1D,0x71,0xA1,0xE8,0x84,0xAE,0x98,0x57,0xE9,0xE6,0xC2,0x97,0x46,0x25,0x7A,0x2B,0xA1,0xD5,0x33,0x18,0xDE,0x16,0xC1,0xAB,0x22,0x2C,0xC2,0x11,0x24,0x81,0x11,0xA8,0x39,0xE3,0xB1,0xDB,0x33,0x1A,0x93,0x31,0xB0,0x61,0xD8,0xDE,0x92,0x1F,0x29,0x20,0xD0,0x9E,0x0F,0x6A,0xF0,0x7C,0xBA,0xCD,0xCC} },#endif { 0x01020003, {0x01,0x02,0x00,0x00,0x00,0x03,0x00,0x14,0x37,0x30,0x31,0x32,0x30,0x36,0x39,0x33,0x34,0x37,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} }, { 0x01020103, {0x01,0x02,0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x17,0x00,0x00,0x01,0x00,0x17,0x00,0x00,0x01,0x04,0x00,0xF3,0x86,0x01,0x1A} }, { 0x01021100, {0x01,0x02,0x58,0x00,0x11,0x00,0x00,0x00} }, { 0x01020903, {0x01,0x02,0x55,0x00,0x09,0x03,0x00,0x00} }, { 0x01020303, {0x01,0x02,0x00,0x00,0x03,0x03,0x02,0x18,0x0F,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} }, { 0x01020400, {0x01,0x02,0x54,0x00,0x04,0x00,0x00,0x00} }, { 0x01050000, {0x01,0x05,0x9D,0x00,0x38,0x00,0x02,0x16,0x00,0x01,0x00,0x13,0xFF,0xFF,0x22,0x88,0xBF,0x02,0x70,0xFA,0x5F,0x80,0xFD,0x1E,0xD4,0xD6,0xF0,0xF1,0x81,0xB3} }, { 0x01010000, {0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0xFF} }, { 0x00000000, // don't delete this one {} } }; const unsigned int cmd=(mem[0]<<24) + (mem[1]<<16) + (mem[2]<<8) + mem[3]; const struct Resp *r=&resp[0]; while(1) { if(!r->cmd) { static const unsigned char fail[] = { 0x01,0x99,0x6f }; PUSH(fail,sizeof(fail)); break; } if(cmd==r->cmd) { const int len=r->data[7]+9-1; int cs=0x3f; for(int i=0 ; i<len ; i++) cs ^= r->data[i]; PUSH(r->data,len); PUSHB(cs); break; } r++; }#else#error No serial emulation mode selected#endif return len;}void cSerial::ToggleRTS(void){ rts=!rts; if(!rts) { #if defined(EMU_SECA) static const unsigned char atr[] = { 0x3b,0x77,0x12,0x00,0x00, 0x60,0x60,0x03,0x0E,0x6C,0xB6,0xD6 };#elif defined(EMU_IRD) static const unsigned char atr[] = { 0x3B,0x9F,0x21,0x0E,#ifdef EMU_IRD_384 0x49,0x52,0x44,0x45,0x54,0x4f,0x20,0x41,0x43,0x53,0x03,0x84,0x55,0xff,0x80,0x6d };#else 0x49,0x52,0x44,0x45,0x54,0x4F,0x20,0x41,0x43,0x53,0x03,0x83,0x95,0x00,0x80,0x55 };#endif#elif defined(EMU_CRYPTO) static const unsigned char atr[] = { 0x3B,0x78,0x12,0x00,0x00, 0x65,0xC4,0x05,0x05,0x8F,0xF1,0x90,0x00 };#else#error No serial emulation mode selected#endif PUSH(atr,sizeof(atr)); PRINTF(L_CORE_SERIAL,"serial: toggle RTS, now off"); } else { PRINTF(L_CORE_SERIAL,"serial: toggle RTS, now on"); }}bool cSerial::CheckCAR(void){#if 0 if(time(0)>=remTime+30) { dsr=!dsr; remTime=time(0); }#endif return dsr;}#endif //SER_EMU// -- cInfoStr -----------------------------------------------------------------cInfoStr::cInfoStr(void):cLineBuff(256){ current=0;}cInfoStr::~cInfoStr(){ free(current);}bool cInfoStr::Get(char *buff, int len){ cMutexLock lock(&mutex); if(current && current[0]) { strn0cpy(buff,current,len); return true; } return false;}void cInfoStr::Begin(void){ Flush();}void cInfoStr::Finish(){ cMutexLock lock(&mutex); free(current); current=Grab();}// -- cSmartCard ---------------------------------------------------------------static const int Ftable[16] = { 372,372,558,744,1116,1488,1860,0,0,512,768,1024,1536,2048,0,0 };static const float Dtable[16] = { 0.0,1.0,2.0,4.0,8.0,16.0,0.0,0.0, 0.0,0.0,0.5,0.25,0.125,0.0625,0.03125,0.015625 }; cSmartCard::cSmartCard(const struct CardConfig *Cfg, const struct StatusMsg *Msg){ cfg=Cfg; msg=Msg; ser=0; atr=0; idStr[0]=0; cardUp=false; needsReset=true;}bool cSmartCard::GetCardIdStr(char *str, int len){ strn0cpy(str,idStr,len); return (str[0]!=0);}bool cSmartCard::GetCardInfoStr(char *str, int len){ return infoStr.Get(str,len);}bool cSmartCard::Setup(cSerial *Ser, const struct Atr *Atr, int Id){ ser=Ser; atr=Atr; id=Id; if(cfg->SerMode==(ser->CurrentMode()&SM_MASK) && Init()) { cardUp=true; needsReset=false; return true; } return false;}#define NEED(x) { \ if(len+(x)>Atr->atrLen) { \ LBPUT("SHORT ATR"); \ return false; \ } \ }bool cSmartCard::ParseAtr(struct Atr *Atr, int id, int clock){ // default values Atr->histLen=0; Atr->T=0; Atr->F=372; Atr->D=1.0; Atr->N=0; Atr->WI=10; Atr->BWI=4; Atr->CWI=0; Atr->Tspec=-1; const unsigned char *atr=Atr->atr; if(atr[0]==0x03) { PRINTF(L_CORE_SC,"%d: indirect convention detected",id); cSmartCard::Invert(Atr->atr,Atr->atrLen); Atr->convention=SM_INDIRECT; } else if(atr[0]==0x3B) { PRINTF(L_CORE_SC,"%d: direct convention detected",id); Atr->convention=SM_DIRECT; } else { PRINTF(L_CORE_SC,"%d: byte mode not supported 0x%02x",id,atr[0]); return false; } // TS TO Atr->histLen=atr[1]&0x0F; int Y=atr[1]&0xF0, i=1, len=2; LBSTARTF(L_CORE_SC); LBPUT("%d: atr decoding TS=%02x hist=%d Y%d=%02x ",id,atr[0],Atr->histLen,i,Y); do { if(Y&0x10) { // TAi NEED(1); LBPUT("TA%d=%02x ",i,atr[len]); if(i==1) { Atr->TA1=atr[len]; Atr->F=Ftable[(atr[len]>>4)&0x0F]; Atr->D=Dtable[ atr[len] &0x0F]; LBPUT("F=%d D=%f ",Atr->F,Atr->D); } else if(i==2) { Atr->Tspec=atr[len]&0x0F; LBPUT("Tspec=%d ",Atr->Tspec); } else if(i==3) { LBPUT("IFSC=%d ",atr[len]); } len++; } if(Y&0x20) { // TBi NEED(1); LBPUT("TB%d=%02x ",i,atr[len]); if(i==3) { Atr->BWI=(atr[len]>>4)&0x0F; Atr->CWI=atr[len]&0x0F; LBPUT("BWI=%d CWI=%d ",Atr->BWI,Atr->CWI); } len++; } if(Y&0x40) { // TCi NEED(1); LBPUT("TC%d=%02x ",i,atr[len]); if(i==1) { Atr->N=atr[len]; LBPUT("N=%d ",Atr->N); } else if(i==2) { Atr->WI=atr[len]; LBPUT("WI=%d ",Atr->WI); } else if(i==3) { LBPUT("CHK=%s ",atr[len]&1 ? "CRC16":"LRC"); } len++; } if(Y&0x80) { // TDi NEED(1); LBPUT("TD%d=%02x ",i,atr[len]); if(i==1) { Atr->T=atr[len]&0x0F; LBPUT("T=%d ",Atr->T); } else { LBPUT("Tn=%d ",atr[len]&0x0F); } Y=atr[len]&0xF0; len++; } else Y=0; i++; LBPUT("Y%d=%02x ",i,Y); } while(Y); NEED(Atr->histLen); LBEND(); LBSTART(L_CORE_SERIAL); LBPUT("%d: historical:",id); for(int i=0 ; i<Atr->histLen ; i++) LBPUT(" %02x",atr[len+i]); LBFLUSH(); LBPUT("%d: historical: '",id); for(int i=0 ; i<Atr->histLen ; i++) LBPUT("%c",isprint(atr[len+i]) ? atr[len+i] : '.'); LBEND(); memcpy(Atr->hist,&atr[len],Atr->histLen); len+=Atr->histLen; // TCK if(Atr->T!=0 && len+1<=Atr->atrLen) { len++; unsigned char cs=XorSum(atr+1,len-1); // according to the ISO the initial TS byte isn't checksumed, but // some cards do so. In this case the checksum is equal TS. if(cs==0) PRINTF(L_CORE_SC,"%d: atr checksum ok",id); else if(cs==atr[0]) PRINTF(L_CORE_SC,"iso: %d: atr checksum is TS (not ISO compliant)",id); else { PRINTF(L_CORE_SC,"%d: atr checksum FAILED (cs:%02x)",id,cs); return false; } } else PRINTF(L_CORE_SC,"%d: atr checksum not given/not required",id); if(Atr->atrLen>len) PRINTF(L_CORE_SC,"%d: long atr read=%d len=%d",id,Atr->atrLen,len); Atr->wwt=960*Atr->WI*Atr->F/(clock/1000); Atr->bwt=(int)(960*(float)(1<<Atr->BWI)*372/(clock/1000)); PRINTF(L_CORE_SC,"%d: indicated wwt(T0)=%d ms, bwt(T1)=%d ms (at %.4f MHz)",id,Atr->wwt,Atr->bwt,(float)clock/1000000); return true;}void cSmartCard::Invert(unsigned char *data, int n){ static const unsigned char swaptab[] = { 15,7,11,3,13,5,9,1,14,6,10,2,12,4,8,0 }; for(int i=n-1; i>=0; i--) data[i]=(swaptab[data[i]&0x0f]<<4) | swaptab[data[i]>>4];}int cSmartCard::SerRead(unsigned char *data, int len, int to){ if(atr->T==1 || atr->T==14) { int r=Read(data,len,to); if(r<0) Test(false); return r; } else { PRINTF(L_CORE_SC,"%d: SerRead() not allowed for ISO compliant cards (T=%d)",id,atr->T); return -1; }}int cSmartCard::SerWrite(const unsigned char *data, int len){ if(atr->T==1 || atr->T==14) { int r=Write(data,len); if(r<0) Test(false); return r; } else { PRINTF(L_CORE_SC,"%d: SerWrite() not allowed for ISO compliant cards (T=%d)",id,atr->T); return -1; }}int cSmartCard::Read(unsigned char *data, int len, int to){ int r=ser->Read(data,len,cfg->serTO,to); if(atr->convention==SM_INDIRECT && r>0) Invert(data,r); return r;}int cSmartCard::Write(const unsigned char *data, int len){ unsigned char tmp[len]; if(atr->convention==SM_INDIRECT) { memcpy(tmp,data,len); Invert(tmp,len); data=tmp; } int r=ser->Write(data,len); if(r>0) { unsigned char buff[r]; int rr=ser->Read(buff,r,cfg->serTO); if(rr<0) r=rr; } return r;}int cSmartCard::Procedure(unsigned char ins, int restLen){ int r; unsigned char buff;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -