Skip to content

Commit ddb3d60

Browse files
committed
Stringify Terminal Risk Management Data (field 9F1D)
1 parent 16001bc commit ddb3d60

File tree

6 files changed

+263
-0
lines changed

6 files changed

+263
-0
lines changed

src/emv_fields.h

+40
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,46 @@ enum emv_iad_format_t {
558558
#define EMV_IAD_VSDC_CVR_BYTE5_CDCVM_PERFORMED (0x02) ///< Card Verification Results (CVR): CDCVM successfully performed
559559
#define EMV_IAD_VSDC_CVR_BYTE5_EMV_SESSION_KEY (0x01) ///< Card Verification Results (CVR): Secure Messaging uses EMV Session key-based derivation
560560

561+
// Terminal Risk Management Data (field 9F1D) byte 1
562+
// See EMV Contactless Book C-2 v2.11, Annex A.1.161
563+
// See M/Chip Requirements for Contact and Contactless, 28 November 2023, Chapter 5, Terminal Risk Management Data
564+
#define EMV_TRMD_BYTE1_RESTART_SUPPORTED (0x80) ///< Terminal Risk Management Data: Restart supported
565+
#define EMV_TRMD_BYTE1_ENCIPHERED_PIN_ONLINE_CONTACTLESS (0x40) ///< Terminal Risk Management Data: Enciphered PIN verified online (Contactless)
566+
#define EMV_TRMD_BYTE1_SIGNATURE_CONTACTLESS (0x20) ///< Terminal Risk Management Data: Signature (paper) (Contactless)
567+
#define EMV_TRMD_BYTE1_ENCIPHERED_PIN_OFFLINE_CONTACTLESS (0x10) ///< Terminal Risk Management Data: Enciphered PIN verification performed by ICC (Contactless)
568+
#define EMV_TRMD_BYTE1_NO_CVM_CONTACTLESS (0x08) ///< Terminal Risk Management Data: No CVM required (Contactless)
569+
#define EMV_TRMD_BYTE1_CDCVM_CONTACTLESS (0x04) ///< Terminal Risk Management Data: CDCVM (Contactless)
570+
#define EMV_TRMD_BYTE1_PLAINTEXT_PIN_OFFLINE_CONTACTLESS (0x02) ///< Terminal Risk Management Data: Plaintext PIN verification performed by ICC (Contactless)
571+
#define EMV_TRMD_BYTE1_PRESENT_AND_HOLD_SUPPORTED (0x01) ///< Terminal Risk Management Data: Present and Hold supported
572+
573+
// Terminal Risk Management Data (field 9F1D) byte 2
574+
// See EMV Contactless Book C-2 v2.11, Annex A.1.161
575+
// See EMV Contactless Book C-8 v1.1, Annex A.1.129
576+
// See M/Chip Requirements for Contact and Contactless, 28 November 2023, Chapter 5, Terminal Risk Management Data
577+
#define EMV_TRMD_BYTE2_CVM_LIMIT_EXCEEDED (0x80) ///< Terminal Risk Management Data: CVM Limit exceeded
578+
#define EMV_TRMD_BYTE2_ENCIPHERED_PIN_ONLINE_CONTACT (0x40) ///< Terminal Risk Management Data: Enciphered PIN verified online (Contact)
579+
#define EMV_TRMD_BYTE2_SIGNATURE_CONTACT (0x20) ///< Terminal Risk Management Data: Signature (paper) (Contact)
580+
#define EMV_TRMD_BYTE2_ENCIPHERED_PIN_OFFLINE_CONTACT (0x10) ///< Terminal Risk Management Data: Enciphered PIN verification performed by ICC (Contact)
581+
#define EMV_TRMD_BYTE2_NO_CVM_CONTACT (0x08) ///< Terminal Risk Management Data: No CVM required (Contact)
582+
#define EMV_TRMD_BYTE2_CDCVM_CONTACT (0x04) ///< Terminal Risk Management Data: CDCVM (Contact)
583+
#define EMV_TRMD_BYTE2_PLAINTEXT_PIN_OFFLINE_CONTACT (0x02) ///< Terminal Risk Management Data: Plaintext PIN verification performed by ICC (Contact)
584+
#define EMV_TRMD_BYTE2_RFU (0x01) ///< Terminal Risk Management Data: RFU
585+
586+
// Terminal Risk Management Data (field 9F1D) byte 3
587+
// See EMV Contactless Book C-2 v2.11, Annex A.1.161
588+
// See M/Chip Requirements for Contact and Contactless, 28 November 2023, Chapter 5, Terminal Risk Management Data
589+
#define EMV_TRMD_BYTE3_MAGSTRIPE_MODE_CONTACTLESS_NOT_SUPPORTED (0x80) ///< Terminal Risk Management Data: Mag-stripe mode contactless transactions not supported
590+
#define EMV_TRMD_BYTE3_EMV_MODE_CONTACTLESS_NOT_SUPPORTED (0x40) ///< Terminal Risk Management Data: EMV mode contactless transactions not supported
591+
#define EMV_TRMD_BYTE3_CDCVM_WITHOUT_CDA_SUPPORTED (0x20) ///< Terminal Risk Management Data: CDCVM without CDA supported
592+
#define EMV_TRMD_BYTE3_RFU (0x1F) ///< Terminal Risk Management Data: RFU
593+
594+
// Terminal Risk Management Data (field 9F1D) byte 4
595+
// See EMV Contactless Book C-2 v2.11, Annex A.1.161
596+
// See EMV Contactless Book C-8 v1.1, Annex A.1.129
597+
#define EMV_TRMD_BYTE4_CDCVM_BYPASS_REQUESTED (0x80) ///< Terminal Risk Management Data: CDCVM bypass requested
598+
#define EMV_TRMD_BYTE4_SCA_EXEMPT (0x40) ///< Terminal Risk Management Data: SCA exempt
599+
#define EMV_TRMD_BYTE4_RFU (0x3F) ///< Terminal Risk Management Data: RFU
600+
561601
// Terminal Transaction Qualifiers (field 9F66) byte 1
562602
// See EMV Contactless Book A v2.10, 5.7, Table 5-4
563603
// See EMV Contactless Book C-3 v2.10, Annex A.2

src/emv_strings.c

+138
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,15 @@ int emv_tlv_get_info(
679679
info->format = EMV_FORMAT_AN;
680680
return emv_tlv_value_get_string(tlv, info->format, 8, value_str, value_str_len);
681681

682+
case EMV_TAG_9F1D_TERMINAL_RISK_MANAGEMENT_DATA:
683+
info->tag_name = "Terminal Risk Management Data";
684+
info->tag_desc =
685+
"Application-specific value used by the contactless card or "
686+
"payment device for risk management purposes. All RFU bits "
687+
"must be set to zero.";
688+
info->format = EMV_FORMAT_B;
689+
return emv_terminal_risk_management_data_get_string_list(tlv->value, tlv->length, value_str, value_str_len);
690+
682691
case EMV_TAG_9F1E_IFD_SERIAL_NUMBER:
683692
info->tag_name = "Interface Device (IFD) Serial Number";
684693
info->tag_desc =
@@ -4433,6 +4442,135 @@ int emv_iad_get_string_list(
44334442
}
44344443
}
44354444

4445+
int emv_terminal_risk_management_data_get_string_list(
4446+
const uint8_t* trmd,
4447+
size_t trmd_len,
4448+
char* str,
4449+
size_t str_len
4450+
)
4451+
{
4452+
struct str_itr_t itr;
4453+
4454+
if (!trmd || !trmd_len) {
4455+
return -1;
4456+
}
4457+
4458+
if (!str || !str_len) {
4459+
// Caller didn't want the value string
4460+
return 0;
4461+
}
4462+
4463+
if (trmd_len != 8) {
4464+
// Terminal Risk Management Data (field 9F1D) must be 8 bytes
4465+
return 1;
4466+
}
4467+
4468+
emv_str_list_init(&itr, str, str_len);
4469+
4470+
// Terminal Risk Management Data (field 9F1D) byte 1
4471+
// See EMV Contactless Book C-2 v2.11, Annex A.1.161
4472+
// See M/Chip Requirements for Contact and Contactless, 28 November 2023, Chapter 5, Terminal Risk Management Data
4473+
if (trmd[0] & EMV_TRMD_BYTE1_RESTART_SUPPORTED) {
4474+
// NOTE: EMV Contactless Book C-8 v1.1, Annex A.1.129 does not define
4475+
// this bit and it avoids confusion if no string is provided when this
4476+
// bit is unset
4477+
emv_str_list_add(&itr, "Restart supported");
4478+
}
4479+
if (trmd[0] & EMV_TRMD_BYTE1_ENCIPHERED_PIN_ONLINE_CONTACTLESS) {
4480+
emv_str_list_add(&itr, "Enciphered PIN verified online (Contactless)");
4481+
}
4482+
if (trmd[0] & EMV_TRMD_BYTE1_SIGNATURE_CONTACTLESS) {
4483+
emv_str_list_add(&itr, "Signature (paper) (Contactless)");
4484+
}
4485+
if (trmd[0] & EMV_TRMD_BYTE1_ENCIPHERED_PIN_OFFLINE_CONTACTLESS) {
4486+
emv_str_list_add(&itr, "Enciphered PIN verification performed by ICC (Contactless)");
4487+
}
4488+
if (trmd[0] & EMV_TRMD_BYTE1_NO_CVM_CONTACTLESS) {
4489+
emv_str_list_add(&itr, "No CVM required (Contactless)");
4490+
}
4491+
if (trmd[0] & EMV_TRMD_BYTE1_CDCVM_CONTACTLESS) {
4492+
emv_str_list_add(&itr, "CDCVM (Contactless)");
4493+
}
4494+
if (trmd[0] & EMV_TRMD_BYTE1_PLAINTEXT_PIN_OFFLINE_CONTACTLESS) {
4495+
emv_str_list_add(&itr, "Plaintext PIN verification performed by ICC (Contactless)");
4496+
}
4497+
if (trmd[0] & EMV_TRMD_BYTE1_PRESENT_AND_HOLD_SUPPORTED) {
4498+
// NOTE: EMV Contactless Book C-8 v1.1, Annex A.1.129 does not define
4499+
// this bit and it avoids confusion if no string is provided when this
4500+
// bit is unset
4501+
emv_str_list_add(&itr, "Present and Hold supported");
4502+
}
4503+
4504+
// Terminal Risk Management Data (field 9F1D) byte 2
4505+
// See EMV Contactless Book C-2 v2.11, Annex A.1.161
4506+
// See EMV Contactless Book C-8 v1.1, Annex A.1.129
4507+
// See M/Chip Requirements for Contact and Contactless, 28 November 2023, Chapter 5, Terminal Risk Management Data
4508+
if (trmd[1] & EMV_TRMD_BYTE2_CVM_LIMIT_EXCEEDED) {
4509+
emv_str_list_add(&itr, "CVM Limit exceeded");
4510+
}
4511+
if (trmd[1] & EMV_TRMD_BYTE2_ENCIPHERED_PIN_ONLINE_CONTACT) {
4512+
emv_str_list_add(&itr, "Enciphered PIN verified online (Contact)");
4513+
}
4514+
if (trmd[1] & EMV_TRMD_BYTE2_SIGNATURE_CONTACT) {
4515+
emv_str_list_add(&itr, "Signature (paper) (Contact)");
4516+
}
4517+
if (trmd[1] & EMV_TRMD_BYTE2_ENCIPHERED_PIN_OFFLINE_CONTACT) {
4518+
emv_str_list_add(&itr, "Enciphered PIN verification performed by ICC (Contact)");
4519+
}
4520+
if (trmd[1] & EMV_TRMD_BYTE2_NO_CVM_CONTACT) {
4521+
emv_str_list_add(&itr, "No CVM required (Contact)");
4522+
}
4523+
if (trmd[1] & EMV_TRMD_BYTE2_CDCVM_CONTACT) {
4524+
emv_str_list_add(&itr, "CDCVM (Contact)");
4525+
}
4526+
if (trmd[1] & EMV_TRMD_BYTE2_PLAINTEXT_PIN_OFFLINE_CONTACT) {
4527+
emv_str_list_add(&itr, "Plaintext PIN verification performed by ICC (Contact)");
4528+
}
4529+
4530+
// Terminal Risk Management Data (field 9F1D) byte 3
4531+
// See EMV Contactless Book C-2 v2.11, Annex A.1.161
4532+
// See M/Chip Requirements for Contact and Contactless, 28 November 2023, Chapter 5, Terminal Risk Management Data
4533+
if (trmd[2] & EMV_TRMD_BYTE3_MAGSTRIPE_MODE_CONTACTLESS_NOT_SUPPORTED) {
4534+
// NOTE: EMV Contactless Book C-8 v1.1, Annex A.1.129 does not define
4535+
// this bit and it avoids confusion if no string is provided when this
4536+
// bit is unset
4537+
emv_str_list_add(&itr, "Mag-stripe mode contactless transactions not supported");
4538+
}
4539+
if (trmd[2] & EMV_TRMD_BYTE3_EMV_MODE_CONTACTLESS_NOT_SUPPORTED) {
4540+
// NOTE: EMV Contactless Book C-8 v1.1, Annex A.1.129 does not define
4541+
// this bit and it avoids confusion if no string is provided when this
4542+
// bit is unset
4543+
emv_str_list_add(&itr, "EMV mode contactless transactions not supported");
4544+
}
4545+
if (trmd[2] & EMV_TRMD_BYTE3_CDCVM_WITHOUT_CDA_SUPPORTED) {
4546+
// NOTE: EMV Contactless Book C-8 v1.1, Annex A.1.129 does not define
4547+
// this bit and it avoids confusion if no string is provided when this
4548+
// bit is unset
4549+
emv_str_list_add(&itr, "CDCVM without CDA supported");
4550+
}
4551+
4552+
// Terminal Risk Management Data (field 9F1D) byte 4
4553+
// See EMV Contactless Book C-2 v2.11, Annex A.1.161
4554+
// See EMV Contactless Book C-8 v1.1, Annex A.1.129
4555+
if (trmd[3] & EMV_TRMD_BYTE4_CDCVM_BYPASS_REQUESTED) {
4556+
emv_str_list_add(&itr, "CDCVM bypass requested");
4557+
}
4558+
if (trmd[3] & EMV_TRMD_BYTE4_SCA_EXEMPT) {
4559+
emv_str_list_add(&itr, "SCA exempt");
4560+
}
4561+
4562+
// Terminal Risk Management Data (field 9F1D) RFU bits
4563+
if ((trmd[1] & EMV_TRMD_BYTE2_RFU) ||
4564+
(trmd[2] & EMV_TRMD_BYTE3_RFU) ||
4565+
(trmd[3] & EMV_TRMD_BYTE4_RFU) ||
4566+
trmd[4] || trmd[5] || trmd[6] || trmd[7]
4567+
) {
4568+
emv_str_list_add(&itr, "RFU");
4569+
}
4570+
4571+
return 0;
4572+
}
4573+
44364574
int emv_ttq_get_string_list(
44374575
const uint8_t* ttq,
44384576
size_t ttq_len,

src/emv_strings.h

+16
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,22 @@ int emv_iad_get_string_list(
572572
size_t str_len
573573
);
574574

575+
/**
576+
* Stringify Terminal Risk Management Data (field 9F1D)
577+
* @note Strings in output buffer are delimited using "\n", including the last string
578+
* @param trmd Terminal Risk Management Data field. Must be 8 bytes.
579+
* @param trmd_len Length of Terminal Risk Management Data field. Must be 8 bytes.
580+
* @param str String buffer output
581+
* @param str_len Length of string buffer in bytes
582+
* @return Zero for success. Less than zero for internal error. Greater than zero for parse error.
583+
*/
584+
int emv_terminal_risk_management_data_get_string_list(
585+
const uint8_t* trmd,
586+
size_t trmd_len,
587+
char* str,
588+
size_t str_len
589+
);
590+
575591
/**
576592
* Stringify Terminal Transaction Qualifiers (field 9F66)
577593
* @note Strings in output buffer are delimited using "\n", including the last string

src/emv_tags.h

+6
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,12 @@ __BEGIN_DECLS
249249
/// @remark Also used as the Card Acceptor Terminal Identification by ISO 8583. See EMV 4.4 Book 4, Annex C, Table 40
250250
#define EMV_TAG_9F1C_TERMINAL_IDENTIFICATION (0x9F1C)
251251

252+
/// EMV tag 9F1D Terminal Risk Management Data
253+
/// @remark See EMV Contactless Book C-2 v2.11, Annex A.1.161
254+
/// @remark See EMV Contactless Book C-8 v1.1, Annex A.1.129
255+
/// @remark See M/Chip Requirements for Contact and Contactless, 28 November 2023, Chapter 5, Terminal Risk Management Data
256+
#define EMV_TAG_9F1D_TERMINAL_RISK_MANAGEMENT_DATA (0x9F1D)
257+
252258
/// EMV tag 9F1E Interface Device (IFD) Serial Number
253259
#define EMV_TAG_9F1E_IFD_SERIAL_NUMBER (0x9F1E)
254260

tools/CMakeLists.txt

+41
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,47 @@ if(TARGET emv-decode AND BUILD_TESTING)
541541
PASS_REGULAR_EXPRESSION ${emv_decode_IAD_test5_regex}
542542
)
543543

544+
add_test(NAME emv_decode_9F1D_test1
545+
COMMAND emv-decode --terminal-risk-management-data 6C7A800000000000
546+
--mcc-json ${MCC_JSON_BUILD_PATH}
547+
)
548+
string(CONCAT emv_decode_9F1D_test1_regex
549+
"^Enciphered PIN verified online \\(Contactless\\)[\r\n]"
550+
"Signature \\(paper\\) \\(Contactless\\)[\r\n]"
551+
"No CVM required \\(Contactless\\)[\r\n]"
552+
"CDCVM \\(Contactless\\)[\r\n]"
553+
"Enciphered PIN verified online \\(Contact\\)[\r\n]"
554+
"Signature \\(paper\\) \\(Contact\\)[\r\n]"
555+
"Enciphered PIN verification performed by ICC \\(Contact\\)[\r\n]"
556+
"No CVM required \\(Contact\\)[\r\n]"
557+
"Plaintext PIN verification performed by ICC \\(Contact\\)[\r\n]"
558+
"Mag-stripe mode contactless transactions not supported[\r\n]"
559+
)
560+
set_tests_properties(emv_decode_9F1D_test1
561+
PROPERTIES
562+
PASS_REGULAR_EXPRESSION ${emv_decode_9F1D_test1_regex}
563+
)
564+
565+
add_test(NAME emv_decode_9F1D_test2
566+
COMMAND emv-decode --9F1D 4C7A800000000000
567+
--mcc-json ${MCC_JSON_BUILD_PATH}
568+
)
569+
string(CONCAT emv_decode_9F1D_test2_regex
570+
"^Enciphered PIN verified online \\(Contactless\\)[\r\n]"
571+
"No CVM required \\(Contactless\\)[\r\n]"
572+
"CDCVM \\(Contactless\\)[\r\n]"
573+
"Enciphered PIN verified online \\(Contact\\)[\r\n]"
574+
"Signature \\(paper\\) \\(Contact\\)[\r\n]"
575+
"Enciphered PIN verification performed by ICC \\(Contact\\)[\r\n]"
576+
"No CVM required \\(Contact\\)[\r\n]"
577+
"Plaintext PIN verification performed by ICC \\(Contact\\)[\r\n]"
578+
"Mag-stripe mode contactless transactions not supported[\r\n]"
579+
)
580+
set_tests_properties(emv_decode_9F1D_test2
581+
PROPERTIES
582+
PASS_REGULAR_EXPRESSION ${emv_decode_9F1D_test2_regex}
583+
)
584+
544585
if(WIN32)
545586
# Ensure that tests can find required DLLs (if any)
546587
# Assume that the PATH already contains the compiler runtime DLLs

tools/emv-decode.c

+22
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ enum emv_decode_mode_t {
6868
EMV_DECODE_MASTERCARD_THIRD_PARTY_DATA,
6969
EMV_DECODE_FFI,
7070
EMV_DECODE_AMEX_ENH_CL_READER_CAPS,
71+
EMV_DECODE_TERMINAL_RISK_MANAGEMENT_DATA,
7172
EMV_DECODE_ISO3166_1,
7273
EMV_DECODE_ISO4217,
7374
EMV_DECODE_ISO639,
@@ -135,6 +136,8 @@ static struct argp_option argp_options[] = {
135136
{ "mastercard-third-party-data", EMV_DECODE_MASTERCARD_THIRD_PARTY_DATA, NULL, 0, "Decode Mastercard Third Party Data (field 9F6E)" },
136137
{ "visa-ffi", EMV_DECODE_FFI, NULL, 0, "Decode Visa Form Factor Indicator (field 9F6E)" },
137138
{ "amex-enh-cl-reader-caps", EMV_DECODE_AMEX_ENH_CL_READER_CAPS, NULL, 0, "Decode Amex Enhanced Contactless Reader Capabilities (field 9F6E)" },
139+
{ "terminal-risk-management-data", EMV_DECODE_TERMINAL_RISK_MANAGEMENT_DATA, NULL, 0, "Decode Terminal Risk Management Data (field 9F1D)" },
140+
{ "9F1D", EMV_DECODE_TERMINAL_RISK_MANAGEMENT_DATA, NULL, OPTION_ALIAS },
138141

139142
{ NULL, 0, NULL, 0, "Other:", 4 },
140143
{ "country", EMV_DECODE_ISO3166_1, NULL, 0, "Lookup country name by ISO 3166-1 alpha-2, alpha-3 or numeric code" },
@@ -255,6 +258,7 @@ static error_t argp_parser_helper(int key, char* arg, struct argp_state* state)
255258
case EMV_DECODE_MASTERCARD_THIRD_PARTY_DATA:
256259
case EMV_DECODE_FFI:
257260
case EMV_DECODE_AMEX_ENH_CL_READER_CAPS:
261+
case EMV_DECODE_TERMINAL_RISK_MANAGEMENT_DATA:
258262
case EMV_DECODE_ISO3166_1:
259263
case EMV_DECODE_ISO4217:
260264
case EMV_DECODE_ISO639:
@@ -739,6 +743,24 @@ int main(int argc, char** argv)
739743
break;
740744
}
741745

746+
case EMV_DECODE_TERMINAL_RISK_MANAGEMENT_DATA: {
747+
char str[2048];
748+
749+
if (data_len != 8) {
750+
fprintf(stderr, "Terminal Risk Management Data (field 9F1D) must be exactly 8 bytes\n");
751+
break;
752+
}
753+
754+
r = emv_terminal_risk_management_data_get_string_list(data, data_len, str, sizeof(str));
755+
if (r) {
756+
fprintf(stderr, "Failed to parse Terminal Risk Management Data (field 9F1D)\n");
757+
break;
758+
}
759+
printf("%s", str); // No \n required for string list
760+
761+
break;
762+
}
763+
742764
case EMV_DECODE_ISO3166_1: {
743765
const char* country;
744766

0 commit comments

Comments
 (0)