00001
00025 #include <avr/io.h>
00026 #include <avr/interrupt.h>
00027 #include <avr/sleep.h>
00028 #include <avr/power.h>
00029 #include <string.h>
00030 #include <stdlib.h>
00031 #include <stdarg.h>
00032
00033 #include "emv.h"
00034 #include "scd_hal.h"
00035 #include "emv_values.h"
00036 #include "scd_values.h"
00037
00038 #define DEBUG 0 // Set DEBUG to 1 to enable debug code
00039
00040
00041
00042
00043
00044
00045
00059 EMVCommandHeader* MakeCommandHeader(uint8_t cla, uint8_t ins, uint8_t p1,
00060 uint8_t p2, uint8_t p3)
00061 {
00062 EMVCommandHeader *cmd = (EMVCommandHeader*)malloc(sizeof(EMVCommandHeader));
00063 if(cmd == NULL) return NULL;
00064
00065 cmd->cla = cla;
00066 cmd->ins = ins;
00067 cmd->p1 = p1;
00068 cmd->p2 = p2;
00069 cmd->p3 = p3;
00070
00071 return cmd;
00072 }
00073
00086 EMVCommandHeader* MakeCommandHeaderC(EMV_CMD command)
00087 {
00088 EMVCommandHeader *cmd = (EMVCommandHeader*)malloc(sizeof(EMVCommandHeader));
00089 if(cmd == NULL) return NULL;
00090
00091
00092 cmd->cla = 0;
00093 cmd->ins = 0;
00094 cmd->p1 = 0;
00095 cmd->p2 = 0;
00096 cmd->p3 = 0;
00097
00098 switch(command)
00099 {
00100 case CMD_SELECT:
00101 cmd->ins = 0xA4;
00102 cmd->p1 = 0x04;
00103 break;
00104
00105 case CMD_GET_RESPONSE:
00106 cmd->ins = 0xC0;
00107 break;
00108
00109 case CMD_READ_RECORD:
00110 cmd->ins = 0xB2;
00111 cmd->p1 = 0x01;
00112 break;
00113
00114 case CMD_GET_PROCESSING_OPTS:
00115 cmd->cla = 0x80;
00116 cmd->ins = 0xA8;
00117 break;
00118
00119 case CMD_VERIFY:
00120 cmd->ins = 0x20;
00121 cmd->p2 = 0x80;
00122 break;
00123
00124 case CMD_GENERATE_AC:
00125 cmd->cla = 0x80;
00126 cmd->ins = 0xAE;
00127 break;
00128
00129 case CMD_GET_DATA:
00130 cmd->cla = 0x80;
00131 cmd->ins = 0xCA;
00132 cmd->p1 = 0x9F;
00133 cmd->p2 = 0x17;
00134 break;
00135
00136 case CMD_INTERNAL_AUTHENTICATE:
00137 cmd->ins = 0x88;
00138 break;
00139
00140 }
00141
00142 return cmd;
00143 }
00144
00145
00166 CAPDU* MakeCommand(uint8_t cla, uint8_t ins, uint8_t p1,
00167 uint8_t p2, uint8_t p3, const uint8_t cmdData[], uint8_t lenData)
00168 {
00169 CAPDU *cmd = (CAPDU*)malloc(sizeof(CAPDU));
00170 if(cmd == NULL) return NULL;
00171
00172 cmd->cmdHeader = MakeCommandHeader(cla, ins, p1, p2, p3);
00173 if(cmd->cmdHeader == NULL)
00174 {
00175 free(cmd);
00176 return NULL;
00177 }
00178
00179 if(cmdData != NULL && lenData != 0)
00180 {
00181 cmd->cmdData = (uint8_t*)malloc(lenData * sizeof(uint8_t));
00182 if(cmd->cmdData == NULL)
00183 {
00184 FreeCAPDU(cmd);
00185 return NULL;
00186 }
00187 memcpy(cmd->cmdData, cmdData, lenData);
00188 cmd->lenData = lenData;
00189 }
00190 else
00191 {
00192 cmd->cmdData = NULL;
00193 cmd->lenData = 0;
00194 }
00195
00196 return cmd;
00197 }
00198
00217 CAPDU* MakeCommandP(const EMVCommandHeader *cmdHdr, const uint8_t cmdData[],
00218 uint8_t lenData)
00219 {
00220 if(cmdHdr == NULL) return NULL;
00221
00222 CAPDU *cmd = (CAPDU*)malloc(sizeof(CAPDU));
00223 if(cmd == NULL) return NULL;
00224
00225 cmd->cmdHeader = MakeCommandHeader(cmdHdr->cla, cmdHdr->ins,
00226 cmdHdr->p1, cmdHdr->p2, cmdHdr->p3);
00227 if(cmd->cmdHeader == NULL)
00228 {
00229 free(cmd);
00230 return NULL;
00231 }
00232
00233 if(cmdData != NULL && lenData != 0)
00234 {
00235 cmd->cmdData = (uint8_t*)malloc(lenData * sizeof(uint8_t));
00236 if(cmd->cmdData == NULL)
00237 {
00238 FreeCAPDU(cmd);
00239 return NULL;
00240 }
00241 memcpy(cmd->cmdData, cmdData, lenData);
00242 cmd->lenData = lenData;
00243 }
00244 else
00245 {
00246 cmd->cmdData = NULL;
00247 cmd->lenData = 0;
00248 }
00249
00250 return cmd;
00251 }
00252
00271 CAPDU* MakeCommandC(EMV_CMD command, const uint8_t cmdData[],
00272 uint8_t lenData)
00273 {
00274 CAPDU *cmd = (CAPDU*)malloc(sizeof(CAPDU));
00275 if(cmd == NULL) return NULL;
00276
00277 cmd->cmdHeader = MakeCommandHeaderC(command);
00278 if(cmd->cmdHeader == NULL)
00279 {
00280 free(cmd);
00281 return NULL;
00282 }
00283
00284 if(cmdData != NULL && lenData != 0)
00285 {
00286 cmd->cmdData = (uint8_t*)malloc(lenData * sizeof(uint8_t));
00287 if(cmd->cmdData == NULL)
00288 {
00289 FreeCAPDU(cmd);
00290 return NULL;
00291 }
00292 memcpy(cmd->cmdData, cmdData, lenData);
00293 cmd->lenData = lenData;
00294 cmd->cmdHeader->p3 = lenData;
00295 }
00296 else
00297 {
00298 cmd->cmdData = NULL;
00299 cmd->lenData = 0;
00300 }
00301
00302 return cmd;
00303 }
00304
00334 uint8_t InitSCDTransaction(uint8_t t_inverse, uint8_t t_TC1,
00335 uint8_t *inverse_convention, uint8_t *proto, uint8_t *TC1,
00336 uint8_t *TA3, uint8_t *TB3)
00337 {
00338 uint8_t tmp;
00339 uint16_t tfreq, tdelay;
00340 int8_t tmpi;
00341
00342
00343 StartCounterTerminal();
00344
00345
00346 while(ReadCounterTerminal() < 10);
00347
00348
00349 tfreq = GetTerminalFreq();
00350 tdelay = 10 * tfreq;
00351
00352
00353
00354
00355 tmp = (uint8_t)((60000 - tdelay) / 372);
00356 LoopTerminalETU(tmp);
00357 if(ActivateICC(0)) return RET_ERROR;
00358
00359
00360 tmpi = (int8_t)((tdelay - 10000) / 372);
00361 if(tmpi < 0) tmpi = 0;
00362 LoopTerminalETU(tmpi);
00363 if(t_inverse)
00364 SendByteTerminalNoParity(0x3F, t_inverse);
00365 else
00366 SendByteTerminalNoParity(0x3B, t_inverse);
00367
00368
00369 LoopTerminalETU(12);
00370 PORTD |= _BV(PD4);
00371
00372
00373
00374 if(WaitForICCData(50000))
00375 {
00376 DeactivateICC();
00377 return RET_ERROR;
00378 }
00379
00380 if(GetATRICC(inverse_convention, proto, TC1, TA3, TB3))
00381 {
00382 DeactivateICC();
00383 return RET_ERROR;
00384 }
00385
00386
00387 SendByteTerminalNoParity(0x60, t_inverse);
00388 LoopTerminalETU(2);
00389 SendByteTerminalNoParity(0x00, t_inverse);
00390 LoopTerminalETU(2);
00391 SendByteTerminalNoParity(t_TC1, t_inverse);
00392 LoopTerminalETU(2);
00393
00394 return 0;
00395 }
00396
00397
00415 uint8_t GetCommandCase(uint8_t cla, uint8_t ins)
00416 {
00417 switch(cla)
00418 {
00419 case 0:
00420 {
00421 switch(ins)
00422 {
00423 case 0xC0:
00424 return 2;
00425 break;
00426
00427 case 0xB2:
00428 return 2;
00429 break;
00430
00431 case 0xA4:
00432 return 4;
00433 break;
00434
00435 case 0x82:
00436 return 3;
00437 break;
00438
00439 case 0x84:
00440 return 2;
00441 break;
00442
00443 case 0x88:
00444 return 4;
00445 break;
00446
00447 case 0x20:
00448 return 3;
00449 break;
00450
00451 default: return 0;
00452 }
00453 }
00454 break;
00455
00456 case 0x8C:
00457 case 0x84:
00458 {
00459 switch(ins)
00460 {
00461 case 0x1E:
00462 return 3;
00463 break;
00464
00465 case 0x18:
00466 return 3;
00467 break;
00468
00469 case 0x16:
00470 return 3;
00471 break;
00472
00473 case 0x24:
00474 return 3;
00475 break;
00476
00477 default: return 0;
00478 }
00479 }
00480 break;
00481
00482 case 0x80:
00483 {
00484 switch(ins)
00485 {
00486 case 0xAE:
00487 return 4;
00488 break;
00489
00490 case 0xCA:
00491 return 2;
00492 break;
00493
00494 case 0xA8:
00495 return 4;
00496 break;
00497
00498 default: return 0;
00499 }
00500 }
00501 break;
00502
00503 default: return 0;
00504 }
00505
00506 return 0;
00507 }
00508
00509
00521 EMVCommandHeader* ReceiveT0CmdHeader(uint8_t inverse_convention, uint8_t TC1)
00522 {
00523 uint8_t tdelay;
00524 EMVCommandHeader *cmdHeader;
00525
00526 cmdHeader = (EMVCommandHeader*)malloc(sizeof(EMVCommandHeader));
00527 if(cmdHeader == NULL) return NULL;
00528
00529 tdelay = 1 + TC1;
00530
00531 if(GetByteTerminalParity(inverse_convention, &(cmdHeader->cla)))
00532 {
00533 free(cmdHeader);
00534 return NULL;
00535 }
00536 LoopTerminalETU(tdelay);
00537
00538 if(GetByteTerminalParity(inverse_convention, &(cmdHeader->ins)))
00539 {
00540 free(cmdHeader);
00541 return NULL;
00542 }
00543 LoopTerminalETU(tdelay);
00544
00545 if(GetByteTerminalParity(inverse_convention, &(cmdHeader->p1)))
00546 {
00547 free(cmdHeader);
00548 return NULL;
00549 }
00550 LoopTerminalETU(tdelay);
00551
00552 if(GetByteTerminalParity(inverse_convention, &(cmdHeader->p2)))
00553 {
00554 free(cmdHeader);
00555 return NULL;
00556 }
00557 LoopTerminalETU(tdelay);
00558
00559 if(GetByteTerminalParity(inverse_convention, &(cmdHeader->p3)))
00560 {
00561 free(cmdHeader);
00562 return NULL;
00563 }
00564
00565 return cmdHeader;
00566 }
00567
00582 uint8_t* ReceiveT0CmdData(uint8_t inverse_convention, uint8_t TC1,
00583 uint8_t len)
00584 {
00585 uint8_t tdelay, i;
00586 uint8_t *cmdData;
00587
00588 cmdData = (uint8_t*)malloc(len*sizeof(uint8_t));
00589 if(cmdData == NULL) return NULL;
00590
00591 tdelay = 1 + TC1;
00592
00593 for(i = 0; i < len - 1; i++)
00594 {
00595 if(GetByteTerminalParity(inverse_convention, &(cmdData[i])))
00596 {
00597 free(cmdData);
00598 return NULL;
00599 }
00600 LoopTerminalETU(tdelay);
00601 }
00602
00603
00604 if(GetByteTerminalParity(inverse_convention, &(cmdData[i])))
00605 {
00606 free(cmdData);
00607 return NULL;
00608 }
00609
00610 return cmdData;
00611 }
00612
00626 CAPDU* ReceiveT0Command(uint8_t inverse_convention, uint8_t TC1)
00627 {
00628 uint8_t tdelay, tmp;
00629 CAPDU *cmd;
00630
00631 tdelay = 1 + TC1;
00632
00633 cmd = (CAPDU*)malloc(sizeof(CAPDU));
00634 if(cmd == NULL) return NULL;
00635 cmd->cmdHeader = NULL;
00636 cmd->cmdData = NULL;
00637 cmd->lenData = 0;
00638
00639 cmd->cmdHeader = ReceiveT0CmdHeader(inverse_convention, TC1);
00640 if(cmd->cmdHeader == NULL)
00641 {
00642 free(cmd);
00643 return NULL;
00644 }
00645 tmp = GetCommandCase(cmd->cmdHeader->cla, cmd->cmdHeader->ins);
00646 if(tmp == 0)
00647 {
00648 FreeCAPDU(cmd);
00649 return NULL;
00650 }
00651
00652
00653 if(tmp == 1 || tmp == 2)
00654 return cmd;
00655
00656
00657 LoopTerminalETU(6);
00658 if(SendByteTerminalParity(cmd->cmdHeader->ins, inverse_convention))
00659 {
00660 free(cmd->cmdHeader);
00661 cmd->cmdHeader = NULL;
00662 free(cmd);
00663 return NULL;
00664 }
00665
00666 LoopTerminalETU(tdelay);
00667 cmd->lenData = cmd->cmdHeader->p3;
00668 cmd->cmdData = ReceiveT0CmdData(inverse_convention, TC1, cmd->lenData);
00669 if(cmd->cmdData == NULL)
00670 {
00671 free(cmd->cmdHeader);
00672 cmd->cmdHeader = NULL;
00673 free(cmd);
00674 return NULL;
00675 }
00676
00677 return cmd;
00678 }
00679
00680
00691 uint8_t SendT0CmdHeader(uint8_t inverse_convention, uint8_t TC1,
00692 EMVCommandHeader *cmdHeader)
00693 {
00694 uint8_t tdelay;
00695
00696 if(cmdHeader == NULL) return RET_ERROR;
00697
00698 tdelay = 1 + TC1;
00699
00700 if(SendByteICCParity(cmdHeader->cla, inverse_convention)) return RET_ERROR;
00701 LoopICCETU(tdelay);
00702
00703 if(SendByteICCParity(cmdHeader->ins, inverse_convention)) return RET_ERROR;
00704 LoopICCETU(tdelay);
00705
00706 if(SendByteICCParity(cmdHeader->p1, inverse_convention)) return RET_ERROR;
00707 LoopICCETU(tdelay);
00708
00709 if(SendByteICCParity(cmdHeader->p2, inverse_convention)) return RET_ERROR;
00710 LoopICCETU(tdelay);
00711
00712 if(SendByteICCParity(cmdHeader->p3, inverse_convention)) return RET_ERROR;
00713
00714 return 0;
00715 }
00716
00717
00728 uint8_t SendT0CmdData(uint8_t inverse_convention, uint8_t TC1,
00729 uint8_t *cmdData, uint8_t len)
00730 {
00731 uint8_t tdelay, i;
00732
00733 if(cmdData == NULL) return RET_ERROR;
00734
00735 tdelay = 1 + TC1;
00736
00737 for(i = 0; i < len - 1; i++)
00738 {
00739 if(SendByteICCParity(cmdData[i], inverse_convention))
00740 return RET_ERROR;
00741 LoopICCETU(tdelay);
00742 }
00743
00744
00745 if(SendByteICCParity(cmdData[i], inverse_convention))
00746 return RET_ERROR;
00747
00748 return 0;
00749 }
00750
00751
00763 uint8_t SendT0Command(uint8_t inverse_convention, uint8_t TC1, CAPDU *cmd)
00764 {
00765 uint8_t tdelay, tmp, tmp2, i;
00766
00767 if(cmd == NULL) return RET_ERROR;
00768 tdelay = 1 + TC1;
00769
00770 tmp = GetCommandCase(cmd->cmdHeader->cla, cmd->cmdHeader->ins);
00771 if(tmp == 0)
00772 return RET_ERROR;
00773 if(SendT0CmdHeader(inverse_convention, TC1, cmd->cmdHeader))
00774 return RET_ERROR;
00775
00776
00777 if(tmp == 1 || tmp == 2)
00778 return 0;
00779
00780
00781 LoopICCETU(6);
00782
00783
00784 if(GetByteICCParity(inverse_convention, &tmp)) return RET_ERROR;
00785
00786 while(tmp == SW1_MORE_TIME)
00787 {
00788 LoopICCETU(1);
00789 if(GetByteICCParity(inverse_convention, &tmp)) return RET_ERROR;
00790 }
00791
00792
00793
00794 if((tmp != cmd->cmdHeader->ins) && (tmp != ~(cmd->cmdHeader->ins)))
00795 {
00796
00797 GetByteICCParity(inverse_convention, &tmp2);
00798 return RET_ERR_CHECK;
00799 }
00800
00801
00802 LoopICCETU(6);
00803
00804 i = 0;
00805
00806 if(tmp != cmd->cmdHeader->ins)
00807 {
00808 if(SendByteICCParity(cmd->cmdData[i++], inverse_convention))
00809 return RET_ERROR;
00810 if(i < cmd->lenData)
00811 LoopICCETU(6);
00812 }
00813
00814
00815 while(tmp != cmd->cmdHeader->ins && i < cmd->lenData)
00816 {
00817 if(GetByteICCParity(inverse_convention, &tmp)) return RET_ERROR;
00818 LoopICCETU(6);
00819
00820 if(tmp != cmd->cmdHeader->ins)
00821 {
00822 if(SendByteICCParity(cmd->cmdData[i++], inverse_convention))
00823 return RET_ERROR;
00824 if(i < cmd->lenData)
00825 LoopICCETU(6);
00826 }
00827 }
00828
00829
00830 for(; i < cmd->lenData - 1; i++)
00831 {
00832 if(SendByteICCParity(cmd->cmdData[i], inverse_convention))
00833 return RET_ERROR;
00834 LoopICCETU(tdelay);
00835 }
00836 if(i == cmd->lenData - 1)
00837 {
00838 if(SendByteICCParity(cmd->cmdData[i], inverse_convention))
00839 return RET_ERROR;
00840 }
00841
00842 return 0;
00843 }
00844
00845
00858 CAPDU* ForwardCommand(uint8_t tInverse, uint8_t cInverse,
00859 uint8_t tTC1, uint8_t cTC1)
00860 {
00861 CAPDU* cmd;
00862
00863 cmd = ReceiveT0Command(tInverse, tTC1);
00864 if(cmd == NULL) return NULL;
00865
00866 if(SendT0Command(cInverse, cTC1, cmd))
00867 {
00868 FreeCAPDU(cmd);
00869 return NULL;
00870 }
00871
00872 return cmd;
00873 }
00874
00875
00876
00887 uint8_t* SerializeCommand(CAPDU *cmd, uint8_t *len)
00888 {
00889 uint8_t *stream, i;
00890
00891 if(cmd == NULL || len == NULL || cmd->cmdHeader == NULL) return NULL;
00892 if(cmd->lenData > 0 && cmd->cmdData == NULL) return NULL;
00893
00894 *len = 5 + cmd->lenData;
00895 stream = (uint8_t*)malloc((*len)*sizeof(uint8_t));
00896 if(stream == NULL)
00897 {
00898 *len = 0;
00899 return NULL;
00900 }
00901
00902 stream[0] = cmd->cmdHeader->cla;
00903 stream[1] = cmd->cmdHeader->ins;
00904 stream[2] = cmd->cmdHeader->p1;
00905 stream[3] = cmd->cmdHeader->p2;
00906 stream[4] = cmd->cmdHeader->p3;
00907
00908 for(i = 0; i < cmd->lenData; i++)
00909 stream[i+5] = cmd->cmdData[i];
00910
00911 return stream;
00912 }
00913
00914
00931 RAPDU* ReceiveT0Response(uint8_t inverse_convention,
00932 EMVCommandHeader *cmdHeader)
00933 {
00934 uint8_t tmp, i;
00935 RAPDU* rapdu;
00936
00937 if(cmdHeader == NULL) return NULL;
00938
00939 rapdu = (RAPDU*)malloc(sizeof(RAPDU));
00940 if(rapdu == NULL) return 0;
00941 rapdu->repStatus = NULL;
00942 rapdu->repData = NULL;
00943 rapdu->lenData = 0;
00944 tmp = GetCommandCase(cmdHeader->cla, cmdHeader->ins);
00945 if(tmp == 0)
00946 {
00947 free(rapdu);
00948 return NULL;
00949 }
00950
00951
00952
00953 if(tmp == 1 || tmp == 3)
00954 {
00955 rapdu->repStatus = (EMVStatus*)malloc(sizeof(EMVStatus));
00956 if(rapdu->repStatus == NULL)
00957 {
00958 free(rapdu);
00959 return NULL;
00960 }
00961
00962 if(GetByteICCParity(inverse_convention, &(rapdu->repStatus->sw1)))
00963 {
00964 free(rapdu->repStatus);
00965 rapdu->repStatus = NULL;
00966 free(rapdu);
00967 return NULL;
00968 }
00969
00970 if(rapdu->repStatus->sw1 == 0x60)
00971 {
00972
00973 free(rapdu->repStatus);
00974 rapdu->repStatus = NULL;
00975 free(rapdu);
00976
00977 return ReceiveT0Response(inverse_convention, cmdHeader);
00978
00979 }
00980
00981 if(GetByteICCParity(inverse_convention, &(rapdu->repStatus->sw2)))
00982 {
00983 free(rapdu->repStatus);
00984 rapdu->repStatus = NULL;
00985 free(rapdu);
00986 return NULL;
00987 }
00988
00989 return rapdu;
00990 }
00991
00992
00993 if(GetByteICCParity(inverse_convention, &tmp))
00994 {
00995 free(rapdu);
00996 return NULL;
00997 }
00998
00999 if(tmp == 0x60)
01000 {
01001
01002 free(rapdu);
01003
01004 return ReceiveT0Response(inverse_convention, cmdHeader);
01005 }
01006
01007 if(tmp == cmdHeader->ins || tmp == ~cmdHeader->ins)
01008 {
01009 if(tmp == cmdHeader->ins)
01010 rapdu->lenData = cmdHeader->p3;
01011 else
01012 rapdu->lenData = 1;
01013
01014 rapdu->repData = (uint8_t*)malloc(rapdu->lenData*sizeof(uint8_t));
01015 if(rapdu->repData == NULL)
01016 {
01017 free(rapdu);
01018 return NULL;
01019 }
01020
01021 for(i = 0; i < rapdu->lenData; i++)
01022 {
01023 if(GetByteICCParity(inverse_convention, &(rapdu->repData[i])))
01024 {
01025 free(rapdu->repData);
01026 rapdu->repData = NULL;
01027 free(rapdu);
01028 return NULL;
01029 }
01030 }
01031
01032 rapdu->repStatus = (EMVStatus*)malloc(sizeof(EMVStatus));
01033 if(rapdu->repStatus == NULL)
01034 {
01035 free(rapdu->repData);
01036 rapdu->repData = NULL;
01037 free(rapdu);
01038 return NULL;
01039 }
01040
01041 if(GetByteICCParity(inverse_convention, &(rapdu->repStatus->sw1)))
01042 {
01043 free(rapdu->repData);
01044 rapdu->repData = NULL;
01045 free(rapdu->repStatus);
01046 rapdu->repStatus = NULL;
01047 free(rapdu);
01048 return NULL;
01049 }
01050
01051 if(GetByteICCParity(inverse_convention, &(rapdu->repStatus->sw2)))
01052 {
01053 free(rapdu->repData);
01054 rapdu->repData = NULL;
01055 free(rapdu->repStatus);
01056 rapdu->repStatus = NULL;
01057 free(rapdu);
01058 return NULL;
01059 }
01060
01061 }
01062 else
01063 {
01064 rapdu->repStatus = (EMVStatus*)malloc(sizeof(EMVStatus));
01065 if(rapdu->repStatus == NULL)
01066 {
01067 free(rapdu);
01068 return NULL;
01069 }
01070
01071 rapdu->repStatus->sw1 = tmp;
01072 if(GetByteICCParity(inverse_convention, &(rapdu->repStatus->sw2)))
01073 {
01074 free(rapdu->repStatus);
01075 rapdu->repStatus = NULL;
01076 free(rapdu);
01077 return NULL;
01078 }
01079 }
01080
01081 return rapdu;
01082 }
01083
01084
01095 uint8_t SendT0Response(uint8_t inverse_convention,
01096 EMVCommandHeader *cmdHeader, RAPDU *response)
01097 {
01098 uint8_t i;
01099
01100 if(cmdHeader == NULL || response == NULL) return RET_ERROR;
01101
01102 if(response->lenData > 0 && response->repData != NULL)
01103 {
01104 if(SendByteTerminalParity(cmdHeader->ins, inverse_convention))
01105 return RET_ERROR;
01106 LoopTerminalETU(2);
01107
01108 for(i = 0; i < response->lenData; i++)
01109 {
01110 if(SendByteTerminalParity(response->repData[i],
01111 inverse_convention))
01112 return RET_ERROR;
01113 LoopTerminalETU(2);
01114 }
01115 }
01116
01117 if(response->repStatus == NULL) return RET_ERROR;
01118
01119 if(SendByteTerminalParity(response->repStatus->sw1, inverse_convention))
01120 return RET_ERROR;
01121 LoopTerminalETU(2);
01122 if(SendByteTerminalParity(response->repStatus->sw2, inverse_convention))
01123 return RET_ERROR;
01124
01125 return 0;
01126 }
01127
01139 RAPDU* ForwardResponse(uint8_t tInverse, uint8_t cInverse,
01140 EMVCommandHeader *cmdHeader)
01141 {
01142 RAPDU* response;
01143
01144 if(cmdHeader == NULL) return NULL;
01145
01146 response = ReceiveT0Response(cInverse, cmdHeader);
01147 if(response == NULL) return NULL;
01148
01149 if(SendT0Response(tInverse, cmdHeader, response))
01150 {
01151 FreeRAPDU(response);
01152 return NULL;
01153 }
01154
01155 return response;
01156 }
01157
01168 uint8_t* SerializeResponse(RAPDU *response, uint8_t *len)
01169 {
01170 uint8_t *stream, i;
01171
01172 if(response == NULL || len == NULL || response->repStatus == NULL)
01173 return NULL;
01174 if(response->lenData > 0 && response->repData == NULL) return NULL;
01175
01176 *len = 2 + response->lenData;
01177 stream = (uint8_t*)malloc((*len)*sizeof(uint8_t));
01178 if(stream == NULL)
01179 {
01180 *len = 0;
01181 return NULL;
01182 }
01183
01184 stream[0] = response->repStatus->sw1;
01185 stream[1] = response->repStatus->sw2;
01186
01187 for(i = 0; i < response->lenData; i++)
01188 stream[i+2] = response->repData[i];
01189
01190 return stream;
01191 }
01192
01193
01209 CRP* ExchangeData(uint8_t tInverse, uint8_t cInverse,
01210 uint8_t tTC1, uint8_t cTC1)
01211 {
01212 CRP* data;
01213
01214 data = (CRP*)malloc(sizeof(CRP));
01215 if(data == NULL) return NULL;
01216
01217 data->cmd = ForwardCommand(tInverse, cInverse, tTC1, cTC1);
01218 if(data->cmd == NULL)
01219 {
01220 free(data);
01221 return NULL;
01222 }
01223
01224 data->response = ForwardResponse (tInverse, cInverse, data->cmd->cmdHeader);
01225 if(data->response == NULL)
01226 {
01227 FreeCAPDU(data->cmd);
01228 free(data);
01229 return NULL;
01230 }
01231
01232 return data;
01233 }
01234
01252 CRP* ExchangeCompleteData(uint8_t tInverse, uint8_t cInverse,
01253 uint8_t tTC1, uint8_t cTC1)
01254 {
01255 CRP *data, *tmp;
01256 uint8_t cont;
01257
01258 data = (CRP*)malloc(sizeof(CRP));
01259 if(data == NULL) return NULL;
01260 data->cmd = NULL;
01261 data->response = NULL;
01262
01263
01264 tmp = ExchangeData(tInverse, cInverse, tTC1, cTC1);
01265 if(tmp == NULL)
01266 {
01267 FreeCRP(data);
01268 return NULL;
01269 }
01270 data->cmd = tmp->cmd;
01271 tmp->cmd = NULL;
01272
01273 cont = (tmp->response->repStatus->sw1 == 0x61 ||
01274 tmp->response->repStatus->sw1 == 0x6C);
01275 if(cont) FreeCRP(tmp);
01276
01277 while(cont)
01278 {
01279 tmp = ExchangeData(tInverse, cInverse, tTC1, cTC1);
01280 if(tmp == NULL)
01281 {
01282 FreeCRP(data);
01283 return NULL;
01284 }
01285
01286 cont = (tmp->response->repStatus->sw1 == 0x61 ||
01287 tmp->response->repStatus->sw1 == 0x6C);
01288
01289 if(cont) FreeCRP(tmp);
01290 }
01291
01292 data->response = tmp->response;
01293 tmp->response = NULL;
01294 FreeCRP(tmp);
01295
01296 return data;
01297 }
01298
01310 ByteArray* MakeByteArray(uint8_t *data, uint8_t len)
01311 {
01312 ByteArray *stream = (ByteArray*)malloc(sizeof(ByteArray));
01313 if(stream == NULL) return NULL;
01314 stream->bytes = data;
01315 stream->len = len;
01316
01317 return stream;
01318 }
01319
01330 ByteArray* MakeByteArrayV(uint8_t nargs, ...)
01331 {
01332 ByteArray *ba;
01333 va_list ap;
01334 uint8_t i;
01335
01336 ba = (ByteArray*)malloc(sizeof(ByteArray));
01337 if(ba == NULL) return NULL;
01338 ba->len = nargs;
01339 ba->bytes = (uint8_t*)malloc(ba->len * sizeof(uint8_t));
01340 if(ba->bytes == NULL)
01341 {
01342 free(ba);
01343 return NULL;
01344 }
01345
01346 va_start(ap, nargs);
01347
01348
01349 for(i = 0; i < nargs; i++)
01350 ba->bytes[i] = (uint8_t)va_arg(ap, int);
01351 va_end(ap);
01352
01353 return ba;
01354 }
01355
01366 ByteArray* CopyByteArray(const uint8_t *data, uint8_t len)
01367 {
01368 ByteArray *stream = (ByteArray*)malloc(sizeof(ByteArray));
01369 if(stream == NULL) return NULL;
01370 stream->bytes = NULL;
01371 stream->len = 0;
01372
01373 if(data != NULL && len > 0)
01374 {
01375 stream->bytes = (uint8_t*)malloc(len * sizeof(uint8_t));
01376 if(stream->bytes == NULL)
01377 {
01378 free(stream);
01379 return NULL;
01380 }
01381 memcpy(stream->bytes, data, len);
01382 stream->len = len;
01383 }
01384
01385 return stream;
01386 }
01387
01393 void FreeByteArray(ByteArray* data)
01394 {
01395 if(data == NULL) return;
01396
01397 if(data->bytes != NULL)
01398 {
01399 free(data->bytes);
01400 data->bytes = NULL;
01401 }
01402 free(data);
01403 }
01404
01410 void FreeCAPDU(CAPDU* cmd)
01411 {
01412 if(cmd == NULL) return;
01413
01414 if(cmd->cmdHeader != NULL)
01415 {
01416 free(cmd->cmdHeader);
01417 cmd->cmdHeader = NULL;
01418 }
01419
01420 if(cmd->cmdData != NULL)
01421 {
01422 free(cmd->cmdData);
01423 cmd->cmdData = NULL;
01424 }
01425 free(cmd);
01426 }
01427
01434 CAPDU* CopyCAPDU(CAPDU* cmd)
01435 {
01436 CAPDU *command;
01437
01438 if(cmd == NULL || cmd->cmdHeader == NULL) return NULL;
01439
01440 command = (CAPDU*)malloc(sizeof(CAPDU));
01441 if(command == NULL) return NULL;
01442 command->cmdHeader = (EMVCommandHeader*)malloc(sizeof(EMVCommandHeader));
01443 if(command->cmdHeader == NULL)
01444 {
01445 free(command);
01446 return NULL;
01447 }
01448 memcpy(command->cmdHeader, cmd->cmdHeader, sizeof(EMVCommandHeader));
01449 if(cmd->cmdData != NULL && cmd->lenData != 0)
01450 {
01451 command->cmdData = (uint8_t*)malloc(cmd->lenData * sizeof(uint8_t));
01452 if(command->cmdData == NULL)
01453 {
01454 FreeCAPDU(command);
01455 return NULL;
01456 }
01457 memcpy(command->cmdData, cmd->cmdData, cmd->lenData);
01458 command->lenData = cmd->lenData;
01459 }
01460 else
01461 {
01462 command->cmdData = NULL;
01463 command->lenData = 0;
01464 }
01465
01466 return command;
01467 }
01468
01474 void FreeRAPDU(RAPDU* response)
01475 {
01476 if(response == NULL) return;
01477
01478 if(response->repStatus != NULL)
01479 {
01480 free(response->repStatus);
01481 response->repStatus = NULL;
01482 }
01483
01484 if(response->repData != NULL)
01485 {
01486 free(response->repData);
01487 response->repData = NULL;
01488 }
01489 free(response);
01490 }
01491
01498 RAPDU* CopyRAPDU(RAPDU* resp)
01499 {
01500 RAPDU *response;
01501
01502 if(resp == NULL || resp->repStatus == NULL) return NULL;
01503
01504 response = (RAPDU*)malloc(sizeof(RAPDU));
01505 if(response == NULL) return NULL;
01506 response->repStatus = (EMVStatus*)malloc(sizeof(EMVStatus));
01507 if(response->repStatus == NULL)
01508 {
01509 free(response);
01510 return NULL;
01511 }
01512 memcpy(response->repStatus, resp->repStatus, sizeof(EMVStatus));
01513 if(resp->repData != NULL && resp->lenData != 0)
01514 {
01515 response->repData = (uint8_t*)malloc(resp->lenData * sizeof(uint8_t));
01516 if(response->repData == NULL)
01517 {
01518 FreeRAPDU(response);
01519 return NULL;
01520 }
01521 memcpy(response->repData, resp->repData, resp->lenData);
01522 response->lenData = resp->lenData;
01523 }
01524 else
01525 {
01526 response->repData = NULL;
01527 response->lenData = 0;
01528 }
01529
01530 return response;
01531 }
01532
01538 void FreeCRP(CRP* data)
01539 {
01540 if(data == NULL) return;
01541
01542 if(data->cmd != NULL)
01543 {
01544 FreeCAPDU(data->cmd);
01545 data->cmd = NULL;
01546 }
01547
01548 if(data->response != NULL)
01549 {
01550 FreeRAPDU(data->response);
01551 data->response = NULL;
01552 }
01553 free(data);
01554 }
01555
01556