/* Rexx */
/* Pervasive (Data Set) Encryption: Step 6 of 10 */
/*-------------------------------------------------------------------*/
/* - Create a skeleton AES CIPHER key. */
/* - Use it to generate a secure AES CIPHER key. */
/* - Store the key in the CKDS. */
/* - Read the key label from the CKDS. */
/* */
/* ICSF HCR77C1 and a CEX6C or higher is required to generate an */
/* AES CIPHER key to use with CPACF. */
/*-------------------------------------------------------------------*/
/* Instructions: */
/* - Update aes_key_label with your desired key label name */
/* */
/* Note: An example key label naming scheme is */
/* DATASET.<datasetname>.ENCRKEY.<seqno> */
/* */
/* - EXECUTE THIS CLIST FROM TSO */
/* (e.g. EX 'HLQ.MLD.LLQ(GENKEYC)') */
/*-------------------------------------------------------------------*/
signal on novalue;
aes_key_label = ,
left('DATASET.EYSHA.ICSF.ENCRYPT.ME.ENCRKEY.00000002',64);
/*-------------------------------------------------------------------*/
/* Create a skeleton AES CIPHER key with key-usage XPRTCPAC that */
/* allows export to CPACF protected key format. This skeleton will */
/* be used in CSNBKGN2 to generate a secure AES CIPHER key. There */
/* are many other key-usage and key-mgmt keywords that may be */
/* specified in the rule_array. */
/* See the ICSF Application Programmer's Guide for more details. */
/*-------------------------------------------------------------------*/
KTB2_rule_array_count = '00000005'x;
KTB2_rule_array = 'INTERNAL'||,
'AES '||,
'CIPHER '||,
'XPRTCPAC'||,
'ANY-MODE' ;
CALL CSNBKTB2;
/*-------------------------------------------------------------------*/
/* Generate a 256-bit AES CIPHER key */
/*-------------------------------------------------------------------*/
KGN2_rule_array_count = '00000002'x;
KGN2_rule_array = 'AES '||,
'OP ';
KGN2_clear_bit_length = '00000100'x; /* 256-bit */
KGN2_key_type_1 = 'TOKEN ';
KGN2_key_type_2 = '';
KGN2_generated_key_id_1_length = '00000384'x;
KGN2_generated_key_id_1 = left(KTB2_target_key_token,900);
KGN2_generated_key_id_2_length = '00000000'x;
KGN2_generated_key_id_2 = '';
Call CSNBKGN2;
/*-------------------------------------------------------------------*/
/* Store the key in the CKDS */
/*-------------------------------------------------------------------*/
KRC2_key_label = aes_key_label;
KRC2_key_token_length = KGN2_generated_key_id_1_length;
KRC2_key_token = ,
substr(KGN2_generated_key_id_1,1,c2d(KGN2_generated_key_id_1_length));
Call CSNBKRC2;
/*-------------------------------------------------------------------*/
/* Read the key from the CKDS */
/*-------------------------------------------------------------------*/
KRR2_rule_array_count = '00000000'x;
KRR2_rule_array = '' ;
KRR2_key_label = aes_key_label;
Call CSNBKRR2;
say "-----------------------------------------------------------------"
say "End of Sample"
say "-----------------------------------------------------------------"
EXIT;
/* --------------------------------------------------------------- */
/* CSNBKTB2 - Key Token Build2 */
/* */
/* Build a skeleton token to use as input to CSNBKGN2. */
/* Returns a variable-length skeleton token. */
/* */
/* See the ICSF Application Programmer's Guide for more details. */
/* --------------------------------------------------------------- */
CSNBKTB2:
KTB2_rc = 'FFFFFFFF'x;
KTB2_rs = 'FFFFFFFF'x;
KTB2_exit_data_length = '00000000'x;
KTB2_exit_data = '';
KTB2_clear_key_bit_length = '00000000'x;
KTB2_clear_key_value = '';
KTB2_key_name_length = '00000000'x;
KTB2_key_name = '';
KTB2_user_data_length = '00000000'x;
KTB2_user_data = '';
KTB2_token_data_length = '00000000'x;
KTB2_token_data = '';
KTB2_service_data_length = '00000000'x;
KTB2_service_data = '';
KTB2_target_key_token_length = '000002D5'x;
KTB2_target_key_token = copies('00'x,725) ;
ADDRESS linkpgm 'CSNBKTB2' ,
'KTB2_rc' 'KTB2_rs' ,
'KTB2_exit_data_length' 'KTB2_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_data_length' 'KTB2_user_data' ,
'KTB2_token_data_length' 'KTB2_token_data' ,
'KTB2_service_data_length' 'KTB2_service_data' ,
'KTB2_target_key_token_length' 'KTB2_target_key_token' ;
IF KTB2_rc /= '00000000'x THEN
DO;
say 'KTB2 Failed (rc=' c2x(KTB2_rc)' rs='c2x(KTB2_rs)')' ;
EXIT;
END;
ELSE
KTB2_target_key_token = ,
substr(KTB2_target_key_token,1,c2d(KTB2_target_key_token_length));
RETURN;
/* --------------------------------------------------------------- */
/* CSNBKGN2 - Key Generate2 */
/* */
/* Generates either one or two HMAC or AES keys of specified */
/* key type. */
/* Returns a variable-length CCA key token. */
/* */
/* See the ICSF Application Programmer's Guide for more details. */
/* --------------------------------------------------------------- */
CSNBKGN2:
KGN2_rc = 'FFFFFFFF'x;
KGN2_rs = 'FFFFFFFF'x;
KGN2_exit_data_length = '00000000'x;
KGN2_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_data_1_length = '00000000'x;
KGN2_user_data_1 = '';
KGN2_user_data_2_length = '00000000'x;
KGN2_user_data_2 = '';
KGN2_kek_id_1_length = '00000000'x;
KGN2_kek_id_1 = '';
KGN2_kek_id_2_length = '00000000'x;
KGN2_kek_id_2 = '';
ADDRESS linkpgm 'CSNBKGN2' ,
'KGN2_rc' 'KGN2_rs' ,
'KGN2_exit_data_length' 'KGN2_exit_data' ,
'KGN2_rule_array_count' 'KGN2_rule_array' ,
'KGN2_clear_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_data_1_length' 'KGN2_user_data_1' ,
'KGN2_user_data_2_length' 'KGN2_user_data_2' ,
'KGN2_kek_id_1_length' 'KGN2_kek_id_1' ,
'KGN2_kek_id_2_length' 'KGN2_kek_id_2' ,
'KGN2_generated_key_id_1_length' 'KGN2_generated_key_id_1' ,
'KGN2_generated_key_id_2_length' 'KGN2_generated_key_id_2' ;
IF KGN2_rc /= '00000000'x THEN
DO;
say 'KGN2 Failed (rc=' c2x(KGN2_rc)' rs='c2x(KGN2_rs)')' ;
EXIT;
END;
ELSE
KGN2_generated_key_id_1 = ,
substr(KGN2_generated_key_id_1,1,c2d(KGN2_generated_key_id_1_length));
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_array_count = '00000000'x;
KRC2_rule_array = '';
ADDRESS LINKPGM 'CSNBKRC2',
'KRC2_rc',
'KRC2_rs',
'KRC2_exit_data_length',
'KRC2_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;
/* --------------------------------------------------------------- */
/* CSNBKRR2 - Key Record Read2 (CKDS) */
/* */
/* Reads a fixed-length or variable-length key token from the CKDS.*/
/* */
/* See the ICSF Application Programmer's Guide for more details. */
/* --------------------------------------------------------------- */
CSNBKRR2:
KRR2_rc = 'FFFFFFFF'x;
KRR2_rs = 'FFFFFFFF'x;
KRR2_exit_data_length = '00000000'x;
KRR2_exit_data = '';
KRR2_key_token_length = '000002D5'x;
KRR2_key_token = copies('00'x, 725);
ADDRESS LINKPGM 'CSNBKRR2',
'KRR2_rc',
'KRR2_rs',
'KRR2_exit_data_length',
'KRR2_exit_data',
'KRR2_rule_array_count',
'KRR2_rule_array',
'KRR2_key_label',
'KRR2_key_token_length',
'KRR2_key_token';
IF KRR2_rc = '00000000'x THEN
DO;
say 'Secure CIPHER key label: ' strip(aes_key_label);
say 'Secure CIPHER key token length: ' c2d(KRR2_key_token_length);
say 'Secure CIPHER key token: ';
say c2x(substr(KRR2_key_token,1,c2d(KRR2_key_token_length)));
EXIT;
END;
RETURN;
/* ----------------------------------------------------------------- */
/* PRINTBLK: */
/* */
/* Helper routine to display hex data with a fixed line length */
/* ----------------------------------------------------------------- */
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