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:
- Read the existing key from the PKDS.
- Write the original key to a new label which is <key label> || ".backup"
- Call CSNDPKT to convert the key to a format usable by RSA PSS operations.
- 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
- Call CSNDDSG with the converted key to ensure it can be used with the RSA PSS signature algorithm.
To use this exec,
- please make sure you have a recent backup of your PKDS prior to running this sample
- update the "existing_label" variable to point to the correct key label in the PKDS.
- update the PKA Key Translate rule_array format restriction keyword setting is needed
- 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.
- 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.
- 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