Example in ILE C: Writing encrypted data to a file

See Code disclaimer information for information pertaining to code examples.

Refer to Scenario: Key Management and File Encryption Using the Cryptographic Services APIs for a description of this scenario.

Start of change
/*-------------------------------------------------------------------*/
/*                                                                   */
/* Sample C program:  Write_Cus                                      */
/*                                                                   */
/*  COPYRIGHT      5722-SS1 (c) IBM Corp 2004                        */
/*                                                                   */
/*  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.                                        */
/*                                                                   */
/* Description:                                                      */
/*  This is a sample program to demonstrate use of the Cryptographic */
/*  Services APIs.  APIs demonstrated in this program are:           */
/*   Create Algorithm Context                                        */
/*   Create Key Context                                              */
/*   Generate Pseudorandom Numbers                                   */
/*   Encrypt Data                                                    */
/*   Destroy Key Context                                             */
/*   Destroy Algorithm Context                                       */
/*                                                                   */
/* Function:                                                         */
/*  Get customer information, encrypt it, and write it to the        */
/*  Customer Data file (CUSDTA).  The file key is kept in the        */
/*  Customer Processing Information file (CUSPI).                    */
/*                                                                   */
/*  Refer to the iSeries (TM) Information Center for a full          */
/*  description of this scenario.                                    */
/*                                                                   */
/* Use the following commands to compile this program:               */
/*   CRTCMOD MODULE(MY_LIB/WRITE_CUS) SRCFILE(MY_LIB/MY_SRC)         */
/*   CRTSRVPGM SRVPGM(MY_LIB/WRITE_CUS) +                            */
/*             MODULE(MY_LIB/WRITE_CUS MY_LIB/GET_CUSTOMER_INFO) +   */
/*             BNDSRVPGM(QC3CTX QC3PRNG QC3DTAEN)                    */
/*                                                                   */
/*-------------------------------------------------------------------*/
 
/*-------------------------------------------------------------------*/
/* Retrieve various structures/utilities.                            */
/*-------------------------------------------------------------------*/
 
#include <stdio.h>                    /* Standard I/O header         */
#include <stdlib.h>                   /* General utilities           */
#include <stddef.h>                   /* Standard definitions        */
#include <string.h>                   /* String handling utilities   */
#include <recio.h>                    /* Record I/O routines         */
#include <qusec.h>                    /* Error code structure        */
#include <qc3ctx.h>                   /* Hdr file for Context APIs   */
#include <qc3prng.h>                  /* Hdr file for PRNG APIs      */
#include <qc3dtaen.h>                 /* Hdr file for Encrypt Dta API*/

/*-------------------------------------------------------------------*/
/* The following structures were generated with GENCSRC.             */
/*-------------------------------------------------------------------*/
 
  #ifdef __cplusplus                                            
  #include <bcd.>>                                              
  #else                                                         
  #include <decimal.h>                                          
  #endif                                                        
  /* ------------------------------------------------------- *  
  // PHYSICAL FILE : MY_LIB/CUSPI                                
  // FILE LAST CHANGE DATE : 2004/02/11                         
  // RECORD FORMAT : CUSPIREC                                   
  // FORMAT LEVEL IDENTIFIER : 248C15A88E09C                    
   * ------------------------------------------------------- */ 
  typedef _Packed struct {                                                 
     char KEY[16];                         /* ENCRYPTION KEY */            
                                                                         
  #ifndef __cplusplus                                                      
     decimal( 8, 0) LASTCUS;                                               
  #else                                                                    
     _DecimalT< 8, 0> LASTCUS;             /* LAST CUSTOMER NUMBER */      
                                           /* BCD class SPECIFIED IN DDS */
  #endif                                                                   
  } CUSPIREC_both_t;                                           

  /* ------------------------------------------------------- *              
  // PHYSICAL FILE : MY_LIB/CUSDTA                                           
  // FILE LAST CHANGE DATE : 2004/02/11                                     
  // RECORD FORMAT : CUSDTAREC                                              
  // FORMAT LEVEL IDENTIFIER : 434C857F6F5B3                                
   * ------------------------------------------------------- */             
  typedef _Packed struct {                                                  
                                                                          
  #ifndef __cplusplus                                                       
     decimal( 8, 0) CUSNUM;                                                 
  #else                                                                     
     _DecimalT< 8, 0> CUSNUM;              /* CUSTOMER NUMBER */            
                                           /* BCD class SPECIFIED IN DDS */
  #endif                                                                    
     char IV[16];                          /* INITIALIZATION VECTOR */      
                                                                          
  #ifndef __cplusplus                                                       
     decimal(10, 2) ARBAL;                                                  
  #else                                                                     
     _DecimalT<10, 2> ARBAL;               /* ACCOUNTS RECEIVABLE BALANCE */
                                           /* BCD class SPECIFIED IN DDS */ 
  #endif                                                                    
     char ECUSDTA[80];                     /* ENCRYPTED CUSTOMER DATA */    
  } CUSDTAREC_both_t;                                          

/*-------------------------------------------------------------------*/
/* Function declarations                                             */
/*-------------------------------------------------------------------*/
                                      /* Get a customer information  */
void Get_Customer_Info(char *customerInfo,
                           decimal(8, 0) *customerNumber);

/*-------------------------------------------------------------------*/
/* Start of mainline code.                                           */
/*-------------------------------------------------------------------*/

int Write_Cus()
{
    
/*-------------------------------------------------------------------*/
/* Return codes                                                      */
/*-------------------------------------------------------------------*/
 
  int                   rtn;          /* Return code                 */
  #define               ERROR  -1
  #define               OK      0
 
/*-------------------------------------------------------------------*/
/* File handling variables                                           */
/*-------------------------------------------------------------------*/

  _RFILE               *cuspiPtr;     /* Pointer to CUSPI  file      */
  _RFILE               *cusdtaPtr;    /* Pointer to CUSDTA file      */
  CUSPIREC_both_t       cuspi;        /* CUSPI record                */
  CUSDTAREC_both_t      cusdtain;     /* CUSDTA input record         */
  CUSDTAREC_both_t      cusdtaout;    /* CUSDTA output record        */
 
/*-------------------------------------------------------------------*/
/* Parameters needed by the Cryptographic Services APIs              */
/*-------------------------------------------------------------------*/
 
  Qus_EC_t              errCode;      /* Error code structure        */
  char                  csp;          /* Crypto service provider     */
  Qc3_Format_ALGD0200_T algD;         /* Block cipher alg description*/
  char                  AESctx[8];    /* AES alg context token       */
  int                   keySize;      /* Key size                    */
  char                  keyFormat;    /* Key format                  */
  int                   keyType;      /* Key type                    */
  char                  keyForm;      /* Key form                    */
  int                   keyStringLen; /* Length of key string        */
  Qc3_Format_KEYD0400_T kskey;        /* Key store key name structure*/
  char                  KEKctx[8];    /* KEK key context token       */
  char                  FKctx[8];     /* File key context token      */
  char                  pcusdta[80];  /* Plaintext customer data     */
  int                   cipherLen;    /* Length of ciphertext        */
  int                   plainLen;     /* Length of plaintext         */
  int                   rtnLen;       /* Return length               */
  char                  PRNtype;      /* PRN type                    */
  char                  PRNparity;    /* PRN parity                  */
  unsigned int          PRNlen;       /* Length of PRN data          */
 
/*-------------------------------------------------------------------*/
/* Input values from Get Customer Information.                       */
/*-------------------------------------------------------------------*/

  char                  inCusInfo[80];/* Customer Information        */
  decimal(8, 0)         inCusNum;     /* Customer number             */

/*-------------------------------------------------------------------*/
/* Initializations                                                   */
/*-------------------------------------------------------------------*/

                                      /* Init to good return         */
  rtn = OK;                   
                                      /* Set to generate exceptions  */
  memset(&errCode, 0, sizeof(errCode));
                                      /* Use any crypto provider     */
  csp = Qc3_Any_CSP;
                                      /* Set inCusInfo to null       */
  memset(inCusInfo, 0, sizeof(inCusInfo));

/*-------------------------------------------------------------------*/
/* Create an AES algorithm context for the key-encrypting key (KEK). */
/*-------------------------------------------------------------------*/
 
  memset(&algD, 0, sizeof(algD));     /* Init alg description to null*/
  algD.Block_Cipher_Alg = Qc3_AES;    /* Set AES algorithm           */
  algD.Block_Length = 16;             /* Block size is 16            */
  algD.Mode = Qc3_CBC;                /* Use cipher block chaining   */
  algD.Pad_Option = Qc3_No_Pad;       /* Do not pad                  */
                                      /* Create algorithm context    */
  Qc3CreateAlgorithmContext((unsigned char *)&algD,
      Qc3_Alg_Block_Cipher, AESctx, &errCode);
 
/*-------------------------------------------------------------------*/
/* Create a key context for the key-encrypting key (KEK).            */
/*-------------------------------------------------------------------*/

  keyFormat = Qc3_KSLabel_Struct;     /* Key format is keystore label*/
  keyStringLen = sizeof(kskey);       /* Length of key string        */
  keyType = Qc3_AES;                  /* Key type is AES             */
  keyForm = Qc3_Clear;                /* Key string is clear         */
  memset(&kskey, 0, sizeof(kskey));   /* Init name structure to null */
                                      /* Set key store file name     */
  memset(kskey.Key_Store, 0x40, sizeof(kskey.Key_Store));
  memcpy(kskey.Key_Store,"CUSKEYFILEMY_LIB", 16);
                                      /* Set key store label         */
  memset(kskey.Record_Label, 0x40, sizeof(kskey.Record_Label));
  memcpy(kskey.Record_Label, "CUSDTAKEK", 9);
                                      /* Create key context          */
  Qc3CreateKeyContext((char*)&kskey, &keyStringLen, &keyFormat, &keyType,
                      &keyForm, NULL, NULL, KEKctx, &errCode);
 
/*-------------------------------------------------------------------*/
/* Open Customer Processing Information file.  Read first record     */
/* to obtain the encrypted file key and last customer number.        */
/*-------------------------------------------------------------------*/
 
                                      /* Open CUSPI file             */
  if ((cuspiPtr = _Ropen("MY_LIB/CUSPI", "rr+, arrseq=Y, riofb=N"))
       == NULL)
  {                                   /* If null ptr returned        */
                                      /* Send error message          */
    printf("Open of Customer Processing Information file (CUSPI) failed.");
    return ERROR;                     /* Return with error           */
  } 
                                      /* Read the first(only) record */
                                      /* to get encrypted file key.  */
  if ((_Rreadf(cuspiPtr, &cuspi, sizeof(cuspi), __DFT))->num_bytes
       == EOF)
  {                                   /* If record not found         */
                                      /* Send error message          */
    printf("Customer Processing Information (CUSPI) record missing.");
    _Rclose(cuspiPtr);                /* Close CUSPI file            */
    return ERROR;                     /* Return with error           */
  }
 
/*-------------------------------------------------------------------*/
/* Create a key context for the file key.                            */
/*-------------------------------------------------------------------*/

  keySize = sizeof(cuspi.KEY);        /* Set key size                */
  keyFormat = Qc3_Bin_String;         /* Key is a binary string      */
  keyType = Qc3_AES;                  /* Key type is AES             */
  keyForm = Qc3_Encrypted;            /* Key is encrypted with a KEK */
                                      /* Create key context          */
  Qc3CreateKeyContext(cuspi.KEY, &keySize, &keyFormat, &keyType,
                      &keyForm, KEKctx, AESctx, FKctx, &errCode);

/*-------------------------------------------------------------------*/
/* Wipe out the encrypted file key value from program storage.       */
/*-------------------------------------------------------------------*/
 
                                      /* Wipe out encrypted file key */
  memset(cuspi.KEY, 0, sizeof(cuspi.KEY));
 
/*-------------------------------------------------------------------*/
/* Open Customer Data file.                                          */
/*-------------------------------------------------------------------*/
 
                                      /* Open CUSDTA file            */
  if ((cusdtaPtr = _Ropen("MY_LIB/CUSDTA", "rr+, riofb=N"))
       == NULL)
  {                                   /* If null ptr returned        */
                                      /* Send error message          */
    printf("Open of CUSDTA file failed.");
    _Rclose(cuspiPtr);                /* Close CUSPI file            */
    return ERROR;                     /* Return with error           */
  }

/*-------------------------------------------------------------------*/
/* Get customer information.                                         */
/*-------------------------------------------------------------------*/

                                      /* Get customer information    */
                                      /*  and customer number        */
    Get_Customer_Info(inCusInfo, &inCusNum);

/*-------------------------------------------------------------------*/
/* Repeat loop until no more customers to add/update.                */
/*-------------------------------------------------------------------*/

                                      /* Exit program when customer  */
  while (inCusNum != 99999999)        /*  number = 99999999          */
  {

/*-------------------------------------------------------------------*/
/* Generate an Initialization Vector for the customer.               */
/*-------------------------------------------------------------------*/

    PRNtype = Qc3PRN_TYPE_NORMAL;     /* Generate real random numbers*/
    PRNparity = Qc3PRN_NO_PARITY;     /* Do not adjust parity        */
    PRNlen = 16;                      /* Generate 16 bytes           */
    Qc3GenPRNs(cusdtaout.IV, PRNlen, PRNtype, PRNparity, &errCode);

/*-------------------------------------------------------------------*/
/* Encrypt customer information.                                     */
/*-------------------------------------------------------------------*/

                                      /* Copy IV to alg description  */
    memcpy(algD.Init_Vector, cusdtaout.IV, 16);

                                      /* Encrypt customer data       */
    plainLen = sizeof(inCusInfo);
    cipherLen = sizeof(cusdtaout.ECUSDTA);
    Qc3EncryptData(inCusInfo, &plainLen, Qc3_Data,
                   (char*)&algD, Qc3_Alg_Block_Cipher,
                   FKctx, Qc3_Key_Token,
                   &csp, NULL, cusdtaout.ECUSDTA, &cipherLen, &rtnLen,
                   &errCode);

/*-------------------------------------------------------------------*/
/* Write customer data to file CUSDTA.                               */
/*-------------------------------------------------------------------*/

    if (inCusNum == 0)                /* If new customer             */
    {
      cuspi.LASTCUS += 1;             /* Increment last customer num */
      cusdtaout.CUSNUM=cuspi.LASTCUS; /* Give new customer a number  */
      cusdtaout.ARBAL = 10;           /* Set balance to setup fee    */
                                      /* Write record to file        */
      if ((_Rwrite(cusdtaPtr, &cusdtaout, sizeof(cusdtaout)))->num_bytes
              < sizeof(cusdtaout))
      {                               /* If write fails              */
                                      /* Send error message          */
        printf("Error occurred writing record to CUSDTA file.");
        inCusNum = 99999999;          /* Set to exit loop            */
        rtn = ERROR;                  /* Indicate error condition    */
      }
    }
    else                              /* If existing customer        */
    {
                                      /* Read existing record        */
      if ((_Rreadk(cusdtaPtr, &cusdtain, sizeof(cusdtain), __KEY_EQ,
           &inCusNum, sizeof(inCusNum))) -> num_bytes < sizeof(cusdtain))
      {                               /* If read fails               */
                                      /* Send error message          */
        printf("Error occurred reading record in CUSDTA file.");
        inCusNum = 99999999;          /* Set to exit loop            */
        rtn = ERROR;                  /* Indicate error condition    */
      }
                                      /* Copy customer number        */
      cusdtaout.CUSNUM = cusdtain.CUSNUM;
                                      /* Copy balance                */
      cusdtaout.ARBAL = cusdtain.ARBAL;
                                      /* Update customer record      */
      if ((_Rupdate(cusdtaPtr, &cusdtaout, sizeof(cusdtaout)))->num_bytes
              < sizeof(cusdtaout))
      {                               /* If update fails             */
                                      /* Send error message          */
        printf("Error occurred updating record in CUSDTA file.");
        inCusNum = 99999999;          /* Set to exit loop            */
        rtn = ERROR;                  /* Indicate error condition    */
      }
    }

/*-------------------------------------------------------------------*/
/* Get customer information.                                         */
/*-------------------------------------------------------------------*/

                                      /* Get customer information    */
    if (rtn == OK)                    /*  and customer number        */
      Get_Customer_Info(inCusInfo, &inCusNum);

  }                                   /* Return to top of while loop */


/*-------------------------------------------------------------------*/
/* Update last customer number in CUSPI file.                        */
/*-------------------------------------------------------------------*/

                                      /* Write record to file        */
  if ((_Rwrite(cuspiPtr, &cuspi, sizeof(cuspi)))->num_bytes
         < sizeof(cuspi))
  {                                   /* If write fails              */
                                      /* Send error message          */
    printf("Error occurred updating record in CUSPI file.");
  }

/*-------------------------------------------------------------------*/
/* Cleanup.                                                          */
/*-------------------------------------------------------------------*/
 
                                      /* Clear plaintext data        */
  memset(inCusInfo, 0, sizeof(inCusInfo));
                                      /* Destroy file key context    */
  Qc3DestroyKeyContext(FKctx, &errCode);
                                      /* Destroy KEK context         */
  Qc3DestroyKeyContext(KEKctx, &errCode);
                                      /* Destroy the alg context     */
  Qc3DestroyAlgorithmContext(AESctx, &errCode);
                                      /* Close CUSDTA file           */
  _Rclose(cusdtaPtr);     
                                      /* Close CUSPI file            */
  _Rclose(cuspiPtr); 
                                      /* Return                      */
  return rtn;

}

End of change



Top | Cryptographic Services APIs |APIs by category