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: CSNBSYE GCM encryption mode using AES CIPHER protected key

By Eysha Shirrine Powers posted Wed March 25, 2020 05:30 PM

  

/* Rexx */

/* --------------------------------------------------------------- */
/* Symmetric Key Encryption/Decryption (CSNBSYE/CSNBSYD) using     */
/*   variable-length AES protected key                             */
/*                                                                 */
/* - call Key Token Build2 (CSNBKTB2) to build variable-length     */
/*     AES CIPHER skeleton tokens that allow rewrapping with       */
/*     CPACF protected key                                         */
/* - use skeleton tokens as inputs to Key Generate2 (CSNBKGN2)     */
/*     to generate a pair of encrypted AES CIPHER tokens;          */
/*     one for use in encryption, the other for use in decryption  */
/* - add generated keys to the CKDS                                */
/* - use keys in SYE/SYD                                           */
/*                                                                 */
/* To use variable-length AES CIPHER key tokens in protected key   */
/* operations requires ICSF HCR77C1 and CEX6C.                     */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for detailed        */
/*   information on the callable services used in this sample.     */
/* --------------------------------------------------------------- */

SIGNAL ON NOVALUE ;


/*---------------------------------------------------*/
/* Build a skeleton variable-length AES CIPHER token */
/* for encryption only.                              */
/*---------------------------------------------------*/
KTB2_rule_array_count = '00000006'x ;
KTB2_rule_array = 'AES     ' ||,
                  'CIPHER  ' ||,
                  'INTERNAL' ||,
                  'ENCRYPT ' ||,
                  'GCM     ' ||,
                  'XPRTCPAC' ; /* required for protected key */
CALL KTB2 ;

/* save skeleton token for use in KGN2 */
KGN2_genkey_id1 = KTB2_skeleton_token ;

/*---------------------------------------------------*/
/* Build a skeleton variable-length AES CIPHER token */
/* for decryption only.                              */
/*---------------------------------------------------*/
KTB2_rule_array_count = '00000006'x ;
KTB2_rule_array = 'AES     ' ||,
                  'CIPHER  ' ||,
                  'INTERNAL' ||,
                  'DECRYPT ' ||,
                  'GCM     ' ||,
                  'XPRTCPAC' ; /* required for protected key */
CALL KTB2 ;

/* save skeleton token for use in KGN2 */
KGN2_genkey_id2 = KTB2_skeleton_token ;


/*---------------------------------------------------*/
/* Use skeleton tokens as inputs to KGN2 to generate */
/* a pair of AES CIPHER keys that can be used in     */
/* protected-key CPACF encryption and decryption.    */
/*---------------------------------------------------*/
KGN2_rule_array_count = '00000002'x ;
KGN2_rule_array       = 'AES     ' ||,
                        'OPOP    ' ;
KGN2_clear_key_bit_length = d2c(256,4) ;
KGN2_key_type_1 = 'TOKEN   ' ;
KGN2_key_type_2 = 'TOKEN   ' ;
KGN2_genkey_id1_length = d2c(900,4) ;
KGN2_genkey_id1 = left(KGN2_genkey_id1,c2d(KGN2_genkey_id1_length));
KGN2_genkey_id2_length = d2c(900,4) ;
KGN2_genkey_id2 = left(KGN2_genkey_id2,c2d(KGN2_genkey_id2_length));

CALL KGN2 ;


/* write generated keys to CKDS */
KRC2_key_label = left('SAMPLE.AES.CIPHER.GCM.ENCRYPT',64) ;
KRC2_key_token_length = KGN2_genkey_id1_length ;
KRC2_key_token        = KGN2_genkey_id1 ;
CALL KRC2 ;

KRC2_key_label = left('SAMPLE.AES.CIPHER.GCM.DECRYPT',64) ;
KRC2_key_token_length = KGN2_genkey_id2_length ;
KRC2_key_token        = KGN2_genkey_id2 ;
CALL KRC2 ;


/* Use generated key in symmetric encryption */
SYE_rule_array_count      = '00000004'x ;
SYE_rule_array            = 'AES     ' ||,
                            'GCM     ' ||,
                            'KEYIDENT' ||,
                            'ONLY    ' ;
SYE_key_id_length         = '00000040'x ;
SYE_key_id                = left('SAMPLE.AES.CIPHER.GCM.ENCRYPT',64) ;
SYE_block_size            = '00000010'x ;
SYE_initial_vector_length = '00000010'x ;
SYE_initial_vector        = '8EBFFE2B973B3121D3858699CB26AAC7'x ;
SYE_clear_text_length     = '00000010'x ;
SYE_clear_text            = '0123456789ABCDEF';
CALL SYE ;

/* Use generated key in symmetric decryption */
SYD_key_id_length         = '00000040'x ;
SYD_key_id                = left('SAMPLE.AES.CIPHER.GCM.DECRYPT',64) ;
CALL SYD ;


EXIT ;

/*-----------------------------------------------------------------*/
/* Key Token Build2                                                */
/*-----------------------------------------------------------------*/
KTB2:

/* initialize parameter list */
KTB2_rc = 'FFFFFFFF'x ;
KTB2_rs = 'FFFFFFFF'x ;

exit_data_length = '00000000'x ;

exit_data = '' ;
KTB2_clear_key_bit_length = '00000000'x ;
KTB2_clear_key_value      = '' ;
KTB2_key_name_length = '00000000'x ;
KTB2_key_name        = '' ;
KTB2_user_assoc_data_length = '00000000'x ;
KTB2_user_assoc_data        = '' ;
KTB2_token_data_length = '00000000'x ;
KTB2_token_data        = '' ;
KTB2_service_data_length = '00000000'x ;
KTB2_service_data        = '' ;
KTB2_skeleton_token_length = d2c(725,4) ;
KTB2_skeleton_token        = d2c(0,725) ;

/* call CSNBKTB2 */
ADDRESS LINKPGM 'CSNBKTB2' ,
                'KTB2_rc' ,
                'KTB2_rs' ,
                'exit_data_length' ,
                'exit_data' ,
                'KTB2_rule_array_count' ,
                'KTB2_rule_array' ,
                'KTB2_clear_key_bit_length' ,
                'KTB2_clear_key_value' ,
                'KTB2_key_name_length' ,
                'KTB2_key_name' ,
                'KTB2_user_assoc_data_length' ,
                'KTB2_user_assoc_data' ,
                'KTB2_token_data_length' ,
                'KTB2_token_data' ,
                'KTB2_service_data_length' ,
                'KTB2_service_data' ,
                'KTB2_skeleton_token_length' ,
                'KTB2_skeleton_token' ;

IF (KTB2_rc /= '00000000'x) THEN
 DO ;
  SAY 'KTB2 failed: rc =' c2x(KTB2_rc) 'rs =' c2x(KTB2_rs) ;
  EXIT ;
 END ;
ELSE
 DO ;
  SAY 'KTB2: rc =' c2x(KTB2_rc) 'rs =' c2x(KTB2_rs) ;
  KTB2_skeleton_token = ,
     substr(KTB2_skeleton_token,1,c2d(KTB2_skeleton_token_length)) ;
  CALL PRINTBLK c2x(KTB2_skeleton_token), 64 ;
 END ;

RETURN ;


/* --------------------------------------------------------------- */
/* Key Generate2                                                   */
/* --------------------------------------------------------------- */
KGN2:

/* initialize parameter list */
KGN2_rc = 'FFFFFFFF'x ;
KGN2_rs = 'FFFFFFFF'x ;

exit_data_length = '00000000'x ;

exit_data = '' ;
KGN2_key_name_1_length = '00000000'x ;
KGN2_key_name_1        = '' ;
KGN2_key_name_2_length = '00000000'x ;
KGN2_key_name_2        = '' ;
KGN2_user_assoc_data_1_length = '00000000'x ;
KGN2_user_assoc_data_1        = '' ;
KGN2_user_assoc_data_2_length = '00000000'x ;
KGN2_user_assoc_data_2        = '' ;
KGN2_KEK_id1_length = '00000000'x ;
KGN2_KEK_id1        = '' ;
KGN2_KEK_id2_length = '00000000'x ;
KGN2_KEK_id2        = '' ;

/* call CSNBKGN2 */
ADDRESS LINKPGM 'CSNBKGN2' ,
                'KGN2_rc' ,
                'KGN2_rs' ,
                'exit_data_length' ,
                'exit_data' ,
                'KGN2_rule_array_count' ,
                'KGN2_rule_array' ,
                'KGN2_clear_key_bit_length' ,
                'KGN2_key_type_1' ,
                'KGN2_key_type_2' ,
                'KGN2_key_name_1_length' ,
                'KGN2_key_name_1' ,
                'KGN2_key_name_2_length' ,
                'KGN2_key_name_2' ,
                'KGN2_user_assoc_data_1_length' ,
                'KGN2_user_assoc_data_1' ,
                'KGN2_user_assoc_data_2_length' ,
                'KGN2_user_assoc_data_2' ,
                'KGN2_KEK_id1_length' ,
                'KGN2_KEK_id1' ,
                'KGN2_KEK_id2_length' ,
                'KGN2_KEK_id2' ,
                'KGN2_genkey_id1_length' ,
                'KGN2_genkey_id1' ,
                'KGN2_genkey_id2_length' ,
                'KGN2_genkey_id2' ;

IF (KGN2_rc /= '00000000'x) THEN
 DO ;
  SAY 'KGN2: rc =' c2x(KGN2_rc) 'rs =' c2x(KGN2_rs) ;
  EXIT ;
 END ;
ELSE
 DO ;
  SAY 'KGN2: rc =' c2x(KGN2_rc) 'rs =' c2x(KGN2_rs) ;
  /* generated key identifier 1 */
  KGN2_genkey_id1 = ,
     substr(KGN2_genkey_id1, 1, c2d(KGN2_genkey_id1_length)) ;
  SAY 'KGN2 generated key 1 length:' c2x(KGN2_genkey_id1_length) ;
  SAY 'KGN2 generated key 1:' ;
  CALL PRINTBLK c2x(KGN2_genkey_id1), 64 ;

  /* generated key identifier 2 */
  KGN2_genkey_id2 = ,
     substr(KGN2_genkey_id2, 1, c2d(KGN2_genkey_id2_length)) ;
  SAY 'KGN2 generated key 2 length:' c2x(KGN2_genkey_id2_length) ;
  SAY 'KGN2 generated key 2:' ;
  CALL PRINTBLK c2x(KGN2_genkey_id2), 64 ;
 END ;

RETURN ;


/*-------------------------------------------------------------------*/
/* Symmetric Key Encipher                                            */
/*-------------------------------------------------------------------*/
SYE:

/* initialize parameter list */
SYE_rc                 = 'FFFFFFFF'x ;
SYE_rs                 = 'FFFFFFFF'x ;

exit_data_length       = '00000000'x ;

exit_data              = '' ;
SYE_key_parms_length   = '0000000C'x ;
SYE_key_parms          = copies('00'x,c2d(SYE_key_parms_length)) ;
SYE_chain_data_length  = '00000040'x ;
SYE_chain_data         = copies('00'x,c2d(SYE_chain_data_length)) ;
SYE_cipher_text_length = SYE_clear_text_length ;
SYE_cipher_text        = copies('00'x,c2d(SYE_cipher_text_length)) ;
SYE_opt_data_length    = '00000000'x ;
SYE_opt_data           = '' ;

/* call CSNBSYE */
ADDRESS LINKPGM 'CSNBSYE' ,
                'SYE_rc' ,
                'SYE_rs' ,
                'exit_data_length' ,
                'exit_data' ,
                'SYE_rule_array_count' ,
                'SYE_rule_array' ,
                'SYE_key_id_length' ,
                'SYE_key_id' ,
                'SYE_key_parms_length' ,
                'SYE_key_parms' ,
                'SYE_block_size' ,
                'SYE_initial_vector_length' ,
                'SYE_initial_vector' ,
                'SYE_chain_data_length' ,
                'SYE_chain_data' ,
                'SYE_clear_text_length' ,
                'SYE_clear_text' ,
                'SYE_cipher_text_length' ,
                'SYE_cipher_text' ,
                'SYE_opt_data_length' ,
                'SYE_opt_data' ;

IF (SYE_rc /= '00000000'x) THEN
 DO ;
  SAY 'SYE failed: rc =' c2x(SYE_rc) 'rs =' c2x(SYE_rs) ;
  EXIT ;
 END ;
ELSE
 DO ;
  SAY 'SYE cipher text length:' c2x(SYE_cipher_text_length) ;
  SAY 'SYE cipher text:' c2x(SYE_cipher_text) ;
 END ;

RETURN ;


/*-------------------------------------------------------------------*/
/* Symmetric Key Decipher                                            */
/*-------------------------------------------------------------------*/
SYD:

/* initialize parameter list */
SYD_rc                    = 'FFFFFFFF'x ;
SYD_rs                    = 'FFFFFFFF'x ;

exit_data_length          = '00000000'x ;

exit_data                 = '' ;
SYD_rule_array_count      = SYE_rule_array_count ;
SYD_rule_array            = SYE_rule_array ;
SYD_key_parms_length      = SYE_key_parms_length ;
SYD_key_parms             = SYE_key_parms ;
SYD_block_size            = SYE_block_size ;
SYD_initial_vector_length = SYE_initial_vector_length ;
SYD_initial_vector        = SYE_initial_vector ;
SYD_chain_data_length     = '00000040'x ;
SYD_chain_data            = copies('00'x,c2d(SYD_chain_data_length)) ;
SYD_cipher_text_length    = SYE_cipher_text_length ;
SYD_cipher_text           = SYE_cipher_text ;
SYD_clear_text_length     = SYD_cipher_text_length ;
SYD_clear_text            = copies('00'x,c2d(SYD_clear_text_length)) ;
SYD_opt_data_length       = SYE_opt_data_length ;
SYD_opt_data              = SYE_opt_data ;

/* call CSNBSYD */
ADDRESS LINKPGM 'CSNBSYD' ,
                'SYD_rc' ,
                'SYD_rs' ,
                'exit_data_length' ,
                'exit_data' ,
                'SYD_rule_array_count' ,
                'SYD_rule_array' ,
                'SYD_key_id_length' ,
                'SYD_key_id' ,
                'SYD_key_parms_length' ,
                'SYD_key_parms' ,
                'SYD_block_size' ,
                'SYD_initial_vector_length' ,
                'SYD_initial_vector' ,
                'SYD_chain_data_length' ,
                'SYD_chain_data' ,
                'SYD_cipher_text_length' ,
                'SYD_cipher_text' ,
                'SYD_clear_text_length' ,
                'SYD_clear_text' ,
                'SYD_opt_data_length' ,
                'SYD_opt_data' ;

IF (SYD_rc /= '00000000'x) THEN
  SAY 'SYD failed: rc =' c2x(SYD_rc) 'rs =' c2x(SYD_rs) ;
ELSE
 DO ;
  SAY 'SYD clear text length:' c2x(SYD_clear_text_length) ;
  SAY 'SYD clear text:' SYD_clear_text ;
  IF SYD_clear_text = SYE_clear_text THEN
    SAY '***** DECIPHERED TEXT MATCHES CLEAR TEXT *****' ;
 END ;

RETURN ;


/*-------------------------------------------------------------------*/
/* Key Record Create2                                                */
/*-------------------------------------------------------------------*/
KRC2:

/* initialize parameter list */
KRC2_rc               = 'FFFFFFFF'x ;
KRC2_rs               = 'FFFFFFFF'x ;

exit_data_length      = '00000000'x ;\

exit_data             = '' ;
KRC2_rule_array_count = '00000000'x ;
KRC2_rule_array       = '' ;

/* call CSNBKRC2 */
ADDRESS LINKPGM 'CSNBKRC2' ,
                'KRC2_rc' ,
                'KRC2_rs' ,
                'exit_data_length' ,
                'exit_data' ,
                'KRC2_rule_array_count' ,
                'KRC2_rule_array' ,
                'KRC2_key_label' ,
                'KRC2_key_token_length' ,
                'KRC2_key_token' ;

If (KRC2_rc /= '00000000'x) THEN
 DO ;
  SAY 'KRC2 failed: rc =' c2x(KRC2_rc) 'rs =' c2x(KRC2_rs) ;
  EXIT ;
 END ;

RETURN ;


/* --------------------------------------------------------------- */
/* PRINTBLK                                                        */
/*                                                                 */
/* Print hex data in specified chunks.                             */
/* --------------------------------------------------------------- */
PRINTBLK:
arg data, max ;

/* The maximum length of an output line */
line_length = max ;
data_length = LENGTH(data) ;
num_lines = data_length % line_length ;

/* Parse the data */
IF data_length // line_length <> 0 THEN num_lines = num_lines + 1 ;
index = 1 ;
DO num_lines ;
  SAY substr(data,index,line_length) ;
  index = index + line_length ;
END ;

RETURN ;


/* --------------------------------------------------------------- */
/* Debug                                                           */
/* --------------------------------------------------------------- */
NOVALUE:
Say "Condition NOVALUE was raised." ;
Say CONDITION("D") "variable was not initialized." ;
Say SOURCELINE(sigl) ;
EXIT ;

0 comments
14 views

Permalink