z/OS Open Cryptographic Services Facility Application Programming
Previous topic | Next topic | Contents | Index | Contact z/OS | Library | PDF


ENCRYPT.C

z/OS Open Cryptographic Services Facility Application Programming
SC24-5899-01

//-------------------------------------------------------------------------
//
// COMPONENT_NAME: file_encrypt
//
// (C) COPYRIGHT International Business Machines Corp. 1999
// All Rights Reserved
// Licensed Materials - Property of IBM
//
//-------------------------------------------------------------------------
//
// FILE: encrypt.c
//
// This file contains functions to take a clear file and produce its
// associated encrypted file. Although
// the symmetric encryption algorithm being used here is DES, others
// could be easily substituted with minimal change.
//
//-------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

#include "cssm.h"
#include "file_encrypt.h"

//
// Suffixes used for the name of the generated file
//

#define ENCRYPTED_FILE_SUFFIX   ".enc"

//
// File maximums
//
#define MAX_CLEAR_FILE_SIZE     4096        // for simplification
#define PATH_MAX                 256        // for simplification
//
// DES algorithm parameters
//

#define DES_PAD_LEN     8
#define DES_IV_LEN      8

static unsigned char 
DESIVBuffer[DES_IV_LEN] = { 0x03, 0xC4, 0x98, 0x1E, 0x71, 0xFF, 0xA2, 0x23 }; 

static CSSM_DATA 
DESIVData = { sizeof DESIVBuffer, DESIVBuffer };


//-------------------------------------------------------------------------
//
// Function: GenerateKey
//
// This function generates a key using the given CSP.
//  
//-------------------------------------------------------------------------
static void GenerateKey(
    CSSM_CSP_HANDLE hCSP,
    CSSM_KEY_PTR Key)
{
    CSSM_CC_HANDLE  hKeyGenContext;     // key generation context
    CSSM_ERROR_PTR  pError;             // error info

    //
    // Create a key generation context which basically packages all 
    // parameters into a "handle" for later reference
    //

    hKeyGenContext = 
        CSSM_CSP_CreateKeyGenContext(hCSP,
                                     CSSM_ALGID_DES,
                                     NULL,
                                     64,
                                     NULL,NULL,NULL,NULL,NULL);

    if (hKeyGenContext == 0)
    {
        printf("Error: could not perform key generation setup.\n");
        pError = CSSM_GetError();
        printf("CSSM_CSP_CreateKeyGenContext error code = %d\n", pError->error);
        exit(1);
    }

    //
    // Generate a key
    //

    memset(Key, 0, sizeof(CSSM_KEY)); 

    if (CSSM_GenerateKey(hKeyGenContext, CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
            CSSM_KEYATTR_MODIFIABLE, NULL, Key) != CSSM_OK)
    {
        printf("Error: could not generate a key.\n");
        pError = CSSM_GetError();
        printf("CSSM_CSP_GenerateKey error code = %d\n", pError->error);
        exit(1);
    }

    //
    // Delete the unneeded key generation context
    //

    if (CSSM_DeleteContext(hKeyGenContext) != CSSM_OK)
    {
        printf("Error: could not delete key generation context\n");
        pError = CSSM_GetError();
        printf("CSSM_DeleteContext error code = %d\n", pError->error);
        exit(1);
    }
}
//-------------------------------------------------------------------------
//
// Function: GenerateSymmetricContext
//
// This function sets the encryption algorithm parameters including the key
// itself, the algorithm mode, etc.
//-------------------------------------------------------------------------
static void GenerateSymmetricContext(
    CSSM_CSP_HANDLE hCSP,
    CSSM_KEY *Key,
    CSSM_CC_HANDLE *hCryptoContext)
{
    CSSM_ERROR_PTR  pError;             // error info

    //
    // Create a symmetric encryption context to package encryption parameters
    //

    *hCryptoContext = 
        CSSM_CSP_CreateSymmetricContext(hCSP, 
                                        CSSM_ALGID_DES, 
                                        CSSM_ALGMODE_CBCPadIV8,
                                        Key,
                                        &DESIVData,
                                        CSSM_PADDING_NONE, 
                                        0);

    if (hCryptoContext == 0)
    {
        printf("Error: could not perform symmetric encryption setup\n");
        pError = CSSM_GetError();
        printf("CSSM_CSP_CreateSymmetricContext error code = %d\n", pError->error);
        exit(1);
    }
}


//-------------------------------------------------------------------------
//
// Function: WriteOutputFile
//
// This function takes a data buffer represented by a CSSM_DATA type and
// writes it out to new file.  The new file's name is composed of the base
// and suffix strings provided.  This function is used to write out the
// encrypted data. 
//
//-------------------------------------------------------------------------
static void WriteOutputFile(
    CSSM_DATA DataToWrite,
    char *FilenameBase,
    char *FilenameSuffix)
{
    char    OutputFilename[PATH_MAX];
    FILE    *OutputFile;
    int     BytesLeft;
    char    *LastByte;
    int     CurrentWritten;
    int     CurrentSize;
    char    *pCurrent;

    //
    // Compose name and open output file
    //

    strcpy(OutputFilename, FilenameBase);
    strcat(OutputFilename, FilenameSuffix);

    if ((OutputFile = fopen(OutputFilename, "wb")) == NULL)
    {
        printf("Error: could not open %s\n", OutputFilename);
        perror("fopen");
        exit(1);
    }

    //
    // Write data
    //

    LastByte    = DataToWrite.Data + DataToWrite.Length - 1;
    BytesLeft   = DataToWrite.Length;

    pCurrent = DataToWrite.Data;

    while (BytesLeft > 0)
    {
        if (pCurrent + BUFSIZ > LastByte)
            CurrentSize = LastByte - pCurrent;
        else
            CurrentSize = BUFSIZ;
        
        CurrentWritten = fwrite(pCurrent, 1, CurrentSize, OutputFile);

        if (ferror(OutputFile))
        {
            printf("Error: failed to write to file %s\n", OutputFilename);
            perror("fwrite");
            exit(1);
        }

        BytesLeft -= CurrentWritten;
    }

    fclose(OutputFile);

}

//-------------------------------------------------------------------------
//
// Function: GenerateContextAndEncrypt
//
// This function encrypts a file using strong encryption.  It performs all
// the necessary prerequisites such as generation of a key (could be 
// replaced by string to key derivation) for the encryption.
//
//-------------------------------------------------------------------------
void GenerateContextAndEncrypt(
    CSSM_CSP_HANDLE hCSP,
    char *InputFilename)
{
    FILE                *ClearFile;         // clear file's handle
    CSSM_CC_HANDLE      hCryptoContext;     // context handle for encryption
    CSSM_KEY            Key;                // the symmetric key for encryption
    int                 BytesRead;          // byte reading counter
    uint32              BytesEncrypted;     // byte encrypting counter
    unsigned char     ClearBuf[MAX_CLEAR_FILE_SIZE]; // buffer for cleartext
    CSSM_DATA           ClearData;          // buffer for cleartext
    CSSM_DATA          EncryptedData;          // buffer for ciphertext
    unsigned char       RemBuf[DES_PAD_LEN];// buffer for padding
    CSSM_DATA           RemData;            // buffer for padding
    CSSM_RETURN         RC;                 // return code
        
    //
    // Normally one would prompt the user for a string and convert it to
    // a clear key, but here is an example of the key generation APIs
    //

    GenerateKey(hCSP, &Key);

    GenerateSymmetricContext(hCSP, &Key, &hCryptoContext);

    //
    // Read the clear file in one buffer for simplification
    //

    if ((ClearFile = fopen(InputFilename, "rb")) == NULL)
    {
        printf("Error: could not open %s\n", InputFilename);
        perror("fopen");
        exit(1);
    }
    
    BytesRead = fread(ClearBuf, 1, MAX_CLEAR_FILE_SIZE, ClearFile);
    ClearData.Length = BytesRead;
    ClearData.Data = ClearBuf;

    if (BytesRead == 0)
    {
        printf("Error: did not read any bytes from file\n");
        exit(1);
    }

    if (!feof(ClearFile))
    {
       printf("Error: exceeded currently supported maximum clear file size\n");
        exit(1);
    }

    fclose(ClearFile);

    //
    // Encrypt the buffer
    //

    // Initialize the buffer that will hold the final block of the encryption
    memset(RemBuf, 0, sizeof(RemBuf));
    RemData.Length  = sizeof(RemBuf);
    RemData.Data    = RemBuf;

    // setup CipherBuf with the same length as ClearBuf
    EncryptedData.Data = (uint8 *) malloc (ClearData.Length);
    EncryptedData.Length = ClearData.Length;

    RC = CSSM_EncryptData(hCryptoContext,
                          &ClearData,
                          1,
                          &EncryptedData,
                          1,
                          &BytesEncrypted,
                          &RemData);

    // Move the final block of data to the end of the EncryptedBuf
    memcpy(EncryptedData.Data + BytesEncrypted, RemData.Data, RemData.Length);
    EncryptedData.Length =BytesEncrypted + RemData.Length;

    //
    // Write the encrypted file
    //

    WriteOutputFile(EncryptedData, InputFilename, ENCRYPTED_FILE_SUFFIX);
}

Go to the previous page Go to the next page




Copyright IBM Corporation 1990, 2014