IBM Crypto Education Community - Group home

Rexx Sample: Archive a key in the CKDS

  

/* Rexx */

/* Sample: Archive a secure AES key                                  */
/*-------------------------------------------------------------------*/
/* Description:                                                      */
/*                                                                   */
/* This REXX contains samples that show how to archive an existing   */
/* key:                                                              */
/*  - Generate and store a 256-bit AES DATA key in the CKDS          */
/*  - Encrypt data using the AES key                                 */
/*  - Decrypt data using the AES key                                 */
/*  - Archive the key                                                */
/*  - Attempt to encrypt/decrypt data with archived key              */
/*                                                                   */
/* How To Run:                                                       */
/* - Execute this script from TSO                                    */
/*   (e.g. EX 'HLQ.MLD.LLQ(KEYARCH)')                                */
/*-------------------------------------------------------------------*/
signal on novalue;

/* CLEANUP labels in use for this sample */
aes_key_label = left('ICSF.KEYSAMP.AES256.KEY001',64);
krd_label = aes_key_label;
Call CSNBKRD;

/*********************************************************************/
/* Generate a 256-bit AES DATA key                                   */
/*********************************************************************/
kgn_key_form           = 'OP  ';
kgn_key_length         = 'KEYLN32 ';
kgn_key_type_1         = 'AESDATA ';
kgn_key_type_2         = '';
kgn_kek_identifier_1   = copies('00'x,64);
kgn_kek_identifier_2   = '';
kgn_generated_key_identifier_1 = copies('00'x,64);
kgn_generated_key_identifier_2 = '';
Call CSNBKGN;

say "aes secure key: " c2x(kgn_generated_key_identifier_1);

/*********************************************************************/
/* Store the key in the CKDS                                         */
/*********************************************************************/
krc2_label = aes_key_label;
krc2_token_length = '00000040'x;
krc2_token = kgn_generated_key_identifier_1;
Call CSNBKRC2;

/*********************************************************************/
/* Encrypt data using the secure key                                 */
/*********************************************************************/
sae_rule_array_count = '00000003'x;
sae_rule_array = 'AES     ' ||,
                 'PKCS-PAD' ||,
                 'KEYIDENT';
sae_key_identifier_length = '00000040'x;
sae_key_identifier = aes_key_label;
sae_init_vector_length = '00000010'x;
sae_init_vector = '11111111111111111111111111111111'x;
sae_block_size = '00000010'x;
sae_clear_text_length = '0000000B'x;
sae_clear_text = 'Secret Data';
sae_cipher_text_length = '00000010'x;
sae_cipher_text = copies('00'x, 16);
Call CSNBSAE;

encrypted_text = substr(sae_cipher_text, 1, c2d(sae_cipher_text_length));
say 'clear_text:     ' sae_clear_text;
say 'encrypted_text: ' c2x(encrypted_text);

/*********************************************************************/
/* Decrypt data using the secure key                                 */
/*********************************************************************/
sad_rule_array_count = sae_rule_array_count;
sad_rule_array = sae_rule_array;
sad_key_identifier_length = '00000040'x;
sad_key_identifier = aes_key_label;
sad_init_vector_length = sae_init_vector_length;
sad_init_vector = sae_init_vector;
sad_block_size = sae_block_size;
sad_cipher_text_length = sae_cipher_text_length;
sad_cipher_text = sae_cipher_text;
sad_clear_text_length = '00000010'x;
sad_clear_text = copies('00'x, 16);
Call CSNBSAD;

decrypted_text = substr(sad_clear_text, 1, c2d(sad_clear_text_length));
say 'decrypted_text: ' decrypted_text;

/*********************************************************************/
/* Archive the key                                                   */
/*********************************************************************/
KDMW_rule_array_count = '00000001'x;
KDMW_rule_array       = 'CKDS    ';
KDMW_label_count      = '00000001'x;
KDMW_label_list       = left(aes_key_label,72);
KDMW_metadata_list_length = '00000005'x;
KDMW_metadata_list    = '0005'x ||,          /* Length of structure  */
                        '0009'x ||,          /* Record archive flag  */
                        '01'x;               /* Turn ON the flag     */
KDMW_results_list     = copies('00'x,8);     /* 4-byte RC, 4-byte RS */
Call CSFKDMW;

/*********************************************************************/
/* Verify the key is archived                                        */
/*********************************************************************/
KDMR_rule_array_count = '00000001'x;
KDMR_rule_array       = 'CKDS    ';
KDMR_record_label     = left(aes_key_label,72);
KDMR_metadata_list_length = '00000004'x;
KDMR_metadata_list    = '0004'x ||,          /* Length of structure  */
                        '0009'x;             /* Record archive flag  */
KDMR_output_list_length = '00000005'x;
KDMR_output_list      = copies('00'x,5);
Call CSFKDMR;

output_block_length = substr(KDMR_output_list,1,2);
output_block_flag = substr(KDMR_output_list,3,1);
output_block_value = substr(KDMR_output_list,5,1);

say '';
if output_block_value = '01'x then
  say 'Key archived!';
else
  say 'Key not archived!';

/*********************************************************************/
/* Attempt to use the archived key                                   */
/*********************************************************************/
sae_clear_text_length = '0000000B'x;
sae_clear_text = 'Secret Data';
sae_cipher_text_length = '00000010'x;
sae_cipher_text = copies('00'x, 16);
say '';
say 'Attempt encryption...';
Call CSNBSAE;

say "-----------------------------------------------------------------";
say "End of Sample";
say "-----------------------------------------------------------------";

exit;

/* --------------------------------------------------------------- */
/* CSNBKGN - Key Generate                                          */
/*                                                                 */
/* Generates either one or two DES or AES keys encrypted under a   */
/* master key (internal form) or KEK (external form).              */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNBKGN:

KGN_RC = 'FFFFFFFF'x;
KGN_RS = 'FFFFFFFF'x;
KGN_exit_data_length         = '00000000'x;
KGN_exit_data                = '';

ADDRESS linkpgm "CSNBKGN",
   'KGN_RC'                          'KGN_RS'               ,
   'KGN_exit_data_length'            'KGN_exit_data'        ,
   'KGN_key_form'                    'KGN_key_length'       ,
   'KGN_key_type_1'                  'KGN_key_type_2'       ,
   'KGN_kek_identifier_1'            'KGN_kek_identifier_2' ,
   'KGN_generated_key_identifier_1'  'KGN_generated_key_identifier_2';

if (KGN_RC /= '00000000'x) Then
  do;
    say 'KGN Failed   (rc=' c2x(KGN_RC)' rs='c2x(KGN_rs)')' ;
    exit;
  end;

Return;

/* --------------------------------------------------------------- */
/* CSNBKRC2 - Key Record Create2                                   */
/*                                                                 */
/* Adds a key token to the CKDS.                                   */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNBKRC2:
krc2_rc = 'FFFFFFFF'x;
krc2_rs = 'FFFFFFFF'x;
krc2_exit_data_length = '00000000'x;
krc2_exit_data = '';
krc2_rule_count = '00000000'x;
krc2_rule_array = '';

ADDRESS LINKPGM "CSNBKRC2",
                "krc2_rc",
                "krc2_rs",
                "krc2_exit_data_length",
                "krc2_exit_data",
                "krc2_rule_count",
                "krc2_rule_array",
                "krc2_label",
                "krc2_token_length",
                "krc2_token";

if (KRC2_RC /= '00000000'x) Then
  do;
    say 'KRC2 Failed   (rc=' c2x(KRC2_RC)' rs='c2x(KRC2_rs)')' ;
    exit;
  end;

return;

/* --------------------------------------------------------------- */
/* CSNBSAE - Symmetric Algorithm Encipher                          */
/*                                                                 */
/* Encrypts data using a secure, symmetric key                     */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNBSAE:
sae_rc = 'FFFFFFFF'x;
sae_rs = 'FFFFFFFF'x;
sae_exit_data_length = '00000000'x;
sae_exit_data = '';
sae_key_parms_length = '00000000'x;
sae_key_parms = '';
sae_chain_data_length = '00000020'x;
sae_chain_data = copies('00'x,32);
sae_optional_data_length = '00000000'x;
sae_optional_data = '';

ADDRESS linkpgm "CSNBSAE",
   'SAE_RC'                          'SAE_RS'               ,
   'SAE_exit_data_length'            'SAE_exit_data'        ,
   'SAE_rule_array_count'            'SAE_rule_array'       ,
   'SAE_key_identifier_length'       'SAE_key_identifier'   ,
   'SAE_key_parms_length'            'SAE_key_parms'        ,
   'SAE_block_size'                                         ,
   'SAE_init_vector_length'          'SAE_init_vector'      ,
   'SAE_chain_data_length'           'SAE_chain_data'       ,
   'SAE_clear_text_length'           'SAE_clear_text'       ,
   'SAE_cipher_text_length'          'SAE_cipher_text'      ,
   'SAE_optional_data_length'        'SAE_optional_data';


if (SAE_RC /= '00000000'x) Then
  do;
    say 'SAE (rc=' c2x(SAE_RC)' rs='c2x(SAE_rs)')' ;
    exit;
  end;

return;

/* --------------------------------------------------------------- */
/* CSNBSAD - Symmetric Algorithm Decipher                          */
/*                                                                 */
/* Decrypts data using a secure, symmetric key                     */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNBSAD:
sad_rc = 'FFFFFFFF'x;
sad_rs = 'FFFFFFFF'x;
sad_exit_data_length = '00000000'x;
sad_exit_data = '';
sad_key_parms_length = '00000000'x;
sad_key_parms = '';
sad_chain_data_length = '00000020'x;
sad_chain_data = copies('00'x,32);
sad_optional_data_length = '00000000'x;
sad_optional_data = '';

ADDRESS linkpgm "CSNBSAD",
   'SAD_RC'                          'SAD_RS'               ,
   'SAD_exit_data_length'            'SAD_exit_data'        ,
   'SAD_rule_array_count'            'SAD_rule_array'       ,
   'SAD_key_identifier_length'       'SAD_key_identifier'   ,
   'SAD_key_parms_length'            'SAD_key_parms'        ,
   'SAD_block_size'                                         ,
   'SAD_init_vector_length'          'SAD_init_vector'      ,
   'SAD_chain_data_length'           'SAD_chain_data'       ,
   'SAD_cipher_text_length'          'SAD_cipher_text'      ,
   'SAD_clear_text_length'           'SAD_clear_text'       ,
   'SAD_optional_data_length'        'SAD_optional_data';


if (SAD_RC /= '00000000'x) Then
  do;
    say 'SAD (rc=' c2x(SAD_RC)' rs='c2x(SAD_rs)')' ;
    exit;
  end;

return;

/* --------------------------------------------------------------- */
/* CSFKDMW - Key Data Set Metadata Write                           */
/*                                                                 */
/* Adds, deletes or modifies metadata of records in an active KDS. */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSFKDMW:
kdmw_rc = 'FFFFFFFF'x;
kdmw_rs = 'FFFFFFFF'x;
kdmw_exit_data_length = '00000000'x;
kdmw_exit_data = '';
kdmw_reserved1_length = '00000000'x;
kdmw_reserved1 = '';
kdmw_reserved2_length = '00000000'x;
kdmw_reserved2 = '';

ADDRESS linkpgm "CSFKDMW",
   'KDMW_rc'                          'KDMW_rs'               ,
   'KDMW_exit_data_length'            'KDMW_exit_data'        ,
   'KDMW_rule_array_count'            'KDMW_rule_array'       ,
   'KDMW_label_count'                 'KDMW_label_list'       ,
   'KDMW_metadata_list_length'        'KDMW_metadata_list'    ,
   'KDMW_results_list'                                        ,
   'KDMW_reserved1_length'            'KDMW_reserved1'        ,
   'KDMW_reserved2_length'            'KDMW_reserved2'        ;

   /* Save the one RC/RS */
   results_list_RC = substr(KDMW_results_list,1,2);

if (KDMW_RC /= '00000000'x | results_list_RC /= '0000'x) Then
  do;
    say 'KDMW Failed';
    say 'KDMW Service (rc=' c2x(KDMW_RC)' rs='c2x(KDMW_rs)')' ;
    say 'KDMW Results (rc=' c2x(results_list_RC)')';
    exit;
  end;

return;

/* --------------------------------------------------------------- */
/* CSFKDMR - Key Data Set Metadata Read                            */
/*                                                                 */
/* Read metadata for records in an active KDS.                     */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSFKDMR:
kdmr_rc = 'FFFFFFFF'x;
kdmr_rs = 'FFFFFFFF'x;
kdmr_exit_data_length = '00000000'x;
kdmr_exit_data = '';
kdmr_reserved1_length = '00000000'x;
kdmr_reserved1 = '';
kdmr_reserved2_length = '00000000'x;
kdmr_reserved2 = '';

ADDRESS linkpgm "CSFKDMR",
   'KDMR_rc'                          'KDMR_rs'               ,
   'KDMR_exit_data_length'            'KDMR_exit_data'        ,
   'KDMR_rule_array_count'            'KDMR_rule_array'       ,
   'KDMR_record_label'                                        ,
   'KDMR_metadata_list_length'        'KDMR_metadata_list'    ,
   'KDMR_output_list_length'          'KDMR_output_list'      ,
   'KDMR_reserved1_length'            'KDMR_reserved1'        ,
   'KDMR_reserved2_length'            'KDMR_reserved2'        ;

if (KDMR_RC /= '00000000'x) Then
  do;
    say 'KDMR Failed   (rc=' c2x(KDMR_RC)' rs='c2x(KDMR_rs)')' ;
    exit;
  end;

return;

/* --------------------------------------------------------------- */
/* CSNBKRD - Key Record Delete                                     */
/*                                                                 */
/* Deletes a key record from the CKDS.                             */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNBKRD:
krd_rc = 'FFFFFFFF'x;
krd_rs = 'FFFFFFFF'x;
krd_exit_data_length = '00000000'x;
krd_exit_data = '';
krd_rule_array_count = '00000001'x;
krd_rule_array = 'LABEL-DL';

ADDRESS LINKPGM "CSNBKRD",
                "krd_rc",
                "krd_rs",
                "krd_exit_data_length",
                "krd_exit_data",
                "krd_rule_array_count",
                "krd_rule_array",
                "krd_label";

if (KRD_RC /= '00000000'x & KRD_RS /= '0000271C'x) Then
  say 'KRD Failed   (rc=' c2x(KRD_RC)' rs='c2x(KRD_rs)')' ;

return;

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