[3181] | 1 | //FIXME Not checked on threadsafety yet; after checking please remove this line
|
---|
[8] | 2 | #include "globals.h"
|
---|
| 3 | #include "reader-common.h"
|
---|
| 4 |
|
---|
| 5 | #define CMD_LEN 5
|
---|
| 6 |
|
---|
[2210] | 7 | static void RotateBytes1(unsigned char *out, unsigned char *in, int n)
|
---|
[8] | 8 | {
|
---|
| 9 | // loop is executed atleast once, so it's not a good idea to
|
---|
| 10 | // call with n=0 !!
|
---|
| 11 | out+=n;
|
---|
| 12 | do { *(--out)=*(in++); } while(--n);
|
---|
| 13 | }
|
---|
| 14 |
|
---|
[2210] | 15 | static void RotateBytes2(unsigned char *in, int n)
|
---|
[8] | 16 | {
|
---|
| 17 | // loop is executed atleast once, so it's not a good idea to
|
---|
| 18 | // call with n=0 !!
|
---|
| 19 | unsigned char *e=in+n-1;
|
---|
| 20 | do
|
---|
| 21 | {
|
---|
| 22 | unsigned char temp=*in;
|
---|
| 23 | *in++=*e;
|
---|
| 24 | *e-- =temp;
|
---|
| 25 | } while(in<e);
|
---|
| 26 | }
|
---|
| 27 |
|
---|
[2210] | 28 | static int Input(BIGNUM *d, unsigned char *in, int n, int LE)
|
---|
[8] | 29 | {
|
---|
| 30 | if (LE)
|
---|
| 31 | {
|
---|
| 32 | unsigned char tmp[n];
|
---|
| 33 | RotateBytes1(tmp,in,n);
|
---|
| 34 | return(BN_bin2bn(tmp,n,d)!=0);
|
---|
| 35 | }
|
---|
| 36 | else
|
---|
| 37 | return(BN_bin2bn(in,n,d)!=0);
|
---|
| 38 | }
|
---|
| 39 |
|
---|
[2210] | 40 | static int Output(unsigned char *out, int n, BIGNUM *r, int LE)
|
---|
[8] | 41 | {
|
---|
| 42 | int s=BN_num_bytes(r);
|
---|
| 43 | if (s>n)
|
---|
| 44 | {
|
---|
| 45 | unsigned char buff[s];
|
---|
[1399] | 46 | cs_debug("[cryptoworks-reader] rsa: RSA len %d > %d, truncating", s, n);
|
---|
[8] | 47 | BN_bn2bin(r,buff);
|
---|
| 48 | memcpy(out,buff+s-n,n);
|
---|
| 49 | }
|
---|
| 50 | else if (s<n)
|
---|
| 51 | {
|
---|
| 52 | int l=n-s;
|
---|
[1399] | 53 | cs_debug("[cryptoworks-reader] rsa: RSA len %d < %d, padding", s, n);
|
---|
[8] | 54 | memset(out,0,l);
|
---|
| 55 | BN_bn2bin(r,out+l);
|
---|
| 56 | }
|
---|
| 57 | else
|
---|
| 58 | BN_bn2bin(r,out);
|
---|
| 59 | if (LE)
|
---|
| 60 | RotateBytes2(out,n);
|
---|
| 61 | return(s);
|
---|
| 62 | }
|
---|
| 63 |
|
---|
[2210] | 64 | static int RSA(unsigned char *out, unsigned char *in, int n, BIGNUM *exp, BIGNUM *mod, int LE)
|
---|
[8] | 65 | {
|
---|
| 66 | int rc=0;
|
---|
| 67 | BN_CTX *ctx;
|
---|
| 68 | BIGNUM *r, *d;
|
---|
| 69 | ctx=BN_CTX_new();
|
---|
| 70 | r=BN_new();
|
---|
| 71 | d=BN_new();
|
---|
| 72 | if (Input(d,in,n,LE))
|
---|
| 73 | {
|
---|
| 74 | if(BN_mod_exp(r,d,exp,mod,ctx))
|
---|
| 75 | rc=Output(out,n,r,LE);
|
---|
| 76 | else
|
---|
[1399] | 77 | cs_log("[cryptoworks-reader] rsa: mod-exp failed");
|
---|
[8] | 78 | }
|
---|
| 79 | BN_CTX_free(ctx);
|
---|
| 80 | BN_free(d);
|
---|
| 81 | BN_free(r);
|
---|
| 82 | return(rc);
|
---|
| 83 | }
|
---|
| 84 |
|
---|
| 85 | static char *chid_date(uchar *ptr, char *buf, int l)
|
---|
| 86 | {
|
---|
| 87 | if (buf)
|
---|
| 88 | {
|
---|
| 89 | snprintf(buf, l, "%04d/%02d/%02d",
|
---|
| 90 | 1990+(ptr[0]>>1), ((ptr[0]&1)<<3)|(ptr[1]>>5), ptr[1]&0x1f);
|
---|
| 91 | }
|
---|
| 92 | return(buf);
|
---|
| 93 | }
|
---|
| 94 |
|
---|
[1951] | 95 | static int select_file(struct s_reader * reader, uchar f1, uchar f2, uchar * cta_res, ushort * p_cta_lr)
|
---|
[8] | 96 | {
|
---|
[1951] | 97 | ushort cta_lr;
|
---|
[8] | 98 | uchar insA4[] = {0xA4, 0xA4, 0x00, 0x00, 0x02, 0x00, 0x00};
|
---|
| 99 | insA4[5]=f1;
|
---|
| 100 | insA4[6]=f2;
|
---|
| 101 | write_cmd(insA4, insA4+5); // select file
|
---|
[1951] | 102 | *p_cta_lr = cta_lr;
|
---|
[8] | 103 | return((cta_res[0]==0x9f)&&(cta_res[1]==0x11));
|
---|
| 104 | }
|
---|
| 105 |
|
---|
[1951] | 106 | static int read_record(struct s_reader * reader, uchar rec, uchar * cta_res)
|
---|
[8] | 107 | {
|
---|
[1951] | 108 | ushort cta_lr;
|
---|
[8] | 109 | uchar insA2[] = {0xA4, 0xA2, 0x00, 0x00, 0x01, 0x00};
|
---|
| 110 | uchar insB2[] = {0xA4, 0xB2, 0x00, 0x00, 0x00};
|
---|
| 111 |
|
---|
| 112 | insA2[5]=rec;
|
---|
| 113 | write_cmd(insA2, insA2+5); // select record
|
---|
| 114 | if (cta_res[0]!=0x9f)
|
---|
| 115 | return(-1);
|
---|
| 116 | insB2[4]=cta_res[1]; // get len
|
---|
[1951] | 117 | write_cmd(insB2, NULL); // read record
|
---|
[8] | 118 | if ((cta_res[cta_lr-2]!=0x90) || (cta_res[cta_lr-1]))
|
---|
| 119 | return(-1);
|
---|
| 120 | return(cta_lr-2);
|
---|
| 121 | }
|
---|
| 122 |
|
---|
[2210] | 123 | /*
|
---|
| 124 | int cryptoworks_send_pin(struct s_reader * reader)
|
---|
| 125 | {
|
---|
| 126 | unsigned char insPIN[] = { 0xA4, 0x20, 0x00, 0x00, 0x04, 0x00,0x00,0x00,0x00 }; //Verify PIN
|
---|
| 127 |
|
---|
| 128 | if(reader->pincode[0] && (reader->pincode[0]&0xF0)==0x30)
|
---|
| 129 | {
|
---|
| 130 | memcpy(insPIN+5,reader->pincode,4);
|
---|
| 131 |
|
---|
| 132 | write_cmd(insPIN, insPIN+5);
|
---|
| 133 | cs_ri_log (reader, "sending pincode to card");
|
---|
| 134 | if((cta_res[0]==0x98)&&(cta_res[1]==0x04)) cs_ri_log (reader, "bad pincode");
|
---|
| 135 |
|
---|
| 136 | return OK;
|
---|
| 137 | }
|
---|
| 138 |
|
---|
| 139 | return(0);
|
---|
| 140 | }
|
---|
| 141 | */
|
---|
[39] | 142 |
|
---|
[1926] | 143 | static int cryptoworks_disable_pin(struct s_reader * reader)
|
---|
[39] | 144 | {
|
---|
[1951] | 145 | def_resp;
|
---|
[39] | 146 | unsigned char insPIN[] = { 0xA4, 0x26, 0x00, 0x00, 0x04, 0x00,0x00,0x00,0x00 }; //disable PIN
|
---|
| 147 |
|
---|
[1926] | 148 | if(reader->pincode[0] && (reader->pincode[0]&0xF0)==0x30)
|
---|
[39] | 149 | {
|
---|
[1926] | 150 | memcpy(insPIN+5,reader->pincode,4);
|
---|
[39] | 151 |
|
---|
| 152 | write_cmd(insPIN, insPIN+5);
|
---|
[1951] | 153 | cs_ri_log (reader, "disable pincode to card");
|
---|
| 154 | if((cta_res[0]==0x98)&&(cta_res[1]==0x04)) cs_ri_log (reader, "bad pincode");
|
---|
[1389] | 155 | return ERROR;
|
---|
[39] | 156 | }
|
---|
[1389] | 157 | return OK;
|
---|
[39] | 158 | }
|
---|
| 159 |
|
---|
[1926] | 160 | int cryptoworks_card_init(struct s_reader * reader, ATR newatr)
|
---|
[8] | 161 | {
|
---|
[1951] | 162 | get_atr;
|
---|
| 163 | def_resp;
|
---|
[8] | 164 | int i;
|
---|
| 165 | unsigned int mfid=0x3F20;
|
---|
[3122] | 166 | static const uchar cwexp[] = { 1, 0 , 1};
|
---|
[8] | 167 | uchar insA4C[]= {0xA4, 0xC0, 0x00, 0x00, 0x11};
|
---|
| 168 | uchar insB8[] = {0xA4, 0xB8, 0x00, 0x00, 0x0c};
|
---|
| 169 | uchar issuerid=0;
|
---|
| 170 | char issuer[20]={0};
|
---|
| 171 | char *unknown="unknown", *pin=unknown, ptxt[CS_MAXPROV<<2]={0};
|
---|
| 172 |
|
---|
[1389] | 173 | if ((atr[6]!=0xC4) || (atr[9]!=0x8F) || (atr[10]!=0xF1)) return ERROR;
|
---|
[8] | 174 |
|
---|
[2210] | 175 | cs_log("[cryptoworks-reader] card detected");
|
---|
| 176 | cs_log("[cryptoworks-reader] type: CryptoWorks");
|
---|
| 177 |
|
---|
[1926] | 178 | reader->caid[0]=0xD00;
|
---|
| 179 | reader->nprov=0;
|
---|
| 180 | reader->ucpk_valid = 0;
|
---|
| 181 | memset(reader->prid, 0, sizeof(reader->prid));
|
---|
[8] | 182 |
|
---|
[1951] | 183 | write_cmd(insA4C, NULL); // read masterfile-ID
|
---|
[8] | 184 | if ((cta_res[0]==0xDF) && (cta_res[1]>=6))
|
---|
| 185 | mfid=(cta_res[6]<<8)|cta_res[7];
|
---|
| 186 |
|
---|
[1951] | 187 | select_file(reader, 0x3f, 0x20, cta_res, &cta_lr);
|
---|
[8] | 188 | insB8[2]=insB8[3]=0; // first
|
---|
| 189 | for(cta_res[0]=0xdf; cta_res[0]==0xdf;)
|
---|
| 190 | {
|
---|
[1951] | 191 | write_cmd(insB8, NULL); // read provider id's
|
---|
[8] | 192 | if (cta_res[0]!=0xdf) break;
|
---|
[1926] | 193 | if (((cta_res[4]&0x1f)==0x1f) && (reader->nprov<CS_MAXPROV))
|
---|
[8] | 194 | {
|
---|
| 195 | sprintf(ptxt+strlen(ptxt), ",%02X", cta_res[5]);
|
---|
[1926] | 196 | reader->prid[reader->nprov++][3]=cta_res[5];
|
---|
[8] | 197 | }
|
---|
| 198 | insB8[2]=insB8[3]=0xff; // next
|
---|
| 199 | }
|
---|
[1926] | 200 | for (i=reader->nprov; i<CS_MAXPROV; i++)
|
---|
| 201 | memset(&reader->prid[i][0], 0xff, 4);
|
---|
[8] | 202 |
|
---|
[1951] | 203 | select_file(reader, 0x2f, 0x01, cta_res, &cta_lr); // read caid
|
---|
| 204 | if (read_record(reader, 0xD1, cta_res)>=4)
|
---|
[1926] | 205 | reader->caid[0]=(cta_res[2]<<8)|cta_res[3];
|
---|
[8] | 206 |
|
---|
[1951] | 207 | if (read_record(reader, 0x80, cta_res)>=7) // read serial
|
---|
[1926] | 208 | memcpy(reader->hexserial, cta_res+2, 5);
|
---|
[1951] | 209 | cs_ri_log (reader, "type: CryptoWorks, caid: %04X, ascii serial: %llu, hex serial: %s",
|
---|
[1926] | 210 | reader->caid[0], b2ll(5, reader->hexserial),cs_hexdump(0, reader->hexserial, 5));
|
---|
[8] | 211 |
|
---|
[1951] | 212 | if (read_record(reader, 0x9E, cta_res)>=66) // read ISK
|
---|
[8] | 213 | {
|
---|
| 214 | uchar keybuf[256];
|
---|
| 215 | BIGNUM *ipk;
|
---|
[1926] | 216 | if (search_boxkey(reader->caid[0], (char *)keybuf))
|
---|
[8] | 217 | {
|
---|
| 218 | ipk=BN_new();
|
---|
[2069] | 219 | BN_bin2bn(cwexp, sizeof(cwexp), &reader->exp);
|
---|
[8] | 220 | BN_bin2bn(keybuf, 64, ipk);
|
---|
[2069] | 221 | RSA(cta_res+2, cta_res+2, 0x40, &reader->exp, ipk, 0);
|
---|
[8] | 222 | BN_free(ipk);
|
---|
[1926] | 223 | reader->ucpk_valid =(cta_res[2]==((mfid & 0xFF)>>1));
|
---|
| 224 | if (reader->ucpk_valid)
|
---|
[8] | 225 | {
|
---|
| 226 | cta_res[2]|=0x80;
|
---|
[2069] | 227 | BN_bin2bn(cta_res+2, 0x40, &reader->ucpk);
|
---|
[8] | 228 | cs_ddump(cta_res+2, 0x40, "IPK available -> session-key:");
|
---|
| 229 | }
|
---|
| 230 | else
|
---|
| 231 | {
|
---|
[1926] | 232 | reader->ucpk_valid =(keybuf[0]==(((mfid & 0xFF)>>1)|0x80));
|
---|
| 233 | if (reader->ucpk_valid)
|
---|
[8] | 234 | {
|
---|
[2069] | 235 | BN_bin2bn(keybuf, 0x40, &reader->ucpk);
|
---|
[8] | 236 | cs_ddump(keybuf, 0x40, "session-key found:");
|
---|
| 237 | }
|
---|
| 238 | else
|
---|
[1926] | 239 | cs_log("[cryptoworks-reader] invalid IPK or session-key for CAID %04X !", reader->caid[0]);
|
---|
[8] | 240 | }
|
---|
| 241 | }
|
---|
| 242 | }
|
---|
[1951] | 243 | if (read_record(reader, 0x9F, cta_res)>=3)
|
---|
[8] | 244 | issuerid=cta_res[2];
|
---|
[1951] | 245 | if (read_record(reader, 0xC0, cta_res)>=16)
|
---|
[8] | 246 | {
|
---|
[1691] | 247 | cs_strncpy(issuer, (const char *)cta_res+2, sizeof(issuer));
|
---|
[8] | 248 | trim(issuer);
|
---|
| 249 | }
|
---|
| 250 | else
|
---|
| 251 | strcpy(issuer, unknown);
|
---|
| 252 |
|
---|
[1951] | 253 | select_file(reader, 0x3f, 0x20, cta_res, &cta_lr);
|
---|
| 254 | select_file(reader, 0x2f, 0x11, cta_res, &cta_lr); // read pin
|
---|
| 255 | if (read_record(reader, atr[8], cta_res)>=7)
|
---|
[8] | 256 | {
|
---|
| 257 | cta_res[6]=0;
|
---|
[70] | 258 | pin=(char *)cta_res+2;
|
---|
[8] | 259 | }
|
---|
[1951] | 260 | cs_ri_log (reader, "issuer: %s, id: %02X, bios: v%d, pin: %s, mfid: %04X", issuer, issuerid, atr[7], pin, mfid);
|
---|
| 261 | cs_ri_log (reader, "providers: %d (%s)", reader->nprov, ptxt+1);
|
---|
[39] | 262 |
|
---|
[2210] | 263 | cryptoworks_disable_pin(reader);
|
---|
[39] | 264 |
|
---|
[1389] | 265 | return OK;
|
---|
[8] | 266 | }
|
---|
| 267 |
|
---|
[1926] | 268 | int cryptoworks_do_ecm(struct s_reader * reader, ECM_REQUEST *er)
|
---|
[8] | 269 | {
|
---|
[1951] | 270 | def_resp;
|
---|
| 271 | int r=0;
|
---|
[3122] | 272 | unsigned char ins4C[] = { 0xA4,0x4C,0x00,0x00,0x00 };
|
---|
| 273 | unsigned char insC0[] = { 0xA4,0xC0,0x00,0x00,0x1C };
|
---|
[8] | 274 | unsigned char nanoD4[10];
|
---|
[2662] | 275 | int secLen=check_sct_len(er->ecm,-5+(reader->ucpk_valid ? sizeof(nanoD4):0));
|
---|
[8] | 276 |
|
---|
| 277 | if(secLen>5)
|
---|
| 278 | {
|
---|
| 279 | int i;
|
---|
| 280 | uchar *ecm=er->ecm;
|
---|
| 281 | uchar buff[MAX_LEN];
|
---|
| 282 |
|
---|
[1926] | 283 | if(reader->ucpk_valid)
|
---|
[8] | 284 | {
|
---|
| 285 | memcpy(buff,er->ecm,secLen);
|
---|
| 286 | nanoD4[0]=0xD4;
|
---|
| 287 | nanoD4[1]=0x08;
|
---|
[1137] | 288 | for (i=2; i<(int)sizeof(nanoD4); i++)
|
---|
[8] | 289 | nanoD4[i]=rand();
|
---|
| 290 | memcpy(&buff[secLen], nanoD4, sizeof(nanoD4));
|
---|
| 291 | ecm=buff;
|
---|
| 292 | secLen+=sizeof(nanoD4);
|
---|
| 293 | }
|
---|
| 294 |
|
---|
[1926] | 295 | ins4C[3]=reader->ucpk_valid ? 2 : 0;
|
---|
[8] | 296 | ins4C[4]=secLen-5;
|
---|
| 297 | write_cmd(ins4C, ecm+5);
|
---|
| 298 | if (cta_res[cta_lr-2]==0x9f)
|
---|
| 299 | {
|
---|
| 300 | insC0[4]=cta_res[cta_lr-1];
|
---|
[1951] | 301 | write_cmd(insC0, NULL);
|
---|
[8] | 302 | for(i=0; i<secLen && r<2; )
|
---|
| 303 | {
|
---|
| 304 | int n=cta_res[i+1];
|
---|
| 305 | switch(cta_res[i])
|
---|
| 306 | {
|
---|
| 307 | case 0x80:
|
---|
[1399] | 308 | cs_debug("[cryptoworks-reader] nano 80 (serial)");
|
---|
[8] | 309 | break;
|
---|
| 310 | case 0xD4:
|
---|
[1399] | 311 | cs_debug("[cryptoworks-reader] nano D4 (rand)");
|
---|
[8] | 312 | if(n<8 || memcmp(&cta_res[i],nanoD4,sizeof(nanoD4)))
|
---|
[1399] | 313 | cs_debug("[cryptoworks-reader] random data check failed after decrypt");
|
---|
[8] | 314 | break;
|
---|
| 315 | case 0xDB: // CW
|
---|
[1399] | 316 | cs_debug("[cryptoworks-reader] nano DB (cw)");
|
---|
[8] | 317 | if(n==0x10)
|
---|
| 318 | {
|
---|
| 319 | memcpy(er->cw, &cta_res[i+2], 16);
|
---|
| 320 | r|=1;
|
---|
| 321 | }
|
---|
| 322 | break;
|
---|
| 323 | case 0xDF: // signature
|
---|
[1399] | 324 | cs_debug("[cryptoworks-reader] nano DF %02x (sig)", n);
|
---|
[8] | 325 | if (n==0x08)
|
---|
| 326 | {
|
---|
| 327 | if((cta_res[i+2]&0x50)==0x50 && !(cta_res[i+3]&0x01) && (cta_res[i+5]&0x80))
|
---|
| 328 | r|=2;
|
---|
| 329 | }
|
---|
| 330 | else if (n==0x40) // camcrypt
|
---|
| 331 | {
|
---|
[1926] | 332 | if(reader->ucpk_valid)
|
---|
[8] | 333 | {
|
---|
[2069] | 334 | RSA(&cta_res[i+2],&cta_res[i+2], n, &reader->exp, &reader->ucpk, 0);
|
---|
[1399] | 335 | cs_debug("[cryptoworks-reader] after camcrypt ");
|
---|
[8] | 336 | r=0; secLen=n-4; n=4;
|
---|
| 337 | }
|
---|
| 338 | else
|
---|
| 339 | {
|
---|
[1399] | 340 | cs_log("[cryptoworks-reader] valid UCPK needed for camcrypt!");
|
---|
[1389] | 341 | return ERROR;
|
---|
[8] | 342 | }
|
---|
| 343 | }
|
---|
| 344 | break;
|
---|
| 345 | default:
|
---|
[1399] | 346 | cs_debug("[cryptoworks-reader] nano %02x (unhandled)",cta_res[i]);
|
---|
[8] | 347 | break;
|
---|
| 348 | }
|
---|
| 349 | i+=n+2;
|
---|
| 350 | }
|
---|
| 351 | }
|
---|
| 352 |
|
---|
[2210] | 353 | /*
|
---|
| 354 | #ifdef LALL
|
---|
| 355 | if ((cta_res[cta_lr-2]==0x9f)&&(cta_res[cta_lr-1]==0x1c))
|
---|
| 356 | {
|
---|
| 357 | write_cmd(insC0, NULL);
|
---|
| 358 | if ((cta_lr>26)&&(cta_res[cta_lr-2]==0x90)&&(cta_res[cta_lr-1]==0))
|
---|
| 359 | {
|
---|
| 360 | if (rc=(((cta_res[20]&0x50)==0x50) &&
|
---|
| 361 | (!(cta_res[21]&0x01)) &&
|
---|
| 362 | (cta_res[23]&0x80)))
|
---|
| 363 | memcpy(er->cw, cta_res+2, 16);
|
---|
| 364 | }
|
---|
| 365 | }
|
---|
| 366 | #endif
|
---|
| 367 | */
|
---|
[8] | 368 | }
|
---|
[2210] | 369 | //return(rc ? 1 : 0);
|
---|
[8] | 370 | return((r==3) ? 1 : 0);
|
---|
| 371 | }
|
---|
| 372 |
|
---|
[1966] | 373 | int cryptoworks_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr)
|
---|
[1766] | 374 | {
|
---|
[1974] | 375 | char dumprdrserial[18];
|
---|
[1972] | 376 |
|
---|
[1966] | 377 | cs_debug_mask(D_EMM, "Entered cryptoworks_get_emm_type ep->emm[0]=%02x",ep->emm[0]);
|
---|
[1766] | 378 | switch (ep->emm[0]) {
|
---|
| 379 | case 0x82:
|
---|
[1966] | 380 | if(ep->emm[3]==0xA9 && ep->emm[4]==0xFF && ep->emm[13]==0x80 && ep->emm[14]==0x05) {
|
---|
[1970] | 381 | ep->type = UNIQUE;
|
---|
| 382 | memset(ep->hexserial, 0, 8);
|
---|
[2019] | 383 | memcpy(ep->hexserial, ep->emm + 5, 5);
|
---|
| 384 | strcpy(dumprdrserial, cs_hexdump(1, rdr->hexserial, 5));
|
---|
[1970] | 385 | cs_debug_mask(D_EMM, "CRYPTOWORKS EMM: UNIQUE, ep = %s rdr = %s",
|
---|
[2019] | 386 | cs_hexdump(1, ep->hexserial, 5), dumprdrserial);
|
---|
[2018] | 387 | return (!memcmp(ep->emm + 5, rdr->hexserial, 5)); // check for serial
|
---|
[1966] | 388 | }
|
---|
| 389 |
|
---|
[1766] | 390 | case 0x84:
|
---|
[1966] | 391 | if(ep->emm[3]==0xA9 && ep->emm[4]==0xFF && ep->emm[12]==0x80 && ep->emm[13]==0x04) {
|
---|
[1766] | 392 | ep->type = SHARED;
|
---|
[1966] | 393 | memset(ep->hexserial, 0, 8);
|
---|
[1970] | 394 | memcpy(ep->hexserial, ep->emm + 5, 4);
|
---|
[1972] | 395 | strcpy(dumprdrserial, cs_hexdump(1, rdr->hexserial, 4));
|
---|
[1966] | 396 | cs_debug_mask(D_EMM, "CRYPTOWORKS EMM: SHARED, ep = %s rdr = %s",
|
---|
[1972] | 397 | cs_hexdump(1, ep->hexserial, 4), dumprdrserial);
|
---|
[1970] | 398 | return (!memcmp(ep->emm + 5, rdr->hexserial, 4)); // check for SA
|
---|
[1966] | 399 | }
|
---|
| 400 |
|
---|
[2019] | 401 | case 0x86:
|
---|
[2431] | 402 | if(ep->emm[3]==0xA9 && ep->emm[4]==0xFF && ep->emm[5]==0x83
|
---|
| 403 | && ep->emm[6]==0x01 && ep->emm[8]==0x85) {
|
---|
| 404 | cs_debug_mask(D_EMM, "CRYPTOWORKS EMM: GLOBAL");
|
---|
| 405 | ep->type = GLOBAL;
|
---|
| 406 | return TRUE;
|
---|
| 407 | }
|
---|
| 408 |
|
---|
[1798] | 409 | case 0x88:
|
---|
[1766] | 410 | case 0x89:
|
---|
[1966] | 411 | if(ep->emm[3]==0xA9 && ep->emm[4]==0xFF && ep->emm[8]==0x83 && ep->emm[9]==0x01) {
|
---|
| 412 | cs_debug_mask(D_EMM, "CRYPTOWORKS EMM: GLOBAL");
|
---|
[1766] | 413 | ep->type = GLOBAL;
|
---|
[1966] | 414 | return TRUE;
|
---|
| 415 | }
|
---|
| 416 |
|
---|
[1992] | 417 | /* FIXME: Dont know how to handle camd3 cryptoworks emms correct */
|
---|
[1966] | 418 | case 0x8F:
|
---|
[1766] | 419 | ep->type = UNKNOWN;
|
---|
[1992] | 420 | cs_debug_mask(D_EMM, "CRYPTOWORKS EMM: UNKNOWN 0x8F via camd3");
|
---|
| 421 | return TRUE;
|
---|
| 422 |
|
---|
| 423 | /* FIXME: Seems to be that all other EMM types are rejected by the card */
|
---|
| 424 | default:
|
---|
| 425 | ep->type = UNKNOWN;
|
---|
[1966] | 426 | cs_debug_mask(D_EMM, "CRYPTOWORKS EMM: UNKNOWN");
|
---|
[1992] | 427 | return FALSE; // skip emm
|
---|
[1766] | 428 | }
|
---|
| 429 | }
|
---|
| 430 |
|
---|
[2074] | 431 | void cryptoworks_get_emm_filter(struct s_reader * rdr, uchar *filter)
|
---|
[1987] | 432 | {
|
---|
[2074] | 433 | filter[0]=0xFF;
|
---|
[2730] | 434 | filter[1]=4;
|
---|
[1987] | 435 |
|
---|
[2074] | 436 | filter[2]=GLOBAL;
|
---|
| 437 | filter[3]=0;
|
---|
[1987] | 438 |
|
---|
[2755] | 439 | filter[4+0] = 0x89;
|
---|
| 440 | filter[4+0+16] = 0xFF;
|
---|
[2074] | 441 | filter[4+1] = 0xA9;
|
---|
| 442 | filter[4+1+16] = 0xFF;
|
---|
| 443 | filter[4+2] = 0xFF;
|
---|
| 444 | filter[4+2+16] = 0xFF;
|
---|
| 445 | filter[4+6] = 0x83;
|
---|
| 446 | filter[4+6+16] = 0xFF;
|
---|
| 447 | filter[4+7] = 0x01;
|
---|
| 448 | filter[4+7+16] = 0xFF;
|
---|
| 449 |
|
---|
| 450 | filter[36]=SHARED;
|
---|
| 451 | filter[37]=0;
|
---|
| 452 |
|
---|
| 453 | filter[38+0] = 0x84;
|
---|
| 454 | filter[38+0+16] = 0xFF;
|
---|
| 455 | filter[38+1] = 0xA9;
|
---|
| 456 | filter[38+1+16] = 0xFF;
|
---|
| 457 | filter[38+2] = 0xFF;
|
---|
| 458 | filter[38+2+16] = 0xFF;
|
---|
| 459 | memcpy(filter+38+3, rdr->hexserial, 4);
|
---|
| 460 | memset(filter+38+3+16, 0xFF, 4);
|
---|
| 461 | filter[38+10] = 0x80;
|
---|
| 462 | filter[38+10+16] = 0xFF;
|
---|
| 463 | filter[38+11] = 0x04;
|
---|
| 464 | filter[38+11+16] = 0xFF;
|
---|
| 465 |
|
---|
| 466 | filter[70]=UNIQUE;
|
---|
| 467 | filter[71]=0;
|
---|
| 468 |
|
---|
| 469 | filter[72+0] = 0x82;
|
---|
| 470 | filter[72+0+16] = 0xFF;
|
---|
| 471 | filter[72+1] = 0xA9;
|
---|
| 472 | filter[72+1+16] = 0xFF;
|
---|
| 473 | filter[72+2] = 0xFF;
|
---|
| 474 | filter[72+2+16] = 0xFF;
|
---|
| 475 | memcpy(filter+72+3, rdr->hexserial, 5);
|
---|
| 476 | memset(filter+72+3+16, 0xFF, 5);
|
---|
| 477 | filter[72+11] = 0x80;
|
---|
| 478 | filter[72+11+16] = 0xFF;
|
---|
| 479 | filter[72+12] = 0x05;
|
---|
| 480 | filter[72+12+16] = 0xFF;
|
---|
| 481 |
|
---|
[2730] | 482 | filter[104]=GLOBAL;
|
---|
| 483 | filter[105]=0;
|
---|
| 484 |
|
---|
| 485 | filter[106+0] = 0x86;
|
---|
| 486 | filter[106+16] = 0xFF;
|
---|
[2743] | 487 | filter[106+6] = 0x84;
|
---|
| 488 | filter[106+6+16] = 0xFF;
|
---|
[2730] | 489 |
|
---|
[2074] | 490 | return;
|
---|
[1987] | 491 | }
|
---|
| 492 |
|
---|
[1926] | 493 | int cryptoworks_do_emm(struct s_reader * reader, EMM_PACKET *ep)
|
---|
[8] | 494 | {
|
---|
[1951] | 495 | def_resp;
|
---|
[39] | 496 | uchar insEMM_GA[] = {0xA4, 0x44, 0x00, 0x00, 0x00};
|
---|
| 497 | uchar insEMM_SA[] = {0xA4, 0x48, 0x00, 0x00, 0x00};
|
---|
| 498 | uchar insEMM_UA[] = {0xA4, 0x42, 0x00, 0x00, 0x00};
|
---|
[8] | 499 | int rc=0;
|
---|
| 500 | uchar *emm=ep->emm;
|
---|
[39] | 501 |
|
---|
[1992] | 502 | /* FIXME: this is the original code how to deal with camd3 EMM's
|
---|
[8] | 503 | if ((emm[0]==0x8f) && (emm[3]==0xa4)) // emm via camd3.5x
|
---|
[39] | 504 | {
|
---|
[8] | 505 | ep->type=emm[4];
|
---|
| 506 | write_cmd(emm+3, emm+3+CMD_LEN);
|
---|
| 507 | if ((cta_lr==2) && (cta_res[0]==0x90) && (cta_res[1]==0))
|
---|
| 508 | rc=1;
|
---|
| 509 | }
|
---|
[39] | 510 | */
|
---|
| 511 |
|
---|
[1798] | 512 | switch(ep->type)
|
---|
[39] | 513 | {
|
---|
[1951] | 514 | // emm via camd3.5x
|
---|
| 515 | case UNKNOWN:
|
---|
| 516 | if(emm[3]==0xA4)
|
---|
[39] | 517 | {
|
---|
| 518 | write_cmd(emm+3, emm+3+CMD_LEN);
|
---|
| 519 | rc=((cta_res[0]==0x90)&&(cta_res[1]==0x00));
|
---|
| 520 | }
|
---|
| 521 | break;
|
---|
| 522 |
|
---|
| 523 | //GA
|
---|
[1798] | 524 | case GLOBAL:
|
---|
[1951] | 525 | insEMM_GA[4]=ep->emm[2]-2;
|
---|
| 526 | if(emm[7]==insEMM_GA[4]-3)
|
---|
| 527 | {
|
---|
| 528 | write_cmd(insEMM_GA, emm+5);
|
---|
| 529 | rc=((cta_res[0]==0x90)&&(cta_res[1]==0x00));
|
---|
| 530 | }
|
---|
[39] | 531 | break;
|
---|
| 532 |
|
---|
| 533 | //SA
|
---|
[1798] | 534 | case SHARED:
|
---|
[1951] | 535 | insEMM_SA[4]=ep->emm[2]-6;
|
---|
[2019] | 536 | //if(emm[11]==insEMM_SA[4]-3)
|
---|
| 537 | //{
|
---|
[1951] | 538 | write_cmd(insEMM_SA, emm+9);
|
---|
| 539 | rc=((cta_res[0]==0x90)&&(cta_res[1]==0x00));
|
---|
[2019] | 540 | //}
|
---|
[39] | 541 | break;
|
---|
| 542 |
|
---|
| 543 | //UA
|
---|
[1798] | 544 | case UNIQUE:
|
---|
[1951] | 545 | insEMM_UA[4]=ep->emm[2]-7;
|
---|
| 546 | if(emm[12]==insEMM_UA[4]-3)
|
---|
| 547 | {
|
---|
| 548 | //cryptoworks_send_pin(); //?? may be
|
---|
| 549 | write_cmd(insEMM_UA, emm+10);
|
---|
| 550 | rc=((cta_res[0]==0x90)&&(cta_res[1]==0x00));
|
---|
| 551 | }
|
---|
[39] | 552 | break;
|
---|
| 553 | }
|
---|
| 554 |
|
---|
[8] | 555 | return(rc);
|
---|
| 556 | }
|
---|
| 557 |
|
---|
[1926] | 558 | int cryptoworks_card_info(struct s_reader * reader)
|
---|
[8] | 559 | {
|
---|
[1951] | 560 | def_resp;
|
---|
| 561 | int i;
|
---|
[8] | 562 | uchar insA21[]= {0xA4, 0xA2, 0x01, 0x00, 0x05, 0x8C, 0x00, 0x00, 0x00, 0x00};
|
---|
| 563 | uchar insB2[] = {0xA4, 0xB2, 0x00, 0x00, 0x00};
|
---|
| 564 | char l_name[20+8]=", name: ";
|
---|
| 565 |
|
---|
[1926] | 566 | for (i=0; i<reader->nprov; i++)
|
---|
[8] | 567 | {
|
---|
| 568 | l_name[8]=0;
|
---|
[1951] | 569 | select_file(reader, 0x1f, reader->prid[i][3], cta_res, &cta_lr); // select provider
|
---|
| 570 | select_file(reader, 0x0e, 0x11, cta_res, &cta_lr); // read provider name
|
---|
| 571 | if (read_record(reader, 0xD6, cta_res)>=16)
|
---|
[8] | 572 | {
|
---|
[1691] | 573 | cs_strncpy(l_name+8, (const char *)cta_res+2, sizeof(l_name)-9);
|
---|
[470] | 574 | l_name[sizeof(l_name)-1]=0;
|
---|
[8] | 575 | trim(l_name+8);
|
---|
| 576 | }
|
---|
| 577 | l_name[0]=(l_name[8]) ? ',' : 0;
|
---|
[1951] | 578 | cs_ri_log (reader, "provider: %d, id: %02X%s", i+1, reader->prid[i][3], l_name);
|
---|
| 579 | select_file(reader, 0x0f, 0x20, cta_res, &cta_lr); // select provider class
|
---|
[8] | 580 | write_cmd(insA21, insA21+5);
|
---|
| 581 | if (cta_res[0]==0x9f)
|
---|
| 582 | {
|
---|
| 583 | insB2[4]=cta_res[1];
|
---|
| 584 | for(insB2[3]=0; (cta_res[0]!=0x94)||(cta_res[1]!=0x2); insB2[3]=1)
|
---|
| 585 | {
|
---|
[1951] | 586 | write_cmd(insB2, NULL); // read chid
|
---|
[8] | 587 | if (cta_res[0]!=0x94)
|
---|
| 588 | {
|
---|
| 589 | char ds[16], de[16];
|
---|
| 590 | chid_date(cta_res+28, ds, sizeof(ds)-1);
|
---|
| 591 | chid_date(cta_res+30, de, sizeof(de)-1);
|
---|
[1951] | 592 | cs_ri_log (reader, "chid: %02X%02X, date: %s - %s, name: %s",
|
---|
[70] | 593 | cta_res[6], cta_res[7], ds, de, trim((char *) cta_res+10));
|
---|
[8] | 594 | }
|
---|
| 595 | }
|
---|
| 596 | }
|
---|
[2210] | 597 |
|
---|
[1951] | 598 | select_file(reader, 0x0f, 0x00, cta_res, &cta_lr); // select provider channel
|
---|
[39] | 599 | write_cmd(insA21, insA21+5);
|
---|
| 600 | if (cta_res[0]==0x9f)
|
---|
| 601 | {
|
---|
| 602 | insB2[4]=cta_res[1];
|
---|
| 603 | for(insB2[3]=0; (cta_res[0]!=0x94)||(cta_res[1]!=0x2); insB2[3]=1)
|
---|
| 604 | {
|
---|
[1951] | 605 | write_cmd(insB2, NULL); // read chid
|
---|
[39] | 606 | if (cta_res[0]!=0x94)
|
---|
| 607 | {
|
---|
| 608 | char ds[16], de[16];
|
---|
| 609 | chid_date(cta_res+28, ds, sizeof(ds)-1);
|
---|
| 610 | chid_date(cta_res+30, de, sizeof(de)-1);
|
---|
| 611 | cta_res[27]=0;
|
---|
[1951] | 612 | cs_ri_log (reader, "chid: %02X%02X, date: %s - %s, name: %s",
|
---|
[70] | 613 | cta_res[6], cta_res[7], ds, de, trim((char *)cta_res+10));
|
---|
[39] | 614 | }
|
---|
| 615 | }
|
---|
| 616 | }
|
---|
[8] | 617 | }
|
---|
[2210] | 618 | cs_log("[cryptoworks-reader] ready for requests");
|
---|
[1389] | 619 | return OK;
|
---|
[8] | 620 | }
|
---|
[3168] | 621 |
|
---|
| 622 | void reader_cryptoworks(struct s_cardsystem *ph)
|
---|
| 623 | {
|
---|
| 624 | ph->do_emm=cryptoworks_do_emm;
|
---|
| 625 | ph->do_ecm=cryptoworks_do_ecm;
|
---|
| 626 | ph->card_info=cryptoworks_card_info;
|
---|
| 627 | ph->card_init=cryptoworks_card_init;
|
---|
| 628 | ph->get_emm_type=cryptoworks_get_emm_type;
|
---|
| 629 | ph->caids[0]=0x0D;
|
---|
| 630 | }
|
---|