|
//-------------------------------------------------------------------------
//
// 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);
}
|