RSA BSAFE Crypto-C

Cryptographic Components for C

Search

Obtaining Algorithm Information

This sample demonstrates how to obtain information from BER-encoded data. It uses an algorithm object set to AI_RC4 and verifies the AI to determine which algorithm was used for encryption before decrypting the encrypted data. This sample also sets an RSA public key and then checks the BER-encoded key data to determine the key type.

/* $Id: alginfo.c,v 1.6 2004/12/03 02:08:34 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.
 * 
 *
 */

#include "bsafe.h"
#include "demoutil.h"    /* in samples/common/include */
#include "bsfutil.h"     /* in samples/common/include */
#include "alginfoutil.h" /* in samples/alginfo */
#include "rsautil.h"     /* in samples/pkalg/rsa */

#define KEY_SIZE 10      /* key size in bytes */
#define RSA_MODULUS_BITS 512

B_ALGORITHM_METHOD *RC4_CHOOSER[] = {
  &AM_RC4_ENCRYPT,
  &AM_RC4_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 alginfoMain
#else
#define MAIN main
#endif

int MAIN(int argc, char *argv[])
{
  B_ALGORITHM_OBJ rc4Encrypter = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ decrypter = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ randomAlgorithm = (B_ALGORITHM_OBJ)NULL_PTR;

  B_KEY_OBJ rc4Key = (B_KEY_OBJ)NULL_PTR;
  B_KEY_OBJ publicKey = (B_KEY_OBJ)NULL_PTR;
  B_KEY_OBJ privateKey = (B_KEY_OBJ)NULL_PTR;
  B_KEY_OBJ keyObject = (B_KEY_OBJ)NULL_PTR;

  ITEM rc4KeyItem = {NULL, 0};
  ITEM myPublicKeyBER = {NULL, 0};
  ITEM *cryptocPublicKeyBER = NULL;
  ITEM *BERinfo = NULL;
  ITEM encodingInfo = {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 = 0;

  unsigned char *decryptedData = NULL_PTR;
  unsigned int decryptedDataLen = 0;

  unsigned int algorithmFlag = 0;
  unsigned int keyFlag = 0;


  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 ("RC4 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;

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

    /*  Set the algorithm to a type that does rc4 encryption.
        This sample uses AI_RC4. */
    if ((status = B_SetAlgorithmInfo (rc4Encrypter, AI_RC4,
                                      NULL_PTR)) != 0)
      break;

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

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

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

    RSA_PrintBuf ("RC4 Key", rc4KeyItem.data, rc4KeyItem.len);

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

    /*  Init */
    if ((status = B_EncryptInit (rc4Encrypter, rc4Key, RC4_CHOOSER,
                                 (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

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

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

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

    outputLenTotal = outputLenUpdate + outputLenFinal;
    encryptedDataLen = outputLenTotal;

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


    outputLenTotal = outputLenUpdate = outputLenFinal = 0;

    /* Obtain the algorithm identifier of the encryption algorithm */
    if ((status = B_GetAlgorithmInfo ((POINTER *)&BERinfo, rc4Encrypter,
                                       AI_RC4_BER)) != 0)
      break;

    encodingInfo.len = BERinfo->len;
    encodingInfo.data = (unsigned char *)T_malloc (encodingInfo.len);
    T_memcpy (encodingInfo.data, BERinfo->data, encodingInfo.len);


    /* Print out the algorithm identifier */
    RSA_PrintBuf ("Algorithm Identifier ", BERinfo->data, BERinfo->len);

    /* Obtain the algorithm information from the identifier */
    if ((status = B_DecodeAlgorithmBER (BERinfo->data, BERinfo->len,
                                        &algorithmFlag)) != 0)
      break;

    /* Pring out the algorithm information */
    RSA_PrintBERInfo (algorithmFlag);


    /* Use the algorithm information from B_DecodeAlgorithmBER to set an
       algorithm object and decrypt the encrypted data */

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

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

    /* Set the algorithm object.  Use a helper function here defined in
     * alginfoutil.c */
    if (( status = RSA_SetAlgorithmObject (&decrypter, algorithmFlag, &encodingInfo)) != 0)
      break;

    /* Init */
    if ((status = B_DecryptInit (decrypter, rc4Key, RC4_CHOOSER,
                                 (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;


    /* Update */
    decryptedDataLen = dataToEncryptLen;
    decryptedData = T_malloc (encryptedDataLen);
    if ((status = (decryptedData == NULL_PTR)) != 0) {
      status = RSA_DEMO_E_ALLOC;
      break;
    }

    if ((status = B_DecryptUpdate
                    (decrypter, decryptedData, &outputLenUpdate,
                     decryptedDataLen, (unsigned char *)encryptedData,
                     encryptedDataLen, (B_ALGORITHM_OBJ)NULL_PTR,
                     (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /* Final */
    if ((status = B_DecryptFinal
                    (decrypter, decryptedData + outputLenUpdate, &outputLenFinal,
                     decryptedDataLen - outputLenFinal,
                     (B_ALGORITHM_OBJ)NULL_PTR,
                     (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    outputLenTotal = outputLenUpdate + outputLenFinal;

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


    /* Let's create an RSA key pair and run through our decoding algorithm
       to see what it tells us */
    RSA_PrintMessage ("\nRSA Keypair:  Generation \n");
    RSA_PrintMessage ("======================== \n");

    if ((status = RSA_CreateRSAKeypair (&publicKey, &privateKey,
                                        RSA_MODULUS_BITS,
                                        randomAlgorithm)) != 0)
      break;

    if ((status = B_GetKeyInfo ((POINTER *)&cryptocPublicKeyBER, publicKey,
                                KI_RSAPublicBER)) != 0)
      break;

    myPublicKeyBER.len = cryptocPublicKeyBER->len;
    myPublicKeyBER.data = T_malloc (myPublicKeyBER.len);
    if (myPublicKeyBER.data == NULL_PTR) {
      status = RSA_DEMO_E_ALLOC;
      break;
    }

    T_memcpy (myPublicKeyBER.data, cryptocPublicKeyBER->data,
              myPublicKeyBER.len);

    /*  Obtain the key information from the BER encoded key format */
    if ((status = B_DecodeAlgorithmBER (myPublicKeyBER.data,
                                        myPublicKeyBER.len,
                                        &keyFlag)) != 0)
      break;

    RSA_PrintBERInfo (keyFlag);



  } while (0);

  if (status != 0)
    RSA_PrintError ("alginfo sample", status);

  /*  Done with the key and algorithm objects, so destroy them.  */
  B_DestroyKeyObject (&rc4Key);
  B_DestroyKeyObject (&publicKey);
  B_DestroyKeyObject (&privateKey);
  B_DestroyKeyObject (&keyObject);
  B_DestroyAlgorithmObject (&rc4Encrypter);
  B_DestroyAlgorithmObject (&decrypter);
  B_DestroyAlgorithmObject (&randomAlgorithm);

  if (encryptedData != NULL_PTR) {
    T_memset (encryptedData, 0, encryptedDataLen);
    T_free (encryptedData);
    encryptedData = NULL_PTR;
  }

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

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

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

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