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

Rexx Sample: Derive an AES key from a pair of ECC keys

By Eysha Shirrine Powers posted Wed March 25, 2020 05:28 PM

  

/* Rexx */

/* Derive an AES key from a pair of ECC keys                         */
/*-------------------------------------------------------------------*/
/* Description:                                                      */
/*                                                                   */
/* This REXX contains samples for deriving an AES key from two ECC   */
/* key pairs.                                                        */
/*  - Create a skeleton for the AES key token                        */
/*  - Generate a sender ECC key pair                                 */
/*  - Generate a receiver ECC key pair                               */
/*  - Derive the AES key token from the sender and receiver ECC keys */
/*                                                                   */
/* How To Run:                                                       */
/* - Execute this script from TSO                                    */
/*   (e.g. EX 'HLQ.MLD.LLQ(DERIVAES)')                               */
/*-------------------------------------------------------------------*/
signal on novalue;

/* CLEANUP labels in use for this sample */
sender_key_label = left('SAMPLE.SENDER.ECC.KEY',64);
krd_label = sender_key_label;
Call CSNDKRD;
receiver_key_label = left('SAMPLE.RECEIVER.ECC.KEY',64);
krd_label = receiver_key_label;
Call CSNDKRD;

/*********************************************************************/
/* Create a skeleton token for the derived key                       */
/*********************************************************************/

ktb_key_type           = 'DATA    ';
ktb_rule_array_count   = '00000003'x;
ktb_rule_array         = 'AES     ' ||,
                         'INTERNAL' ||,
                         'KEYLN32 ';
ktb_key_value          = '';
ktb_key_token          = copies('00'x,64)
Call CSNBKTB;


/*********************************************************************/
/* Create the "Sender" ECC Public / Private Key Pair                 */
/*********************************************************************/

/* Create a record for the ECC Key Pair in the PKDS */
krc_label        = sender_key_label;
krc_token        = '';
krc_token_length = '00000000'x;
Call CSNDKRC;

/* Build the skeleton token for the Key Pair */
pkb_rule_count                 = '00000002'x;
pkb_rule_array                 = 'ECC-PAIR' ||,
                                 'KEY-MGMT';
pkb_key_value_structure_length = '00000008'x;
pkb_key_value_structure        = '00'x   ||,  /* Prime curve         */
                                 '00'x   ||,  /* reserved            */
                                 '0209'x ||,  /* P-521 curve in bits */
                                 '0000'x ||,  /* length of d in bytes*/
                                 '0000'x;     /* public key q, bytes */
pkb_private_key_name_length    = '00000040'x;
pkb_private_key_name           = sender_key_label;
pkb_key_token_length           = '00000DAC'x;
pkb_key_token                  = copies('00'x,3500);
Call CSNDPKB;

/* Generate the Key Pair from the skeleton. Store in the PKDS. */
pkg_rule_count                     = '00000001'x;
pkg_rule_array                     = 'MASTER  ';
pkg_regeneration_data_length       = '00000000'x;
pkg_regeneration_data              = '';
pkg_skeleton_key_id_length         = pkb_key_token_length;
pkg_skeleton_key_id                = pkb_key_token;
pkg_transport_key_identifier       = copies('00'x,64);
pkg_generated_key_token_length     = '00000040'x;
pkg_generated_key_token            = sender_key_label;
Call CSNDPKG;

/* Read the Key Pair from the PKDS */
krr_label        = sender_key_label;
krr_token_length = '00000DAC'x;
krr_token        = copies('00'x, 3500);
Call CSNDKRR;

sender_ecc_key        = substr(krr_token,1,c2d(krr_token_length));
sender_ecc_key_length = krr_token_length;
say "sender_ecc_key " c2x(sender_ecc_key);
say "sender_ecc_key_length " c2d(sender_ecc_key_length);

/*********************************************************************/
/* Create the "Receiver" ECC Public / Private Key Pair               */
/*********************************************************************/

/* Create a record for the ECC Key Pair in the PKDS */
krc_label        = receiver_key_label;
krc_token        = '';
krc_token_length = '00000000'x;
Call CSNDKRC;

/* Build the skeleton token for the Key Pair */
pkb_rule_count                 = '00000001'x;
pkb_rule_array                 = 'ECC-PAIR' ||,
                                 'KEY-MGMT';
pkb_key_value_structure_length = '00000008'x;
pkb_key_value_structure        = '00'x   ||,  /* Prime curve         */
                                 '00'x   ||,  /* reserved            */
                                 '0209'x ||,  /* P-521 curve in bits */
                                 '0000'x ||,  /* length of d in bytes*/
                                 '0000'x;     /* public key q, bytes */
pkb_private_key_name_length    = '00000040'x;
pkb_private_key_name           = receiver_key_label;
pkb_key_token_length           = '00000DAC'x;
pkb_key_token                  = copies('00'x,3500);
Call CSNDPKB;

/* Generate the Key Pair from the skeleton. Store in the PKDS. */
pkg_rule_count                     = '00000001'x;
pkg_rule_array                     = 'MASTER  ';
pkg_regeneration_data_length       = '00000000'x;
pkg_regeneration_data              = '';
pkg_skeleton_key_id_length         = pkb_key_token_length;
pkg_skeleton_key_id                = pkb_key_token;
pkg_transport_key_identifier       = copies('00'x,64);
pkg_generated_key_token_length     = '00000040'x;
pkg_generated_key_token            = receiver_key_label;
Call CSNDPKG;

/* Read the Key Pair from the PKDS */
krr_label        = receiver_key_label;
krr_token_length = '00000DAC'x;
krr_token        = copies('00'x, 3500);
Call CSNDKRR;

receiver_ecc_key        = substr(krr_token,1,c2d(krr_token_length));
receiver_ecc_key_length = krr_token_length;
say "receiver_ecc_key " c2x(receiver_ecc_key);
say "receiver_ecc_key_length " c2d(receiver_ecc_key_length);


/*********************************************************************/
/* Derive the AES Key                                                */
/*********************************************************************/
edh_rule_array_count      = '00000002'x;
edh_rule_array            = 'DERIV01 ' ||,
                            'KEY-AES ';
edh_private_key_id_length = '00000040'x;
edh_private_key_id        = sender_key_label;
edh_public_key_id_length  = '00000040'x;
edh_public_key_id         = receiver_key_label;
edh_party_id_length       = '0000000E'x;
edh_party_id              = 'transaction-id';
edh_key_bit_length        = '00000100'x;       /* 256-bit AES */
edh_output_key_id_length  = '00000040'x;
edh_output_key_id         = ktb_key_token;
Call CSNDEDH;

say 'derived_key' c2x(edh_output_key_id);
say 'derived_key_length' c2d(edh_output_key_id_length);

say "-----------------------------------------------------------------"
say "End of Sample"
say "-----------------------------------------------------------------"

exit;

/* --------------------------------------------------------------- */
/* CSNBKTB - Key Token Build                                       */
/*                                                                 */
/* Builds a skeleton key token to be used as input for the key     */
/* generate (CSNBKGN) or diversify key generate (CSNBDKG) callable */
/* service.                                                        */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNBKTB:

KTB_RC = 'FFFFFFFF'x;
KTB_RS = 'FFFFFFFF'x;
KTB_exit_data_length           = '00000000'x;
KTB_exit_data                  = '';
KTB_master_key_version_num     = '00000000'x
KTB_key_register_num           = '00000000'x
KTB_token_data_1               = ''
KTB_control_vector     = '';
KTB_initialization_vector      = ''
KTB_pad_character              = '00000000'x
KTB_cryptographic_period_start = '';
KTB_masterkey_verify_parm      = '';

ADDRESS linkpgm "CSNBKTB",
   'KTB_RC'                      'KTB_RS'               ,
   'KTB_exit_data_length'        'KTB_exit_data'        ,
   'KTB_key_token'               'KTB_key_type'         ,
   'KTB_rule_array_count'        'KTB_rule_array'       ,
   'KTB_key_value'               'KTB_master_key_version_num',
   'KTB_key_register_num'        'KTB_token_data_1'     ,
   'KTB_control_vector'          'KTB_initialization_vector',
   'KTB_pad_character'           'KTB_cryptographic_period_start',
   'KTB_masterkey_verify_parm';

if (KTB_RC /= '00000000'x) Then
  do;
    say 'KTB Failed   (rc=' c2x(KTB_RC)' rs='c2x(KTB_rs)')' ;
    exit;
  end;

Return;

/* --------------------------------------------------------------- */
/* CSNDPKB - PKA Key Token Build                                   */
/*                                                                 */
/* Builds a skeleton key token which can be used as input for the  */
/* key generate (CSNDPKG) callable service.                        */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNDPKB:

PKB_RC = 'FFFFFFFF'x;
PKB_RS = 'FFFFFFFF'x;
PKB_exit_data_length  = '00000000'x;
PKB_exit_data  = '';
PKB_reserved_1_length = '00000000'x;
PKB_reserved_1 = '';
PKB_reserved_2_length = '00000000'x;
PKB_reserved_2 = '';
PKB_reserved_3_length = '00000000'x;
PKB_reserved_3 = '';
PKB_reserved_4_length = '00000000'x;
PKB_reserved_4 = '';
PKB_reserved_5_length = '00000000'x;
PKB_reserved_5 = '';

ADDRESS linkpgm "CSNDPKB",
   'PKB_RC'                         'PKB_RS'                     ,
   'PKB_exit_data_length'           'PKB_exit_data'              ,
   'PKB_rule_count'                 'PKB_rule_array'             ,
   'PKB_key_value_structure_length' 'PKB_key_value_structure'    ,
   'PKB_private_key_name_length'    'PKB_private_key_name'       ,
   'PKB_reserved_1_length'          'PKB_reserved_1'             ,
   'PKB_reserved_2_length'          'PKB_reserved_2'             ,
   'PKB_reserved_3_length'          'PKB_reserved_3'             ,
   'PKB_reserved_4_length'          'PKB_reserved_4'             ,
   'PKB_reserved_5_length'          'PKB_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;

Return;

/* --------------------------------------------------------------- */
/* CSNDPKG - PKA Key Generate                                      */
/*                                                                 */
/* Generates RSA or ECC key pairs.                                 */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNDPKG:

PKG_RC                         = 'FFFFFFFF'x;
PKG_RS                         = 'FFFFFFFF'x;
PKG_exit_data_length           = '00000000'x;
PKG_exit_data                  = '';

ADDRESS linkpgm "CSNDPKG",
   'PKG_RC'                          'PKG_RS'                 ,
   'PKG_exit_data_length'            'PKG_exit_data'          ,
   'PKG_rule_count'                  'PKG_rule_array'         ,
   'PKG_regeneration_data_length'    'PKG_regeneration_data'  ,
   'PKG_skeleton_key_id_length'      'PKG_skeleton_key_id'    ,
   'PKG_transport_key_identifier'                             ,
   'PKG_generated_key_token_length'  'PKG_generated_key_token';

if (PKG_RC /= '00000000'x) Then
  do;
    say 'PKG Failed   (rc=' c2x(PKG_RC)' rs='c2x(PKG_rs)')' ;
    exit;
  end;

Return;

/* --------------------------------------------------------------- */
/* CSNBKRC - Key Record Create (CKDS)                              */
/*                                                                 */
/* Adds a key record to the CKDS which can be used by CSNBKRW to   */
/* write a key token to the CKDS.                                  */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNBKRC:
krc_rc = 'FFFFFFFF'x;
krc_rs = 'FFFFFFFF'x;
krc_exit_data_length = '00000000'x;
krc_exit_data = '';

ADDRESS LINKPGM "CSNBKRC",
                "krc_rc",
                "krc_rs",
                "krc_exit_data_length",
                "krc_exit_data",
                "krc_label";

if (KRC_RC /= '00000000'x) Then
  do;
    say 'KRC Failed   (rc=' c2x(KRC_RC)' rs='c2x(KRC_rs)')' ;
    exit;
  end;

return;

/* --------------------------------------------------------------- */
/* CSNDKRC - Key Record Create (PKDS)                              */
/*                                                                 */
/* Adds a key record and key token to the PKDS.                    */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNDKRC:
krc_rc = 'FFFFFFFF'x;
krc_rs = 'FFFFFFFF'x;
krc_exit_data_length = '00000000'x;
krc_exit_data = '';
krc_rule_count = '00000000'x;
krc_rule_array = '';

ADDRESS LINKPGM "CSNDKRC",
                "krc_rc",
                "krc_rs",
                "krc_exit_data_length",
                "krc_exit_data",
                "krc_rule_count",
                "krc_rule_array",
                "krc_label",
                "krc_token_length",
                "krc_token";

if (KRC_RC /= '00000000'x) Then
  do;
    say 'KRC Failed   (rc=' c2x(KRC_RC)' rs='c2x(KRC_rs)')' ;
    exit;
  end;

return;

/* --------------------------------------------------------------- */
/* CSNBKRR - Key Record Read (CKDS)                                */
/*                                                                 */
/* Reads a key token from the CKDS.                                */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNBKRR:
krr_rc = 'FFFFFFFF'x;
krr_rs = 'FFFFFFFF'x;
krr_exit_data_length = '00000000'x;
krr_exit_data = '';
krr_token = copies('00'x,64);

ADDRESS LINKPGM "CSNBKRR",
                "krr_rc",
                "krr_rs",
                "krr_exit_data_length",
                "krr_exit_data",
                "krr_label",
                "krr_token";

if (KRR_RC /= '00000000'x) Then
  do;
    say 'KRR Failed   (rc=' c2x(KRR_RC)' rs='c2x(KRR_rs)')' ;
    exit;
  end;

return;

/* --------------------------------------------------------------- */
/* CSNDKRR - Key Record Read (PKDS)                                */
/*                                                                 */
/* Reads a key token from the PKDS.                                */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNDKRR:
krr_rc = 'FFFFFFFF'x;
krr_rs = 'FFFFFFFF'x;
krr_exit_data_length = '00000000'x;
krr_exit_data    = '';
krr_rule_count   = '00000000'x;
krr_rule_array   = '';

ADDRESS LINKPGM "CSNDKRR",
                "krr_rc",
                "krr_rs",
                "krr_exit_data_length",
                "krr_exit_data",
                "krr_rule_count",
                "krr_rule_array",
                "krr_label",
                "krr_token_length",
                "krr_token";

if (KRR_RC /= '00000000'x) Then
  do;
    say 'KRR Failed   (rc=' c2x(KRR_RC)' rs='c2x(KRR_rs)')' ;
    exit;
  end;

return;

/* --------------------------------------------------------------- */
/* CSNBKRD - Key Record Delete (CKDS)                              */
/*                                                                 */
/* Deletes a key record from the CKDS.                             */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNBKRD:
krd_rc = 'FFFFFFFF'x;
krd_rs = 'FFFFFFFF'x;
krd_exit_data_length = '00000000'x;
krd_exit_data = '';
krd_rule_array_count = '00000001'x;
krd_rule_array = 'LABEL-DL';

ADDRESS LINKPGM "CSNBKRD",
                "krd_rc",
                "krd_rs",
                "krd_exit_data_length",
                "krd_exit_data",
                "krd_rule_array_count",
                "krd_rule_array",
                "krd_label";

if (KRD_RC /= '00000000'x & KRD_RS /= '0000271C'x) Then
  say 'KRD Failed   (rc=' c2x(KRD_RC)' rs='c2x(KRD_rs)')' ;

return;

/* --------------------------------------------------------------- */
/* CSNDKRD - Key Record Delete (PKDS)                              */
/*                                                                 */
/* Deletes a key record from the PKDS.                             */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNDKRD:
krd_rc = 'FFFFFFFF'x;
krd_rs = 'FFFFFFFF'x;
krd_exit_data_length = '00000000'x;
krd_exit_data = '';
krd_rule_array_count = '00000001'x;
krd_rule_array = 'LABEL-DL';

ADDRESS LINKPGM "CSNDKRD",
                "krd_rc",
                "krd_rs",
                "krd_exit_data_length",
                "krd_exit_data",
                "krd_rule_array_count",
                "krd_rule_array",
                "krd_label";

if (KRD_RC /= '00000000'x & KRD_RS /= '0000271C'x) Then
  say 'KRD Failed   (rc=' c2x(KRD_RC)' rs='c2x(KRD_rs)')' ;

return;

/* --------------------------------------------------------------- */
/* CSNDEDH - ECC Diffie-Hellman                                    */
/*                                                                 */
/* Creates symmetric key material from a pair of ECC keys.         */
/*                                                                 */
/* See the ICSF Application Programmer's Guide for more details.   */
/* --------------------------------------------------------------- */
CSNDEDH:

EDH_RC                    = 'FFFFFFFF'x;
EDH_RS                    = 'FFFFFFFF'x;
EDH_exit_data_length      = '00000000'x;
EDH_exit_data             = '';
EDH_private_kek_id_length = '00000000'x;
EDH_private_kek_id        = '';
EDH_chain_vector_length   = '00000000'x;
EDH_chain_vector          = '';
EDH_reserved_length       = '00000000'x;
EDH_reserved              = '';
EDH_reserved2_length      = '00000000'x;
EDH_reserved2             = '';
EDH_reserved3_length      = '00000000'x;
EDH_reserved3             = '';
EDH_reserved4_length      = '00000000'x;
EDH_reserved4             = '';
EDH_reserved5_length      = '00000000'x;
EDH_reserved5             = '';
EDH_output_kek_id_length  = '00000000'x;
EDH_output_kek_id         = '';

ADDRESS linkpgm "CSNDEDH",
   'EDH_RC'                          'EDH_RS'                     ,
   'EDH_exit_data_length'            'EDH_exit_data'              ,
   'EDH_rule_array_count'            'EDH_rule_array'             ,
   'EDH_private_key_id_length'       'EDH_private_key_id'         ,
   'EDH_private_kek_id_length'       'EDH_private_kek_id'         ,
   'EDH_public_key_id_length'        'EDH_public_key_id'          ,
   'EDH_chain_vector_length'         'EDH_chain_vector'           ,
   'EDH_party_id_length'             'EDH_party_id'               ,
   'EDH_key_bit_length'                                           ,
   'EDH_reserved_length'             'EDH_reserved'               ,
   'EDH_reserved2_length'            'EDH_reserved2'              ,
   'EDH_reserved3_length'            'EDH_reserved3'              ,
   'EDH_reserved4_length'            'EDH_reserved4'              ,
   'EDH_reserved5_length'            'EDH_reserved5'              ,
   'EDH_output_kek_id_length'        'EDH_output_kek_id'          ,
   'EDH_output_key_id_length'        'EDH_output_key_id'          ;

if (EDH_RC /= '00000000'x) Then
  do;
    say 'EDH Failed   (rc=' c2x(EDH_RC)' rs='c2x(EDH_rs)')' ;
    exit;
  end;

Return;

/* --------------------------------------------------------------- */
/* Debug ;-)                                                       */
/* --------------------------------------------------------------- */
NOVALUE:
Say "Condition NOVALUE was raised."
Say CONDITION("D") "variable was not initialized."
Say SOURCELINE(sigl)
Exit

0 comments
16 views

Permalink