Example: ILE RPG program for registering a public key hash

Change this program example to suit your needs for registering a hash of a public key certificate.

Change this program example to suit your needs for registering a hash of a public key certificate.
Note: Read the Code license and disclaimer information for important legal information.
     D*************************************************************
     D* REGHASH
     D*
     D* Sample program to register the hash of a CCA public key
     D* certificate.
     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: Stream file containing public key certificate
     D*
     D* Example:
     D*   CALL PGM(REGHASH) PARM(CERTFILE)
     D*
     D* Use these commands to compile this program on the system:
     D* CRTRPGMOD MODULE(REGHASH) SRCFILE(SAMPLE)
     D* CRTPGM  PGM(REGHASH) MODULE(REGHASH)
     D*         BNDDIR(QCCA/QC6BNDDIR)
     D*
     D* Note: Authority to the CSNDPKH and CSNBOWH service programs
     D*       in the QCCA library is assumed.
     D*
     D* The Common Cryptographic Architecture (CCA) verbs used are
     D* PKA_Public_Key_Hash_Register (CSNDPKH) and One_Way_Hash
     C* (CSNBOWH).
     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 token
     DTOKEN            DS          2500
     DTOKENARRAY                      1    DIM(2500)
     D*                **  Chaining vector length
     DCHAINVCTLEN      S              9B 0 INZ(128)
     D*                **  Chaining vector
     DCHAINVCT         S            128
     D*                **  Hash length
     DHASHLEN          S              9B 0 INZ(20)
     D*                **  Hash
     DHASH             S             20
     D*                **  Text length
     DTXTLENGTH        S              9B 0
     D*                **  Name of retained key
     DNAME             S             64
     D*                **  Structure used for aligning 2 bytes into a
     D*                **  2 byte integer.
     DLENSTRUCT        DS             2
     DMSB                      1      1
     DLSB                      2      2
     DLENGTH                   1      2B 0
     D*
     D*                **  Certificate section length
     DCRTSECLEN        S              9B 0
     D*                **  Public key section length
     DPUBSECLEN        S              9B 0
     D*                **  Index into PKA key token
     DTKNINDEX         S              9B 0
     D*                **  Index into PKA key token
     DTMPINDEX         S              9B 0
     D*                **  File descriptor
     DFILED            S              9B 0
     D*                **  File path and path length
     DPATH             S             80    INZ(*ALLX'00')
     DPATHLEN          S              9B 0
     D*                ** Open Flag - Open for Read only
     DOFLAG            S             10I 0 INZ(1)
     D*
     D**********************************************************
     D* Prototype for PKA_Public_Key_Hash_Register (CSNDPKH)
     D**********************************************************
     DCSNDPKH          PR
     DRETCOD                          9B 0
     DRSNCOD                          9B 0
     DEXTDTALN                        9B 0
     DEXTDT                           4
     DRARRYCT                         9B 0
     DRARRY                          16
     DKYNAM                          64
     DHSHL                            9B 0
     DHSH                            20    OPTIONS(*VARSIZE)
     D*
     D**********************************************************
     D* Prototype for One_Way_Hash (CSNBOWH)
     D**********************************************************
     DCSNBOWH          PR
     DRETCOD                          9B 0
     DRSNCOD                          9B 0
     DEXTDTALN                        9B 0
     DEXTDT                           4
     DRARRYCT                         9B 0
     DRARRY                          16
     DTXTLEN                          9B 0
     DTXT                           500    OPTIONS(*VARSIZE)
     DCHNVCTLEN                       9B 0
     DCHNVCT                        128
     DHSHLEN                          9B 0
     DHSH                            20
     D*
     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 read()
     D**********************************************************
     D*    value returned = number of bytes actually read, or -1
     Dread             PR             9B 0 EXTPROC('read')
     D*    File descriptor returned from open()
     D                                9B 0 VALUE
     D*    Input buffer
     D                             2500    OPTIONS(*VARSIZE)
     D*    Length of data to be read
     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(6) CTDATA PERRCD(1)
     DMSGLENGTH        S              9B 0 INZ(75)
     D                 DS
     DMSGTEXT                  1     80
     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                    FILEPARM         50
     C**************************************************************
     C* Open certificate file
     C**************************************************************
     C*   *---------------------*
     C*   ** Build path name    *
     C*   *---------------------*
     C                   EVAL      PATHLEN = %LEN(%TRIM(FILEPARM))
     C     PATHLEN       SUBST     FILEPARM:1    PATH
     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(1)        MSGTEXT
     C                   EXSR      SNDMSG
     C                   RETURN
     C*
     C                   ENDIF
     C*     *--------------------------------------------------*
     C*     * Open worked, read certificate and close the file *
     C*     *--------------------------------------------------*
     C                   EVAL      TOKENLEN = read(FILED: TOKEN: TOKENLEN)
     C                   CALLP     close         (FILED)
     C*
     C*     *--------------------------------------*
     C*     * Check if read operation was OK       *
     C*     *--------------------------------------*
     C     TOKENLEN      IFEQ      -1
     C                   MOVEL     MSG(2)        MSGTEXT
     C                   EXSR      SNDMSG
     C                   RETURN
     C                   ENDIF
     C*
     C*     *--------------------------------------*
     C*     * Check if certificate length is valid *
     C*     * The length bytes start at position 3 *
     C*     *--------------------------------------*
     C                   EVAL      MSB = TOKENARRAY(3)
     C                   EVAL      LSB = TOKENARRAY(4)
     C     LENGTH        IFLT      TOKENLEN
     C*        *-----------------------------------*
     C*        * Certificate length is not valid   *
     C*        *-----------------------------------*
     C                   MOVEL     MSG(3)        MSGTEXT
     C                   EXSR      SNDMSG
     C                   RETURN
     C                   ENDIF
     C*
     C**************************************************************
     C* Find the certificate in the token
     C*
     C* The layout of the token is
     C*
     C* - Token header - 8 bytes - including 2 length bytes
     C* - Public key section - length bytes at position 3 (11 overall)
     C* - Private key name - 68 bytes
     C* - Certificate section
     C*
     C* Note: 1 is added because RPG arrays start at 1.
     C**************************************************************
     C                   EVAL      MSB = TOKENARRAY(11)
     C                   EVAL      LSB = TOKENARRAY(12)
     C                   EVAL      PUBSECLEN = LENGTH
     C                   EVAL      TKNINDEX = PUBSECLEN + 68 + 8 + 1
     C*
     C*     *-----------------------------------------*
     C*     * Determine length of certificate section *
     C*     * Length bytes are at position 2 of the   *
     C*     * section.
     C*     *-----------------------------------------*
     C                   EVAL      MSB = TOKENARRAY(TKNINDEX + 2)
     C                   EVAL      LSB = TOKENARRAY(TKNINDEX + 3)
     C                   EVAL      CRTSECLEN = LENGTH
     C                   EVAL      TMPINDEX = TKNINDEX + 4
     C*
     C*     *-----------------------------------------------------*
     C*     * Parse each subsection of the certificate until the  *
     C*     * signature subsection is found or the end is reached.*
     C*     * (Identifier for signature subsection is Hex 45.)    *
     C*     *-----------------------------------------------------*
     C                   DOW       (TOKENARRAY(TMPINDEX) <> X'45') AND
     C                             (TMPINDEX < TKNINDEX + CRTSECLEN)
     C                   EVAL      MSB = TOKENARRAY(TMPINDEX + 2)
     C                   EVAL      LSB = TOKENARRAY(TMPINDEX + 3)
     C     TMPINDEX      ADD       LENGTH        TMPINDEX
     C                   ENDDO
     C*
     C*     *----------------------------------------------------*
     C*     * Check if no signature was found before the end of  *
     C*     * the certificate section.                           *
     C*     *----------------------------------------------------*
     C                   IF        TOKENARRAY(TMPINDEX) <> X'45'
     C                   MOVEL     MSG(4)        MSGTEXT
     C                   EXSR      SNDMSG
     C                   RETURN
     C                   ENDIF
     C*
     C**************************************************************
     C* Hash the certificate
     C**************************************************************
     C*   *------------------------------------------*
     C*   * Calculate the length to hash             *
     C*   *------------------------------------------*
     C                   EVAL      TXTLENGTH = TMPINDEX - TKNINDEX + 70
     C*   *------------------------------------------*
     C*   * Set the keywords in the rule array       *
     C*   *------------------------------------------*
     C                   MOVEL     'SHA-1   '    RULEARRAY
     C                   Z-ADD     1             RULEARRAYCNT
     C*   *-------------------------*
     C*   * Call One Way Hash SAPI  *
     C*   *-------------------------*
     C                   CALLP     CSNBOWH       (RETURNCODE:
     C                                            REASONCODE:
     C                                            EXITDATALEN:
     C                                            EXITDATA:
     C                                            RULEARRAYCNT:
     C                                            RULEARRAY:
     C                                            TXTLENGTH:
     C                                            TOKENARRAY(TKNINDEX):
     C                                            CHAINVCTLEN:
     C                                            CHAINVCT:
     C                                            HASHLEN:
     C                                            HASH)
     C*  *------------------------*
     C*  * Check the return code  *
     C*  *------------------------*
     C     RETURNCODE    IFGT      0
     C*     *-----------------------*
     C*     *  Send failure message *
     C*     *-----------------------*
     C                   MOVEL     MSG(5)        MSGTEXT
     C                   MOVE      RETURNCODE    FAILRETC
     C                   MOVE      REASONCODE    FAILRSNC
     C                   MOVEL     'CSNBOWH'     SAPI
     C                   EXSR      SNDMSG
     C                   RETURN
     C                   ENDIF
     C*
     C**************************************************************
     C* Register the certificate hash
     C**************************************************************
     C*   *------------------------------------------*
     C*   * Set the keywords in the rule array       *
     C*   *------------------------------------------*
     C                   MOVEL     'SHA-1   '    RULEARRAY
     C                   MOVE      'CLONE   '    RULEARRAY
     C                   Z-ADD     2             RULEARRAYCNT
     C*   *------------------------------------------*
     C*   * Build the key name (FILENAME.RETAINED)   *
     C*   *------------------------------------------*
     C                   EVAL      %SUBST(NAME: 1: PATHLEN) =
     C                                     %SUBST(PATH: 1: PATHLEN)
     C                   EVAL      %SUBST(NAME:PATHLEN+1:9) = '.RETAINED'

     C*   *-----------------------------------*
     C*   * Call PKA Public Key Hash Register *
     C*   *-----------------------------------*
     C                   CALLP     CSNDPKH       (RETURNCODE:
     C                                            REASONCODE:
     C                                            EXITDATALEN:
     C                                            EXITDATA:
     C                                            RULEARRAYCNT:
     C                                            RULEARRAY:
     C                                            NAME:
     C                                            HASHLEN:
     C                                            HASH)
     C*  *------------------------*
     C*  * Check the return code  *
     C*  *------------------------*
     C     RETURNCODE    IFGT      0
     C*     *-----------------------*
     C*     *  Send failure message *
     C*     *-----------------------*
     C                   MOVEL     MSG(5)        MSGTEXT
     C                   MOVE      RETURNCODE    FAILRETC
     C                   MOVE      REASONCODE    FAILRSNC
     C                   MOVEL     'CSNDPKH'     SAPI
     C                   EXSR      SNDMSG
     C                   ELSE
     C*     *-----------------------*
     C*     *  Send success message *
     C*     *-----------------------*
     C                   MOVEL     MSG(6)        MSGTEXT
     C                   EVAL      %SUBST(MSGTEXT: 41: PATHLEN + 9) =
     C                                     %SUBST(NAME: 1: PATHLEN + 9)
     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
**
The file could not be opened.
There was an error reading from the file.
The length of the certificate is not valid.
The certificate is not valid.
CSNBOWH failed with return/reason codes 9999/9999.
The hash was successfully registered as