Skip to content

Commit fad8d4a

Browse files
committed
Update EMV TTL tests
* Use emv_cardreader_emul object library * Add debug output for emv_ttl_pcsc_test
1 parent 87c5324 commit fad8d4a

File tree

3 files changed

+105
-183
lines changed

3 files changed

+105
-183
lines changed

tests/CMakeLists.txt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
cmake_minimum_required(VERSION 3.16)
99

1010
if (BUILD_TESTING)
11+
add_library(emv_cardreader_emul OBJECT EXCLUDE_FROM_ALL emv_cardreader_emul.c)
12+
1113
add_executable(emv_debug_test emv_debug_test.c)
1214
target_link_libraries(emv_debug_test PRIVATE print_helpers emv)
1315
add_test(emv_debug_test emv_debug_test)
@@ -25,11 +27,11 @@ if (BUILD_TESTING)
2527
add_test(emv_atr_parse_test emv_atr_parse_test)
2628

2729
add_executable(emv_ttl_tpdu_test emv_ttl_tpdu_test.c)
28-
target_link_libraries(emv_ttl_tpdu_test PRIVATE print_helpers emv)
30+
target_link_libraries(emv_ttl_tpdu_test PRIVATE emv_cardreader_emul print_helpers emv)
2931
add_test(emv_ttl_tpdu_test emv_ttl_tpdu_test)
3032

3133
add_executable(emv_ttl_pcsc_test emv_ttl_pcsc_test.c)
32-
target_link_libraries(emv_ttl_pcsc_test PRIVATE print_helpers emv)
34+
target_link_libraries(emv_ttl_pcsc_test PRIVATE emv_cardreader_emul print_helpers emv)
3335
add_test(emv_ttl_pcsc_test emv_ttl_pcsc_test)
3436

3537
add_executable(emv_str_parse_test emv_str_parse_test.c)
@@ -44,8 +46,8 @@ if (BUILD_TESTING)
4446
target_link_libraries(emv_cvmlist_test PRIVATE emv)
4547
add_test(emv_cvmlist_test emv_cvmlist_test)
4648

47-
add_executable(emv_build_candidate_list_test emv_build_candidate_list_test.c emv_cardreader_emul.c)
48-
target_link_libraries(emv_build_candidate_list_test PRIVATE print_helpers emv)
49+
add_executable(emv_build_candidate_list_test emv_build_candidate_list_test.c)
50+
target_link_libraries(emv_build_candidate_list_test PRIVATE emv_cardreader_emul print_helpers emv)
4951
add_test(emv_build_candidate_list_test emv_build_candidate_list_test)
5052

5153
add_executable(isocodes_test isocodes_test.c)

tests/emv_ttl_pcsc_test.c

Lines changed: 50 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @file emv_ttl_pcsc_test.c
33
* @brief Unit tests for EMV TTL APDU cases using typical PC/SC APDUs
44
*
5-
* Copyright (c) 2021 Leon Lynch
5+
* Copyright (c) 2021, 2024 Leon Lynch
66
*
77
* This program is free software; you can redistribute it and/or
88
* modify it under the terms of the GNU Lesser General Public
@@ -20,24 +20,19 @@
2020
*/
2121

2222
#include "emv_ttl.h"
23+
#include "emv_cardreader_emul.h"
2324

2425
#include <stdint.h>
2526
#include <stdio.h>
2627
#include <string.h>
2728

2829
// For debug output
30+
#include "emv_debug.h"
2931
#include "print_helpers.h"
3032

31-
struct apdu_t {
32-
size_t c_apdu_len;
33-
const uint8_t* c_apdu;
34-
size_t r_apdu_len;
35-
const uint8_t* r_apdu;
36-
};
37-
3833
// PC/SC exchanges for case 1 normal processing
3934
// See EMV 4.3 Book 1, Annex A1
40-
static const struct apdu_t test_pcsc_case_1_normal[] = {
35+
static const struct xpdu_t test_pcsc_case_1_normal[] = {
4136
{
4237
4, (uint8_t[]){ 0x12, 0x34, 0x56, 0x78 },
4338
2, (uint8_t[]){ 0x90, 0x00 },
@@ -48,7 +43,7 @@ static const uint8_t test_pcsc_case_1_normal_data[] = { 0x90, 0x00 };
4843

4944
// PC/SC exchanges for case 1 error processing
5045
// See EMV 4.3 Book 1, Annex A1
51-
static const struct apdu_t test_pcsc_case_1_error[] = {
46+
static const struct xpdu_t test_pcsc_case_1_error[] = {
5247
{
5348
4, (uint8_t[]){ 0x12, 0x34, 0x56, 0x78 },
5449
2, (uint8_t[]){ 0x6A, 0x81 }, // Function not supported
@@ -59,7 +54,7 @@ static const uint8_t test_pcsc_case_1_error_data[] = { 0x6A, 0x81 };
5954

6055
// PC/SC exchanges for case 2 normal processing
6156
// See EMV 4.3 Book 1, Annex A2
62-
static const struct apdu_t test_pcsc_case_2_normal[] = {
57+
static const struct xpdu_t test_pcsc_case_2_normal[] = {
6358
{
6459
5, (uint8_t[]){ 0x00, 0xB2, 0x01, 0x0C, 0x00 }, // READ RECORD 1,1
6560
2, (uint8_t[]){ 0x6C, 0x1C },
@@ -76,7 +71,7 @@ static const uint8_t test_pcsc_case_2_normal_data[] = {
7671

7772
// PC/SC exchanges for case 2 error processing (early)
7873
// See EMV 4.3 Book 1, Annex A2
79-
static const struct apdu_t test_pcsc_case_2_error_early[] = {
74+
static const struct xpdu_t test_pcsc_case_2_error_early[] = {
8075
{
8176
5, (uint8_t[]){ 0x00, 0xB2, 0x01, 0x0C, 0x00 }, // READ RECORD 1,1
8277
2, (uint8_t[]){ 0x6A, 0x81 }, // Function not supported
@@ -87,7 +82,7 @@ static const uint8_t test_pcsc_case_2_error_early_data[] = { 0x6A, 0x81 };
8782

8883
// PC/SC exchanges for case 2 error processing (late)
8984
// See EMV 4.3 Book 1, Annex A2
90-
static const struct apdu_t test_pcsc_case_2_error_late[] = {
85+
static const struct xpdu_t test_pcsc_case_2_error_late[] = {
9186
{
9287
5, (uint8_t[]){ 0x00, 0xB2, 0x01, 0x0C, 0x00 }, // READ RECORD 1,1
9388
2, (uint8_t[]){ 0x6C, 0x1C },
@@ -102,7 +97,7 @@ static const uint8_t test_pcsc_case_2_error_late_data[] = { 0x65, 0x81 };
10297

10398
// PC/SC exchanges for case 3 normal processing
10499
// See EMV 4.3 Book 1, Annex A3
105-
static const struct apdu_t test_pcsc_case_3_normal[] = {
100+
static const struct xpdu_t test_pcsc_case_3_normal[] = {
106101
{
107102
9, (uint8_t[]){ 0x00, 0x82, 0x00, 0x00, 0x04, 0xde, 0xad, 0xbe, 0xef }, // EXTERNAL AUTHENTICATE
108103
2, (uint8_t[]){ 0x90, 0x00 },
@@ -113,7 +108,7 @@ static const uint8_t test_pcsc_case_3_normal_data[] = { 0x90, 0x00 };
113108

114109
// PC/SC exchanges for case 3 error processing
115110
// See EMV 4.3 Book 1, Annex A3
116-
static const struct apdu_t test_pcsc_case_3_error[] = {
111+
static const struct xpdu_t test_pcsc_case_3_error[] = {
117112
{
118113
9, (uint8_t[]){ 0x00, 0x82, 0x00, 0x00, 0x04, 0xde, 0xad, 0xbe, 0xef }, // EXTERNAL AUTHENTICATE
119114
2, (uint8_t[]){ 0x6A, 0x81 }, // Function not supported
@@ -123,7 +118,7 @@ static const uint8_t test_pcsc_case_3_error_data[] = { 0x6A, 0x81 };
123118

124119
// PC/SC exchanges for case 4 normal processing
125120
// See EMV 4.3 Book 1, Annex A4
126-
static const struct apdu_t test_pcsc_case_4_normal[] = {
121+
static const struct xpdu_t test_pcsc_case_4_normal[] = {
127122
{
128123
20, (uint8_t[]){ 0x00, 0xA4, 0x04, 0x00, 0x0E, 0x31, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00 }, // SELECT
129124
2, (uint8_t[]){ 0x61, 0x26 },
@@ -140,7 +135,7 @@ static const uint8_t test_pcsc_case_4_normal_data[] = {
140135

141136
// PC/SC exchanges for case 4 error processing
142137
// See EMV 4.3 Book 1, Annex A4
143-
static const struct apdu_t test_pcsc_case_4_error_early[] = {
138+
static const struct xpdu_t test_pcsc_case_4_error_early[] = {
144139
{
145140
20, (uint8_t[]){ 0x00, 0xA4, 0x04, 0x00, 0x0E, 0x31, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00 }, // SELECT
146141
2, (uint8_t[]){ 0x6A, 0x82 }, // File or application not found
@@ -151,7 +146,7 @@ static const uint8_t test_pcsc_case_4_error_early_data[] = { 0x6A, 0x82 };
151146

152147
// PC/SC exchanges for case 4 error processing (late)
153148
// See EMV 4.3 Book 1, Annex A4
154-
static const struct apdu_t test_pcsc_case_4_error_late[] = {
149+
static const struct xpdu_t test_pcsc_case_4_error_late[] = {
155150
{
156151
20, (uint8_t[]){ 0x00, 0xA4, 0x04, 0x00, 0x0E, 0x31, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00 }, // SELECT
157152
2, (uint8_t[]){ 0x61, 0x26 },
@@ -166,7 +161,7 @@ static const uint8_t test_pcsc_case_4_error_late_data[] = { 0x65, 0x81 };
166161

167162
// PC/SC exchanges for case 2 using both '61' and '6C' procedure bytes
168163
// See EMV 4.3 Book 1, Annex A5
169-
static const struct apdu_t test_pcsc_case_2_normal_advanced[] = {
164+
static const struct xpdu_t test_pcsc_case_2_normal_advanced[] = {
170165
{
171166
5, (uint8_t[]){ 0x00, 0xB2, 0x01, 0x0C, 0x00 }, // READ RECORD 1,1
172167
2, (uint8_t[]){ 0x6C, 0x1C },
@@ -193,7 +188,7 @@ static const uint8_t test_pcsc_case_2_normal_advanced_data[] = {
193188

194189
// PC/SC exchanges for case 4 (using multiple '61' procedure bytes)
195190
// See EMV 4.3 Book 1, Annex A6
196-
static const struct apdu_t test_pcsc_case_4_normal_advanced[] = {
191+
static const struct xpdu_t test_pcsc_case_4_normal_advanced[] = {
197192
{
198193
20, (uint8_t[]){ 0x00, 0xA4, 0x04, 0x00, 0x0E, 0x31, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00 }, // SELECT
199194
2, (uint8_t[]){ 0x61, 0x26 },
@@ -214,7 +209,7 @@ static const uint8_t test_pcsc_case_4_normal_advanced_data[] = {
214209

215210
// PC/SC exchanges for case 4 warning processing
216211
// See EMV 4.3 Book 1, Annex A4
217-
static const struct apdu_t test_pcsc_case_4_warning[] = {
212+
static const struct xpdu_t test_pcsc_case_4_warning[] = {
218213
{
219214
20, (uint8_t[]){ 0x00, 0xA4, 0x04, 0x00, 0x0E, 0x31, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00 }, // SELECT
220215
2, (uint8_t[]){ 0x62, 0x86 }, // No input available from a sensor on the card
@@ -233,50 +228,12 @@ static const uint8_t test_pcsc_case_4_warning_data[] = {
233228
0x6F, 0x24, 0x84, 0x0E, 0x31, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0xA5, 0x12, 0x88, 0x01, 0x01, 0x5F, 0x2D, 0x08, 0x65, 0x6E, 0x65, 0x73, 0x66, 0x72, 0x64, 0x65, 0x9F, 0x11, 0x01, 0x01,
234229
};
235230

236-
struct emv_cardreader_ctx_t {
237-
const struct apdu_t* apdu_list;
238-
const struct apdu_t* apdu_current;
239-
};
240-
241-
static int emv_cardreader_emul(
242-
void* ctx,
243-
const void* tx_buf,
244-
size_t tx_buf_len,
245-
void* rx_buf,
246-
size_t* rx_buf_len
247-
) {
248-
struct emv_cardreader_ctx_t* emul_ctx = ctx;
249-
const struct apdu_t* apdu;
250-
251-
if (!emul_ctx->apdu_current) {
252-
emul_ctx->apdu_current = emul_ctx->apdu_list;
253-
}
254-
if (!emul_ctx->apdu_current->c_apdu_len) {
255-
return -101;
256-
}
257-
apdu = emul_ctx->apdu_current;
258-
259-
if (tx_buf_len != apdu->c_apdu_len) {
260-
return -102;
261-
}
262-
if (memcmp(tx_buf, apdu->c_apdu, apdu->c_apdu_len) != 0) {
263-
return -103;
264-
}
265-
266-
memcpy(rx_buf, apdu->r_apdu, apdu->r_apdu_len);
267-
*rx_buf_len = apdu->r_apdu_len;
268-
269-
emul_ctx->apdu_current++;
270-
271-
return 0;
272-
}
273-
274231
int main(void)
275232
{
276233
int r;
277234

278235
struct emv_ttl_t ttl;
279-
struct emv_cardreader_ctx_t emul_ctx;
236+
struct emv_cardreader_emul_ctx_t emul_ctx;
280237
ttl.cardreader.mode = EMV_CARDREADER_MODE_APDU;
281238
ttl.cardreader.ctx = &emul_ctx;
282239
ttl.cardreader.trx = &emv_cardreader_emul;
@@ -287,10 +244,17 @@ int main(void)
287244
size_t data_len;
288245
uint16_t sw1sw2;
289246

247+
// Enable debug output
248+
r = emv_debug_init(EMV_DEBUG_SOURCE_ALL, EMV_DEBUG_ALL, &print_emv_debug);
249+
if (r) {
250+
fprintf(stderr, "emv_debug_init() failed; r=%d\n", r);
251+
return 1;
252+
}
253+
290254
// Test APDU case 1; normal processing
291255
printf("\nTesting APDU case 1 (PC/SC mode); normal processing...\n");
292-
emul_ctx.apdu_list = test_pcsc_case_1_normal;
293-
emul_ctx.apdu_current = NULL;
256+
emul_ctx.xpdu_list = test_pcsc_case_1_normal;
257+
emul_ctx.xpdu_current = NULL;
294258
r_apdu_len = sizeof(r_apdu);
295259

296260
r = emv_ttl_trx(
@@ -322,8 +286,8 @@ int main(void)
322286

323287
// Test APDU case 1; error processing
324288
printf("\nTesting APDU case 1 (PC/SC mode); error processing...\n");
325-
emul_ctx.apdu_list = test_pcsc_case_1_error;
326-
emul_ctx.apdu_current = NULL;
289+
emul_ctx.xpdu_list = test_pcsc_case_1_error;
290+
emul_ctx.xpdu_current = NULL;
327291
r_apdu_len = sizeof(r_apdu);
328292

329293
r = emv_ttl_trx(
@@ -355,8 +319,8 @@ int main(void)
355319

356320
// Test APDU case 2; normal processing
357321
printf("\nTesting APDU case 2 (PC/SC mode); normal processing...\n");
358-
emul_ctx.apdu_list = test_pcsc_case_2_normal;
359-
emul_ctx.apdu_current = NULL;
322+
emul_ctx.xpdu_list = test_pcsc_case_2_normal;
323+
emul_ctx.xpdu_current = NULL;
360324
data_len = sizeof(data);
361325

362326
r = emv_ttl_read_record(
@@ -388,8 +352,8 @@ int main(void)
388352

389353
// Test APDU case 2; error processing (early)
390354
printf("\nTesting APDU case 2 (PC/SC mode); error processing (early)...\n");
391-
emul_ctx.apdu_list = test_pcsc_case_2_error_early;
392-
emul_ctx.apdu_current = NULL;
355+
emul_ctx.xpdu_list = test_pcsc_case_2_error_early;
356+
emul_ctx.xpdu_current = NULL;
393357
data_len = sizeof(data);
394358

395359
r = emv_ttl_read_record(
@@ -421,8 +385,8 @@ int main(void)
421385

422386
// Test APDU case 2; error processing (late)
423387
printf("\nTesting APDU case 2 (PC/SC mode); error processing (late)...\n");
424-
emul_ctx.apdu_list = test_pcsc_case_2_error_late;
425-
emul_ctx.apdu_current = NULL;
388+
emul_ctx.xpdu_list = test_pcsc_case_2_error_late;
389+
emul_ctx.xpdu_current = NULL;
426390
data_len = sizeof(data);
427391

428392
r = emv_ttl_read_record(
@@ -454,8 +418,8 @@ int main(void)
454418

455419
// Test APDU case 3; normal processing
456420
printf("\nTesting APDU case 3 (PC/SC mode); normal processing...\n");
457-
emul_ctx.apdu_list = test_pcsc_case_3_normal;
458-
emul_ctx.apdu_current = NULL;
421+
emul_ctx.xpdu_list = test_pcsc_case_3_normal;
422+
emul_ctx.xpdu_current = NULL;
459423
r_apdu_len = sizeof(r_apdu);
460424

461425
r = emv_ttl_trx(
@@ -487,8 +451,8 @@ int main(void)
487451

488452
// Test APDU case 3; error processing
489453
printf("\nTesting APDU case 3 (PC/SC mode); error processing...\n");
490-
emul_ctx.apdu_list = test_pcsc_case_3_error;
491-
emul_ctx.apdu_current = NULL;
454+
emul_ctx.xpdu_list = test_pcsc_case_3_error;
455+
emul_ctx.xpdu_current = NULL;
492456
r_apdu_len = sizeof(r_apdu);
493457

494458
r = emv_ttl_trx(
@@ -520,8 +484,8 @@ int main(void)
520484

521485
// Test APDU case 4; normal processing
522486
printf("\nTesting APDU case 4 (PC/SC mode); normal processing...\n");
523-
emul_ctx.apdu_list = test_pcsc_case_4_normal;
524-
emul_ctx.apdu_current = NULL;
487+
emul_ctx.xpdu_list = test_pcsc_case_4_normal;
488+
emul_ctx.xpdu_current = NULL;
525489
data_len = sizeof(data);
526490

527491
const uint8_t PSE[] = "1PAY.SYS.DDF01";
@@ -554,8 +518,8 @@ int main(void)
554518

555519
// Test APDU case 4; error processing (early)
556520
printf("\nTesting APDU case 4 (PC/SC mode); error processing (early)...\n");
557-
emul_ctx.apdu_list = test_pcsc_case_4_error_early;
558-
emul_ctx.apdu_current = NULL;
521+
emul_ctx.xpdu_list = test_pcsc_case_4_error_early;
522+
emul_ctx.xpdu_current = NULL;
559523
data_len = sizeof(data);
560524

561525
r = emv_ttl_select_by_df_name(
@@ -587,8 +551,8 @@ int main(void)
587551

588552
// Test APDU case 4; error processing (late)
589553
printf("\nTesting APDU case 4 (PC/SC mode); error processing (late)...\n");
590-
emul_ctx.apdu_list = test_pcsc_case_4_error_late;
591-
emul_ctx.apdu_current = NULL;
554+
emul_ctx.xpdu_list = test_pcsc_case_4_error_late;
555+
emul_ctx.xpdu_current = NULL;
592556
data_len = sizeof(data);
593557

594558
r = emv_ttl_select_by_df_name(
@@ -620,8 +584,8 @@ int main(void)
620584

621585
// Test APDU case 2; normal processing (using both '61' and '6C' procedure bytes)
622586
printf("\nTesting APDU case 2 (PC/SC mode); normal processing (using both '61' and '6C' procedure bytes)...\n");
623-
emul_ctx.apdu_list = test_pcsc_case_2_normal_advanced;
624-
emul_ctx.apdu_current = NULL;
587+
emul_ctx.xpdu_list = test_pcsc_case_2_normal_advanced;
588+
emul_ctx.xpdu_current = NULL;
625589
data_len = sizeof(data);
626590

627591
r = emv_ttl_read_record(
@@ -653,8 +617,8 @@ int main(void)
653617

654618
// Test APDU case 4; normal processing (using multiple '61' procedure bytes)
655619
printf("\nTesting APDU case 4 (PC/SC mode); normal processing (using multiple '61' procedure bytes)...\n");
656-
emul_ctx.apdu_list = test_pcsc_case_4_normal_advanced;
657-
emul_ctx.apdu_current = NULL;
620+
emul_ctx.xpdu_list = test_pcsc_case_4_normal_advanced;
621+
emul_ctx.xpdu_current = NULL;
658622
data_len = sizeof(data);
659623

660624
r = emv_ttl_select_by_df_name(
@@ -686,8 +650,8 @@ int main(void)
686650

687651
// Test APDU case 4; warning processing
688652
printf("\nTesting APDU case 4 (PC/SC mode); warning processing...\n");
689-
emul_ctx.apdu_list = test_pcsc_case_4_warning;
690-
emul_ctx.apdu_current = NULL;
653+
emul_ctx.xpdu_list = test_pcsc_case_4_warning;
654+
emul_ctx.xpdu_current = NULL;
691655
data_len = sizeof(data);
692656

693657
r = emv_ttl_select_by_df_name(

0 commit comments

Comments
 (0)