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

CSNDDSG example with RSA DSI PKCS #1 v1.5

By Eleanor Chan posted Mon February 14, 2022 04:09 PM

  
/* Rexx */

/*--------------------------------------------------------------------*/
/* This Rexx sample clist will:                                       */
/* - Build a skeleton RSA private key token using CSNDPKB.            */
/* - Use skeleton token in CSNDPKG to generate a secure RSA private   */
/* key.                                                               */
/* - Store the generated RSA private key in the PKDS.                 */
/* - Extract the public key from the private key.                     */
/* - Store the RSA public key in the PKDS.                            */
/* - Use the RSA key in CSNDDSG to generate a digital signature using */
/* the RSA PKCS-1.1 signature formatting method as defined in the     */
/* RSASSA-PKCS1-v1_5 signature scheme.                                */
/*--------------------------------------------------------------------*/
/* See the ICSF Application Programmer's Guide (APG) for detailed     */
/* information on the callable services used in this sample.          */
/*--------------------------------------------------------------------*/

/* PKDS key label for the generated RSA private and public keys */
RSA_pvt_key_label = left('SAMPLE.RSA.PVT.MOD4096.SIGONLY',64) ;
RSA_pub_key_label = left('SAMPLE.RSA.PUB.MOD4096',64) ;


/*--------------------------------------------------------------------*/
/* Call CSNDPKB to build a skeleton RSA private key token.            */
/*--------------------------------------------------------------------*/
PKB_rc = 'FFFFFFFF'x ;
PKB_rs = 'FFFFFFFF'x ;
exit_data_length = '00000000'x ;
exit_data = '' ;
rule_array_count = '00000002'x ;
rule_array = 'RSA-CRT '||, /* key type */
             'SIG-ONLY' ; /* key usage */
key_value_structure = '0800'x||, /* mod bit length */
                      '0000'x||, /* mod byte length */
                      '0000'x||, /* public exp length */
                      '0000'x||, /* reserved */
                      '0000'x||, /* length of p */
                      '0000'x||, /* length of q */
                      '0000'x||, /* length of dp */
                      '0000'x||, /* length of dq */
                      '0000'x ;

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) ;

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 ;
  SAY 'PKB key token length:' c2x(PKB_key_token_length) ;
  PKB_key_token = substr(PKB_key_token,1,c2d(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/public key.     */
/*--------------------------------------------------------------------*/
PKG_rc = 'FFFFFFFF'x ;
PKG_rs = 'FFFFFFFF'x ;
exit_data_length = '00000000'x ;
exit_data = '' ;
rule_array_count = '00000001'x ;
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) ;

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/public key in the PKDS */
PKRC_rc = 'FFFFFFFF'x ;
PKRC_rs = 'FFFFFFFF'x ;
exit_data_length = '00000000' ;
exit_data = '' ;
rule_array_count = '00000000'x ;
rule_array = '' ;
key_label = RSA_pvt_key_label ;
key_token_length = generated_key_token_length ;
key_token = generated_key_token ;

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 ;


/*--------------------------------------------------------------------*/
/* Extract the public key from the private/public 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 = generated_key_token_length ;
source_key_identifier = generated_key_token ;
target_public_key_token_length = d2c(3500,4) ;
target_public_key_token = copies('00'x,3500) ;

ADDRESS LINKPGM 'CSNDPKX' ,
                'PKX_rc' ,
                'PKX_rs' ,
                'exit_data_length' ,
                'exit_data' ,
                'rule_array_count' ,
                'rule_array' ,
                'source_key_identifier_length' ,
                'source_key_identifier' ,
                'target_public_key_token_length' ,
                'target_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 ;
  SAY 'PKX target_public_key_token_length:' ,
   c2x(target_public_key_token_length) ;
  target_public_key_token = ,
   substr(target_public_key_token,1,c2d(target_public_key_token_length))
  SAY 'PKX public key token:' ;
  CALL PRINTBLK c2x(target_public_key_token), 64 ;
 END ;


/* Store the RSA public key in the PKDS */
PKRC_rc = 'FFFFFFFF'x ;
PKRC_rs = 'FFFFFFFF'x ;
exit_data_length = '00000000' ;
exit_data = '' ;
rule_array_count = '00000000'x ;
rule_array = '' ;
key_label = RSA_pub_key_label ;
key_token_length = target_public_key_token_length ;
key_token = target_public_key_token ;

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 ;


/*--------------------------------------------------------------------*/
/* Use the generated RSA private key to generate a signature using    */
/* the PKCS-1.1 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-1.1'||, /* formatting method */
             'MESSAGE '||, /* data specifies message */
             'SHA-256 ' ; /* hash method */
RSA_private_key_length = d2c(64,4) ;
RSA_private_key = RSA_pvt_key_label ;
DSG_data_length = '00000014'x
DSG_data = 'MESSAGE TO BE HASHED' ;
signature_field_length = '00000100'x ;
signature_bit_length = '00000800'x ;
signature_field = copies('00'x,c2d(signature_field_length)) ;

ADDRESS LINKPGM 'CSNDDSG' ,
                'DSG_rc' ,
                'DSG_rs' ,
                'exit_data_length' ,
                'exit_data' ,
                'rule_array_count' ,
                'rule_array' ,
                'RSA_private_key_length' ,
                'RSA_private_key' ,
                'DSG_data_length' ,
                'DSG_data' ,
                'signature_field_length' ,
                'signature_bit_length' ,
                'signature_field' ;

IF DSG_rc /= '00000000'x THEN
 DO ;
  SAY 'DSG failed: rc =' c2x(DSG_rc) 'rs =' c2x(DSG_rs) ;
  EXIT ;
 END ;
ELSE
 DO ;
  signature_field = ,
   substr(signature_field,1,c2d(signature_field_length)) ;
  SAY 'signature field length:' c2x(signature_field_length) ;
  SAY 'signature bit length:' c2x(signature_bit_length) ;
  SAY 'signature:' ;
  CALL PRINTBLK c2x(signature_field), 64 ;
 END ;


/*--------------------------------------------------------------------*/
/* The RSA public key, message and digital signature are sent to a    */
/* client for verification.                                           */
/*--------------------------------------------------------------------*/
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-1.1'||, /* formatting method */
             'MESSAGE '||, /* data specifies message */
             'SHA-256 ' ; /* hash method */
RSA_public_key_length = d2c(64,4) ;
RSA_public_key = RSA_pub_key_label ;
DSV_data_length = '00000014'x
DSV_data = 'MESSAGE TO BE HASHED' ;
signature_field_length = '00000100'x
signature_field = ,
'8DFBE671A97E7AA07CA6A23753EA326E4C1A325FD05E874B8570D9DEF5928787'x||,
'1D05B2818825F41C9EF3E6A3A492ACCCFE177D84DAD42C7837FCA463A6A65B42'x||,
'4DC52B17F232D776939ED170E9AD8E272E92ED4C492595A98CA59C925060EEE6'x||,
'A0D772E2692AC083FDE411369752B57EB92F04671915F822FF0D925B9064FC18'x||,
'A3272D1C01FDC71FCF3CD555344E231411A7155C3A126A5DBFB67F3C52E4CE00'x||,
'E9E5F4B568EC47214C869433B400C285B95A1895B51AD34CB2E9772E0871A290'x||,
'0575B185BFEC9907A85A95603D6EA073EF0B6B6DDA1B6D62ECB6044E669E584A'x||,
'D24A271763D7D4F3FD85B07FDDA71ADF43D267CB767056A98ED58B06619B00A4'x ;

ADDRESS LINKPGM 'CSNDDSV' ,
                'DSV_rc' ,
                'DSV_rs' ,
                'exit_data_length' ,
                'exit_data' ,
                'rule_array_count' ,
                'rule_array' ,
                'RSA_public_key_length' ,
                'RSA_public_key' ,
                'DSV_data_length' ,
                'DSV_data' ,
                'signature_field_length' ,
                'signature_field' ;

IF DSV_rc /= '00000000'x THEN
 SAY 'DSV failed: rc =' c2x(DSV_rc) 'rs =' c2x(DSV_rs) ;
ELSE
 SAY 'DSV SIGNATURE VERIFIED'


EXIT ;

/*--------------------------------------------------------------------*/
/* 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
0 comments
30 views

Permalink