/* REXX */
/* ----------------------------------------------------------------- */
/* This sample will demonstrate how to combine symmetric */
/* cryptographic key services CSNBDCM, CSNBDSK, and CSNBGIM with the */
/* EMV transaction service CSNBEAC to support the use of VISA CVN 18 */
/* cryptograms. */
/* */
/* To create the Master Derivation Key (MDK): */
/* 1) Call CSNBGIM to create the MDK, type DKYGENKY DMAC DKYL1. */
/* */
/* To create the Unique DEA Key (UDK): */
/* 2a) Pass the MDK into CSNBDCM to create the UDK, type DKYGENKY */
/* DMAC DKYL0. */
/* */
/* To derive the Application Cryptogram session key: */
/* 2b) Pass the UDK into CSNBDSK to derive the session key, type MAC.*/
/* 2) Pass the MDK into CSNBDSK to derive the session key, type MAC.*/
/* This will not create a UDK. This step is commented out in the */
/* sample below. */
/* */
/* To generate the Authorization Request Cryptogram (ARQC): */
/* 3) Pass the session key into CSNBMGN. This will output the ARQC, */
/* type MAC. */
/* */
/* To generate the ARPC and verify the ARQC: */
/* 4) Pass the MDK and ARQC into CSNBEAC. This service */
/* verifies the ARQC and generates the Authorization Response */
/* Cryptogram (ARPC). */
/* */
/* Please refer to the Visa Integrated Circuit Card Specification */
/* V1.6 for more information regarding CVN 18. */
/* */
/* See the ICSF Application Programmer's Guide (APG) for more */
/* information on the callable services used in this sample. */
/* */
/* CVN 18 support is available with OA58880 on ICSF HCR77D1. */
/* ----------------------------------------------------------------- */
/* expected results */
ExpRC = '00000000'x ;
ExpRS = '00000000'x ;
/* Labels of keys to be generated */
MDK_label = LEFT('MDK.DKYGENKY.DMAC.DKYL1.ISSUER.AC',64);
CSU_PAD_ON = '80800000'x;
CSU_PAD_OFF = '00800000'x;
/* ----------------------------------------------------------------- */
/* Replace values as needed */
/* ----------------------------------------------------------------- */
CSU_Pad = CSU_PAD_ON;
optional_PAD_length = D2C(8,4);
optional_PAD = 'OPTIONAL'; /* Proprietary Authentication Data */
PAN = '0000000000000000'x; /* Primary Account Number */
PAN_seq_number = '01'x ; /* PAN Sequence Number */
auth_amt = '000000012300'x ; /* Authorized Amount */
cashback_amt = '000000000000'x ; /* Cashback Amount */
term_cntry = '0000'x ; /* Terminal country code */
TVR = '0000000000'x ; /* Terminal verification results */
cur_cd = '0000'x ; /* Cryptogram currency code */
tran_dt = '010101'x ; /* Terminal transaction date */
tran_typ = '00'x ; /* Cryptogram transaction type */
unp_nbr = '9BADBADB'x; /* Unpredictable number */
AIP = '0000'x ; /* Application Interchange Profile*/
ATC = '0000'x ; /* Application Transaction Counter*/
IAD = '00000000000000'x; /* Issuer Application Data */
Cryptogram_info = auth_amt || cashback_amt || term_cntry || TVR ||,
cur_cd ||tran_dt || tran_typ || unp_nbr || AIP ||,
ATC || IAD ;
/* ----------------------------------------------------------------- */
/* 1) CSNBGIM - Generate an Issuer Master Application Cryptogram */
/* Key (AC). The Master Derivation Key (MDK) will be a */
/* DKYGENKY DMAC DKYL1 key token, added to the CKDS. */
/* ----------------------------------------------------------------- */
GIM_rc = 'FFFFFFFF'x ;
GIM_rs = 'FFFFFFFF'x ;
GIM_exit_data_length = '00000000'x ;
GIM_exit_data = '' ;
GIM_rule_array_count = D2C(4,4) ;
GIM_rule_array = 'TDES '||'VISA '||'AC '||'CVN18 ';
GIM_issuer_MK_length = D2C(64,4) ;
GIM_issuer_MK = MDK_label;
GIM_issuer_ARPC_MK_length = D2C(0,4) ;
GIM_issuer_ARPC_MK = '' ;
GIM_transport_key_length = D2C(0,4);
GIM_transport_key = '';
GIM_reserved1_length = D2C(0,4) ;
GIM_reserved2_length = D2C(0,4) ;
ADDRESS LINKPGM 'CSNBGIM' ,
'GIM_rc' 'GIM_rs' ,
'GIM_exit_data_length' 'GIM_exit_data' ,
'GIM_rule_array_count' 'GIM_rule_array' ,
'GIM_issuer_MK_length' 'GIM_issuer_MK' ,
'GIM_issuer_ARPC_MK_length' 'GIM_issuer_ARPC_MK' ,
'GIM_transport_key_length' 'GIM_transport_key' ,
'GIM_reserved1_length' 'GIM_reserved1' ,
'GIM_reserved2_length' 'GIM_reserved2' ;
IF (GIM_rc /= ExpRC| GIM_rs /= ExpRS) THEn
DO;
SAY 'GIM failed: rc =' C2X(GIM_rc) 'rs =' C2X(GIM_rs);
EXIT;
END;
/* --------------------------------------------------------------- */
/* 2a) CSNBDCM - Generate an ICC Master Application Cryptogram Key */
/* (AC). The Unique DEA Key will be a DKYGENKY DMAC */
/* DKYL0 token. */
/* --------------------------------------------------------------- */
DCM_rc = 'FFFFFFFF'x ;
DCM_rs = 'FFFFFFFF'x ;
DCM_exit_data_length = '00000000'x ;
DCM_exit_data = '' ;
DCM_rule_array_count = D2C(6,4) ;
DCM_rule_array = 'TDES '||'VISA '||'AC '||,
'APPANSEQ'||'CVN18 '||'PAN-16 ';
DCM_issuer_MK_length = D2C(64,4) ;
DCM_issuer_MK = MDK_label ;
DCM_icc_MK_length = D2C(64,4) ;
DCM_icc_MK = D2C(0,64) ;
DCM_xport_key_length = D2C(0,4) ;
DCM_xport_key = '';
DCM_pan_length = D2C(10,4) ;
DCM_pan = RIGHT(PAN,10,'00'x);
DCM_pan_seq_number = PAN_seq_number ;
DCM_reserved1_length = D2C(0,4) ;
DCM_reserved1 = '';
DCM_reserved2_length = D2C(0,4) ;
DCM_reserved2 = '';
ADDRESS LINKPGM 'CSNBDCM' ,
'DCM_rc' 'DCM_rs' ,
'DCM_exit_data_length' 'DCM_exit_data' ,
'DCM_rule_array_count' 'DCM_rule_array' ,
'DCM_issuer_MK_length' 'DCM_issuer_MK' ,
'DCM_icc_MK_length' 'DCM_icc_MK' ,
'DCM_xport_key_length' 'DCM_xport_key' ,
'DCM_pan_length' 'DCM_pan' ,
'DCM_pan_seq_number' ,
'DCM_reserved1_length' 'DCM_reserved1' ,
'DCM_reserved2_length' 'DCM_reserved2' ;
IF (DCM_rc /= ExpRC | DCM_rs /= ExpRS) THEN
DO ;
SAY 'DCM failed: rc =' c2x(DCM_rc) 'rs =' c2x(DCM_rs) ;
EXIT;
END ;
UDK_token = DCM_icc_MK;
/* --------------------------------------------------------------- */
/* 2b) CSNBDSK - Derive the AC session key, type MAC, from the UDK.*/
/* --------------------------------------------------------------- */
DSK_rc = 'FFFFFFFF'x ;
DSK_rs = 'FFFFFFFF'x ;
DSK_exit_data_length = '00000000'x ;
DSK_exit_data = '' ;
DSK_rule_array_count = D2C(6,4) ;
DSK_rule_array = 'TDES '||'VISA '||'AC '||,
'APPANSEQ'||'CVN18 '||'PAN-16 ';
DSK_master_key_length = D2C(64,4) ;
DSK_master_key = UDK_token ;
DSK_session_key_length = D2C(64,4) ;
DSK_session_key = D2C(0,64) ;
DSK_pan_length = D2C(10,4) ;
DSK_pan = RIGHT(PAN,10,'00'x);
DSK_pan_seq_number = PAN_seq_number ;
DSK_atc = ATC ;
DSK_unpredictable_number_length = D2C(4,4) ;
DSK_unpredictable_number = unp_nbr ;
DSK_reserved1_length = '00000000'x ;
DSK_reserved1 = '' ;
DSK_reserved2_length = '00000000'x ;
DSK_reserved2 = '' ;
ADDRESS LINKPGM 'CSNBDSK' ,
'DSK_rc' 'DSK_rs' ,
'DSK_exit_data_length' 'DSK_exit_data' ,
'DSK_rule_array_count' 'DSK_rule_array' ,
'DSK_master_key_length' 'DSK_master_key' ,
'DSK_session_key_length' 'DSK_session_key' ,
'DSK_pan_length' 'DSK_pan' ,
'DSK_pan_seq_number' 'DSK_atc' ,
'DSK_unpredictable_number_length' 'DSK_unpredictable_number' ,
'DSK_reserved1_length' 'DSK_reserved1' ,
'DSK_reserved2_length' 'DSK_reserved2' ;
IF (DSK_rc /= ExpRc | DSK_rs /= ExpRs) THEN
DO ;
SAY 'DSK failed: rc =' c2x(DSK_rc) 'rs =' c2x(DSK_rs) ;
EXIT;
END ;
Session_key_token = DSK_session_key;
/* --------------------------------------------------------------- */
/* 2) CSNBDSK - Derive the AC session key, type MAC, from the MDK. */
/* */
/* Comment out (2a) and (2b), and uncomment below to derive the */
/* session key without generating a UDK. */
/* --------------------------------------------------------------- */
/*
DSK_rc = 'FFFFFFFF'x ;
DSK_rs = 'FFFFFFFF'x ;
DSK_exit_data_length = '00000000'x ;
DSK_exit_data = '' ;
DSK_rule_array_count = D2C(6,4) ;
DSK_rule_array = 'TDES '||'VISA '||'AC '||,
'APPANSEQ'||'CVN18 '||'PAN-16 ';
DSK_master_key_length = D2C(64,4) ;
DSK_master_key = MDK_label ;
DSK_session_key_length = D2C(64,4) ;
DSK_session_key = D2C(0,64) ;
DSK_pan_length = D2C(10,4) ;
DSK_pan = RIGHT(PAN,10,'00'x);
DSK_pan_seq_number = PAN_seq_number ;
DSK_atc = ATC ;
DSK_unpredictable_number_length = D2C(4,4) ;
DSK_unpredictable_number = unp_nbr ;
DSK_reserved1_length = '00000000'x ;
DSK_reserved1 = '' ;
DSK_reserved2_length = '00000000'x ;
DSK_reserved2 = '' ;
ADDRESS LINKPGM 'CSNBDSK' ,
'DSK_rc' 'DSK_rs' ,
'DSK_exit_data_length' 'DSK_exit_data' ,
'DSK_rule_array_count' 'DSK_rule_array' ,
'DSK_master_key_length' 'DSK_master_key' ,
'DSK_session_key_length' 'DSK_session_key' ,
'DSK_pan_length' 'DSK_pan' ,
'DSK_pan_seq_number' 'DSK_atc' ,
'DSK_unpredictable_number_length' 'DSK_unpredictable_number' ,
'DSK_reserved1_length' 'DSK_reserved1' ,
'DSK_reserved2_length' 'DSK_reserved2' ;
IF (DSK_rc /= ExpRc | DSK_rs /= ExpRs) THEN
DO ;
SAY 'DSK failed: rc =' c2x(DSK_rc) 'rs =' c2x(DSK_rs) ;
EXIT;
END ;
Session_key_token = DSK_session_key;
*/
/*-------------------------------------------------------------------*/
/* 3) CSNBMGN - Generate the ARQC. */
/*-------------------------------------------------------------------*/
MGN_rc = 'FFFFFFFF'x ;
MGN_rs = 'FFFFFFFF'x ;
MGN_exit_data_length = '00000000'x ;
MGN_exit_data = '' ;
MGN_key_identifier = Session_key_token;
MGN_text = Cryptogram_info ;
MGN_text_length = D2C(LENGTH(MGN_text),4) ;
MGN_rule_array_count = d2c(2,4) ;
MGN_rule_array = 'EMVMACD '||'MACLEN8 ' ;
MGN_chaining_vector = copies('00'x,128) ;
MGN_mac = d2c(0,8) ;
ADDRESS LINKPGM 'CSNBMGN' ,
'MGN_rc' 'MGN_rs' ,
'MGN_exit_data_length' 'MGN_exit_data' ,
'MGN_key_identifier' ,
'MGN_text_length' 'MGN_text' ,
'MGN_rule_array_count' 'MGN_rule_array',
'MGN_chaining_vector' 'MGN_mac' ;
IF (MGN_rc /= ExpRc | MGN_rs /= ExpRs) THEN
DO ;
SAY 'MGN FAILED: rc =' c2x(MGN_rc) 'rs =' c2x(MGN_rs) ;
EXIT ;
END ;
/* Authorization Request Cryptogram (ARQC) to be verified */
ARQC = MGN_mac;
/*-------------------------------------------------------------------*/
/* 4) CSNBEAC - Verify the Authorization Request Cryptogram (ARQC) */
/* and generate the Authorization Response Cryptogram */
/* (ARPC) using the MDK and session key. */
/*-------------------------------------------------------------------*/
EAC_rc = 'FFFFFFFF'x ;
EAC_rs = 'FFFFFFFF'x ;
EAC_exit_data_length = '00000000'x ;
EAC_exit_data = '' ;
EAC_rule_array_count = D2C(6,4);
EAC_rule_array = 'TDES '||'VERGEN '||'VISA '||,
'APPANSEQ'||'CVN18 '||'PAN-16 ';
EAC_issuer_MK_length = D2C(64,4) ;
EAC_issuer_MK = MDK_label ;
EAC_issuer_ARPC_MK_length = D2C(0,4) ; /* not used with VISA */
EAC_issuer_ARPC_MK = '';
EAC_pan_length = D2C(10,4) ;
EAC_pan = RIGHT(PAN,10,'00'x);
EAC_pan_sequence_number = PAN_seq_number ;
EAC_cryptogram_info = Cryptogram_info;
EAC_cryptogram_info_length = D2C(LENGTH(EAC_cryptogram_info),4) ;
EAC_atc = ATC ;
EAC_arc_or_csu = CSU_PAD;
EAC_arqc = ARQC ;
EAC_arpc = COPIES('00'x,4) ;
EAC_unpredictable_number = unp_nbr ;
EAC_optional_data1_length = optional_PAD_length;
EAC_optional_data1 = optional_PAD ;
EAC_reserved2_length = D2C(0,4) ;
EAC_reserved2 = '' ;
address linkpgm 'CSNBEAC' ,
'EAC_rc' 'EAC_rs' ,
'EAC_exit_data_length' 'EAC_exit_data' ,
'EAC_rule_array_count' 'EAC_rule_array' ,
'EAC_issuer_MK_length' 'EAC_issuer_MK' ,
'EAC_issuer_ARPC_MK_length' 'EAC_issuer_ARPC_MK' ,
'EAC_pan_length' 'EAC_pan' ,
'EAC_pan_sequence_number' ,
'EAC_cryptogram_info_length' 'EAC_cryptogram_info' ,
'EAC_atc' 'EAC_arc_or_csu' ,
'EAC_arqc' 'EAC_arpc' ,
'EAC_unpredictable_number' ,
'EAC_optional_data1_length' 'EAC_optional_data1' ,
'EAC_reserved2_length' 'EAC_reserved2' ;
IF (EAC_rc /= ExpRC | EAC_rs /= ExpRS) then
do ;
say 'EAC failed: rc =' c2x(EAC_rc) 'rs =' c2x(EAC_rs) ;
EXIT;
end ;
SAY 'Sample ended successfully';
EXIT ;