int main() { /*Se hace un test con la cadena hexadecimal 6F1A840E315041592E5359532E4444463031A5088801025F2D02656E cuyo significado es el siguiente: 6F(File Control Information(FCI) Template) 1A 84(Dedicated File(DF) Name) 0E -len 315041592E5359532E4444463031 - value(1PAY.SYS.DDF01 en hexa) A5(File Control information(FCI) Propietary template) 08-len 88(Short File Identifier(SFI)) 01- len 02 -value 5F2D(language preference) 02-len 656E-value */ dict_t *dict[HASHSIZE]; memset(dict, 0, sizeof(dict)); emvInit(dict); displayTable(dict); unsigned char test[] = {0x6F,0x1A,0x84,0x0E,0x31,0x50,0x41,0x59,0x2E,0x53,0x59, 0x53,0x2E,0x44,0x44,0x46,0x30,0x31,0xA5,0x08,0x88,0x01, 0x02,0x5F,0x2D,0x02,0x65,0x6E, 0x6F,0x1A,0x84,0x0E,0x31,0x50,0x41,0x59,0x2E,0x53,0x59, 0x53,0x2E,0x44,0x44,0x46,0x30,0x31,0xA5,0x08,0x88,0x01, 0x02,0x5F,0x2D,0x02,0x65,0x6E }; //unsigned char test[] = {0x9F, 0x35, 0x00}; //consulta de tag unsigned short size = sizeof(test)/sizeof(test[0]); tlvInfo_t *t=malloc(sizeof(tlvInfo_t)*size); memset(t,0,size); tlvInfo_init(t); int tindex =0; emvparse(test, size, t, &tindex , 0, dict); emvPrint_result(t, tindex); return 0; }
void DoEmvTransaction(){ unsigned char transaction_data[4096]; unsigned int transaction_data_len = 0; unsigned char custom_data[1024]; unsigned int custom_data_len = 0; unsigned char hexKsn[21]; unsigned char encryptedHexBuffer[128]; char hex[256]; unsigned char panToken[32]; unsigned char hexToken[32]; char *outputBuffer; char *sesitiveTagBuffer; char *clearTagBuffer; int samSlot = 1; char pToken[32] = {0}; l2bool result = L2FALSE; int rcTransaction = 0; int rcResponse = 0; int rc = 0; int i = 0; int tindex = 0; /* Perform EMVCo L2 transaction */ rcTransaction = l2manager_PerformTransaction(&tp, &onRequestOutcome, &onRestartOutcome, samSlot, pToken); /* Evaluate return value */ printf("\nl2manager_PerformTransaction() returns with %d\n\n", rcTransaction); switch (rcTransaction) { case EMV_OFFLINE_ACCEPT: case EMV_GO_ONLINE: #ifdef DEBUG if (onRequestOutcome.m_bpresent) printf("onRequestOutcome.m_ucmsgid: %d\n", (int)onRequestOutcome.m_ucmsgid); if (onRestartOutcome.m_bpresent) printf("onRestartOutcome.m_ucmsgid: %d\n", (int)onRestartOutcome.m_ucmsgid); #endif if (rcTransaction == EMV_OFFLINE_ACCEPT) { emvSuccessVisualization(); } /* Get transaction data. * Please see description of * rdol_<kernel_id>_emv.txt or rdol_<kernel_id>_ms.txt. */ result = l2manager_GetTransactionData(transaction_data, sizeof(transaction_data), &transaction_data_len); if (result == L2TRUE) { #ifdef DEBUG printf("TRANSACTION DATA:\n"); for (i = 0; i < transaction_data_len; i++) printf("%02X", transaction_data[i]); printf("\n\n"); #endif tlvInfo_t *t=malloc(sizeof(tlvInfo_t)*transaction_data_len); memset(t,0,transaction_data_len); tlvInfo_init(t); tindex = 0; asprintf(&clearTagBuffer, ""); asprintf(&sesitiveTagBuffer, ""); emvparse(transaction_data, transaction_data_len, t, &tindex, 0, &clearTagBuffer, &sesitiveTagBuffer); free(t); //Get PAN Token SHA256_CTX ctx; sha256_init(&ctx); sha256_update(&ctx,sesitiveTagBuffer, strlen(sesitiveTagBuffer)); sha256_final(&ctx,panToken); #ifdef DEBUG printf("hash DATA:\n"); for (i = 0; i < 32; i++) printf("%02X", panToken[i]); printf("\n\n"); #endif //TODO Test PAN Token against deny list here //********** DO DUKPT Crypto dukptEncrypt(hSession, sesitiveTagBuffer, strlen(sesitiveTagBuffer), hexKsn, encryptedHexBuffer); #ifdef DEBUG printf("EMV - Clear Data : %s\n", sesitiveTagBuffer); printf("EMV - KSN : %s\n", hexKsn); printf("EMV - CipherText : %s\n", encryptedHexBuffer); #endif strcpy(hexToken, bin2hex(hex, panToken, 32)); // Output format for CULR call to Creditcall //unsigned short size = sizeof(transaction_data)/sizeof(transaction_data[0]); formatOutputBuffer(&outputBuffer, hexKsn, &clearTagBuffer, encryptedHexBuffer, rcTransaction, hexToken); //Clear out transaction_data buffer that contains sensitive data to zero memset(&transaction_data[0], 0, sizeof(transaction_data)); //TODO Clear out sensitive data to zero memset(&sesitiveTagBuffer[0], 0, strlen(sesitiveTagBuffer)); free(sesitiveTagBuffer); free(clearTagBuffer); printf("%s",outputBuffer); } #ifdef DEBUG /* Get custom data. * Please see description of rdol_clear.txt. */ result = l2manager_GetCustomData(custom_data, sizeof(custom_data), &custom_data_len); if (result == L2TRUE) { printf("RDOL:\n"); for (i = 0; i < custom_data_len; i++) printf("%02X", custom_data[i]); printf("\n\n"); } #endif /** If the return value is EMV_GO_ONLINE you must call the * function l2manager_ProcessOnlineResponse(). **/ if (rcTransaction == EMV_GO_ONLINE) { /** ATTENTION * It is absolutely necessary to call the function * l2manager_ProcessOnlineResponse() if the code * EMV_GO_ONLINE is returned from function * l2manager_PerformTransaction() ! * If you want to abort the transaction, or the backend * is not reachable or something else, you should set * the ucOnlineRespData and OnlineRespDataLen to zero. * In such a case the return code will be * EMV_ONLINE_DECLINE. **/ //NEED to get return buffer //doSslCall(outputBuffer); unsigned char OnlineRespData[1024] = {0}; unsigned int OnlineRespDataLen = 0; #ifdef EMV_ONLINE_SUCCESS /* Successfull Online Verification = 0x30 0x30 */ OnlineRespDataLen = 16; memcpy(OnlineRespData, "\x8A\x02\x30\x30\x91\x0A\x60\x6D\x6C\x6C\x37\xD4\xAC\x51\x30\x30", OnlineRespDataLen); #endif memset(&onRequestOutcome, 0, sizeof(UIRequest)); memset(&onRestartOutcome, 0, sizeof(UIRequest)); rcResponse = l2manager_ProcessOnlineResponse(OnlineRespData, OnlineRespDataLen, &onRequestOutcome, &onRestartOutcome); switch (rcResponse) { case EMV_ONLINE_ACCEPT: printf("%s returns with EMV_ONLINE_ACCEPT\n", "l2manager_ProcessOnlineResponse()"); emvSuccessVisualization(1, 1); disable_bar(); enable_running_led(); break; case EMV_ONLINE_DECLINE: printf("%s returns with EMV_ONLINE_DECLINE\n", "\nl2manager_ProcessOnlineResponse()"); /* EMVCo alert tone. * Buzzer Beep @ 750Hz for 200ms * [On -> Off -> On] */ emvAlertTone(); break; default: printf("%s returns with undefined code (%d)\n", "\nl2manager_ProcessOnlineResponse()", rcTransaction); /* EMVCo alert tone. * Buzzer Beep @ 750Hz for 200ms * [On -> Off -> On] */ emvAlertTone(); break; } } else { /* EMVCo success tone. * Buzzer Beep @ 1500Hz for 500ms */ if (rcTransaction == EMV_OFFLINE_ACCEPT) { if (threadRunning){ //wait for thread to finish WaitEmvThreadFinnish(); } //Create thread for sending data int err; err = pthread_create(&inc_x_thread,NULL,&thread_doSslCall,(void *)outputBuffer); if (err != 0){ printf("\n\n\nCan't create thread...\n"); threadRunning = false; } else { printf("\n\n\nThread created...\n"); threadRunning = true; } disable_bar(); enable_running_led(); ClearTransactionData(); SetTransactionData(); } } break; case EMV_PPSE_NOT_SUPPORTED_BY_CARD: case EMV_NO_MATCHING_APP: /** At this point you could do some "closed loop" processing, * because the EMVCo kernel refuse the card. * Maybe it is no credit card, or the application is not * supported. * The card is still activated and remains in ISO 14443-4 state. */ /* EMVCo alert tone. * Buzzer Beep @ 750Hz for 200ms [On -> Off -> On] */ emvAlertTone(); break; /* case ...: * break; */ default: /* The other codes should be treated as error. */ /* EMVCo alert tone. * Buzzer Beep @ 750Hz for 200ms [On -> Off -> On] */ emvAlertTone(); break; } /* Check TransactionMode */ rc = l2manager_GetTransactionMode(); switch (rc) { case 1: printf("Transaction mode = Magstripe\n"); break; case 2: printf("Transaction mode = Magstripe [CVN_17]\n"); break; case 3: printf("Transaction mode = EMV\n"); break; default: printf("Transaction mode = (%d) - UNKNOWN\n", rc); break; } /* Needed for Mastercard processing */ /* This function is used to clear TORN for paypass transactions */ result = l2manager_ClearTorn(); if (result != L2TRUE) printf("Error in function l2manager_ClearTorn()\n"); }