RSA BSAFE Crypto-C

Cryptographic Components for C

Search

multencr.c

/* $Id: multencr.c,v 1.5 2004/12/03 02:08:42 sparki Exp $ */
/*
 * Copyright (C) 1998-2004 RSA Security Inc.
 *
 * This file shall only be used to demonstrate how to interface to an
 * RSA Security Inc. licensed development product.
 *
 * You have a royalty-free right to use, reproduce and distribute this
 * demonstration file, provided that you agree that RSA Security Inc.
 * has no warranty, implied or otherwise, or liability for this
 * demonstration file (including any modified version).  This software
 * is provided "as is" without warranties or representations of any
 * kind. RSA Security disclaims all conditions and warranties, statutory
 * and otherwise, both express and implied, with respect to the software,
 * its quality and performance, including but not limited to, all
 * implied warranties of merchantability, fitness for a particular
 * purpose, title and noninfringement of third party rights. Without
 * limiting the foregoing, RSA Security does not warrant that the
 * software is error-free or that errors in the product will be
 * corrected. You agree that RSA Security shall not be liable for any
 * direct, indirect, incidental, special, consequential, punitive or
 * other damages whatsoever resulting from your use of this software
 * or any modified version.
 *
 *
 */

/*  This program illustrates the process of calling B_EncryptUpdate multiple
 *  times.  The user is prompted for a file containing data to encrypt,
 *  with the default being "infile.dat".  It will read a specified number of
 *  bytes from the file, encrypt it, then write the encrypted bytes out to an
 *  output file, "encrfile.dat" by default, until the end of file is reached.
 *  To get back the original data or plaintext, compile "multdecr.c" and
 *  run.
 */

#include <stdio.h>
#include "bsafe.h"
#include "demoutil.h"  /* in samples/common/include */

#define BLOCK_SIZE              0  /* RC4 is a stream cipher */
#define DEMO_UPDATE_SIZE        64
#define DEMO_UPDATE_OUTPUT_SIZE (DEMO_UPDATE_SIZE + BLOCK_SIZE)

int GetDataFromFile PROTO_LIST
  ((FILE *, unsigned int, unsigned char *, unsigned int *, int *));

int AppendDataToFile PROTO_LIST
  ((FILE *, unsigned char *, unsigned int));

B_ALGORITHM_METHOD *DEMO_ALGORITHM_CHOOSER[] = {
  &AM_RC4_ENCRYPT,
  (B_ALGORITHM_METHOD *)NULL_PTR
/* This will fix a problem that the IA64 compiler finds when *
 * seeing a short chooser list */
#ifdef IA64_FORCE_LARGE
                IA64_FORCE_LARGE
#endif
};



#ifdef CRYPTOC_APP
#define MAIN multencrMain
#else
#define MAIN main
#endif

int MAIN(int argc, char *argv[])
{
  B_KEY_OBJ rc4Key = (B_KEY_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ encryptionObject = (B_ALGORITHM_OBJ)NULL_PTR;

  static unsigned char rc4KeyData[10] = {
    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12
  };
  unsigned int rc4KeyDataLen = 10;
  ITEM rc4KeyItem = {NULL, 0};

  FILE *inputFile = (FILE *)NULL_PTR;
  FILE *outputFile = (FILE *)NULL_PTR;

  unsigned char dataToEncrypt[DEMO_UPDATE_SIZE];
  unsigned char blockOfEncryptedData[DEMO_UPDATE_OUTPUT_SIZE];
  unsigned int dataToEncryptLen, totalBytesSoFar;
  unsigned int outputLenUpdate, outputLenFinal;
  unsigned int sizeToUpdate = DEMO_UPDATE_SIZE;
  int endFlag, status;

  char userInput[RSA_DEMO_MAX_LINE_LEN];

  do {
    /* The RSA_* demo code utilities are described in
       common/include/demoutil.h.  This procedure simply checks the
       command-line arguments for input or output options. */
    if ((status = RSA_SetOptions (argc, argv)) != 0)
      break;

    RSA_PrintMessage ("RC4 algorithm - Multiple Updates\n");
    RSA_PrintMessage ("================================\n");

    RSA_PrintMessage ("Enter name of file containing data to encrypt\n");
    if ((status = RSA_GetCommand (userInput, sizeof (userInput),
                                  "(default infile.dat)")) != 0)
      break;

    if (userInput[0] == '\0')
      T_strcpy (userInput, "infile.dat");

    inputFile = fopen (userInput, "rb");
    if (inputFile == (FILE *)NULL_PTR) {
      status = RSA_DEMO_E_FILE_IO;
      break;
    };

    RSA_PrintMessage ("Enter name of file for storing encrypted data\n");
    if ((status = RSA_GetCommand (userInput, sizeof (userInput),
                                  "(default encrfile.dat)")) != 0)
      break;

    if (userInput[0] == '\0')
      T_strcpy (userInput, "encrfile.dat");

    outputFile = fopen (userInput, "wb");
    if (outputFile == (FILE *)NULL_PTR) {
      status = RSA_DEMO_E_FILE_IO;
      break;
    }

    RSA_PrintMessage ("Encryption phase (calling Update multiple times)\n");
    RSA_PrintMessage ("================================================\n");

    totalBytesSoFar = 0;

    /*  Create a key object. */
    if ((status = B_CreateKeyObject (&rc4Key)) != 0)
      break;

    /*  Set the key to be a RC4 key and set it to the rc4KeyData declared
        above. */
    rc4KeyItem.data = rc4KeyData;
    rc4KeyItem.len = rc4KeyDataLen;

    if ((status = B_SetKeyInfo (rc4Key, KI_Item, (POINTER)&rc4KeyItem)) != 0)
      break;

    /*  Create an algorithm object. */
    if ((status = B_CreateAlgorithmObject (&encryptionObject)) != 0)
      break;

    /*  Set the algorithm object for the RC4 operation  */
    if ((status = B_SetAlgorithmInfo (encryptionObject, AI_RC4, NULL)) != 0)
      break;

    /*  Ready to encrypt. Use B_EncryptInit, B_EncryptUpdate and B_EncryptFinal
     */
    if ((status = B_EncryptInit (encryptionObject, rc4Key,
                                 DEMO_ALGORITHM_CHOOSER,
                                 (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    while ((status = GetDataFromFile (inputFile, sizeToUpdate, dataToEncrypt,
                                      &dataToEncryptLen, &endFlag)) == 0) {

      RSA_PrintBuf ("Data To Encrypt", dataToEncrypt, dataToEncryptLen);

      if ((status = B_EncryptUpdate (encryptionObject, blockOfEncryptedData,
                                     &outputLenUpdate, DEMO_UPDATE_OUTPUT_SIZE,
                                     dataToEncrypt, dataToEncryptLen,
                                     (B_ALGORITHM_OBJ)NULL_PTR,
                                     (A_SURRENDER_CTX *)NULL_PTR)) != 0)
        break;

      /*  Save the encrypted data  */
      if ((status = AppendDataToFile (outputFile, blockOfEncryptedData,
                                      outputLenUpdate)) != 0)
        break;

      totalBytesSoFar += outputLenUpdate;
      if (endFlag == 1)
        break;
    } /*  end while  */

    /*  If there was an error in the above while loop, break out of the
        do-while construct.  */
    if (status != 0)
      break;

    /*  Call B_EncryptFinal once after all Updates.  */
    if ((status = B_EncryptFinal (encryptionObject, blockOfEncryptedData,
                                  &outputLenFinal, DEMO_UPDATE_OUTPUT_SIZE,
                                  (B_ALGORITHM_OBJ)NULL_PTR,
                                  (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Save the encrypted data  */
    if ((status = AppendDataToFile (outputFile, blockOfEncryptedData,
                                    outputLenFinal)) != 0)
      break;

    totalBytesSoFar += outputLenFinal;

    RSA_PrintMessage ("Total ciphertext length = %i\n", totalBytesSoFar);
  } while (0);

  if (status != 0)
    RSA_PrintError ("RC4 Encryption with multiple updates", status);

  /*  Done with the key and algorithm objects, so destroy them.  */
  B_DestroyKeyObject (&rc4Key);
  B_DestroyAlgorithmObject (&encryptionObject);

  /*  Free up any memory allocated, save it to a file or print it out first
      if you need to save it.  */
  T_memset (dataToEncrypt, 0, sizeof (dataToEncrypt));

  if (inputFile != (FILE *)NULL_PTR)
    fclose (inputFile);
  if (outputFile != (FILE *)NULL_PTR)
    fclose (outputFile);

  return (status);
} /*  end main  */

int GetDataFromFile(FILE *inputFile, unsigned int sizeToUpdate,
  unsigned char *dataToEncrypt, unsigned int *dataToEncryptLen, int *endFlag)
{
  unsigned char dummy;

  do {
    *dataToEncryptLen = fread (dataToEncrypt, 1, sizeToUpdate, inputFile);
    if (*dataToEncryptLen == sizeToUpdate)
    /* Read exactly sizeToUpdate bytes, so reading one more will set
       end of file if there were exactly sizeToUpdate bytes in the file.  */
      fread (&dummy, 1, 1, inputFile);

    if (feof (inputFile)) {
      *endFlag = 1;
      fclose (inputFile);
    }
    else {
      *endFlag = 0;
      fseek (inputFile, -1, SEEK_CUR);
    }
  } while (0);
  return (0);
}  /*  end GetDataFromFile  */


int AppendDataToFile(FILE *outputFile, unsigned char *blockOfEncryptedData,
  unsigned int outputLenUpdate)
{
  do {
    if (fwrite (blockOfEncryptedData, 1, outputLenUpdate, outputFile)
          < outputLenUpdate) {
      fclose (outputFile);
    }
  } while (0);
  return (0);
}  /*  end AppendDataToFile  */

Copyright (c) 1999-2005 RSA Security Inc. All rights reserved. 068-001001-6210-001-000 - 6.2.1