IBM Crypto Education Community

IBM Crypto Education Community

IBM Crypto Education Community

Join the IBM Crypto Education community to explore and understand IBM cryptography technology. This community is operated and maintained by the IBM Crypto Development team.

 View Only

REXX Sample: VISA CVN 18 Support

By Anna Deng posted Tue February 09, 2021 09:10 AM

  
/* 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 ;
0 comments
67 views

Permalink