IBM Crypto Education Community - Group home

Translate and replace an RSA key for RSA PSS

  

This exec is a supplement to one previously uploaded here: https://community.ibm.com/community/user/ibmz-and-linuxone/blogs/eysha-shirrine-powers2/2020/03/25/translate-an-existing-rsa-private-key-to-be-used-in-pkcs-pss-digital-signature-formatting-method?lang=en

The difference is in how the translated key is handled. The exec below follows this procedure:

  1. Read the existing key from the PKDS.
  2. Write the original key to a new label which is <key label> || ".backup"
  3. Call CSNDPKT to convert the key to a format usable by RSA PSS operations.
  4. Write the converted key to the PKDS with the same key label as the original key, overlaying the old key with the new converted RSA PSS capable key
  5. Call CSNDDSG with the converted key to ensure it can be used with the RSA PSS signature algorithm.



To use this exec,

  1. please make sure you have a recent backup of your PKDS prior to running this sample
  2. update the "existing_label" variable to point to the correct key label in the PKDS.
  3. update the PKA Key Translate rule_array format restriction keyword setting is needed
    1. if you are considering to convert the private key of the certificate used by RACDCERT using the rule array 'FR-PSS ' (format restriction keyword), it will prevent you from signing with the regular RSA signature. If you don't want the restriction, use rule array FR-NONE instead.
    2. if you are converting the private key of the certificate to be usable for TLS 1.3 and to remain usable with earlier SSL/TLS protocols, you will want to use rule array FR-NONE.
  4. After running the exec, if the backup key (created in Step 2) is no longer needed, it can be deleted using the "PKDS Keys" utility (ICSF -> (5) Utilities -> (6) PKDS Keys


/* Rexx */

/* Rexx */

/*--------------------------------------------------------------------*/
/* This sample will convert an existing RSA private key so that it */
/* can be used with the PKCS-PSS digital-signature hash formatting */
/* method. */
/* */
/* The RSA key to be converted must be an existing secure key */
/* encrypted under the RSA master key. The RSA key may be in */
/* modulus-exponent (ME) format or Chinese Remainder Theorem (CRT) */
/* format. The RSA key token formats are described in the ICSF */
/* Application Programmer's Guide (APG), Appendix "Key token formats".*/
/* */
/* See the ICSF APG for more 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". */
/*--------------------------------------------------------------------*/

existing_label = "ECHAN.DSGX931.RSA.CRT08.1792.PRIV.SIGONLY"
existing_token = PKRR(existing_label)
backup_label = LEFT(existing_label || ".BACKUP",64)

/* Overwrite existing key in the PKDS w/ converted key */
key_label = backup_label ;
key_token_length = D2C(LENGTH(existing_token),4)
key_token = existing_token ;
CALL PKRC ;
Say "Original RSA token backed up to new PKDS key:"
Say '"' || backup_label || '"'


/*-------------------*/
/* PKA Key Translate */
/*-------------------*/
PKT_rc = 'FFFFFFFF'x ;
PKT_rs = 'FFFFFFFF'x ;
exit_data_length = '00000000'x ;
exit_data = '' ;
rule_array_count = d2c(2,4) ;
rule_array = 'INTDWAKW'||,
'FR-PSS ' ; /* format restriction keyword */
/* Once converted, this key may only be used with the PKCS-PSS
digital-signature hash formatting method. For no restriction
on usage, specify FR-NONE. See the ICSF Application
Programmer's Guide for more information.
*/
source_key_length = d2c(64,4) ;
source_key = LEFT(existing_label,64) ;
source_xport_key_length = d2c(0,4) ;
source_xport_key = '' ;
target_xport_key_length = d2c(0,4) ;
target_xport_key = '' ;
target_key_length = d2c(3500,4) ;
target_key = COPIES('00'x,3500) ;

/* CALL CSNDPKT */
ADDRESS LINKPGM 'CSNDPKT' ,
'PKT_rc' ,
'PKT_rs' ,
'exit_data_length' ,
'exit_data' ,
'rule_array_count' ,
'rule_array' ,
'source_key_length' ,
'source_key' ,
'source_xport_key_length' ,
'source_xport_key' ,
'target_xport_key_length' ,
'target_xport_key' ,
'target_key_length' ,
'target_key' ;

IF PKT_rc /= '00000000'x THEN
DO ;
SAY 'PKT failed: rc =' c2x(PKT_rc) 'rs =' c2x(PKT_rs) ;
EXIT ;
END ;
Else Do
Say "CSNDPKT Successful."
End


/* Overwrite existing key in the PKDS w/ converted key */
key_label = existing_label ;
key_token_length = target_key_length ;
key_token = target_key ;
CALL PKRW ;
Say "New RSA PSS capable key written to:"
Say '"' || existing_label || '"'

/*-----------------------------------------------------------------*/
/* Use the converted 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 '||,
'PKCS-PSS'||,
'HASH '||,
'SHA-256 ' ;
private_key_length = target_key_length
private_key = target_key
data_length = '00000024'x ;
data = '00000020'x||, /* salt length */
'9EFDE926830891B7F2889646D0105BD8'x||, /* hash */
'09C64F6217EC046F5B384F625C9CCF66'x ;
sig_field_length = '00000200'x ; /* 512 decimal */
sig_bit_length = '00001000'x ; /* 4096 decimal */
sig_field = copies('00'x,512) ;

/* 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
SAY 'DSG failed: rc =' c2x(DSG_rc) 'rs =' c2x(DSG_rs) ;
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:' c2x(sig_field) ;
END ;



EXIT ;

/*------------------------*/
/* PKDS Key Record Create */
/*------------------------*/
PKRC:

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 ;

PKRW:
PKRW_return_code = 'FFFFFFFF'x
PKRW_reason_code = 'FFFFFFFF'x
PKRW_exit_data_length = '00000000'x
PKRW_exit_data = ''
PKRW_rule_array_count = '00000001'x
PKRW_rule_array = "OVERLAY "
PKRW_label = LEFT(key_label,64)
PKRW_token_length = key_token_length
PKRW_token = key_token
Address LINKPGM 'CSNDKRW',
'PKRW_return_code' 'PKRW_reason_code',
'PKRW_exit_data_length' 'PKRW_exit_data',
'PKRW_rule_array_count' 'PKRW_rule_array',
'PKRW_label',
'PKRW_token_length' 'PKRW_token'
IF PKRW_return_code <> '00000000'x THEN
DO ;
SAY 'PKRW failed: rc =' c2x(PKRW_return_code) 'rs =' c2x(PKRW_reason_code) ;
EXIT ;
END ;


Return

PKRR:
Arg label
PKRR_return_code = 'FFFFFFFF'x
PKRR_reason_code = 'FFFFFFFF'x
PKRR_exit_data_length = '00000000'x
PKRR_exit_data = ''
PKRR_rule_array_count = '00000000'x
PKRR_rule_array = ''
PKRR_label = LEFT(label,64)
PKRR_token_length = D2C(3500,4)
PKRR_token = COPIES('00'x,3500)
Address LINKPGM 'CSNDKRR',
'PKRR_return_code' 'PKRR_reason_code',
'PKRR_exit_data_length' 'PKRR_exit_data',
'PKRR_rule_array_count' 'PKRR_rule_array',
'PKRR_label',
'PKRR_token_length' 'PKRR_token'
IF PKRR_return_code <> '00000000'x THEN
DO ;
SAY 'PKRR failed: rc =' c2x(PKRR_return_code) 'rs =' c2x(PKRR_reason_code) ;
EXIT ;
END ;
len = C2D(PKRR_token_length)
token = LEFT(PKRR_token,len)
Return token