00001
00034 #include <avr/io.h>
00035 #include <avr/interrupt.h>
00036 #include <avr/sleep.h>
00037 #include <avr/power.h>
00038 #include <util/delay.h>
00039 #include <string.h>
00040 #include <stdlib.h>
00041 #include <stdarg.h>
00042
00043 #include "emv.h"
00044 #include "scd_hal.h"
00045 #include "scd_io.h"
00046 #include "emv_values.h"
00047 #include "scd_values.h"
00048 #include "counter.h"
00049
00050 #define DEBUG 1 // Set DEBUG to 1 to enable debug code
00051
00052
00066 uint8_t ResetICC(
00067 uint8_t warm,
00068 uint8_t *inverse_convention,
00069 uint8_t *proto,
00070 uint8_t *TC1,
00071 uint8_t *TA3,
00072 uint8_t *TB3,
00073 log_struct_t *logger)
00074 {
00075 uint32_t time;
00076 uint16_t atr_selection;
00077 uint8_t atr_bytes[32];
00078 uint8_t atr_tck;
00079 uint8_t icc_T0, icc_TS;
00080 uint8_t error;
00081
00082
00083 time = GetCounter();
00084 error = ActivateICC(warm);
00085 if(error)
00086 {
00087 error = RET_ICC_INIT_ACTIVATE;
00088 goto enderror;
00089 }
00090 if(logger)
00091 {
00092 LogByte4(
00093 logger,
00094 LOG_TIME_GENERAL,
00095 (time & 0xFF),
00096 ((time >> 8) & 0xFF),
00097 ((time >> 16) & 0xFF),
00098 ((time >> 24) & 0xFF));
00099 LogByte1(logger, LOG_ICC_ACTIVATED, 0);
00100 }
00101
00102
00103 LoopICCETU(112);
00104
00105
00106 SetICCResetLine(1);
00107 if(logger)
00108 LogByte1(logger, LOG_ICC_RST_HIGH, 0);
00109
00110
00111 if(WaitForICCData(ICC_RST_WAIT))
00112 {
00113 if(warm == 0)
00114 return ResetICC(1, inverse_convention, proto, TC1, TA3, TB3, logger);
00115
00116 error = RET_ICC_INIT_RESPONSE;
00117 goto enderror;
00118 }
00119
00120
00121 error = GetATRICC(
00122 inverse_convention, proto, &icc_TS, &icc_T0,
00123 &atr_selection, atr_bytes, &atr_tck, logger);
00124 if(error)
00125 {
00126 if(warm == 0)
00127 return ResetICC(1, inverse_convention, proto, TC1, TA3, TB3, logger);
00128 goto enderror;
00129 }
00130 *TC1 = atr_bytes[2];
00131 *TA3 = atr_bytes[8];
00132 *TB3 = atr_bytes[9];
00133
00134 return 0;
00135
00136 enderror:
00137 DeactivateICC();
00138 if(logger)
00139 LogByte1(logger, LOG_ICC_DEACTIVATED, 0);
00140
00141 return error;
00142 }
00143
00144
00145
00146
00147
00148
00160 void SendT0ATRTerminal(
00161 uint8_t inverse_convention,
00162 uint8_t TC1,
00163 log_struct_t *logger)
00164 {
00165 if(inverse_convention)
00166 {
00167 SendByteTerminalNoParity(0x3F, inverse_convention);
00168 if(logger)
00169 LogByte1(logger, LOG_BYTE_ATR_TO_TERMINAL, 0x3F);
00170 }
00171 else
00172 {
00173 SendByteTerminalNoParity(0x3B, inverse_convention);
00174 if(logger)
00175 LogByte1(logger, LOG_BYTE_ATR_TO_TERMINAL, 0x3B);
00176 }
00177
00178 LoopTerminalETU(250);
00179 SendByteTerminalNoParity(0x60, inverse_convention);
00180 if(logger)
00181 LogByte1(logger, LOG_BYTE_ATR_TO_TERMINAL, 0x60);
00182 LoopTerminalETU(2);
00183 SendByteTerminalNoParity(0x00, inverse_convention);
00184 if(logger)
00185 LogByte1(logger, LOG_BYTE_ATR_TO_TERMINAL, 0x00);
00186 LoopTerminalETU(2);
00187 SendByteTerminalNoParity(TC1, inverse_convention);
00188 if(logger)
00189 LogByte1(logger, LOG_BYTE_ATR_TO_TERMINAL, TC1);
00190 LoopTerminalETU(2);
00191 }
00192
00219 uint8_t GetATRICC(
00220 uint8_t *inverse_convention,
00221 uint8_t *proto,
00222 uint8_t *TS,
00223 uint8_t *T0,
00224 uint16_t *selection,
00225 uint8_t bytes[32],
00226 uint8_t *tck,
00227 log_struct_t *logger)
00228 {
00229 uint8_t history, i, ta, tb, tc, td, nb;
00230 uint8_t check = 0;
00231 uint8_t error, index;
00232
00233 if(inverse_convention == NULL ||
00234 proto == NULL || TS == NULL || T0 == NULL ||
00235 selection == NULL || bytes == NULL || tck == NULL)
00236 {
00237 error = RET_ERR_PARAM;
00238 goto enderror;
00239 }
00240
00241 *selection = 0;
00242 memset(bytes, 0, 32);
00243
00244
00245 GetByteICCNoParity(0, TS);
00246 if(logger)
00247 LogByte1(logger, LOG_BYTE_ATR_FROM_ICC, *TS);
00248 if(*TS == 0x3B) *inverse_convention = 0;
00249 else if(*TS == 0x03) *inverse_convention = 1;
00250 else
00251 {
00252 error = RET_ICC_INIT_ATR_TS;
00253 goto enderror;
00254 }
00255
00256
00257 error = GetByteICCNoParity(*inverse_convention, T0);
00258 if(error)
00259 goto enderror;
00260 if(logger)
00261 LogByte1(logger, LOG_BYTE_ATR_FROM_ICC, *T0);
00262 check ^= *T0;
00263 history = *T0 & 0x0F;
00264 ta = *T0 & 0x10;
00265 tb = *T0 & 0x20;
00266 tc = *T0 & 0x40;
00267 td = *T0 & 0x80;
00268 if(tb == 0)
00269 {
00270 error = RET_ICC_INIT_ATR_T0;
00271 goto enderror;
00272 }
00273
00274 index = 0;
00275 if(ta){
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 error = GetByteICCNoParity(*inverse_convention, &bytes[index]);
00290 if(error)
00291 goto enderror;
00292 if(logger)
00293 LogByte1(logger, LOG_BYTE_ATR_FROM_ICC, bytes[index]);
00294 check ^= bytes[index];
00295 *selection |= (1 << (15-index));
00296 }
00297 index++;
00298
00299
00300 error = GetByteICCNoParity(*inverse_convention, &bytes[index]);
00301 if(error)
00302 goto enderror;
00303 if(logger)
00304 LogByte1(logger, LOG_BYTE_ATR_FROM_ICC, bytes[index]);
00305 check ^= bytes[index];
00306 *selection |= (1 << (15-index));
00307 if(bytes[index] != 0)
00308 {
00309 error = RET_ICC_INIT_ATR_TB1;
00310 goto enderror;
00311 }
00312 index++;
00313
00314
00315 if(tc)
00316 {
00317 error = GetByteICCNoParity(*inverse_convention, &bytes[index]);
00318 if(error)
00319 goto enderror;
00320 if(logger)
00321 LogByte1(logger, LOG_BYTE_ATR_FROM_ICC, bytes[index]);
00322 check ^= bytes[index];
00323 *selection |= (1 << (15-index));
00324 }
00325 index++;
00326
00327 if(td){
00328
00329 error = GetByteICCNoParity(*inverse_convention, &bytes[index]);
00330 if(error)
00331 goto enderror;
00332 if(logger)
00333 LogByte1(logger, LOG_BYTE_ATR_FROM_ICC, bytes[index]);
00334 check ^= bytes[index];
00335 *selection |= (1 << (15-index));
00336 nb = bytes[index] & 0x0F;
00337 ta = bytes[index] & 0x10;
00338 tb = bytes[index] & 0x20;
00339 tc = bytes[index] & 0x40;
00340 td = bytes[index] & 0x80;
00341 if(nb == 0x01) *proto = 1;
00342 else if(nb == 0x00) *proto = 0;
00343 else
00344 {
00345 error = RET_ICC_INIT_ATR_TD1;
00346 goto enderror;
00347 }
00348 index++;
00349
00350
00351
00352 if(ta)
00353 {
00354 error = RET_ICC_INIT_ATR_TA2;
00355 goto enderror;
00356 }
00357 index++;
00358
00359 if(tb)
00360 {
00361 error = RET_ICC_INIT_ATR_TB2;
00362 goto enderror;
00363 }
00364 index++;
00365
00366 if(tc){
00367
00368 error = GetByteICCNoParity(*inverse_convention, &bytes[index]);
00369 if(error)
00370 goto enderror;
00371 if(logger)
00372 LogByte1(logger, LOG_BYTE_ATR_FROM_ICC, bytes[index]);
00373 check ^= bytes[index];
00374 *selection |= (1 << (15-index));
00375 if(bytes[index] != 0x0A)
00376 {
00377 error = RET_ICC_INIT_ATR_TC2;
00378 goto enderror;
00379 }
00380 }
00381 index++;
00382
00383 if(td){
00384
00385 error = GetByteICCNoParity(*inverse_convention, &bytes[index]);
00386 if(error)
00387 goto enderror;
00388 if(logger)
00389 LogByte1(logger, LOG_BYTE_ATR_FROM_ICC, bytes[index]);
00390 check ^= bytes[index];
00391 *selection |= (1 << (15-index));
00392 nb = bytes[index] & 0x0F;
00393 ta = bytes[index] & 0x10;
00394 tb = bytes[index] & 0x20;
00395 tc = bytes[index] & 0x40;
00396 td = bytes[index] & 0x80;
00397 index++;
00398
00399
00400
00401 if(ta)
00402 {
00403
00404 error = GetByteICCNoParity(*inverse_convention, &bytes[index]);
00405 if(error)
00406 goto enderror;
00407 if(logger)
00408 LogByte1(logger, LOG_BYTE_ATR_FROM_ICC, bytes[index]);
00409 check ^= bytes[index];
00410 *selection |= (1 << (15-index));
00411 if(bytes[index] < 0x0F || bytes[index] == 0xFF)
00412 {
00413 error = RET_ICC_INIT_ATR_TA3;
00414 goto enderror;
00415 }
00416 }
00417 else
00418 bytes[index] = 0x20;
00419 index++;
00420
00421 if(*proto == 1 && tb == 0)
00422 {
00423 error = RET_ICC_INIT_ATR_TB3;
00424 goto enderror;
00425 }
00426
00427 if(tb)
00428 {
00429
00430 error = GetByteICCNoParity(*inverse_convention, &bytes[index]);
00431 if(logger)
00432 LogByte1(logger, LOG_BYTE_ATR_FROM_ICC, bytes[index]);
00433 check ^= bytes[index];
00434 *selection |= (1 << (15-index));
00435 nb = bytes[index] & 0x0F;
00436 if(nb > 5)
00437 {
00438 error = RET_ICC_INIT_ATR_TB3;
00439 goto enderror;
00440 }
00441 nb = bytes[index] & 0xF0;
00442 if(nb > 64)
00443 {
00444 error = RET_ICC_INIT_ATR_TB3;
00445 goto enderror;
00446 }
00447 }
00448 index++;
00449
00450 if(*proto == 0 && tc != 0)
00451 {
00452 error = RET_ICC_INIT_ATR_TC3;
00453 goto enderror;
00454 }
00455 if(tc)
00456 {
00457
00458 error = GetByteICCNoParity(*inverse_convention, &bytes[index]);
00459 if(error)
00460 goto enderror;
00461 if(logger)
00462 LogByte1(logger, LOG_BYTE_ATR_FROM_ICC, bytes[index]);
00463 check ^= bytes[index];
00464 *selection |= (1 << (15-index));
00465 if(bytes[index] != 0)
00466 {
00467 error = RET_ICC_INIT_ATR_TC3;
00468 goto enderror;
00469 }
00470 }
00471 index++;
00472 }
00473 }
00474 else
00475 *proto = 0;
00476
00477
00478 index = 16;
00479 for(i = 0; i < history; i++)
00480 {
00481 error = GetByteICCNoParity(*inverse_convention, &bytes[index + i]);
00482 if(logger)
00483 LogByte1(logger, LOG_BYTE_ATR_FROM_ICC, bytes[index + i]);
00484 check ^= bytes[index + i];
00485 }
00486
00487
00488 if(*proto == 1)
00489 {
00490 error = GetByteICCNoParity(*inverse_convention, tck);
00491 if(error)
00492 goto enderror;
00493 if(logger)
00494 LogByte1(logger, LOG_BYTE_ATR_FROM_ICC, *tck);
00495 check ^= *tck;
00496 if(check != 0)
00497 {
00498 error = RET_ICC_INIT_ATR_T1_CHECK;
00499 goto enderror;
00500 }
00501 }
00502
00503 error = 0;
00504
00505 enderror:
00506 return error;
00507 }
00508
00509
00510
00511
00525 EMVCommandHeader* MakeCommandHeader(uint8_t cla, uint8_t ins, uint8_t p1,
00526 uint8_t p2, uint8_t p3)
00527 {
00528 EMVCommandHeader *cmd = (EMVCommandHeader*)malloc(sizeof(EMVCommandHeader));
00529 if(cmd == NULL) return NULL;
00530
00531 cmd->cla = cla;
00532 cmd->ins = ins;
00533 cmd->p1 = p1;
00534 cmd->p2 = p2;
00535 cmd->p3 = p3;
00536
00537 return cmd;
00538 }
00539
00552 EMVCommandHeader* MakeCommandHeaderC(EMV_CMD command)
00553 {
00554 EMVCommandHeader *cmd = (EMVCommandHeader*)malloc(sizeof(EMVCommandHeader));
00555 if(cmd == NULL) return NULL;
00556
00557
00558 cmd->cla = 0;
00559 cmd->ins = 0;
00560 cmd->p1 = 0;
00561 cmd->p2 = 0;
00562 cmd->p3 = 0;
00563
00564 switch(command)
00565 {
00566 case CMD_SELECT:
00567 cmd->ins = 0xA4;
00568 cmd->p1 = 0x04;
00569 break;
00570
00571 case CMD_GET_RESPONSE:
00572 cmd->ins = 0xC0;
00573 break;
00574
00575 case CMD_READ_RECORD:
00576 cmd->ins = 0xB2;
00577 cmd->p1 = 0x01;
00578 break;
00579
00580 case CMD_GET_PROCESSING_OPTS:
00581 cmd->cla = 0x80;
00582 cmd->ins = 0xA8;
00583 break;
00584
00585 case CMD_VERIFY:
00586 cmd->ins = 0x20;
00587 cmd->p2 = 0x80;
00588 break;
00589
00590 case CMD_GENERATE_AC:
00591 cmd->cla = 0x80;
00592 cmd->ins = 0xAE;
00593 break;
00594
00595 case CMD_GET_DATA:
00596 cmd->cla = 0x80;
00597 cmd->ins = 0xCA;
00598 cmd->p1 = 0x9F;
00599 cmd->p2 = 0x17;
00600 break;
00601
00602 case CMD_INTERNAL_AUTHENTICATE:
00603 cmd->ins = 0x88;
00604 break;
00605
00606 case CMD_PIN_CHANGE_UNBLOCK:
00607 cmd->cla = 0x8C;
00608 cmd->ins = 0x24;
00609 break;
00610 }
00611
00612 return cmd;
00613 }
00614
00615
00636 CAPDU* MakeCommand(uint8_t cla, uint8_t ins, uint8_t p1,
00637 uint8_t p2, uint8_t p3, const uint8_t cmdData[], uint8_t lenData)
00638 {
00639 CAPDU *cmd = (CAPDU*)malloc(sizeof(CAPDU));
00640 if(cmd == NULL) return NULL;
00641
00642 cmd->cmdHeader = MakeCommandHeader(cla, ins, p1, p2, p3);
00643 if(cmd->cmdHeader == NULL)
00644 {
00645 free(cmd);
00646 return NULL;
00647 }
00648
00649 if(cmdData != NULL && lenData != 0)
00650 {
00651 cmd->cmdData = (uint8_t*)malloc(lenData * sizeof(uint8_t));
00652 if(cmd->cmdData == NULL)
00653 {
00654 FreeCAPDU(cmd);
00655 return NULL;
00656 }
00657 memcpy(cmd->cmdData, cmdData, lenData);
00658 cmd->lenData = lenData;
00659 }
00660 else
00661 {
00662 cmd->cmdData = NULL;
00663 cmd->lenData = 0;
00664 }
00665
00666 return cmd;
00667 }
00668
00687 CAPDU* MakeCommandP(const EMVCommandHeader *cmdHdr, const uint8_t cmdData[],
00688 uint8_t lenData)
00689 {
00690 if(cmdHdr == NULL) return NULL;
00691
00692 CAPDU *cmd = (CAPDU*)malloc(sizeof(CAPDU));
00693 if(cmd == NULL) return NULL;
00694
00695 cmd->cmdHeader = MakeCommandHeader(cmdHdr->cla, cmdHdr->ins,
00696 cmdHdr->p1, cmdHdr->p2, cmdHdr->p3);
00697 if(cmd->cmdHeader == NULL)
00698 {
00699 free(cmd);
00700 return NULL;
00701 }
00702
00703 if(cmdData != NULL && lenData != 0)
00704 {
00705 cmd->cmdData = (uint8_t*)malloc(lenData * sizeof(uint8_t));
00706 if(cmd->cmdData == NULL)
00707 {
00708 FreeCAPDU(cmd);
00709 return NULL;
00710 }
00711 memcpy(cmd->cmdData, cmdData, lenData);
00712 cmd->lenData = lenData;
00713 }
00714 else
00715 {
00716 cmd->cmdData = NULL;
00717 cmd->lenData = 0;
00718 }
00719
00720 return cmd;
00721 }
00722
00741 CAPDU* MakeCommandC(EMV_CMD command, const uint8_t cmdData[],
00742 uint8_t lenData)
00743 {
00744 CAPDU *cmd = (CAPDU*)malloc(sizeof(CAPDU));
00745 if(cmd == NULL) return NULL;
00746
00747 cmd->cmdHeader = MakeCommandHeaderC(command);
00748 if(cmd->cmdHeader == NULL)
00749 {
00750 free(cmd);
00751 return NULL;
00752 }
00753
00754 if(cmdData != NULL && lenData != 0)
00755 {
00756 cmd->cmdData = (uint8_t*)malloc(lenData * sizeof(uint8_t));
00757 if(cmd->cmdData == NULL)
00758 {
00759 FreeCAPDU(cmd);
00760 return NULL;
00761 }
00762 memcpy(cmd->cmdData, cmdData, lenData);
00763 cmd->lenData = lenData;
00764 cmd->cmdHeader->p3 = lenData;
00765 }
00766 else
00767 {
00768 cmd->cmdData = NULL;
00769 cmd->lenData = 0;
00770 }
00771
00772 return cmd;
00773 }
00774
00809 uint8_t InitSCDTransaction(uint8_t t_inverse, uint8_t t_TC1,
00810 uint8_t *inverse_convention, uint8_t *proto, uint8_t *TC1,
00811 uint8_t *TA3, uint8_t *TB3, log_struct_t *logger)
00812 {
00813 uint8_t tmp;
00814 uint16_t tfreq, tdelay;
00815 int8_t tmpi;
00816 uint32_t time;
00817 uint16_t atr_selection;
00818 uint8_t atr_bytes[32];
00819 uint8_t atr_tck;
00820 uint8_t icc_T0, icc_TS;
00821 uint8_t error;
00822 uint8_t index;
00823 uint8_t history;
00824
00825
00826 StartCounterTerminal();
00827
00828
00829 while(ReadCounterTerminal() < 10);
00830 time = GetCounter();
00831 if(logger)
00832 {
00833 LogByte4(
00834 logger,
00835 LOG_TIME_GENERAL,
00836 (time & 0xFF),
00837 ((time >> 8) & 0xFF),
00838 ((time >> 16) & 0xFF),
00839 ((time >> 24) & 0xFF));
00840 LogByte1(logger, LOG_TERMINAL_CLK_ACTIVE, 0);
00841 }
00842
00843
00844 tfreq = GetTerminalFreq();
00845 tdelay = 10 * tfreq;
00846
00847
00848
00849
00850 tmp = (uint8_t)((60000 - tdelay) / 372);
00851 LoopTerminalETU(tmp);
00852 if(ActivateICC(0))
00853 {
00854 error = RET_ERROR;
00855 goto enderror;
00856 }
00857 if(logger)
00858 LogByte1(logger, LOG_ICC_ACTIVATED, 0);
00859
00860
00861 tmpi = (int8_t)((tdelay - 10000) / 372);
00862 if(tmpi < 0) tmpi = 0;
00863 LoopTerminalETU(tmpi);
00864 if(t_inverse)
00865 {
00866 SendByteTerminalNoParity(0x3F, t_inverse);
00867 if(logger)
00868 LogByte1(logger, LOG_BYTE_ATR_TO_TERMINAL, 0x3F);
00869 }
00870 else
00871 {
00872 SendByteTerminalNoParity(0x3B, t_inverse);
00873 if(logger)
00874 LogByte1(logger, LOG_BYTE_ATR_TO_TERMINAL, 0x3B);
00875 }
00876
00877
00878 LoopTerminalETU(12);
00879 PORTD |= _BV(PD4);
00880 if(logger)
00881 LogByte1(logger, LOG_ICC_RST_HIGH, 0);
00882
00883
00884
00885 if(WaitForICCData(50000))
00886 {
00887 error = RET_ERROR;
00888 DeactivateICC();
00889 if(logger)
00890 LogByte1(logger, LOG_ICC_DEACTIVATED, 0);
00891 goto enderror;
00892 }
00893
00894 error = GetATRICC(
00895 inverse_convention, proto, &icc_TS, &icc_T0,
00896 &atr_selection, atr_bytes, &atr_tck, logger);
00897 if(error)
00898 {
00899 DeactivateICC();
00900 if(logger)
00901 LogByte1(logger, LOG_ICC_DEACTIVATED, 0);
00902 goto enderror;
00903 }
00904 *TC1 = atr_bytes[2];
00905 *TA3 = atr_bytes[8];
00906 *TB3 = atr_bytes[9];
00907 history = icc_T0 & 0x0F;
00908
00909
00910 SendByteTerminalNoParity(icc_T0, t_inverse);
00911 if(logger)
00912 LogByte1(logger, LOG_BYTE_ATR_TO_TERMINAL, icc_T0);
00913 LoopTerminalETU(2);
00914
00915 for(index = 0; index < 16; index++)
00916 {
00917 if(atr_selection & (1 << (15-index)))
00918 {
00919 SendByteTerminalNoParity(atr_bytes[index], t_inverse);
00920 if(logger)
00921 LogByte1(logger, LOG_BYTE_ATR_TO_TERMINAL, atr_bytes[index]);
00922 LoopTerminalETU(2);
00923 }
00924 }
00925
00926 for(index = 0; index < history; index++)
00927 {
00928 SendByteTerminalNoParity(atr_bytes[16 + index], t_inverse);
00929 if(logger)
00930 LogByte1(logger, LOG_BYTE_ATR_TO_TERMINAL, atr_bytes[16 + index]);
00931 LoopTerminalETU(2);
00932 }
00933
00934 error = 0;
00935
00936 enderror:
00937 return 0;
00938 }
00939
00940
00958 uint8_t GetCommandCase(uint8_t cla, uint8_t ins)
00959 {
00960 switch(cla)
00961 {
00962 case 0:
00963 {
00964 switch(ins)
00965 {
00966 case 0xC0:
00967 return 2;
00968 break;
00969
00970 case 0xB2:
00971 return 2;
00972 break;
00973
00974 case 0xA4:
00975 return 4;
00976 break;
00977
00978 case 0x82:
00979 return 3;
00980 break;
00981
00982 case 0x84:
00983 return 2;
00984 break;
00985
00986 case 0x88:
00987 return 4;
00988 break;
00989
00990 case 0x20:
00991 return 3;
00992 break;
00993
00994 default: return 0;
00995 }
00996 }
00997 break;
00998
00999 case 0x8C:
01000 case 0x84:
01001 {
01002 switch(ins)
01003 {
01004 case 0x1E:
01005 return 3;
01006 break;
01007
01008 case 0x18:
01009 return 3;
01010 break;
01011
01012 case 0x16:
01013 return 3;
01014 break;
01015
01016 case 0x24:
01017 return 3;
01018 break;
01019
01020 default: return 0;
01021 }
01022 }
01023 break;
01024
01025 case 0x80:
01026 {
01027 switch(ins)
01028 {
01029 case 0xAE:
01030 return 4;
01031 break;
01032
01033 case 0xCA:
01034 return 2;
01035 break;
01036
01037 case 0xA8:
01038 return 4;
01039 break;
01040
01041 default: return 0;
01042 }
01043 }
01044 break;
01045
01046 default: return 0;
01047 }
01048
01049 return 0;
01050 }
01051
01052
01065 EMVCommandHeader* ReceiveT0CmdHeader(
01066 uint8_t inverse_convention,
01067 uint8_t TC1,
01068 log_struct_t *logger)
01069 {
01070 uint8_t tdelay, result;
01071 EMVCommandHeader *cmdHeader;
01072
01073 cmdHeader = (EMVCommandHeader*)malloc(sizeof(EMVCommandHeader));
01074 if(cmdHeader == NULL)
01075 {
01076 if(logger)
01077 LogByte1(logger, LOG_ERROR_MEMORY, 0);
01078 return NULL;
01079 }
01080
01081 tdelay = 1 + TC1;
01082
01083 result = GetByteTerminalParity(
01084 inverse_convention, &(cmdHeader->cla), MAX_WAIT_TERMINAL);
01085 if(result != 0)
01086 goto enderror;
01087 if(logger)
01088 LogByte1(logger, LOG_BYTE_FROM_TERMINAL, cmdHeader->cla);
01089 LoopTerminalETU(tdelay);
01090
01091 result = GetByteTerminalParity(
01092 inverse_convention, &(cmdHeader->ins), MAX_WAIT_TERMINAL);
01093 if(result != 0)
01094 goto enderror;
01095 if(logger)
01096 LogByte1(logger, LOG_BYTE_FROM_TERMINAL, cmdHeader->ins);
01097 LoopTerminalETU(tdelay);
01098
01099 result = GetByteTerminalParity(
01100 inverse_convention, &(cmdHeader->p1), MAX_WAIT_TERMINAL);
01101 if(result != 0)
01102 goto enderror;
01103 if(logger)
01104 LogByte1(logger, LOG_BYTE_FROM_TERMINAL, cmdHeader->p1);
01105 LoopTerminalETU(tdelay);
01106
01107 result = GetByteTerminalParity(
01108 inverse_convention, &(cmdHeader->p2), MAX_WAIT_TERMINAL);
01109 if(result != 0)
01110 goto enderror;
01111 if(logger)
01112 LogByte1(logger, LOG_BYTE_FROM_TERMINAL, cmdHeader->p2);
01113 LoopTerminalETU(tdelay);
01114
01115 result = GetByteTerminalParity(
01116 inverse_convention, &(cmdHeader->p3), MAX_WAIT_TERMINAL);
01117 if(result != 0)
01118 goto enderror;
01119 if(logger)
01120 LogByte1(logger, LOG_BYTE_FROM_TERMINAL, cmdHeader->p3);
01121
01122 return cmdHeader;
01123
01124 enderror:
01125 free(cmdHeader);
01126 if(logger)
01127 {
01128 if(result == RET_TERMINAL_RESET_LOW)
01129 {
01130 LogByte1(logger, LOG_TERMINAL_RST_LOW, 0);
01131 }
01132 else if(result == RET_TERMINAL_TIME_OUT)
01133 {
01134 LogByte1(logger, LOG_TERMINAL_TIME_OUT, 0);
01135 }
01136 else if(result == RET_ERROR)
01137 {
01138 LogByte1(logger, LOG_TERMINAL_ERROR_RECEIVE, 0);
01139 }
01140 }
01141 return NULL;
01142 }
01143
01159 uint8_t* ReceiveT0CmdData(
01160 uint8_t inverse_convention,
01161 uint8_t TC1,
01162 uint8_t len,
01163 log_struct_t *logger)
01164 {
01165 uint8_t tdelay, i, result;
01166 uint8_t *cmdData;
01167
01168 cmdData = (uint8_t*)malloc(len*sizeof(uint8_t));
01169 if(cmdData == NULL)
01170 {
01171 if(logger)
01172 LogByte1(logger, LOG_ERROR_MEMORY, 0);
01173 return NULL;
01174 }
01175
01176 tdelay = 1 + TC1;
01177
01178 for(i = 0; i < len - 1; i++)
01179 {
01180 result = GetByteTerminalParity(
01181 inverse_convention, &(cmdData[i]), MAX_WAIT_TERMINAL);
01182 if(result != 0)
01183 goto enderror;
01184 if(logger)
01185 LogByte1(logger, LOG_BYTE_FROM_TERMINAL, cmdData[i]);
01186 LoopTerminalETU(tdelay);
01187 }
01188
01189
01190 result = GetByteTerminalParity(
01191 inverse_convention, &(cmdData[i]), MAX_WAIT_TERMINAL);
01192 if(result != 0)
01193 goto enderror;
01194 if(logger)
01195 LogByte1(logger, LOG_BYTE_FROM_TERMINAL, cmdData[i]);
01196
01197 return cmdData;
01198
01199 enderror:
01200 free(cmdData);
01201 if(logger)
01202 {
01203 if(result == RET_TERMINAL_RESET_LOW)
01204 {
01205 LogByte1(logger, LOG_TERMINAL_RST_LOW, 0);
01206 }
01207 else if(result == RET_TERMINAL_TIME_OUT)
01208 {
01209 LogByte1(logger, LOG_TERMINAL_TIME_OUT, 0);
01210 }
01211 else if(result == RET_ERROR)
01212 {
01213 LogByte1(logger, LOG_TERMINAL_ERROR_RECEIVE, 0);
01214 }
01215 }
01216 return NULL;
01217 }
01218
01233 CAPDU* ReceiveT0Command(
01234 uint8_t inverse_convention,
01235 uint8_t TC1,
01236 log_struct_t *logger)
01237 {
01238 uint8_t tdelay, tmp;
01239 CAPDU *cmd;
01240
01241 tdelay = 1 + TC1;
01242
01243 cmd = (CAPDU*)malloc(sizeof(CAPDU));
01244 if(cmd == NULL)
01245 {
01246 if(logger)
01247 LogByte1(logger, LOG_ERROR_MEMORY, 0);
01248 return NULL;
01249 }
01250 cmd->cmdHeader = NULL;
01251 cmd->cmdData = NULL;
01252 cmd->lenData = 0;
01253
01254 cmd->cmdHeader = ReceiveT0CmdHeader(inverse_convention, TC1, logger);
01255 if(cmd->cmdHeader == NULL)
01256 {
01257 free(cmd);
01258 return NULL;
01259 }
01260 tmp = GetCommandCase(cmd->cmdHeader->cla, cmd->cmdHeader->ins);
01261 if(tmp == 0)
01262 {
01263 FreeCAPDU(cmd);
01264 return NULL;
01265 }
01266
01267
01268 if(tmp == 1 || tmp == 2)
01269 return cmd;
01270
01271
01272
01273 LoopTerminalETU(6);
01274 if(SendByteTerminalParity(cmd->cmdHeader->ins, inverse_convention))
01275 {
01276 free(cmd->cmdHeader);
01277 cmd->cmdHeader = NULL;
01278 free(cmd);
01279 if(logger)
01280 LogByte1(logger, LOG_TERMINAL_ERROR_SEND, 0);
01281 return NULL;
01282 }
01283 if(logger)
01284 LogByte1(logger, LOG_BYTE_TO_TERMINAL, cmd->cmdHeader->ins);
01285
01286 LoopTerminalETU(tdelay);
01287 cmd->lenData = cmd->cmdHeader->p3;
01288 cmd->cmdData = ReceiveT0CmdData(
01289 inverse_convention, TC1, cmd->lenData, logger);
01290 if(cmd->cmdData == NULL)
01291 {
01292 free(cmd->cmdHeader);
01293 cmd->cmdHeader = NULL;
01294 free(cmd);
01295 return NULL;
01296 }
01297
01298 return cmd;
01299 }
01300
01301
01312 uint8_t SendT0CmdHeader(
01313 uint8_t inverse_convention,
01314 uint8_t TC1,
01315 EMVCommandHeader *cmdHeader,
01316 log_struct_t *logger)
01317 {
01318 uint8_t tdelay;
01319
01320 if(cmdHeader == NULL) return RET_ERROR;
01321
01322 tdelay = 1 + TC1;
01323
01324 if(SendByteICCParity(cmdHeader->cla, inverse_convention))
01325 {
01326 if(logger)
01327 LogByte1(logger, LOG_ICC_ERROR_SEND, 0);
01328 return RET_ERROR;
01329 }
01330 if(logger)
01331 LogByte1(logger, LOG_BYTE_TO_ICC, cmdHeader->cla);
01332 LoopICCETU(tdelay);
01333
01334 if(SendByteICCParity(cmdHeader->ins, inverse_convention))
01335 {
01336 if(logger)
01337 LogByte1(logger, LOG_ICC_ERROR_SEND, 0);
01338 return RET_ERROR;
01339 }
01340 if(logger)
01341 LogByte1(logger, LOG_BYTE_TO_ICC, cmdHeader->ins);
01342 LoopICCETU(tdelay);
01343
01344 if(SendByteICCParity(cmdHeader->p1, inverse_convention))
01345 {
01346 if(logger)
01347 LogByte1(logger, LOG_ICC_ERROR_SEND, 0);
01348 return RET_ERROR;
01349 }
01350 if(logger)
01351 LogByte1(logger, LOG_BYTE_TO_ICC, cmdHeader->p1);
01352 LoopICCETU(tdelay);
01353
01354 if(SendByteICCParity(cmdHeader->p2, inverse_convention))
01355 {
01356 if(logger)
01357 LogByte1(logger, LOG_ICC_ERROR_SEND, 0);
01358 return RET_ERROR;
01359 }
01360 if(logger)
01361 LogByte1(logger, LOG_BYTE_TO_ICC, cmdHeader->p2);
01362 LoopICCETU(tdelay);
01363
01364 if(SendByteICCParity(cmdHeader->p3, inverse_convention))
01365 {
01366 if(logger)
01367 LogByte1(logger, LOG_ICC_ERROR_SEND, 0);
01368 return RET_ERROR;
01369 }
01370 if(logger)
01371 LogByte1(logger, LOG_BYTE_TO_ICC, cmdHeader->p3);
01372
01373 return 0;
01374 }
01375
01376
01388 uint8_t SendT0CmdData(
01389 uint8_t inverse_convention,
01390 uint8_t TC1,
01391 uint8_t *cmdData,
01392 uint8_t len,
01393 log_struct_t *logger)
01394 {
01395 uint8_t tdelay, i;
01396
01397 if(cmdData == NULL) return RET_ERROR;
01398
01399 tdelay = 1 + TC1;
01400
01401 for(i = 0; i < len - 1; i++)
01402 {
01403 if(SendByteICCParity(cmdData[i], inverse_convention))
01404 {
01405 if(logger)
01406 LogByte1(logger, LOG_ICC_ERROR_SEND, 0);
01407 return RET_ERROR;
01408 }
01409 if(logger)
01410 LogByte1(logger, LOG_BYTE_TO_ICC, cmdData[i]);
01411 LoopICCETU(tdelay);
01412 }
01413
01414
01415 if(SendByteICCParity(cmdData[i], inverse_convention))
01416 {
01417 if(logger)
01418 LogByte1(logger, LOG_ICC_ERROR_SEND, 0);
01419 return RET_ERROR;
01420 }
01421 if(logger)
01422 LogByte1(logger, LOG_BYTE_TO_ICC, cmdData[i]);
01423
01424 return 0;
01425 }
01426
01427
01440 uint8_t SendT0Command(
01441 uint8_t inverse_convention,
01442 uint8_t TC1,
01443 CAPDU *cmd,
01444 log_struct_t *logger)
01445 {
01446 uint8_t tdelay, tmp, tmp2, i;
01447 uint32_t time;
01448
01449 if(cmd == NULL) return RET_ERROR;
01450 tdelay = 1 + TC1;
01451 if(logger)
01452 {
01453 time = GetCounter();
01454 LogByte4(
01455 logger,
01456 LOG_TIME_DATA_TO_ICC,
01457 (time & 0xFF),
01458 ((time >> 8) & 0xFF),
01459 ((time >> 16) & 0xFF),
01460 ((time >> 24) & 0xFF));
01461 }
01462
01463 tmp = GetCommandCase(cmd->cmdHeader->cla, cmd->cmdHeader->ins);
01464 if(tmp == 0)
01465 return RET_ERROR;
01466 if(SendT0CmdHeader(inverse_convention, TC1, cmd->cmdHeader, logger))
01467 return RET_ERROR;
01468
01469
01470 if(tmp == 1 || tmp == 2)
01471 return 0;
01472
01473
01474 LoopICCETU(6);
01475
01476
01477 if(GetByteICCParity(inverse_convention, &tmp))
01478 {
01479 if(logger)
01480 LogByte1(logger, LOG_ICC_ERROR_RECEIVE, 0);
01481 return RET_ERROR;
01482 }
01483 if(logger)
01484 LogByte1(logger, LOG_BYTE_FROM_ICC, tmp);
01485
01486 while(tmp == SW1_MORE_TIME)
01487 {
01488 LoopICCETU(1);
01489 if(GetByteICCParity(inverse_convention, &tmp))
01490 {
01491 if(logger)
01492 LogByte1(logger, LOG_ICC_ERROR_RECEIVE, 0);
01493 return RET_ERROR;
01494 }
01495 if(logger)
01496 LogByte1(logger, LOG_BYTE_FROM_ICC, tmp);
01497 }
01498
01499
01500
01501 if((tmp != cmd->cmdHeader->ins) && (tmp != ~(cmd->cmdHeader->ins)))
01502 {
01503 if(GetByteICCParity(inverse_convention, &tmp2))
01504 {
01505 if(logger)
01506 LogByte1(logger, LOG_ICC_ERROR_RECEIVE, 0);
01507 return RET_ERROR;
01508 }
01509 if(logger)
01510 LogByte1(logger, LOG_BYTE_FROM_ICC, tmp2);
01511 return RET_ERR_CHECK;
01512 }
01513
01514
01515 LoopICCETU(6);
01516
01517 i = 0;
01518
01519 if(tmp != cmd->cmdHeader->ins)
01520 {
01521 if(SendByteICCParity(cmd->cmdData[i++], inverse_convention))
01522 {
01523 if(logger)
01524 LogByte1(logger, LOG_ICC_ERROR_SEND, 0);
01525 return RET_ERROR;
01526 }
01527 if(logger)
01528 LogByte1(logger, LOG_BYTE_TO_ICC, cmd->cmdData[i-1]);
01529 if(i < cmd->lenData)
01530 LoopICCETU(6);
01531 }
01532
01533
01534 while(tmp != cmd->cmdHeader->ins && i < cmd->lenData)
01535 {
01536 if(GetByteICCParity(inverse_convention, &tmp))
01537 {
01538 if(logger)
01539 LogByte1(logger, LOG_ICC_ERROR_RECEIVE, 0);
01540 return RET_ERROR;
01541 }
01542 if(logger)
01543 LogByte1(logger, LOG_BYTE_FROM_ICC, tmp);
01544 LoopICCETU(6);
01545
01546 if(tmp != cmd->cmdHeader->ins)
01547 {
01548 if(SendByteICCParity(cmd->cmdData[i++], inverse_convention))
01549 {
01550 if(logger)
01551 LogByte1(logger, LOG_ICC_ERROR_SEND, 0);
01552 return RET_ERROR;
01553 }
01554 if(logger)
01555 LogByte1(logger, LOG_BYTE_TO_ICC, cmd->cmdData[i-1]);
01556 if(i < cmd->lenData)
01557 LoopICCETU(6);
01558 }
01559 }
01560
01561
01562 for(; i < cmd->lenData - 1; i++)
01563 {
01564 if(SendByteICCParity(cmd->cmdData[i], inverse_convention))
01565 {
01566 if(logger)
01567 LogByte1(logger, LOG_ICC_ERROR_SEND, 0);
01568 return RET_ERROR;
01569 }
01570 if(logger)
01571 LogByte1(logger, LOG_BYTE_TO_ICC, cmd->cmdData[i]);
01572 LoopICCETU(tdelay);
01573 }
01574 if(i == cmd->lenData - 1)
01575 {
01576 if(SendByteICCParity(cmd->cmdData[i], inverse_convention))
01577 {
01578 if(logger)
01579 LogByte1(logger, LOG_ICC_ERROR_SEND, 0);
01580 return RET_ERROR;
01581 }
01582 if(logger)
01583 LogByte1(logger, LOG_BYTE_TO_ICC, cmd->cmdData[i]);
01584 }
01585
01586 return 0;
01587 }
01588
01589
01603 CAPDU* ForwardCommand(
01604 uint8_t tInverse,
01605 uint8_t cInverse,
01606 uint8_t tTC1,
01607 uint8_t cTC1,
01608 log_struct_t *logger)
01609 {
01610 CAPDU* cmd;
01611
01612 cmd = ReceiveT0Command(tInverse, tTC1, logger);
01613 if(cmd == NULL) return NULL;
01614
01615 if(SendT0Command(cInverse, cTC1, cmd, logger))
01616 {
01617 FreeCAPDU(cmd);
01618 return NULL;
01619 }
01620
01621 return cmd;
01622 }
01623
01624
01635 uint8_t* SerializeCommand(CAPDU *cmd, uint8_t *len)
01636 {
01637 uint8_t *stream, i = 0;
01638
01639 if(cmd == NULL || len == NULL || cmd->cmdHeader == NULL) return NULL;
01640 if(cmd->lenData > 0 && cmd->cmdData == NULL) return NULL;
01641
01642 *len = 5 + cmd->lenData;
01643 stream = (uint8_t*)malloc((*len)*sizeof(uint8_t));
01644 if(stream == NULL)
01645 {
01646 *len = 0;
01647 return NULL;
01648 }
01649
01650 stream[i++] = cmd->cmdHeader->cla;
01651 stream[i++] = cmd->cmdHeader->ins;
01652 stream[i++] = cmd->cmdHeader->p1;
01653 stream[i++] = cmd->cmdHeader->p2;
01654 stream[i++] = cmd->cmdHeader->p3;
01655
01656 while(i < cmd->lenData)
01657 {
01658 stream[i] = cmd->cmdData[i];
01659 i++;
01660 }
01661
01662 return stream;
01663 }
01664
01665
01683 RAPDU* ReceiveT0Response(
01684 uint8_t inverse_convention,
01685 EMVCommandHeader *cmdHeader,
01686 log_struct_t *logger)
01687 {
01688 uint8_t tmp, i;
01689 RAPDU* rapdu;
01690
01691 if(cmdHeader == NULL) return NULL;
01692
01693 rapdu = (RAPDU*)malloc(sizeof(RAPDU));
01694 if(rapdu == NULL) return 0;
01695 rapdu->repStatus = NULL;
01696 rapdu->repData = NULL;
01697 rapdu->lenData = 0;
01698 tmp = GetCommandCase(cmdHeader->cla, cmdHeader->ins);
01699 if(tmp == 0)
01700 {
01701 free(rapdu);
01702 return NULL;
01703 }
01704
01705
01706
01707 if(tmp == 1 || tmp == 3)
01708 {
01709 rapdu->repStatus = (EMVStatus*)malloc(sizeof(EMVStatus));
01710 if(rapdu->repStatus == NULL)
01711 {
01712 free(rapdu);
01713 return NULL;
01714 }
01715
01716 if(GetByteICCParity(inverse_convention, &(rapdu->repStatus->sw1)))
01717 {
01718 free(rapdu->repStatus);
01719 rapdu->repStatus = NULL;
01720 free(rapdu);
01721 return NULL;
01722 }
01723 if(logger)
01724 LogByte1(logger, LOG_BYTE_FROM_ICC, rapdu->repStatus->sw1);
01725
01726 if(rapdu->repStatus->sw1 == 0x60)
01727 {
01728
01729 free(rapdu->repStatus);
01730 rapdu->repStatus = NULL;
01731 free(rapdu);
01732
01733 return ReceiveT0Response(inverse_convention, cmdHeader, logger);
01734
01735 }
01736
01737 if(GetByteICCParity(inverse_convention, &(rapdu->repStatus->sw2)))
01738 {
01739 free(rapdu->repStatus);
01740 rapdu->repStatus = NULL;
01741 free(rapdu);
01742 return NULL;
01743 }
01744 if(logger)
01745 LogByte1(logger, LOG_BYTE_FROM_ICC, rapdu->repStatus->sw2);
01746
01747 return rapdu;
01748 }
01749
01750
01751 if(GetByteICCParity(inverse_convention, &tmp))
01752 {
01753 free(rapdu);
01754 return NULL;
01755 }
01756 if(logger)
01757 LogByte1(logger, LOG_BYTE_FROM_ICC, tmp);
01758
01759 if(tmp == 0x60)
01760 {
01761
01762 free(rapdu);
01763
01764 return ReceiveT0Response(inverse_convention, cmdHeader, logger);
01765 }
01766
01767 if(tmp == cmdHeader->ins || tmp == ~cmdHeader->ins)
01768 {
01769 if(tmp == cmdHeader->ins)
01770 rapdu->lenData = cmdHeader->p3;
01771 else
01772 rapdu->lenData = 1;
01773
01774 rapdu->repData = (uint8_t*)malloc(rapdu->lenData*sizeof(uint8_t));
01775 if(rapdu->repData == NULL)
01776 {
01777 #if DEBUG
01778 fprintf(stderr, "Failed MALLOC\n");
01779 _delay_ms(1000);
01780 #endif
01781 free(rapdu);
01782 return NULL;
01783 }
01784
01785 for(i = 0; i < rapdu->lenData; i++)
01786 {
01787 if(GetByteICCParity(inverse_convention, &(rapdu->repData[i])))
01788 {
01789 free(rapdu->repData);
01790 rapdu->repData = NULL;
01791 free(rapdu);
01792 return NULL;
01793 }
01794 if(logger)
01795 LogByte1(logger, LOG_BYTE_FROM_ICC, rapdu->repData[i]);
01796 }
01797
01798 rapdu->repStatus = (EMVStatus*)malloc(sizeof(EMVStatus));
01799 if(rapdu->repStatus == NULL)
01800 {
01801 free(rapdu->repData);
01802 rapdu->repData = NULL;
01803 free(rapdu);
01804 return NULL;
01805 }
01806
01807 if(GetByteICCParity(inverse_convention, &(rapdu->repStatus->sw1)))
01808 {
01809 free(rapdu->repData);
01810 rapdu->repData = NULL;
01811 free(rapdu->repStatus);
01812 rapdu->repStatus = NULL;
01813 free(rapdu);
01814 return NULL;
01815 }
01816 if(logger)
01817 LogByte1(logger, LOG_BYTE_FROM_ICC, rapdu->repStatus->sw1);
01818
01819 if(GetByteICCParity(inverse_convention, &(rapdu->repStatus->sw2)))
01820 {
01821 free(rapdu->repData);
01822 rapdu->repData = NULL;
01823 free(rapdu->repStatus);
01824 rapdu->repStatus = NULL;
01825 free(rapdu);
01826 return NULL;
01827 }
01828 if(logger)
01829 LogByte1(logger, LOG_BYTE_FROM_ICC, rapdu->repStatus->sw2);
01830
01831 }
01832 else
01833 {
01834 rapdu->repStatus = (EMVStatus*)malloc(sizeof(EMVStatus));
01835 if(rapdu->repStatus == NULL)
01836 {
01837 free(rapdu);
01838 return NULL;
01839 }
01840
01841 rapdu->repStatus->sw1 = tmp;
01842 if(GetByteICCParity(inverse_convention, &(rapdu->repStatus->sw2)))
01843 {
01844 free(rapdu->repStatus);
01845 rapdu->repStatus = NULL;
01846 free(rapdu);
01847 return NULL;
01848 }
01849 if(logger)
01850 LogByte1(logger, LOG_BYTE_FROM_ICC, rapdu->repStatus->sw2);
01851 }
01852
01853 return rapdu;
01854 }
01855
01856
01868 uint8_t SendT0Response(
01869 uint8_t inverse_convention,
01870 EMVCommandHeader *cmdHeader,
01871 RAPDU *response,
01872 log_struct_t *logger)
01873 {
01874 uint8_t i;
01875
01876 if(cmdHeader == NULL || response == NULL) return RET_ERROR;
01877
01878 if(response->lenData > 0 && response->repData != NULL)
01879 {
01880 if(SendByteTerminalParity(cmdHeader->ins, inverse_convention))
01881 return RET_ERROR;
01882 if(logger)
01883 LogByte1(logger, LOG_BYTE_TO_TERMINAL, cmdHeader->ins);
01884 LoopTerminalETU(2);
01885
01886 for(i = 0; i < response->lenData; i++)
01887 {
01888 if(SendByteTerminalParity(response->repData[i], inverse_convention))
01889 return RET_ERROR;
01890 if(logger)
01891 LogByte1(logger, LOG_BYTE_TO_TERMINAL, response->repData[i]);
01892 LoopTerminalETU(2);
01893 }
01894 }
01895
01896 if(response->repStatus == NULL) return RET_ERROR;
01897
01898 if(SendByteTerminalParity(response->repStatus->sw1, inverse_convention))
01899 return RET_ERROR;
01900 if(logger)
01901 LogByte1(logger, LOG_BYTE_TO_TERMINAL, response->repStatus->sw1);
01902 LoopTerminalETU(2);
01903 if(SendByteTerminalParity(response->repStatus->sw2, inverse_convention))
01904 return RET_ERROR;
01905 if(logger)
01906 LogByte1(logger, LOG_BYTE_TO_TERMINAL, response->repStatus->sw2);
01907
01908 return 0;
01909 }
01910
01923 RAPDU* ForwardResponse(
01924 uint8_t tInverse,
01925 uint8_t cInverse,
01926 EMVCommandHeader *cmdHeader,
01927 log_struct_t *logger)
01928 {
01929 RAPDU* response;
01930
01931 if(cmdHeader == NULL) return NULL;
01932
01933 response = ReceiveT0Response(cInverse, cmdHeader, logger);
01934 if(response == NULL) return NULL;
01935
01936 if(SendT0Response(tInverse, cmdHeader, response, logger))
01937 {
01938 FreeRAPDU(response);
01939 return NULL;
01940 }
01941
01942 return response;
01943 }
01944
01955 uint8_t* SerializeResponse(RAPDU *response, uint8_t *len)
01956 {
01957 uint8_t *stream, i = 0;
01958
01959 if(response == NULL || len == NULL || response->repStatus == NULL)
01960 return NULL;
01961 if(response->lenData > 0 && response->repData == NULL) return NULL;
01962
01963 *len = 2 + response->lenData;
01964 stream = (uint8_t*)malloc((*len)*sizeof(uint8_t));
01965 if(stream == NULL)
01966 {
01967 *len = 0;
01968 return NULL;
01969 }
01970
01971 stream[i++] = response->repStatus->sw1;
01972 stream[i++] = response->repStatus->sw2;
01973
01974 while(i < response->lenData)
01975 {
01976 stream[i] = response->repData[i];
01977 i++;
01978 }
01979
01980 return stream;
01981 }
01982
01983
02000 CRP* ExchangeData(
02001 uint8_t tInverse,
02002 uint8_t cInverse,
02003 uint8_t tTC1,
02004 uint8_t cTC1,
02005 log_struct_t *logger)
02006 {
02007 CRP* data;
02008
02009 data = (CRP*)malloc(sizeof(CRP));
02010 if(data == NULL)
02011 {
02012 if(logger)
02013 LogByte1(logger, LOG_ERROR_MEMORY, 0);
02014 return NULL;
02015 }
02016
02017 data->cmd = ForwardCommand(tInverse, cInverse, tTC1, cTC1, logger);
02018 if(data->cmd == NULL)
02019 {
02020 free(data);
02021 return NULL;
02022 }
02023
02024 data->response = ForwardResponse(
02025 tInverse, cInverse, data->cmd->cmdHeader, logger);
02026 if(data->response == NULL)
02027 {
02028 FreeCAPDU(data->cmd);
02029 free(data);
02030 return NULL;
02031 }
02032
02033 return data;
02034 }
02035
02055 CRP* ExchangeCompleteData(
02056 uint8_t tInverse,
02057 uint8_t cInverse,
02058 uint8_t tTC1,
02059 uint8_t cTC1,
02060 log_struct_t *logger)
02061 {
02062 CRP *data, *tmp;
02063 uint8_t cont;
02064
02065 data = (CRP*)malloc(sizeof(CRP));
02066 if(data == NULL)
02067 {
02068 if(logger)
02069 LogByte1(logger, LOG_ERROR_MEMORY, 0);
02070 return NULL;
02071 }
02072 data->cmd = NULL;
02073 data->response = NULL;
02074
02075
02076 tmp = ExchangeData(tInverse, cInverse, tTC1, cTC1, logger);
02077 if(tmp == NULL)
02078 {
02079 FreeCRP(data);
02080 return NULL;
02081 }
02082 data->cmd = tmp->cmd;
02083 tmp->cmd = NULL;
02084
02085 cont = (tmp->response->repStatus->sw1 == 0x61 ||
02086 tmp->response->repStatus->sw1 == 0x6C);
02087 if(cont) FreeCRP(tmp);
02088
02089 while(cont)
02090 {
02091 tmp = ExchangeData(tInverse, cInverse, tTC1, cTC1, logger);
02092 if(tmp == NULL)
02093 {
02094 FreeCRP(data);
02095 return NULL;
02096 }
02097
02098 cont = (tmp->response->repStatus->sw1 == 0x61 ||
02099 tmp->response->repStatus->sw1 == 0x6C);
02100
02101 if(cont) FreeCRP(tmp);
02102 }
02103
02104 data->response = tmp->response;
02105 tmp->response = NULL;
02106 FreeCRP(tmp);
02107
02108 return data;
02109 }
02110
02122 ByteArray* MakeByteArray(uint8_t *data, uint8_t len)
02123 {
02124 ByteArray *stream = (ByteArray*)malloc(sizeof(ByteArray));
02125 if(stream == NULL) return NULL;
02126 stream->bytes = data;
02127 stream->len = len;
02128
02129 return stream;
02130 }
02131
02142 ByteArray* MakeByteArrayV(uint8_t nargs, ...)
02143 {
02144 ByteArray *ba;
02145 va_list ap;
02146 uint8_t i;
02147
02148 ba = (ByteArray*)malloc(sizeof(ByteArray));
02149 if(ba == NULL) return NULL;
02150 ba->len = nargs;
02151 ba->bytes = (uint8_t*)malloc(ba->len * sizeof(uint8_t));
02152 if(ba->bytes == NULL)
02153 {
02154 free(ba);
02155 return NULL;
02156 }
02157
02158 va_start(ap, nargs);
02159
02160
02161 for(i = 0; i < nargs; i++)
02162 ba->bytes[i] = (uint8_t)va_arg(ap, int);
02163 va_end(ap);
02164
02165 return ba;
02166 }
02167
02178 ByteArray* CopyByteArray(const uint8_t *data, uint8_t len)
02179 {
02180 ByteArray *stream = (ByteArray*)malloc(sizeof(ByteArray));
02181 if(stream == NULL) return NULL;
02182 stream->bytes = NULL;
02183 stream->len = 0;
02184
02185 if(data != NULL && len > 0)
02186 {
02187 stream->bytes = (uint8_t*)malloc(len * sizeof(uint8_t));
02188 if(stream->bytes == NULL)
02189 {
02190 free(stream);
02191 return NULL;
02192 }
02193 memcpy(stream->bytes, data, len);
02194 stream->len = len;
02195 }
02196
02197 return stream;
02198 }
02199
02205 void FreeByteArray(ByteArray* data)
02206 {
02207 if(data == NULL) return;
02208
02209 if(data->bytes != NULL)
02210 {
02211 free(data->bytes);
02212 data->bytes = NULL;
02213 }
02214 free(data);
02215 }
02216
02222 void FreeCAPDU(CAPDU* cmd)
02223 {
02224 if(cmd == NULL) return;
02225
02226 if(cmd->cmdHeader != NULL)
02227 {
02228 free(cmd->cmdHeader);
02229 cmd->cmdHeader = NULL;
02230 }
02231
02232 if(cmd->cmdData != NULL)
02233 {
02234 free(cmd->cmdData);
02235 cmd->cmdData = NULL;
02236 }
02237 free(cmd);
02238 }
02239
02246 CAPDU* CopyCAPDU(CAPDU* cmd)
02247 {
02248 CAPDU *command;
02249
02250 if(cmd == NULL || cmd->cmdHeader == NULL) return NULL;
02251
02252 command = (CAPDU*)malloc(sizeof(CAPDU));
02253 if(command == NULL) return NULL;
02254 command->cmdHeader = (EMVCommandHeader*)malloc(sizeof(EMVCommandHeader));
02255 if(command->cmdHeader == NULL)
02256 {
02257 free(command);
02258 return NULL;
02259 }
02260 memcpy(command->cmdHeader, cmd->cmdHeader, sizeof(EMVCommandHeader));
02261 if(cmd->cmdData != NULL && cmd->lenData != 0)
02262 {
02263 command->cmdData = (uint8_t*)malloc(cmd->lenData * sizeof(uint8_t));
02264 if(command->cmdData == NULL)
02265 {
02266 FreeCAPDU(command);
02267 return NULL;
02268 }
02269 memcpy(command->cmdData, cmd->cmdData, cmd->lenData);
02270 command->lenData = cmd->lenData;
02271 }
02272 else
02273 {
02274 command->cmdData = NULL;
02275 command->lenData = 0;
02276 }
02277
02278 return command;
02279 }
02280
02286 void FreeRAPDU(RAPDU* response)
02287 {
02288 if(response == NULL) return;
02289
02290 if(response->repStatus != NULL)
02291 {
02292 free(response->repStatus);
02293 response->repStatus = NULL;
02294 }
02295
02296 if(response->repData != NULL)
02297 {
02298 free(response->repData);
02299 response->repData = NULL;
02300 }
02301 free(response);
02302 }
02303
02310 RAPDU* CopyRAPDU(RAPDU* resp)
02311 {
02312 RAPDU *response;
02313
02314 if(resp == NULL || resp->repStatus == NULL) return NULL;
02315
02316 response = (RAPDU*)malloc(sizeof(RAPDU));
02317 if(response == NULL) return NULL;
02318 response->repStatus = (EMVStatus*)malloc(sizeof(EMVStatus));
02319 if(response->repStatus == NULL)
02320 {
02321 free(response);
02322 return NULL;
02323 }
02324 memcpy(response->repStatus, resp->repStatus, sizeof(EMVStatus));
02325 if(resp->repData != NULL && resp->lenData != 0)
02326 {
02327 response->repData = (uint8_t*)malloc(resp->lenData * sizeof(uint8_t));
02328 if(response->repData == NULL)
02329 {
02330 FreeRAPDU(response);
02331 return NULL;
02332 }
02333 memcpy(response->repData, resp->repData, resp->lenData);
02334 response->lenData = resp->lenData;
02335 }
02336 else
02337 {
02338 response->repData = NULL;
02339 response->lenData = 0;
02340 }
02341
02342 return response;
02343 }
02344
02350 void FreeCRP(CRP* data)
02351 {
02352 if(data == NULL) return;
02353
02354 if(data->cmd != NULL)
02355 {
02356 FreeCAPDU(data->cmd);
02357 data->cmd = NULL;
02358 }
02359
02360 if(data->response != NULL)
02361 {
02362 FreeRAPDU(data->response);
02363 data->response = NULL;
02364 }
02365 free(data);
02366 }
02367
02368