Skip to content

Commit

Permalink
Implement --ignore-padding option for emv-decode
Browse files Browse the repository at this point in the history
Invalid data is assumed to be padding if it is either less than 8 bytes
when the total data length is a multiple of 8 bytes (for example DES) or
if it is less than 16 bytes when the total data length is a multiple of
16 bytes (for example AES).

Note that this option will also apply to nested constructed fields that
contain padded cleartext data intended for encryption.
  • Loading branch information
leonlynch committed Nov 19, 2024
1 parent 0fb838a commit 13e202b
Show file tree
Hide file tree
Showing 4 changed files with 411 additions and 47 deletions.
74 changes: 74 additions & 0 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,80 @@ if(TARGET emv-decode AND BUILD_TESTING)
PASS_REGULAR_EXPRESSION ${emv_decode_9F27_test3_regex}
)

add_test(NAME emv_decode_padding_test1
COMMAND emv-decode --ber 701870105F2A0208409F1A0208409F15025999123456789ABCDED002DEADFEDC --ignore-padding
--mcc-json ${MCC_JSON_BUILD_PATH}
)
string(CONCAT emv_decode_padding_test1_regex
"^70 : \\[24\\][\r\n]"
" 70 : \\[16\\][\r\n]"
" 5F2A : \\[2\\] 08 40[\r\n]"
" 9F1A : \\[2\\] 08 40[\r\n]"
" 9F15 : \\[2\\] 59 99[\r\n]"
" Padding : \\[1\\] 12[\r\n]"
" Padding : \\[6\\] 34 56 78 9A BC DE[\r\n]"
"D0 : \\[2\\] DE AD[\r\n]"
"Padding : \\[2\\] FE DC[\r\n]$"
)
set_tests_properties(emv_decode_padding_test1
PROPERTIES
PASS_REGULAR_EXPRESSION ${emv_decode_padding_test1_regex}
)

add_test(NAME emv_decode_padding_test2
COMMAND emv-decode --ber 701870105F2A0208409F1A0208409F15025999123456789ABCDED002DEADFEDC
--mcc-json ${MCC_JSON_BUILD_PATH}
)
string(CONCAT emv_decode_padding_test2_regex
"^70 : \\[24\\][\r\n]"
" 70 : \\[16\\][\r\n]"
" 5F2A : \\[2\\] 08 40[\r\n]"
" 9F1A : \\[2\\] 08 40[\r\n]"
" 9F15 : \\[2\\] 59 99[\r\n]"
"BER decoding error -11 at offset 19\\; remaining invalid data: 12 34 56 78 9A BC DE D0 02 DE AD FE DC[\r\n]$"
)
set_tests_properties(emv_decode_padding_test2
PROPERTIES
PASS_REGULAR_EXPRESSION ${emv_decode_padding_test2_regex}
)

add_test(NAME emv_decode_padding_test3
COMMAND emv-decode --tlv 701870105F2A0208409F1A0208409F15025999123456789ABCDED002DEADFEDC --ignore-padding
--mcc-json ${MCC_JSON_BUILD_PATH}
)
string(CONCAT emv_decode_padding_test3_regex
"^70 \\| EMV Data Template : \\[24\\][\r\n]"
" 70 \\| EMV Data Template : \\[16\\][\r\n]"
" 5F2A \\| Transaction Currency Code : \\[2\\] 08 40 \\(US Dollar\\)[\r\n]"
" 9F1A \\| Terminal Country Code : \\[2\\] 08 40 \\(United States\\)[\r\n]"
" 9F15 \\| Merchant Category Code \\(MCC\\) : \\[2\\] 59 99 \\(Miscellaneous and Specialty Retail Stores\\)[\r\n]"
" Padding : \\[1\\] 12[\r\n]"
" Padding : \\[6\\] 34 56 78 9A BC DE[\r\n]"
"D0 : \\[2\\] DE AD[\r\n]"
"Padding : \\[2\\] FE DC[\r\n]$"
)
set_tests_properties(emv_decode_padding_test3
PROPERTIES
PASS_REGULAR_EXPRESSION ${emv_decode_padding_test3_regex}
)

add_test(NAME emv_decode_padding_test4
COMMAND emv-decode --tlv 701870105F2A0208409F1A0208409F15025999123456789ABCDED002DEADFEDC
--mcc-json ${MCC_JSON_BUILD_PATH}
)
string(CONCAT emv_decode_padding_test4_regex
"^70 \\| EMV Data Template : \\[24\\][\r\n]"
" 70 \\| EMV Data Template : \\[16\\][\r\n]"
" 5F2A \\| Transaction Currency Code : \\[2\\] 08 40 \\(US Dollar\\)[\r\n]"
" 9F1A \\| Terminal Country Code : \\[2\\] 08 40 \\(United States\\)[\r\n]"
" 9F15 \\| Merchant Category Code \\(MCC\\) : \\[2\\] 59 99 \\(Miscellaneous and Specialty Retail Stores\\)[\r\n]"
"BER decoding error -11 at offset 19\\; remaining invalid data: 12 34 56 78 9A BC DE D0 02 DE AD FE DC[\r\n]$"
)
set_tests_properties(emv_decode_padding_test4
PROPERTIES
PASS_REGULAR_EXPRESSION ${emv_decode_padding_test4_regex}
)

if(WIN32)
# Ensure that tests can find required DLLs (if any)
# Assume that the PATH already contains the compiler runtime DLLs
Expand Down
15 changes: 13 additions & 2 deletions tools/emv-decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "iso8859.h"

#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
Expand Down Expand Up @@ -88,11 +89,13 @@ enum emv_decode_mode_t {
EMV_DECODE_ISO8859_13,
EMV_DECODE_ISO8859_14,
EMV_DECODE_ISO8859_15,
EMV_DECODE_IGNORE_PADDING,
EMV_DECODE_VERSION,
EMV_DECODE_OVERRIDE_ISOCODES_PATH,
EMV_DECODE_OVERRIDE_MCC_JSON,
};
static enum emv_decode_mode_t emv_decode_mode = EMV_DECODE_NONE;
static bool ignore_padding = false;

// Testing parameters
static char* isocodes_path = NULL;
Expand Down Expand Up @@ -166,6 +169,8 @@ static struct argp_option argp_options[] = {
{ "iso8859-14", EMV_DECODE_ISO8859_14, NULL, OPTION_HIDDEN },
{ "iso8859-15", EMV_DECODE_ISO8859_15, NULL, OPTION_HIDDEN },

{ "ignore-padding", EMV_DECODE_IGNORE_PADDING, NULL, 0, "Ignore invalid data if the input aligns with either the DES or AES cipher block size and invalid data is less than the cipher block size. Only applies to --ber and --tlv" },

{ "version", EMV_DECODE_VERSION, NULL, 0, "Display emv-utils version" },

// Hidden options for testing
Expand Down Expand Up @@ -306,6 +311,11 @@ static error_t argp_parser_helper(int key, char* arg, struct argp_state* state)
return 0;
}

case EMV_DECODE_IGNORE_PADDING: {
ignore_padding = true;
return 0;
}

case EMV_DECODE_OVERRIDE_ISOCODES_PATH: {
isocodes_path = strdup(arg);
return 0;
Expand Down Expand Up @@ -462,12 +472,12 @@ int main(int argc, char** argv)
}

case EMV_DECODE_BER: {
print_ber_buf(data, data_len, " ", 0);
print_ber_buf(data, data_len, " ", 0, ignore_padding);
break;
}

case EMV_DECODE_TLV: {
print_emv_buf(data, data_len, " ", 0);
print_emv_buf(data, data_len, " ", 0, ignore_padding);
break;
}

Expand Down Expand Up @@ -896,6 +906,7 @@ int main(int argc, char** argv)
}

case EMV_DECODE_ISO8859_X:
case EMV_DECODE_IGNORE_PADDING:
case EMV_DECODE_VERSION:
case EMV_DECODE_OVERRIDE_ISOCODES_PATH:
case EMV_DECODE_OVERRIDE_MCC_JSON:
Expand Down
Loading

0 comments on commit 13e202b

Please sign in to comment.