Example: ILE RPG 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.
     D*************************************************************
     D* GENRETAIN
     D*
     D* Sample program to generate a retained key to be used for
     D* master key cloning.
     D*
     D*
     D* COPYRIGHT 5769-SS1 (C) IBM CORP. 2000, 2000
     D*
     D* This material contains programming source code for your
     D* consideration.  These example has not been thoroughly
     D* tested under all conditions.  IBM, therefore, cannot
     D* guarantee or imply reliability, serviceability, or function
     D* of these programs.  All programs contained herein are
     D* provided to you "AS IS".  THE IMPLIED WARRANTIES OF
     D* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     D* ARE EXPRESSLY DISCLAIMED.  IBM provides no program services for
     D* these programs and files.
     D*
     D*
     D* Note: Input format is more fully described in Chapter 2 of
     D*       IBM  CCA Basic Services Reference and Guide
     D*       (SC31-8609) publication.
     D*
     D* Parameters: RETAINED_KEY_NAME
     D*
     D* Example:
     D*   CALL PGM(GENRETAIN) PARM(TESTKEY)
     D*
     D* Use these commands to compile this program on the system:
     D* CRTRPGMOD MODULE(GENRETAIN) SRCFILE(SAMPLE)
     D* CRTPGM  PGM(GENRETAIN) MODULE(GENRETAIN)
     D*         BNDDIR(QCCA/QC6BNDDIR)
     D*
     D* Note: Authority to the CSNDPKG and CSNDPKB service programs
     D*       in the QCCA library is assumed.
     D*
     D* The Common Cryptographic Architecture (CCA) verbs used are
     D* PKA_Key_Token_Build (CSNDPKB) and PKA_Key_Generate (CSNDPKG).
     D*
     D**************************************************************
     D*--------------------------------------------------------
     D* Declare variables used by CCA SAPI calls
     D*--------------------------------------------------------
     D*                **  Return code
     DRETURNCODE       S              9B 0
     D*                **  Reason code
     DREASONCODE       S              9B 0
     D*                **  Exit data length
     DEXITDATALEN      S              9B 0
     D*                **  Exit data
     DEXITDATA         S              4
     D*                **  Rule array count
     DRULEARRAYCNT     S              9B 0
     D*                **  Rule array
     DRULEARRAY        S             16
     D*                **  Token length
     DTOKENLEN         S              9B 0 INZ(2500)
     D*                **  Token and array for subscripting
     DTOKEN            DS          2500
     DTOKENARRAY                      1    DIM(2500)
     D*                **  Regeneration data
     DREGENDATA        S              4    INZ(X'00000000')
     D*                **  Transport key encrypting key
     DTRANSPORTKEK     S              4    INZ(X'00000000')
     D*                **  Generated keyid
     DGENKEY           S           2500
     D*                **  Generated keyid length
     DGENKEYLEN        S              9B 0 INZ(2500)
     D*                **  Key name and length
     DKEYNAME          S             64
     DKEYNAMEL         S              9B 0 INZ(64)
     D*                **  Key structure for PKA Key Token Build
     DKEYSTRUCT        DS
     DMODLEN                   1      2B 0
     DMODLENFLD                3      4B 0
     DPUBEXPLEN                5      6B 0
     DPRVEXPLEN                7      8B 0
     DPUBEXP                   9     12B 0
     D*                **  Null parms needed for CSNDPKB and CSNDPKG
     DZERO             S              9B 0 INZ(0)
     DNULLPTR          S               *   INZ(*NULL)
     D*                **  Key structure length
     DKEYSTRUCTLEN     S              9B 0 INZ(12)
     D*                **  Data structure for aligning 2 bytes into
     D*                **  a 2 bytes integer
     DLENSTRUCT        DS             2
     DMSB                      1      1
     DLSB                      2      2
     DLENGTH                   1      2B 0
     D*                **  Private key section length
     DPRVSECLEN        S              9B 0
     D*                **  Public key section length
     DPUBSECLEN        S              9B 0
     D*                **  Index into Token array
     DINDEX            S              9B 0
     D*                **  Declares for copying private key name
     DNAMEPTR1         S               *
     DNAME1            S             64    BASED(NAMEPTR1)
     DNAMEPTR2         S               *
     DNAME2            S             64    BASED(NAMEPTR2)
     D*                **  Loop counter
     DI                S              9B 0
     D*                **  File descriptor
     DFILED            S              9B 0
     D*                **  File path and length
     DPATH             S             80    INZ(*ALLX'00')
     DPATHLEN          S              9B 0
     D*                ** Open flag - Create on open, open for writing,
     D*                **             and clear if exists
     DOFLAG            S             10I 0 INZ(X'4A')
     D*
     D**********************************************************
     D* Prototype for PKA_Key_Token_Build (CSNDPKB)
     D**********************************************************
     DCSNDPKB          PR
     DRETCODE                         9B 0
     DRSNCODE                         9B 0
     DEXTDTALEN                       9B 0
     DEXTDTA                          4
     DRARRAYCT                        9B 0
     DRARRAY                         16
     DKEYSTRLEN                       9B 0
     DKEYSTR                         10
     DKEYNML                          9B 0
     DKEYNM                          64
     DRSRVLN1                         9B 0
     DRSRV1                            *   VALUE
     DRSRVLN2                         9B 0
     DRSRV2                            *   VALUE
     DRSRVLN3                         9B 0
     DRSRV3                            *   VALUE
     DRSRVLN4                         9B 0
     DRSRV4                            *   VALUE
     DRSRVLN5                         9B 0
     DRSRV5                            *   VALUE
     DTKNLEN                          9B 0
     DTKN                          2500    OPTIONS(*VARSIZE)
     D*
     D**********************************************************
     D* Prototype for PKA_Key_Generate (CSNDPKG)
     D**********************************************************
     DCSNDPKG          PR
     DRETCOD                          9B 0
     DRSNCOD                          9B 0
     DEXTDTALN                        9B 0
     DEXTDT                           4
     DRARRYCT                         9B 0
     DRARRY                          16
     DREGDTAL                         9B 0
     DREGDTA                         20    OPTIONS(*VARSIZE)
     DSKTKNL                          9B 0
     DSKTKN                        2500    OPTIONS(*VARSIZE)
     DTRNKEK                         64    OPTIONS(*VARSIZE)
     DGENKEYL                         9B 0
     DGENKEY                       2500    OPTIONS(*VARSIZE)
     D*
     D**********************************************************
     D* Prototype for open()
     D**********************************************************
     D*    value returned = file descriptor (OK), -1 (error)
     Dopen             PR             9B 0 EXTPROC('open')
     D*    path name of file to be opened.
     D                              128    OPTIONS(*VARSIZE)
     D*    Open flags
     D                                9B 0 VALUE
     D*    (OPTIONAL) mode - access rights
     D                               10U 0 VALUE OPTIONS(*NOPASS)
     D*    (OPTIONAL) codepage
     D                               10U 0 VALUE OPTIONS(*NOPASS)
     D*
     D*********************************************************************
     D* Prototype for write()
     D**********************************************************
     D*    value returned = number of bytes actually written, or -1
     Dwrite            PR             9B 0 EXTPROC('write')
     D*    File descriptor returned from open()
     D                                9B 0 VALUE
     D*    Data to be written
     D                             1200    OPTIONS(*VARSIZE)
     D*    Length of data to write
     D                                9B 0 VALUE
     D*
     D*********************************************************************
     D* Prototype for close()
     D*********************************************************************
     D*    value returned = 0 (OK), or -1
     Dclose            PR             9B 0 EXTPROC('close')
     D*    File descriptor returned from open()
     D                                9B 0 VALUE
     D*
     D*-------------------------------------------------------------
     D*                **  Declares for sending messages to the
     D*                **  job log using the QMHSNDPM API
     D*-------------------------------------------------------------
     DMSG              S             75    DIM(4) CTDATA PERRCD(1)
     DMSGLENGTH        S              9B 0 INZ(75)
     D                 DS
     DMSGTEXT                  1     75
     DSAPI                     1      7
     DFAILRETC                41     44
     DFAILRSNC                46     49
     DMESSAGEID        S              7    INZ('       ')
     DMESSAGEFILE      S             21    INZ('                     ')
     DMSGKEY           S              4    INZ('    ')
     DMSGTYPE          S             10    INZ('*INFO     ')
     DSTACKENTRY       S             10    INZ('*         ')
     DSTACKCOUNTER     S              9B 0 INZ(2)
     DERRCODE          DS
     DBYTESIN                  1      4B 0 INZ(0)
     DBYTESOUT                 5      8B 0 INZ(0)
     C*
     C**************************************************************
     C* START OF PROGRAM                                           *
     C*                                                            *
     C     *ENTRY        PLIST
     C                   PARM                    KEYNAMEPARM      50
     C*   *------------------------*
     C*   * Initialize tokens to 0 *
     C*   *------------------------*
     C                   MOVEL     *ALLX'00'     TOKEN
     C                   MOVEL     *ALLX'00'     GENKEY
     C*   *------------------------*
     C*   * Initialize key struct  *
     C*   *------------------------*
     C                   Z-ADD     1024          MODLEN
     C                   Z-ADD     0             MODLENFLD
     C                   Z-ADD     3             PUBEXPLEN
     C                   Z-ADD     0             PRVEXPLEN
     C                   EVAL      PUBEXP = 65537 * 256
     C*   *------------------------*
     C*   * Copy key name from parm*
     C*   *------------------------*
     C                   MOVEL     KEYNAMEPARM   KEYNAME
     C*   *------------------------------------*
     C*   * Set the keywords in the rule array *
     C*   *------------------------------------*
     C                   MOVEL     'RSA-PRIV'    RULEARRAY
     C                   MOVE      'KEY-MGMT'    RULEARRAY
     C                   Z-ADD     2             RULEARRAYCNT
     C**************************************************************
     C* Call PKA_Key_Token_Build SAPI
     C**************************************************************
     C                   CALLP     CSNDPKB       (RETURNCODE:
     C                                            REASONCODE:
     C                                            EXITDATALEN:
     C                                            EXITDATA:
     C                                            RULEARRAYCNT:
     C                                            RULEARRAY:
     C                                            KEYSTRUCTLEN:
     C                                            KEYSTRUCT:
     C                                            KEYNAMEL:
     C                                            KEYNAME:
     C                                            ZERO:
     C                                            NULLPTR:
     C                                            ZERO:
     C                                            NULLPTR:
     C                                            ZERO:
     C                                            NULLPTR:
     C                                            ZERO:
     C                                            NULLPTR:
     C                                            ZERO:
     C                                            NULLPTR:
     C                                            TOKENLEN:
     C                                            TOKEN)
     C*   *------------------------*
     C*   * Check the return code  *
     C*   *------------------------*
     C     RETURNCODE    IFGT      0
     C*     *------------------------*
     C*     * Send failure message   *
     C*     *------------------------*
     C                   MOVEL     MSG(1)        MSGTEXT
     C                   MOVE      RETURNCODE    FAILRETC
     C                   MOVE      REASONCODE    FAILRSNC
     C                   MOVEL     'CSNDPKB'     SAPI
     C                   EXSR      SNDMSG
     C                   RETURN
     C                   ENDIF
     C*
     C*------------------------------------------------------------*
     C* Build the certificate                                      *
     C*------------------------------------------------------------*
     C*    Get the private section length.  The length is at position 11
     C*    of the token
     C                   EVAL      MSB = TOKENARRAY(10+1)
     C                   EVAL      LSB = TOKENARRAY(11+1)
     C                   MOVE      LENGTH        PRVSECLEN
     C*    Get the public section length.  The length is at position
     C*    (11 + Private key section length).
     C                   EVAL      MSB = TOKENARRAY(10 + PRVSECLEN + 1)
     C                   EVAL      LSB = TOKENARRAY(11 + PRVSECLEN + 1)
     C                   MOVE      LENGTH        PUBSECLEN
     C*    Calculate the certificate section length
     C*       Cert Section length = Signature length (328) +
     C*                             EID section length (20) +
     C*                             Serial number length (12) +
     C*                             Info subsection header length (4) +
     C*                             Public Key section length +
     C*                             Cert section header length (4)
     C                   EVAL      LENGTH = 328 + 20 + 12 + 4 + PUBSECLEN + 4
     C*    Fill Certificate section header
     C                   MOVE      TOKENLEN      INDEX
     C                   EVAL      TOKENARRAY(INDEX +1) = X'40'
     C                   EVAL      TOKENARRAY(INDEX +2) = X'00'
     C                   EVAL      TOKENARRAY(INDEX +3) = MSB
     C                   EVAL      TOKENARRAY(INDEX +4) = LSB
     C*    Fill in public key subsection
     C                   EVAL      TOKENARRAY(INDEX +5) = X'41'
     C                   ADD       5             INDEX
     C                   Z-ADD     1             I
     C*    Copy the public key section of the token into the public key
     C*    subsection of the certificate section.
     C     I             DOWLT     PUBSECLEN
     C                   EVAL      TOKENARRAY(INDEX + I) =
     C                              TOKENARRAY(PRVSECLEN + I + 8 + 1)
     C     1             ADD       I             I
     C                   ENDDO
     C                   EVAL      INDEX  = INDEX + PUBSECLEN - 1
     C*    Fill in Optional Information subsection header
     C                   Z-ADD     36            LENGTH
     C                   EVAL      TOKENARRAY(INDEX +1) = X'42'
     C                   EVAL      TOKENARRAY(INDEX +2) = X'00'
     C                   EVAL      TOKENARRAY(INDEX +3) = MSB
     C                   EVAL      TOKENARRAY(INDEX +4) = LSB
     C*    Fill in Public Key Certficate EID
     C                   EVAL      INDEX  = INDEX  + 4
     C                   EVAL      TOKENARRAY(INDEX +1) = X'51'
     C                   EVAL      TOKENARRAY(INDEX +4) = X'14'
     C*    Fill in Public Key Certficate Serial Number TLV
     C                   EVAL      INDEX  = INDEX  + 20
     C                   EVAL      TOKENARRAY(INDEX +1) = X'52'
     C                   EVAL      TOKENARRAY(INDEX +4) = X'0C'
     C*    Fill in Signature Subsection
     C                   EVAL      INDEX  = INDEX  + 12
     C                   EVAL      TOKENARRAY(INDEX +1) = X'45'
     C                   EVAL      TOKENARRAY(INDEX +3) = X'01'
     C                   EVAL      TOKENARRAY(INDEX +4) = X'48'
     C                   EVAL      TOKENARRAY(INDEX +5) = X'01'
     C                   EVAL      TOKENARRAY(INDEX +6) = X'01'
     C*    Fill in private key name
     C                   EVAL      INDEX  = INDEX  + 6
     C                   EVAL      NAMEPTR1 = %ADDR(TOKENARRAY(INDEX +1))
     C                   EVAL      NAMEPTR2 =
     C                              %ADDR(TOKENARRAY(PRVSECLEN+PUBSECLEN+12+1))
     C                   MOVEL     NAME2         NAME1
     C*    Adjust token length
     C                   EVAL      LENGTH = INDEX  + 64 + 258
     C                   MOVE      MSB           TOKENARRAY(3)
     C                   MOVE      LSB           TOKENARRAY(4)
     C                   EVAL      TOKENLEN = LENGTH
     C*   *------------------------------------*
     C*   * Set the keywords in the rule array *
     C*   *------------------------------------*
     C                   MOVEL     'RETAIN  '    RULEARRAY
     C                   MOVE      'CLONE   '    RULEARRAY
     C                   Z-ADD     2             RULEARRAYCNT
     C
     C*------------------------------------------------------*
     C* Call PKA_Key_Generate SAPI                           *
     C*------------------------------------------------------*
     C                   CALLP     CSNDPKG       (RETURNCODE:
     C                                            REASONCODE:
     C                                            EXITDATALEN:
     C                                            EXITDATA:
     C                                            RULEARRAYCNT:
     C                                            RULEARRAY:
     C                                            ZERO:
     C                                            REGENDATA:
     C                                            TOKENLEN:
     C                                            TOKEN:
     C                                            TRANSPORTKEK:
     C                                            GENKEYLEN:
     C                                            GENKEY)
     C*-----------------------*
     C* Check the return code *
     C*-----------------------*
     C     RETURNCODE    IFGT      0
     C*      *----------------------*
     C*      * Send failure message *
     C*      *----------------------*
     C                   MOVEL     MSG(1)        MSGTEXT
     C                   MOVE      RETURNCODE    FAILRETC
     C                   MOVE      REASONCODE    FAILRSNC
     C                   MOVEL     'CSNDPKG'     SAPI
     C                   EXSR      SNDMSG
     C                   RETURN
     C                   ENDIF
     C*
     C*      *----------------------*
     C*      * Send success message *
     C*      *----------------------*
     C                   MOVEL     MSG(2)        MSGTEXT
     C                   EXSR      SNDMSG
     C*
     C*-------------------------------*
     C* Write certificate out to file *
     C*-------------------------------*
     C*    ** Build path name
     C                   EVAL      PATHLEN = %LEN(%TRIM(KEYNAMEPARM))
     C     PATHLEN       SUBST     KEYNAMEPARM:1 PATH
     C                   EVAL      %SUBST(PATH:PATHLEN+1:4) = '.PUB'
     C*
     C*    ** Open the file
     C*
     C                   EVAL      FILED = open(PATH: OFLAG)
     C*
     C*    ** Check if open worked
     C*
     C     FILED         IFEQ      -1
     C*
     C*      ** Open failed, send an error message
     C*
     C                   MOVEL     MSG(3)        MSGTEXT
     C                   EXSR      SNDMSG
     C*
     C                   ELSE
     C*
     C*      ** Open worked, write certificate out to file and close file
     C*
     C                   CALLP     write         (FILED:
     C                                            GENKEY:
     C                                            GENKEYLEN)
     C                   CALLP     close         (FILED)
     C*
     C*      ** Send completion message
     C*
     C                   MOVEL     MSG(4)        MSGTEXT
     C                   EVAL      %SUBST(MSGTEXT: 32: PATHLEN + 4) =
     C                                     %SUBST(PATH: 1: PATHLEN + 4)
     C                   EXSR      SNDMSG
     C                   ENDIF
     C*
     C                   SETON                                            LR
     C*
     C**************************************************************
     C* Subroutine to send a message
     C**************************************************************
     C     SNDMSG        BEGSR
     C                   CALL      'QMHSNDPM'
     C                   PARM                    MESSAGEID
     C                   PARM                    MESSAGEFILE
     C                   PARM                    MSGTEXT
     C                   PARM                    MSGLENGTH
     C                   PARM                    MSGTYPE
     C                   PARM                    STACKENTRY
     C                   PARM                    STACKCOUNTER
     C                   PARM                    MSGKEY
     C                   PARM                    ERRCODE
     C                   ENDSR
     C*
**
CSNDPKB failed with return/reason codes 9999/9999.
The retained key was successfully created.
The file could not be opened.
The certificate was written to