- Timestamp:
- 11/24/09 15:49:02 (2 years ago)
- File:
-
- 1 edited
-
trunk/src/ifd/ifd-rutoken.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/ifd/ifd-rutoken.c
r1152 r1174 9 9 #include <unistd.h> 10 10 #include <string.h> 11 #include <stdlib.h> 11 12 12 13 #define MAX_BUF_T0_LEN 256 … … 362 363 } 363 364 365 static void swap_pair(unsigned char *buf, size_t len) 366 { 367 size_t i; 368 unsigned char tmp; 369 370 for (i = 0; i + 1 < len; i += 2) { 371 tmp = buf[i]; 372 buf[i] = buf[i + 1]; 373 buf[i + 1] = tmp; 374 } 375 } 376 377 static void swap_four(unsigned char *buf, size_t len) 378 { 379 size_t i; 380 unsigned char tmp; 381 382 for (i = 0; i + 3 < len; i += 4) { 383 tmp = buf[i]; 384 buf[i] = buf[i + 3]; 385 buf[i + 3] = tmp; 386 387 swap_pair(&buf[i + 1], 2); 388 } 389 } 390 391 static int read_tag(unsigned char *buf, size_t buf_len, 392 unsigned char tag_in, unsigned char *out, size_t out_len) 393 { 394 unsigned char tag; 395 size_t taglen, i = 0; 396 397 while (i + 2 <= buf_len) { 398 tag = buf[i]; 399 taglen = buf[i + 1]; 400 i += 2; 401 if (taglen + i > buf_len) 402 return -1; 403 if (tag == tag_in) { 404 if (taglen != out_len) 405 return -1; 406 memcpy(out, buf + i, out_len); 407 return 0; 408 } 409 i += taglen; 410 } 411 return -1; 412 } 413 414 static int convert_doinfo_to_rtprot(void *data, size_t data_len) 415 { 416 unsigned char dohdr[32] = { 0 }; 417 unsigned char secattr[40], data_a5[0xff]; 418 unsigned char *p = data; 419 size_t i, data_a5_len; 420 421 if (read_tag(p, data_len, 0x80, &dohdr[0], 2) == 0) { 422 swap_pair(&dohdr[0], 2); 423 ifd_debug(6, "tag 0x80 (file size) = %02x %02x", dohdr[0], dohdr[1]); 424 } 425 data_a5_len = dohdr[1] & 0xff; 426 if (read_tag(p, data_len, 0xA5, data_a5, data_a5_len) == 0) 427 ifd_debug(6, "tag 0xA5 = %s", ct_hexdump(data_a5, data_a5_len)); 428 else 429 data_a5_len = 0; 430 if (data_len < sizeof(dohdr) + data_a5_len) { 431 ifd_debug(6, "data_len = %u", data_len); 432 return -1; 433 } 434 if (read_tag(p, data_len, 0x83, &dohdr[2], 2) == 0) 435 ifd_debug(6, "tag 0x83 (Type,ID) = %02x %02x", dohdr[2], dohdr[3]); 436 if (read_tag(p, data_len, 0x85, &dohdr[4], 3) == 0) 437 ifd_debug(6, "tag 0x85 (Opt,Flags,MaxTry) = %02x %02x %02x", 438 dohdr[4], dohdr[5], dohdr[6]); 439 if (read_tag(p, data_len, 0x86, secattr, sizeof(secattr)) == 0) { 440 i = 17; 441 memcpy(dohdr + i, secattr, 8); 442 for (i += 8, p = &secattr[8]; i < sizeof(dohdr); ++i, p += 4) 443 dohdr[i] = *p; 444 ifd_debug(6, "tag 0x86 = %s", ct_hexdump(&dohdr[17], 15)); 445 } 446 memcpy(data, dohdr, sizeof(dohdr)); 447 memcpy((unsigned char*)data + sizeof(dohdr), data_a5, data_a5_len); 448 return sizeof(dohdr) + data_a5_len; 449 } 450 451 static int convert_fcp_to_rtprot(void *data, size_t data_len) 452 { 453 unsigned char rtprot[32] = { 0 }; 454 unsigned char secattr[40]; 455 unsigned char *p = data; 456 size_t i; 457 458 if (data_len < sizeof(rtprot)) { 459 ifd_debug(6, "data_len = %u", data_len); 460 return -1; 461 } 462 /* 0x62 - FCP */ 463 if (p[0] != 0x62 || (size_t)p[1] + 2 > data_len) { 464 ifd_debug(6, "Tag = %02x len = %u", p[0], p[1]); 465 return -1; 466 } 467 p += 2; 468 data_len -= 2; 469 /* file type */ 470 if (read_tag(p, data_len, 0x82, &rtprot[4], 2) != 0) 471 return -1; 472 ifd_debug(6, "tag 0x82 (file type) = %02x %02x", rtprot[4], rtprot[5]); 473 /* file id */ 474 if (read_tag(p, data_len, 0x83, &rtprot[6], 2) != 0) 475 return -1; 476 swap_pair(&rtprot[6], 2); 477 ifd_debug(6, "tag 0x83 (file id) = %02x %02x", rtprot[6], rtprot[7]); 478 /* file size */ 479 if (read_tag(p, data_len, 0x81, &rtprot[0], 2) == 0) { 480 swap_pair(&rtprot[0], 2); 481 ifd_debug(6, "tag 0x81 (complete file size) = %02x %02x", 482 rtprot[0], rtprot[1]); 483 } 484 if (read_tag(p, data_len, 0x80, &rtprot[2], 2) == 0) { 485 swap_pair(&rtprot[2], 2); 486 ifd_debug(6, "tag 0x80 (file size) = %02x %02x", rtprot[2], rtprot[3]); 487 } 488 if (read_tag(p, data_len, 0x86, secattr, sizeof(secattr)) == 0) { 489 i = 17; 490 memcpy(rtprot + i, secattr, 8); 491 for (i += 8, p = &secattr[8]; i < sizeof(rtprot); ++i, p += 4) 492 rtprot[i] = *p; 493 ifd_debug(6, "tag 0x86 = %s", ct_hexdump(&rtprot[17], 15)); 494 } 495 memcpy(data, rtprot, sizeof(rtprot)); 496 return sizeof(rtprot); 497 } 498 499 static int convert_rtprot_to_doinfo(void *data, size_t data_len) 500 { 501 unsigned char doinfo[0xff] = { 0 }; 502 unsigned char *pdata = data; 503 size_t i, doinfo_len = 0; 504 505 if (data_len < 32) { 506 ifd_debug(6, "data_len = %u", data_len); 507 return -1; 508 } 509 if (pdata[0] != 0 && pdata[0] < sizeof(doinfo) - 4 - 4 - 5 - 42 - 2) { 510 /* Tag 0x80 */ 511 doinfo[doinfo_len++] = 0x80; 512 doinfo[doinfo_len++] = 2; 513 memcpy(doinfo + doinfo_len, pdata, 2); 514 swap_pair(doinfo + doinfo_len, 2); 515 doinfo_len += 2; 516 } 517 /* Tag 0x83 */ 518 doinfo[doinfo_len++] = 0x83; 519 doinfo[doinfo_len++] = 2; 520 doinfo[doinfo_len++] = pdata[2]; 521 doinfo[doinfo_len++] = pdata[3]; 522 523 /* Tag 0x85 */ 524 doinfo[doinfo_len++] = 0x85; 525 doinfo[doinfo_len++] = 3; 526 doinfo[doinfo_len++] = pdata[4]; 527 doinfo[doinfo_len++] = pdata[5]; 528 doinfo[doinfo_len++] = pdata[6]; 529 530 /* Tag 0x86 */ 531 doinfo[doinfo_len++] = 0x86; 532 doinfo[doinfo_len++] = 40; 533 memcpy(doinfo + doinfo_len, pdata + 17, 8); 534 doinfo_len += 8; 535 for (i = 0; i < 7 && doinfo_len + 3 < sizeof(doinfo); ++i, doinfo_len += 4) 536 doinfo[doinfo_len] = pdata[17 + 8 + i]; 537 doinfo_len += 4; /* for reserved */ 538 if (pdata[0] != 0 && pdata[0] + doinfo_len + 2 < sizeof(doinfo)) { 539 /* Tag 0xA5 */ 540 if (data_len - 32 < pdata[0]) { 541 ifd_debug(6, "for tag 0xA5 incorrect data_len = %u", data_len); 542 return -1; 543 } 544 doinfo[doinfo_len++] = 0xA5; 545 doinfo[doinfo_len++] = pdata[0]; 546 memcpy(doinfo + doinfo_len, pdata + 32, pdata[0]); 547 doinfo_len += pdata[0]; 548 } 549 ifd_debug(6, "doinfo = %s", ct_hexdump(doinfo, doinfo_len)); 550 memcpy(data, doinfo, doinfo_len); 551 return doinfo_len; 552 } 553 554 static int convert_rtprot_to_fcp(void *data, size_t data_len) 555 { 556 unsigned char fcp[63] = { 557 0x62, sizeof(fcp) - 2, 558 0x81, 2, 0, 0, 559 0x80, 2, 0, 0, 560 0x82, 2, 0, 0, 561 0x83, 2, 0, 0, 562 0x8A, 1, 0, 563 0x86, 40 564 }; 565 unsigned char *p = data; 566 size_t i; 567 568 if (data_len < sizeof(fcp)) { 569 ifd_debug(6, "data_len = %u", data_len); 570 return -1; 571 } 572 /* Tag 0x81 */ 573 memcpy(fcp + 4, p, 2); 574 swap_pair(fcp + 4, 2); 575 /* Tag 0x80 */ 576 memcpy(fcp + 8, p + 2, 2); 577 swap_pair(fcp + 8, 2); 578 /* Tag 0x82 */ 579 memcpy(fcp + 12, p + 4, 2); 580 /* Tag 0x83 */ 581 memcpy(fcp + 16, p + 6, 2); 582 swap_pair(fcp + 16, 2); 583 /* Tag 0x8A */ 584 fcp[20] = p[8]; 585 586 /* Tag 0x86 */ 587 memcpy(fcp + 23, p + 17, 8); 588 for (i = 0; i < 7 && sizeof(fcp) > 23 + 8 + i * 4; ++i) 589 fcp[23 + 8 + i * 4] = p[17 + 8 + i]; 590 ifd_debug(6, "fcp = %s", ct_hexdump(fcp, sizeof(fcp))); 591 memcpy(data, fcp, sizeof(fcp)); 592 return sizeof(fcp); 593 } 594 364 595 static int rutoken_transparent( ifd_reader_t * reader, int dad, 365 596 const void *sbuf, size_t slen, 366 597 void *rbuf, size_t rlen) 367 598 { 368 int rrecv = 0; 599 unsigned char sw[2], *send_buf_trn = NULL; 600 const void *send_buf = sbuf; 601 int len, rrecv = -1, iscase4 = 0; 369 602 ifd_iso_apdu_t iso; 603 370 604 ifd_debug(6, "buffer %s rlen = %d", ct_hexdump(sbuf, slen), rlen); 371 605 if ( ifd_iso_apdu_parse(sbuf, slen, &iso) < 0) 372 606 return -1; 373 607 ifd_debug(6, "iso.le = %d", iso.le); 608 609 if (iso.cla == 0 && slen > 5) { 610 send_buf_trn = malloc(slen); 611 if (!send_buf_trn) { 612 ifd_debug(5, "out of memory (slen = %u)", slen); 613 return IFD_ERROR_NO_MEMORY; 614 } 615 memcpy(send_buf_trn, sbuf, slen); 616 /* select file, delete file */ 617 if (iso.ins == 0xa4 || iso.ins == 0xe4) 618 swap_pair(send_buf_trn + 5, slen - 5); 619 /* create file */ 620 else if (iso.ins == 0xe0) { 621 len = convert_fcp_to_rtprot(send_buf_trn + 5, slen - 5); 622 ifd_debug(6, "convert_fcp_to_rtprot = %i", len); 623 if (len > 0) { 624 slen = len + 5; 625 send_buf_trn[4] = len; /* replace le */ 626 } 627 } 628 /* create_do, key_gen */ 629 else if (iso.ins == 0xda && iso.p1 == 1 630 && (iso.p2 == 0x65 || iso.p2 == 0x62)) { 631 len = convert_doinfo_to_rtprot(send_buf_trn + 5, slen - 5); 632 ifd_debug(6, "convert_doinfo_to_rtprot = %i", len); 633 if (len > 0) { 634 slen = len + 5; 635 send_buf_trn[4] = len; /* replace le */ 636 } 637 } 638 ifd_debug(6, "le = %u", send_buf_trn[4]); 639 send_buf = send_buf_trn; 640 } 374 641 switch(iso.cse){ 642 case IFD_APDU_CASE_2S: 643 case IFD_APDU_CASE_3S: 644 if (iso.cla == 0 && iso.ins == 0xa4) 645 iscase4 = 1; /* FIXME: */ 375 646 case IFD_APDU_CASE_1: 376 case IFD_APDU_CASE_2S: 377 case IFD_APDU_CASE_3S: 378 return rutoken_send_tpducomand(reader, dad, sbuf, slen, 379 rbuf, rlen, 0); 647 rrecv = rutoken_send_tpducomand(reader, dad, send_buf, slen, 648 rbuf, rlen, iscase4); 380 649 break; 381 650 case IFD_APDU_CASE_4S: 382 651 // make send case 4 command 383 rrecv = rutoken_send_tpducomand(reader, dad, s buf, slen-1,652 rrecv = rutoken_send_tpducomand(reader, dad, send_buf, slen-1, 384 653 rbuf, rlen, 1); 385 return rrecv;386 654 break; 387 655 default: 388 656 break; 389 657 } 390 return -1; 658 if (send_buf_trn) 659 free(send_buf_trn); 660 661 if (rrecv > 0 && (size_t)rrecv >= sizeof(sw)) { 662 memcpy(sw, (unsigned char*)rbuf + rrecv - sizeof(sw), sizeof(sw)); 663 if (sw[0] != 0x90 || sw[1] != 0) 664 /* do nothing */; 665 /* select file */ 666 else if (iso.cla == 0 && iso.ins == 0xa4 667 && rrecv == sizeof(sw) + 32 /* size rtprot */) { 668 len = convert_rtprot_to_fcp(rbuf, rlen); 669 ifd_debug(6, "convert_rtprot_to_fcp = %i", len); 670 if (len > 0) { 671 rrecv = -1; 672 if (rlen >= len + sizeof(sw)) { 673 memcpy((unsigned char*)rbuf+len, sw, sizeof(sw)); 674 rrecv = len + sizeof(sw); 675 } 676 } 677 } 678 /* get_do_info */ 679 else if (iso.cla == 0x80 && iso.ins == 0x30 680 && (size_t)rrecv >= sizeof(sw) + 32 /* size rtprot */) { 681 len = convert_rtprot_to_doinfo(rbuf, rlen); 682 ifd_debug(6, "convert_rtprot_to_doinfo = %i", len); 683 if (len > 0) { 684 rrecv = -1; 685 if (rlen >= len + sizeof(sw)) { 686 memcpy((unsigned char*)rbuf+len, sw, sizeof(sw)); 687 rrecv = len + sizeof(sw); 688 } 689 } 690 } 691 else if (iso.cla == 0 && iso.ins == 0xca && iso.p1 == 1) { 692 /* get_serial, get_free_mem */ 693 if (iso.p2 == 0x81 || iso.p2 == 0x8a) 694 swap_four(rbuf, rrecv - sizeof(sw)); 695 /* get_current_ef */ 696 else if (iso.p2 == 0x11) 697 swap_pair(rbuf, rrecv - sizeof(sw)); 698 } 699 } 700 return rrecv; 391 701 } 392 702
Note: See TracChangeset
for help on using the changeset viewer.
