IBM Crypto Education Community - Group home

REXX Sample: VISA CVN 18 Support

  
/* 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 ;