RSA BSAFE Crypto-C

Cryptographic Components for C

Search

rc5.c

/* $Id: rc5.c,v 1.7 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 encrypts and decrypts using RC5 in CBC mode.
 */

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

#define KEY_SIZE 10    /* number of bytes in the key */
#define BLOCK_SIZE 8

B_ALGORITHM_METHOD *RC5_CHOOSER[] = {
  &AM_RC5_CBC_ENCRYPT,
  &AM_RC5_CBC_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 rc5Main
#else
#define MAIN main
#endif

int MAIN(int argc, char *argv[])
{
  B_KEY_OBJ rc5Key = (B_KEY_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ rc5Encrypter = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ rc5Decrypter = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ randomAlgorithm = (B_ALGORITHM_OBJ)NULL_PTR;

  unsigned char initVector[BLOCK_SIZE];

  A_RC5_CBC_PARAMS rc5Params;

  ITEM rc5KeyItem = {NULL, 0};

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

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

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

  int status = 0;

  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 ("RC5 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 here for 8 bytes  */
    if ((status = B_GenerateRandomBytes
                    (randomAlgorithm, (unsigned char *)initVector, BLOCK_SIZE,
                     (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    RSA_PrintBuf ("Random IV", initVector, BLOCK_SIZE);

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

    /*  Set the algorithm to a type that does RC5 encryption
                in CBC mode with padding.  */

    rc5Params.version = 0x10;
    rc5Params.rounds = 12;
    /* double the word size to get the block size */
    rc5Params.wordSizeInBits = BLOCK_SIZE * 4;
    rc5Params.iv = (unsigned char *)initVector;

    if ((status = B_SetAlgorithmInfo
                    (rc5Encrypter, AI_RC5_CBCPad, (POINTER)&rc5Params)) != 0)
      break;

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

    /*  Set the key object with a random RC5 key  */
    rc5KeyItem.data = NULL_PTR;
    rc5KeyItem.len = KEY_SIZE;
    rc5KeyItem.data = T_malloc (rc5KeyItem.len);
    if ((status = (rc5KeyItem.data == NULL_PTR)) != 0)
      break;

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

    RSA_PrintBuf ("Random RC5 Key", rc5KeyItem.data, rc5KeyItem.len);

    if ((status = B_SetKeyInfo (rc5Key, KI_Item, (POINTER)&rc5KeyItem)) != 0)
      break;

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

    /*  Init */
    if ((status = B_EncryptInit (rc5Encrypter, rc5Key, RC5_CHOOSER,
                                 (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Update */
    encryptedDataLen = dataToEncryptLen + BLOCK_SIZE;
    encryptedData = T_malloc (encryptedDataLen);
    if ((status = (encryptedData == NULL_PTR)) != 0)
      break;

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

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

    outputLenTotal = outputLenUpdate + outputLenFinal;

    RSA_PrintBuf ("Encrypted Data", encryptedData, outputLenTotal);

    RSA_PrintMessage ("RC5 algorithm:  Decryption phase \n");
    RSA_PrintMessage ("================================ \n");

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

    /*  Use the same AI and parameters as for encryption */
    if ((status = B_SetAlgorithmInfo
                    (rc5Decrypter, AI_RC5_CBCPad, (POINTER)&rc5Params)) != 0)
      break;

    /*  Use the same key as for encryption */
    if ((status = B_DecryptInit (rc5Decrypter, rc5Key, RC5_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. */
    decryptedDataLen = encryptedDataLen;
    decryptedData = T_malloc (decryptedDataLen);
    if ((status = (decryptedData == NULL_PTR)) != 0)
      break;

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

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

    decryptedLenTotal = decryptedLenUpdate + decryptedLenFinal;
    RSA_PrintBuf ("Decrypted Data", decryptedData, decryptedLenTotal);

    if ((decryptedLenTotal == dataToEncryptLen) &&
        (T_memcmp (dataToEncrypt, decryptedData, decryptedLenTotal)) == 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 ("rc5 example", status);

  /*  Destroy the key and algorithm objects  */
  B_DestroyKeyObject (&rc5Key);
  B_DestroyAlgorithmObject (&rc5Encrypter);
  B_DestroyAlgorithmObject (&randomAlgorithm);
  B_DestroyAlgorithmObject (&rc5Decrypter);

  /*  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_memset (encryptedData, 0, encryptedDataLen);
    T_free (encryptedData);
    encryptedData = NULL_PTR;
  }

  if (decryptedData != NULL_PTR)
  {
    T_memset (decryptedData, 0, decryptedDataLen);
    T_free (decryptedData);
    decryptedData = NULL_PTR;
  }

  if (rc5KeyItem.data != NULL_PTR) {
    T_memset (rc5KeyItem.data, 0, rc5KeyItem.len);
    T_free (rc5KeyItem.data);
    rc5KeyItem.data = NULL_PTR;
    rc5KeyItem.len = 0;
  }

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

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