/* Rexx */
/*--------------------------------------------------------------------*/
/* This Rexx sample clist will: */
/* - Build a skeleton RSA private key token using CSNDPKB with */
/* key-usage FR-PSS, which renders the RSA private key usable with */
/* the PKCS-PSS digital-signature hash formatting method. */
/* - Use skeleton token in CSNDPKG to generate a secure RSA private */
/* key. */
/* - Store the generated RSA private key in the PKDS using CSNDKRC. */
/* - Use the RSA private key in CSNDDSG to generate a digital */
/* signature using the RSA PKCS-PSS signature formatting method as */
/* defined in the RSA PKCS #11 v2.2 standard for the RSASSA-PSS */
/* signature scheme. */
/* - If signature will be sent to receiver system for verification, */
/* use CSNDPKX to extract the RSA public key from the private key. */
/* Send the public key, signature and message or hash to receiver. */
/* */
/* (The remaining steps are performed on the receiver system.) */
/* - Store the RSA public key in the PKDS using CSNDKRC. */
/* - Use the RSA public key in CSNDDSV to verify the signature. */
/*--------------------------------------------------------------------*/
/* See the ICSF Application Programmer's Guide (APG) for detailed */
/* information on the callable services used in this sample. */
/* */
/* PKCS-PSS formatting method is supported on ICSF HCR77C0 and CEX5C */
/* and above. The coprocessor ECC master key must be active. If the */
/* ECC master key is not active, see the ICSF Administrator's Guide */
/* "Updating the key data sets with additional master keys". */
/*--------------------------------------------------------------------*/
/* PKDS key label for the generated RSA private key */
RSA_pvt_key_label = left('SAMPLE.RSA.MOD2048.PSS',64) ;
/* PKDS key label for the RSA public key */
RSA_pub_key_label = left('SAMPLE.RSA.MOD2048.PSS.PUBLIC',64) ;
/*--------------------------------------------------------------------*/
/* Call CSNDPKB to build a skeleton RSA private key token. */
/* Key type must be RSA-AESM (modulus-exponent form) or RSA-AESC */
/* (Chinese Remainder Theorem form). Key types RSA-AESM and RSA-AESC */
/* require ICSF HCR77C0 or higher. */
/*--------------------------------------------------------------------*/
PKB_rc = 'FFFFFFFF'x ;
PKB_rs = 'FFFFFFFF'x ;
exit_data_length = '00000000'x ;
exit_data = '' ;
rule_array_count = '00000003'x ;
rule_array = 'RSA-AESM'||, /* key type */
'SIG-ONLY'||, /* key usage */
'FR-PSS ' ; /* format restriction */
key_value_structure = '0800'x||, /* mod bit length */
'0000'x||, /* mod byte length */
'0003'x||, /* public exp length */
'0000'x||, /* private exp length */
'010001'x ; /* public exponent */
key_value_structure_length = d2c(length(key_value_structure),4) ;
private_key_name_length = '00000000'x ;
private_key_name = '' ;
user_definable_associated_data_length = '00000000'x ;
user_definable_associated_data = '' ;
key_derivation_data_length = '00000000'x ;
key_derivation_data = '' ;
reserved_3_length = '00000000'x ; reserved_3 = '' ;
reserved_4_length = '00000000'x ; reserved_4 = '' ;
reserved_5_length = '00000000'x ; reserved_5 = '' ;
PKB_key_token_length = d2c(3500,4) ;
PKB_key_token = copies('00'x,3500) ;
/* CALL CSNDPKB */
ADDRESS LINKPGM 'CSNDPKB' ,
'PKB_rc' ,
'PKB_rs' ,
'exit_data_length' ,
'exit_data' ,
'rule_array_count' ,
'rule_array' ,
'key_value_structure_length' ,
'key_value_structure' ,
'private_key_name_length' ,
'private_key_name' ,
'user_definable_associated_data_length' ,
'user_definable_associated_data' ,
'key_derivation_data_length' ,
'key_derivation_data' ,
'reserved_3_length' 'reserved_3' ,
'reserved_4_length' 'reserved_4' ,
'reserved_5_length' 'reserved_5' ,
'PKB_key_token_length' ,
'PKB_key_token' ;
IF (PKB_rc /= '00000000'x) THEN
DO ;
SAY 'PKB failed: rc =' c2x(PKB_rc) 'rs =' c2x(PKB_rs) ;
EXIT ;
END ;
ELSE
DO ;
PKB_key_token = substr(PKB_key_token,1,c2d(PKB_key_token_length)) ;
SAY 'PKB key token length:' c2x(PKB_key_token_length) ;
SAY 'PKB key token:' ;
CALL printblk c2x(PKB_key_token), 64 ;
END ;
/*--------------------------------------------------------------------*/
/* Use the skeleton token to generate the RSA private key. A CEX5C or */
/* higher is required and the ECC master key must be active. */
/*--------------------------------------------------------------------*/
PKG_rc = 'FFFFFFFF'x ;
PKG_rs = 'FFFFFFFF'x ;
exit_data_length = '00000000'x ;
exit_data = '' ;
rule_array_count = d2c(1,4) ;
rule_array = 'MASTER ' ; /* generated key will be encrypted
under the master key */
regeneration_data_length = '00000000'x ;
regeneration_data = '' ;
skeleton_key_identifier_length = PKB_key_token_length ;
skeleton_key_identifier = PKB_key_token ;
transport_key_identifier = '' ;
generated_key_token_length = d2c(3500,4) ;
generated_key_token = copies('00'x,3500) ;
/* CALL CSNDPKG */
ADDRESS LINKPGM 'CSNDPKG' ,
'PKG_rc' ,
'PKG_rs' ,
'exit_data_length' ,
'exit_data' ,
'rule_array_count' ,
'rule_array' ,
'regeneration_data_length' ,
'regeneration_data' ,
'skeleton_key_identifier_length' ,
'skeleton_key_identifier' ,
'transport_key_identifier' ,
'generated_key_token_length' ,
'generated_key_token' ;
IF (PKG_rc /= '00000000'x) THEN
DO ;
SAY 'PKG failed: rc =' c2x(PKG_rc) 'rs =' c2x(PKG_rs) ;
EXIT ;
END ;
ELSE
DO ;
SAY 'PKG generated key token length:' c2x(generated_key_token_length);
generated_key_token = ,
substr(generated_key_token,1,c2d(generated_key_token_length)) ;
SAY 'PKG generated key token:' ;
CALL PRINTBLK c2x(generated_key_token), 64 ;
END ;
/* Store the generated RSA private key in the PKDS. */
key_label = RSA_pvt_key_label ;
key_token_length = generated_key_token_length ;
key_token = generated_key_token ;
CALL PKRC ;
/*--------------------------------------------------------------------*/
/* Use the generated RSA private key to generate a signature using */
/* the PKCS-PSS digital signature formatting hash method. */
/*--------------------------------------------------------------------*/
DSG_rc = 'FFFFFFFF'x ;
DSG_rs = 'FFFFFFFF'x ;
exit_data_length = '00000000'x ;
exit_data = '' ;
rule_array_count = '00000004'x ;
rule_array = 'RSA '||, /* algorithm */
'PKCS-PSS'||, /* formatting method */
'MESSAGE '||, /* data type */
'SHA-256 ' ; /* hash method */
private_key_length = d2c(64,4) ;
private_key = RSA_pvt_key_label ;
data = '00000020'x||, /* salt length */
'MESSAGE TO BE HASHED' ; /* message */
data_length = d2c(length(data),4) ;
sig_field_length = '00000100'x ;
sig_bit_length = '00000800'x ;
sig_field = copies('00'x,c2d(sig_field_length)) ;
/* CALL CSNDDSG */
ADDRESS LINKPGM 'CSNDDSG' ,
'DSG_rc' ,
'DSG_rs' ,
'exit_data_length' ,
'exit_data' ,
'rule_array_count' ,
'rule_array' ,
'private_key_length' ,
'private_key' ,
'data_length' ,
'data' ,
'sig_field_length' ,
'sig_bit_length' ,
'sig_field' ;
IF DSG_rc /= '00000000'x THEN
DO ;
SAY 'DSG failed: rc =' c2x(DSG_rc) 'rs =' c2x(DSG_rs) ;
EXIT ;
END ;
ELSE
DO ;
sig_field = substr(sig_field,1,c2d(sig_field_length)) ;
SAY 'signature field length:' c2x(sig_field_length) ;
SAY 'signature bit length:' c2x(sig_bit_length) ;
SAY 'signature:' ;
CALL PRINTBLK c2x(sig_field), 64 ;
END ;
/*------------------------------------------------------------------*/
/* If signature will be sent to receiver system for verification, */
/* use CSNDPKX to extract the RSA public key from the private key. */
/* Send the public key, signature and message or hash to receiver. */
/*------------------------------------------------------------------*/
/* Extract the public key from the RSA private key. */
PKX_rc = 'FFFFFFFF'x ;
PKX_rs = 'FFFFFFFF'x ;
exit_data_length = '00000000'x ;
exit_data = '' ;
rule_array_count = '00000000'x ;
rule_array = '' ;
source_key_identifier_length = d2c(64,4) ;
source_key_identifier = RSA_pvt_key_label ;
public_key_token_length = d2c(3500,4) ;
public_key_token = copies('00'x,c2d(public_key_token_length)) ;
/* CALL CSNDPKX */
ADDRESS LINKPGM 'CSNDPKX' ,
'PKX_rc' ,
'PKX_rs' ,
'exit_data_length' ,
'exit_data' ,
'rule_array_count' ,
'rule_array' ,
'source_key_identifier_length' ,
'source_key_identifier' ,
'public_key_token_length' ,
'public_key_token' ;
IF PKX_rc /= '00000000'x THEN
DO ;
SAY 'PKX failed: rc =' c2x(PKX_rc) 'rs =' c2x(PKX_rs) ;
EXIT ;
END ;
ELSE
DO ;
public_key_token = ,
substr(public_key_token,1,c2d(public_key_token_length)) ;
SAY 'public key token:' ;
CALL PRINTBLK c2x(public_key_token), 64 ;
END ;
/*-----------------------------------------------------------*/
/* The remaining steps are performed on the receiver system. */
/*-----------------------------------------------------------*/
/* Store the RSA public key in the PKDS. */
key_label = RSA_pub_key_label ;
key_token_length = public_key_token_length ;
key_token = public_key_token ;
CALL PKRC ;
/* Use the RSA public key to verify the signature. */
DSV_rc = 'FFFFFFFF'x ;
DSV_rs = 'FFFFFFFF'x ;
exit_data_length = '00000000'x ;
exit_data = '' ;
rule_array_count = '00000004'x ;
rule_array = 'RSA '||, /* algorithm */
'PKCS-PSS'||, /* formatting method */
'MESSAGE '||, /* data type */
'SHA-256 ' ; /* hash method */
public_key_identifier_length = d2c(64,4) ;
public_key_identifier = RSA_pub_key_label ;
data = '00000020'x||, /* salt length */
'MESSAGE TO BE HASHED' ; /* message */
data_length = d2c(length(data),4) ;
/* FROM CSNDDSG
sig_field_length
sig_field
*/
/* CALL CSNDDSV */
ADDRESS LINKPGM 'CSNDDSV' ,
'DSV_rc' ,
'DSV_rs' ,
'exit_data_length' ,
'exit_data' ,
'rule_array_count' ,
'rule_array' ,
'public_key_identifier_length' ,
'public_key_identifier' ,
'data_length' ,
'data' ,
'sig_field_length' ,
'sig_field' ;
IF DSV_rc /= '00000000'x THEN
SAY 'DSV failed: rc =' c2x(DSV_rc) 'rs =' c2x(DSV_rs) ;
ELSE
DO ;
SAY 'PKCS-PSS signature verified' ;
END ;
EXIT ;
/*--------------------------------------------------------------------*/
/* PKDS Key Record Create */
/* - Store the key token in the PKDS */
/*--------------------------------------------------------------------*/
PKRC:
/* parameter list */
PKRC_rc = 'FFFFFFFF'x ;
PKRC_rs = 'FFFFFFFF'x ;
exit_data_length = '00000000' ;
exit_data = '' ;
rule_array_count = '00000000'x ;
rule_array = '' ;
/* CALL CSNDKRC */
ADDRESS LINKPGM 'CSNDKRC' ,
'PKRC_rc' ,
'PKRC_rs' ,
'exit_data_length' ,
'exit_data' ,
'rule_array_count' ,
'rule_array' ,
'key_label' ,
'key_token_length' ,
'key_token' ;
IF PKRC_rc /= '00000000'x THEN
DO ;
SAY 'PKRC failed: rc =' c2x(PKRC_rc) 'rs =' c2x(PKRC_rs) ;
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