Example: ILE C program for generating a retained key pair for cloning master keys

Change this program example to suit your needs for generating a retained key pair for cloning master keys

.
Note: Read the Code license and disclaimer information for important legal information.
/*-------------------------------------------------------------------*/
/* GENRETAIN                                                         */
/*                                                                   */
/* Sample program to generate a retained key to be used for          */
/* master key cloning.                                               */
/*                                                                   */
/*  COPYRIGHT 5769-SS1 (C) IBM CORP. 1999, 1999                      */
/*                                                                   */
/*  This material contains programming source code for your          */
/*  consideration.  These examples have not been thoroughly          */
/*  tested under all conditions.  IBM, therefore, cannot             */
/*  guarantee or imply reliability, serviceability, or function      */
/*  of these program.  All programs contained herein are             */
/*  provided to you "AS IS".  THE IMPLIED WARRANTIES OF              */
/*  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE         */
/*  ARE EXPRESSLY DISCLAIMED.  IBM provides no program services for  */
/*  these programs and files.                                        */
/*                                                                   */
/*                                                                   */
/* Note: Input format is more fully described in Chapter 2 of        */
/*       IBM  CCA Basic Services Reference and Guide             */
/*       (SC31-8609) publication.                                    */
/*                                                                   */
/* Parameters: RETAINED_KEY_NAME                                     */
/*                                                                   */
/* Example:                                                          */
/*   CALL PGM(GENRETAIN) PARM(TESTKEY)                               */
/*                                                                   */
/*                                                                   */
/* Note: This program assumes the card with the profile is           */
/*       already identified either by defaulting to the CRP01        */
/*       device or by being explicitly named using the               */
/*       Cryptographic_Resource_Allocate verb. Also this             */
/*       device must be varied on and you must be authorized         */
/*       to use this device description.                             */
/*                                                                   */
/* The Common Cryptographic Architecture (CCA) verbs used are        */
/* PKA_Key_Token_Build (CSNDPKB) and PKA_Key_Generate (CSNDPKG).     */
/*                                                                   */
/* Use these commands to compile this program on the system:         */
/* ADDLIBLE LIB(QCCA)                                                */
/* CRTCMOD MODULE(GENRETAIN) SRCFILE(SAMPLE)                         */
/* CRTPGM  PGM(GENRETAIN)  MODULE(GENRETAIN)                         */
/*         BNDDIR(QCCA/QC6BNDDIR)                                    */
/*                                                                   */
/* Note: Authority to the CSNDPKG and CSNDPKB service programs       */
/*       in the QCCA library is assumed.                             */
/*                                                                   */
/*-------------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include "csucincl.h"

int main(int argc, char *argv[])
 {
 /*------------------------------------------------------------------*/
 /* Declares for CCA parameters                                      */
 /*------------------------------------------------------------------*/
 long return_code = 0;
 long reason_code = 0;
 long exit_data_length = 0;
 char exit_data[4];
 char rule_array[24];
 long rule_array_count;
 long token_len = 2500;
 char token[2500];
 char regen_data[4];
 char transport_key_id[4];
 struct {
        short modlen;
        short modlenfld;
        short pubexplen;
        short prvexplen;
        long  pubexp;
       } key_struct;        /* Key structure for PKA Key Token Build */
 long key_struct_length;
 long zero = 0;
 /*------------------------------------------------------------------*/
 /* Declares for working with a PKA token                            */
 /*------------------------------------------------------------------*/
 long pub_sec_len;          /* Public section length                 */
 long prv_sec_len;          /* Private section length                */
 long cert_sec_len;         /* Certificate section length            */
 long info_subsec_len;      /* Information subsection length         */
 long offset;               /* Offset into token                     */
 long tempOffset;           /* (Another) Offset into token           */
 long tempLength;           /* Length variable                       */
 long tempLen1, tempLen2;   /* temporary length variables            */
 char pub_token[2500];
 long pub_token_len;
 long name_len;
 char name[64];


 int i;                     /* Loop counter                          */
 FILE *fp;                  /* File pointer                          */


 if (argc < 2)              /* Check the number of parameters passed */
  {
    printf("Need to enter a private key name\n");
    return 1;
  }

  memset(token,0,2500);     /* Initialize token to 0                 */
  memcpy((void*)rule_array,"RSA-PRIVKEY-MGMT",16); /* Set rule array */
  rule_array_count = 2;

  memset(name,' ', 64);     /* Copy key name parameter               */
  memcpy(name, argv[1], strlen(argv[1]));
  name_len = 64;

  /*---------------------------*/
  /* Initialize key structure  */
  /*---------------------------*/
  memset((void*)&key_struct, 0, sizeof(key_struct));
  key_struct.modlen = 1024;         /* Modulus length is 1024        */
  key_struct.pubexplen = 3;
  key_struct.pubexp = 0x01000100;   /* Public exponent is 65537      */
  key_struct_length = sizeof(key_struct);
  /*****************************************/
  /* Call PKA_Key_Token_Build SAPI         */
  /*****************************************/
  CSNDPKB( &return_code, &reason_code, &exit_data_length,
           exit_data,
           &rule_array_count,
           rule_array,
           &key_struct_length,
           (unsigned char *)&key_struct,
           &name_len,
           name,
           &zero,            /* 1 */
           NULL,
           &zero,           /* 2 */
           NULL,
           &zero,           /* 3 */
           NULL,
           &zero,           /* 4 */
           NULL,
           &zero,           /* 5 */
           NULL,
           &token_len,
           token);

    if (return_code != 0)
    {
     printf("PKA Key Token Build Failed : return code %d : reason code %d\n",
             return_code, reason_code);
      return 1;
    }

    /**************************************************************/
    /* Build certificate                                          */
    /**************************************************************/
                            /* Determine length of token from length */
                            /* bytes at offset 2 and 3.              */
    token_len = ((256 * token[2]) + token[3]);
                            /* Determine length of private key       */
                            /* section from length bytes at offset   */
                            /* 10.                                   */
    prv_sec_len = ((256 * token[10]) + token[11]);
                            /* Determine length of public key section*/
                            /* section from length bytes at offset   */
                            /* 10 + private section length           */
    pub_sec_len = ((256 * token[prv_sec_len + 10]) +
                   token[prv_sec_len +   11]);

                            /* Calculate the signature section length*/
    cert_sec_len = 328 +    /* from the signature subsection length, */
                   20  +    /* EID subsection length,                */
                   12  +    /* Serial number subsection length,      */
                   4   +    /* Information subsection header length, */
                   pub_sec_len +  /* Public key subsection length,   */
                   4;       /* and the certificate section hdr length*/

    offset = token_len;     /* Offset for additions to token         */

    /* Fill in certicate section header      */
    tempLen1 = cert_sec_len;
    tempLen1 >>= 8;
    token[offset++] = 0x40;
    token[offset++] = 0x00;
    token[offset++] = tempLen1;
    token[offset++] = cert_sec_len;

    /* Fill in public key subsection */
    token[offset++] = 0x41;
    for (i = 1 ; i < pub_sec_len  ; i ++)
     {
       /* Copy public key to certificate */
        token[offset++] = token[prv_sec_len +(i+8)];
     }

    /* Fill Optional Information Subsection Header */
    info_subsec_len = 20  +  /* Length of EID section                */
                      12  +  /* Length of serial number section      */
                      4;     /* Length of Info subsection header     */
    tempLen1 = info_subsec_len;
    tempLen1 >>= 8;
    token[offset++] = 0x42;
    token[offset++] = 0x00;
    token[offset++] = tempLen1;
    token[offset++] = info_subsec_len;

    /* Fill in Public Key Certficate EID subsection */
    token[offset++] = 0x51;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x14;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;

    /* Public key Certificate Serial Number TLV */
    token[offset++] = 0x52;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x0c;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;
    token[offset++] = 0x00;

    /* Fill in Signature Subsection */
    token[offset++] = 0x45;
    token[offset++] = 0x00;
    token[offset++] = 0x01;
    token[offset++] = 0x48;
    token[offset++] = 0x01;
    token[offset++] = 0x01;

    for (i = 0 ; i < 64 ;i++)
          {
           /* Copy private key name out of private key name section */
           /* into certificate                                      */
           token[offset++] =
                token[prv_sec_len + pub_sec_len + 12 + i];
          }

    token_len = offset + 258;     /* add 258 to allow for digtal sig. */
    token[3] = token_len;         /* Set new token length  */
    token[2] = token_len >> 8;


    /******************************************************************/
    /* Generate Retained key using PKA token with certificate         */
    /******************************************************************/
    memcpy((void*)rule_array,"RETAIN  CLONE   ",16);
    rule_array_count = 2;
    memset(pub_token,0,2500);
    pub_token_len = 2500;
    memset(transport_key_id,0,4);

   /*****************************************/
   /* Call PKA_Key_Generate SAPI            */
   /*****************************************/
    CSNDPKG( &return_code, &reason_code, &exit_data_length,
             exit_data,
             &rule_array_count,
             rule_array,
             &zero,               /* regenerated data length         */
             regen_data,
             &token_len,
             token,
             transport_key_id,
             &pub_token_len,
             pub_token);

    if (return_code != 0)
    {
     printf("PKA Key Generate Failed : return code %d :reason code %d\n",
               return_code, reason_code);
      return 1;
    }

    /******************************************************************/
    /* Write public key token out to file                             */
    /******************************************************************/
                            /* Append ".PUB" to key name             */
    memcpy((void*)&name[strlen(argv[1])],".PUB",5);
    fp = fopen(name,"wb");  /* Open the file                         */

    if (!fp)
      {
       printf("File open failed\n");
      }
    else
      {
       fwrite(pub_token,pub_token_len,1,fp);  /* Write token to file */

       fclose(fp);          /* Close the file                        */
       printf("Public token written to file %s.\n",name);
      }


    name[strlen(argv[1])] = 0;  /* Convert name to string            */
    printf("Private key %s is retained in the hardware\n",name);
    return 0;
}