Example: Encrypting data with your Cryptographic Coprocessor

Change this program example to suit your needs for encrypting data with your Cryptographic Coprocessor.

Note: Read the Code license and disclaimer information for important legal information.

If you choose to use this program example, change it to suit your specific needs. For security reasons, IBM® recommends that you individualize these program examples rather than using the default values provided.

/*-------------------------------------------------------------------*/
/*                                                                   */
/* Sample C program for enciphering data in a file.                  */
/*                                                                   */
/*  COPYRIGHT      5769-SS1 (c) IBM Corp 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 programs.  All programs contained herein are            */
/*  provided to you "AS IS". THE IMPLIED WARRANTIES OF               */
/*  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE         */
/*  EXPRESSLY DISCLAIMED. IBM provides no program services for       */
/*  these programs and files.                                        */
/*                                                                   */
/* Parameters:                                                       */
/*  char * key label,  1 to 64 characters                            */
/*  char * input file name,  1 to 21 characters (lib/file)           */
/*  char * output file name,  1 to 21 characters (lib/file)          */
/*                                                                   */
/* Example:                                                          */
/*   CALL PGM(ENCFILE) PARM( 'MY.KEY.LABEL' 'QGPL/MYDATA' +          */
/*                           'QGPL/CRYPTDATA' )                      */
/*                                                                   */
/* Note: This program assumes the device you want to use is          */
/*       already identified either by defaulting to the CRP01        */
/*       device or has been 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.                             */
/*                                                                   */
/*       This program assumes the key store file you will use is     */
/*       already identifed either by being specified on the          */
/*       cryptographic device or has been previously named           */
/*       using the Key_Store_Designate verb. Also you must be        */
/*       authorized to add and update records in this file.          */
/*                                                                   */
/*       The output file should NOT have key fields since all        */
/*       data in the file will be encrypted and therefore trying     */
/*       to sort the data will be meaningless.                       */
/*       (This is NOT checked by the program)                        */
/*                                                                   */
/* Use the following commands to compile this program:               */
/* ADDLIBLE LIB(QCCA)                                                */
/* CRTCMOD MODULE(ENCFILE) SRCFILE(SAMPLE)                           */
/* CRTPGM  PGM(ENCFILE) MODULE(ENCFILE) +                            */
/*         BNDSRVPGM(QCCA/CSNBENC)                                   */
/*                                                                   */
/* Note: authority to the CSNBENC service program in the             */
/*       QCCA library is assumed.                                    */
/*                                                                   */
/* Common Cryptographic Architecture (CCA) verbs used:               */
/*   Encipher (CSNBENC)                                              */
/*                                                                   */
/*-------------------------------------------------------------------*/


/*-------------------------------------------------------------------*/
/* Retrieve various structures/utilities that are used in program.   */
/*-------------------------------------------------------------------*/

#include <stdio.h>                /* Standard I/O header.            */
#include <stdlib.h>               /* General utilities.              */
#include <stddef.h>               /* Standard definitions.           */
#include <string.h>               /* String handling utilities.      */
#include "csucincl.h"             /* header file for CCA Cryptographic
                                    Service Provider                       */

/*-------------------------------------------------------------------*/
/* Declares for working with files.                                  */
/*-------------------------------------------------------------------*/
#include <xxfdbk.h>               /* Feedback area structures.       */
#include <recio.h>                /* Record I/O routines             */
_RFILE           *dbfptr;        /* Pointer to database file.        */
_RFILE           *dbfptre;       /* Pointer to database file.        */
_RIOFB_T         *db_fdbk;       /* I/O Feedback - data base file    */
_XXOPFB_T        *db_opfb;
_XXOPFB_T        *db_opfbe;


/*-------------------------------------------------------------------*/
/* Declares for working with user space objects.                     */
/*-------------------------------------------------------------------*/
#include "qusptrus.h"
#include "quscrtus.h"
#include "qusdltus.h"
#define USSPC_ATTR              "PF        "
#define USSPC_INIT_VAL          0x40
#define USSPC_AUTH              "*EXCLUDE  "
#define USSPC_TEXT              "Sample user space"
#define USSPC_REPLACE           "*YES      "
      
char     space_name[21] = "PLAINTXT  QTEMP     "; /* Name of user
                                   space for plain text              */
char     cipher_name[21] = "CIPHER    QTEMP     "; /* Name for user
                                   space containing ciphertext       */

struct {                        /* Error code structure required for */
                                /* the User Space API's.             */
    int  in_len;                /* the length of the error code.     */
    int  out_len;               /* the length of the exception data. */
    char excp_id[7];            /* the Exception ID.                 */
    char rev;                   /* Reserved Field.                   */
    char excp_data[120];        /* the output data associated        */
} error_code;                   /* the exception ID.                 */
  
char            ext_atr[11]  = USSPC_ATTR;  /*  Space attribute      */
char            initial_val  = USSPC_INIT_VAL;
                                            /*  Space initial value  */
char            auth[11]     = USSPC_AUTH;
                                            /*  Space authority      */
char            desc[51]     = USSPC_TEXT;
                                            /*  Space text           */
char            replace[11]  = USSPC_REPLACE;
                                           /*Space replace attribute*/

/*-------------------------------------------------------------------*/
/* Start of mainline code.                                           */
/*-------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
    
/*-------------------------------------------------------------------*/
/* standard return codes                                             */
/*-------------------------------------------------------------------*/

#define ERROR -1
#define OK     0

/*-------------------------------------------------------------------*/
/* standard CCA parameters                                           */
/*-------------------------------------------------------------------*/

    long return_code;
    long reason_code;
    long exit_data_length;
    char exit_data[2];
    long rule_array_count;

    char            *user_space_ptr;
    char            *user_space;
    char            *cipher_spc;
    long            file_bytes;
    long            i;
    long            j;
    char            key_label[64];

    long            text_len, pad_character;
    char            initial_vector[8];
    char            chaining_vector[18];

/*-------------------------------------------------------------------*/
/* Open database files.                                              */
/*-------------------------------------------------------------------*/

    if (argc < 4)                          /* were the correct number
                                            of parameters passed?    */
                                         
    {
        printf("This program needs 3 parameters - ");
        printf("key label, input file name, output file name\n");
        
        return ERROR; 
    }

    else
    {

        file_bytes = 0;                     /* Set initial number of
                                             bytes to encipher to 0 */

        /* Open the input file. If the file pointer, dbfptr is not
           NULL, then the file was successfully opened.              */
        
        if (( dbfptr = _Ropen(argv[2], "rr riofb=n"))
            != NULL)
        {

/*-------------------------------------------------------------------*/
/* Determine the number of bytes that will be enciphered.            */
/*-------------------------------------------------------------------*/
            db_opfb = _Ropnfbk( dbfptr );   /* Get pointer to the File
                                             open feedback area.     */

            file_bytes = db_opfb->num_records *   
              db_opfb->pgm_record_len  
              + 1;                          /* 1 is added to prevent an
                                                end of space error   */
                                             
            j = db_opfb->num_records;       /* Save number of records*/
   /*----------------------------------------------------------------*/
   /* Create user space and get pointer to it.                       */
   /*----------------------------------------------------------------*/
            error_code.in_len = 136;        /* Set length of error   */
                                            /* structure.            */
            QUSDLTUS(space_name,&error_code); /* Delete the user space
                                               if it already exists. */

	    /* Create the plaintext user space object   */
            QUSCRTUS(space_name,ext_atr,file_bytes, 
                     &initial_val,auth,             
                     desc, replace,&error_code);

            error_code.in_len = 48;         /* Set length of error
                                             structure                */

            QUSPTRUS(space_name,            /* Retrieve a pointer to  */
                     (void *)&user_space,   /* the user space.        */
                     (char*)&error_code);

            user_space_ptr = user_space;    /* Make copy of pointer   */

            error_code.in_len = 136;        /* Set length of error    */
                                            /* structure.             */
            QUSDLTUS(cipher_name,&error_code);    /* Delete cipher space
                                               if already exists.     */

	    /* Create ciphertext user space object   */
            QUSCRTUS(cipher_name,ext_atr,   
                     file_bytes,&initial_val,auth, 
                     desc, replace,&error_code);

            error_code.in_len = 48;         /* Set length of error    */
                                            /* structure              */
            QUSPTRUS(cipher_name,           /* Retrieve pointer to    */
                     (void *)&cipher_spc,   /* ciphertext user space  */
                     (char*)&error_code);

   /*----------------------------------------------------------------*/
   /* Read file and fill space                                       */
   /*----------------------------------------------------------------*/
            for (i=1; i<=j; i++)            /* Repeat for each record */
            {
                /* Read a record and place in user space.             */
                db_fdbk = _Rreadn(dbfptr, user_space_ptr,
                                  db_opfb->pgm_record_len, __DFT);

                 /* Move the user space ahead the length of a record  */
                user_space_ptr = user_space_ptr +  
                  db_opfb->pgm_record_len;
            }                                 

            if (dbfptr != NULL)                   /* Close the file.  */
                _Rclose(dbfptr);
   /*----------------------------------------------------------------*/
   /* Encrypt data in space                                          */
   /*----------------------------------------------------------------*/

            memset((char *)key_label,' ',64);   /* Initialize key label
                                                 to all blanks.        */
            memcpy((char *)key_label,           /* Copy key label parm */
                   argv[1],strlen(argv[1]));

            text_len = file_bytes - 1;
            rule_array_count = 1;
	    pad_character = 40;
	    exit_data_length = 0;
            memset((char *)initial_vector,'\0',8);

            /* Encipher data in  ciphertext user space               */
            CSNBENC(&return_code,         
                    &reason_code,        
                    &exit_data_length,                
                    exit_data,
                    key_label,
                    &text_len,
                    user_space,
                    initial_vector,
                    &rule_array_count,
                    "CBC     ",                 /*  rule_array       */
                    &pad_character,
                    chaining_vector,
                    cipher_spc );

             if (return_code == 0) {
   /*----------------------------------------------------------------*/
   /* Open output file                                               */
   /*----------------------------------------------------------------*/
                if (( dbfptre = _Ropen(argv[3],
                                       "wr riofb=n")) != NULL)
                {
                    db_opfbe = _Ropnfbk( dbfptr );   /* Get pointer to
                                             the File open feedback
                                             area.                   */
                    if(text_len % db_opfbe->pgm_record_len != 0)
                    {
                        printf("encrypted data will not fit into ");
                        printf("an even number of records\n");

                        if (dbfptre != NULL)  /* Close the file.     */
                            _Rclose(dbfptre);
                        
                       /*--------------------------------------------*/
                       /* Delete both user spaces.                   */
                       /*--------------------------------------------*/
                        error_code.in_len = 136;  /* Set length of
                                                   error structure.  */
                        QUSDLTUS(space_name,&error_code); /* Delete the
                                                   user space        */
                        QUSDLTUS(cipher_name,&error_code); /* Delete
                                                   ciphertext  space */

                        return ERROR;
                    }

   /*----------------------------------------------------------------*/
   /* Write data from space to file.                                 */
   /*----------------------------------------------------------------*/
                    user_space_ptr = cipher_spc;  /* Save pointer to
                                                   cipher space.     */

		    j = text_len / db_opfbe->pgm_record_len; /* find
						     how many records
						     are needed to store
						     result in output
                                                     file            */
                    for (i=1; i<=j; i++)          /* Repeat for each
                                                   record            */
                    {
                        /* Write data to output file */
                        db_fdbk = _Rwrite(dbfptre, user_space_ptr,  
                                          db_opfbe->pgm_record_len);

                        /* Advance pointer ahead the length of a record */
                        user_space_ptr = user_space_ptr +   
                          db_opfbe->pgm_record_len;   
                    }
                    if (dbfptre != NULL)          /* Close the file  */
                        _Rclose(dbfptre);

                }                                 /* end of open open
                                                   output file       */
                else
                {
		    printf("Output file %s could not be opened\n",
			   argv[3]);

                   /*--------------------------------------------*/
                   /* Delete both user spaces.                   */
                   /*--------------------------------------------*/
                    error_code.in_len = 136;      /* Set length of
                                                   error structure.  */
                    QUSDLTUS(space_name,&error_code); /* Delete the
                                                   user space        */
                    QUSDLTUS(cipher_name,&error_code); /* Delete
                                                   ciphertext  space */
                    return ERROR; 
                }

             }                                    /* If return code = 0 */
            else
            {
		printf("Bad return/reason code : %d/%d \n",
		       return_code,reason_code);
              /*--------------------------------------------*/
              /* Delete both user spaces.                   */
              /*--------------------------------------------*/
                error_code.in_len = 136;          /* Set length of
                                                   error structure.  */
                QUSDLTUS(space_name,&error_code); /* Delete the
                                                   user space        */
                QUSDLTUS(cipher_name,&error_code); /* Delete
                                                   ciphertext  space */
                return ERROR; 
            }

   /*----------------------------------------------------------------*/
   /* Delete both user spaces.                                       */
   /*----------------------------------------------------------------*/
            error_code.in_len = 136;              /* Set length of
                                                   error structure.  */
            QUSDLTUS(space_name,&error_code);     /* Delete the user
                                                   space             */
            QUSDLTUS(cipher_name,&error_code);    /* Delete ciphertext
                                                   space             */

        }                                        /* End of open
                                                    input file       */
        else
        {
            printf("Input file %s could not be opened\n", argv[2]);
            return ERROR; 
        }
    }                                           /* argv[] == null    */
    return OK;
}