IBM Crypto Education Community - Group home

Rexx Sample: CSNBSYE GCM encryption mode using AES CIPHER protected key

  

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