RSA BSAFE Crypto-C

Cryptographic Components for C

Search

rc2.c

/* $Id: rc2.c,v 1.6 2004/12/03 02:08:41 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 encrypts & decrypts using RC2 in CBC mode.  */

#include "bsafe.h"
#include "demoutil.h"  /* in samples/common/include */
#include "bsfutil.h"   /* in samples/common/include */

#define BLOCK_SIZE 8
#define KEY_SIZE 24

B_ALGORITHM_METHOD *RC2_CHOOSER[] = {
  &AM_CBC_ENCRYPT,
  &AM_CBC_DECRYPT,
  &AM_RC2_ENCRYPT,
  &AM_RC2_DECRYPT,
  (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 rc2Main
#else
#define MAIN main
#endif

int MAIN(int argc, char *argv[])
{
  B_KEY_OBJ rc2Key = (B_KEY_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ rc2Encrypter = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ rc2Decrypter = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ randomAlgorithm = (B_ALGORITHM_OBJ)NULL_PTR;

  unsigned char initVector[BLOCK_SIZE];
  ITEM ivItem = {NULL, 0}, rc2KeyItem = {NULL, 0};
  A_RC2_PARAMS rc2Params;

  B_BLK_CIPHER_W_FEEDBACK_PARAMS fbParams;

  unsigned char *dataToEncrypt = (unsigned char *)"Encrypt this sentence.";
  unsigned int dataToEncryptLen;

  unsigned char *encryptedData = NULL_PTR;
  unsigned int outputLenUpdate, outputLenFinal;
  unsigned int encryptedDataLen;

  unsigned char *decryptedData = NULL_PTR;
  unsigned int decryptedLenUpdate, decryptedLenFinal;
  unsigned int decryptedDataLen;

  int status;

  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 ("RC2 w/CBC Pad algorithm:  Encryption phase\n");
    RSA_PrintMessage ("==========================================\n");

    dataToEncryptLen = T_strlen ((char *)dataToEncrypt) + 1;

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

    /*  Initialize a random algorithm object using a procedure described in
        samples/common/include/bsfutil.h  */
    if ((status = RSA_CreateRandomAlgorithmObject (&randomAlgorithm)) != 0)
      break;

    /*  B_GenerateRandomBytes is called for 8 bytes, which is the block size.  */
    if ((status = B_GenerateRandomBytes (randomAlgorithm, initVector,
                                         sizeof (initVector), NULL)) != 0)
      break;

    RSA_PrintBuf ("Initialization Vector", initVector, sizeof (initVector));

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

    /*  Set the algorithm to a type that does RC2 encryption. In this case
        AI_RC2_CBCPad. This algorithm type needs an 8-byte initialization 
                vector (IV), and an effective key size in bits.
        Both are set by declaring a struct of type, A_RC2_CBC_PARAMS.
        The IV will be set with 8 random bytes, and the effective key
        bits will be set to 80.   */
    rc2Params.effectiveKeyBits = 80;

    ivItem.data = initVector;
    ivItem.len = sizeof (initVector);

    fbParams.encryptionMethodName = (unsigned char *)"rc2";
    fbParams.encryptionParams = (POINTER)&rc2Params;
    fbParams.feedbackMethodName = (unsigned char *)"cbc";
    fbParams.feedbackParams = (POINTER)&ivItem;
    fbParams.paddingMethodName = (unsigned char *)"pad";
    fbParams.paddingParams = NULL_PTR;

    if ((status = B_SetAlgorithmInfo (rc2Encrypter, AI_FeedbackCipher,
                                      (POINTER)&fbParams)) != 0)
      break;

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

    /*  Set the key object with a random 24-byte key  */
    rc2KeyItem.len = KEY_SIZE;
    rc2KeyItem.data = T_malloc (rc2KeyItem.len);
    if (rc2KeyItem.data == NULL_PTR) {
      status = RSA_DEMO_E_ALLOC;
      break;
    }

    if ((status = B_GenerateRandomBytes
                    (randomAlgorithm, rc2KeyItem.data,
                     rc2KeyItem.len, (A_SURRENDER_CTX *)NULL_PTR)) != 0)
         break;

    RSA_PrintBuf ("RC2 Key Bytes", rc2KeyItem.data, rc2KeyItem.len);

    if ((status = B_SetKeyInfo (rc2Key, KI_Item, (POINTER)&rc2KeyItem)) != 0)
         break;

    /*  Zeroize the memory and free it up immediately after
        setting the key for security reasons.  */
    if (rc2KeyItem.data != NULL_PTR) {
      T_memset (rc2KeyItem.data, 0, rc2KeyItem.len);
      T_free (rc2KeyItem.data);
      rc2KeyItem.data = NULL_PTR;
      rc2KeyItem.len = 0;
    }

    /*  Init */
    if ((status = B_EncryptInit (rc2Encrypter, rc2Key, RC2_CHOOSER,
                                 (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Update  */
    encryptedDataLen = dataToEncryptLen + BLOCK_SIZE;
    encryptedData = T_malloc (encryptedDataLen);
    if (encryptedData == NULL_PTR) {
      status = RSA_DEMO_E_ALLOC;
      break;
    }

    if ((status = B_EncryptUpdate (rc2Encrypter, encryptedData,
                                   &outputLenUpdate, encryptedDataLen,
                                   dataToEncrypt, dataToEncryptLen,
                                   (B_ALGORITHM_OBJ)NULL_PTR,
                                   (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Final */
    if ((status = B_EncryptFinal (rc2Encrypter,
                                  encryptedData + outputLenUpdate,
                                  &outputLenFinal,
                                  encryptedDataLen - outputLenUpdate,
                                  (B_ALGORITHM_OBJ)NULL_PTR,
                                  (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    encryptedDataLen = outputLenUpdate + outputLenFinal;

    RSA_PrintBuf ("EncryptedData", encryptedData, encryptedDataLen);

    RSA_PrintMessage ("\nRC2 w/CBC Pad algorithm:  Decryption phase\n");
    RSA_PrintMessage ("==========================================\n");

    if ((status = B_CreateAlgorithmObject (&rc2Decrypter)) != 0)
      break;

    /*  Use the same AI and initialization vector as for encryption  */
    if ((status = B_SetAlgorithmInfo (rc2Decrypter, AI_FeedbackCipher,
                                      (POINTER)&fbParams)) != 0)
      break;

    /*  Use the same key as for encryption  */
    if ((status = B_DecryptInit (rc2Decrypter, rc2Key, RC2_CHOOSER,
                                 (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /* Set the buffer that will take the decrypted data to be the same size
     * as the encrypted data's buffer.  With AI_RC2_CBCPad, there will be
     * fewer bytes in the decrypted data than in the encrypted data, since
     * Crypto-C will strip the padding. But we do not know how many, so for
     * simplicity, make the buffer the same size.
     */
    decryptedDataLen = encryptedDataLen;
    decryptedData = T_malloc (decryptedDataLen);
    if ((status = (decryptedData == NULL_PTR)) != 0)
      break;

    if ((status = B_DecryptUpdate (rc2Decrypter, decryptedData,
                                   &decryptedLenUpdate, decryptedDataLen,
                                   encryptedData, encryptedDataLen,
                                   (B_ALGORITHM_OBJ)NULL_PTR,
                                   (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    if ((status = B_DecryptFinal (rc2Decrypter,
                                  decryptedData + decryptedLenUpdate,
                                  &decryptedLenFinal,
                                  decryptedDataLen - decryptedLenUpdate,
                                  (B_ALGORITHM_OBJ)NULL_PTR,
                                  (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    decryptedDataLen = decryptedLenUpdate + decryptedLenFinal;

    RSA_PrintBuf ("Decrypted Data", decryptedData, decryptedDataLen);

    if ((decryptedDataLen == dataToEncryptLen) &&
        (T_memcmp (dataToEncrypt, decryptedData, decryptedDataLen)) == 0) {
      RSA_PrintMessage ("Success!  ");
      RSA_PrintMessage ("The decrypted data matches the original data.\n");
    } else {
      RSA_PrintMessage ("The decrypted data does not match the original data.");
      status = RSA_DEMO_E_INFO_DOES_NOT_VERIFY;
    }
  } while (0);

  if (status != 0)
    RSA_PrintError ("rc2", status);

  /*  Destroy the key and algorithm objects.  */
  B_DestroyKeyObject (&rc2Key);
  B_DestroyAlgorithmObject (&rc2Encrypter);
  B_DestroyAlgorithmObject (&randomAlgorithm);
  B_DestroyAlgorithmObject (&rc2Decrypter);

  /*  Free up any memory allocated, save it to a file or print it out first
      if you need to save it.  */
  if (encryptedData != NULL_PTR) {
    T_free (encryptedData);
    encryptedData = NULL_PTR;
  }

  if (decryptedData != NULL_PTR) {
    T_free (decryptedData);
    decryptedData = NULL_PTR;
  }

  if (rc2KeyItem.data != NULL_PTR) {
    T_free (rc2KeyItem.data);
    rc2KeyItem.data = NULL_PTR;
    rc2KeyItem.len = 0;
  }

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

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