RSA BSAFE Crypto-C

Cryptographic Components for C

Search

rsapkcs.c

/* $Id: rsapkcs.c,v 1.7 2004/12/03 02:08:38 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 will generate a RSA keypair, encrypt with the public key,
 *  then decrypt with the private key -- i.e. Digital Envelope.
 */

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

B_ALGORITHM_METHOD *RSA_SAMPLE_CHOOSER[] = {
  &AM_RSA_ENCRYPT,
  &AM_RSA_DECRYPT,
  &AM_RSA_CRT_ENCRYPT,
  &AM_RSA_CRT_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
};


#define RSA_MODULUS_BITS 512
#define BLOCK_SIZE ((RSA_MODULUS_BITS + 7) / 8)

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

int MAIN(int argc, char *argv[])
{
  B_ALGORITHM_OBJ randomAlgorithm = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ rsaEncryptor = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ rsaDecryptor = (B_ALGORITHM_OBJ)NULL_PTR;
  B_KEY_OBJ publicKey = (B_KEY_OBJ)NULL_PTR;
  B_KEY_OBJ privateKey = (B_KEY_OBJ)NULL_PTR;

  A_SURRENDER_CTX generalSurrenderContext;
  int generalFlag;

  ITEM *cryptocPublicKeyBER;
  ITEM myPublicKeyBER = {NULL, 0};

  ITEM *getPrivateKey;
  ITEM privateKeyBER = {NULL, 0};

  /* This could be a DES or RC4 key, for example... */
  unsigned char dataToEncryptWithRSA[] = {
    0x4a, 0x72, 0x55, 0x36, 0xda, 0x2f, 0xb9, 0x51
  };

  unsigned int dataToEncryptLen = sizeof(dataToEncryptWithRSA);

  unsigned char encryptedData[BLOCK_SIZE];
  unsigned char decryptedData[BLOCK_SIZE];
  unsigned int outputLenUpdate, outputLenFinal, outputLenTotal;

  int status;

  /* See samples/common/source/surrctx.c for RSA_GeneralSurrenderFunction */
  generalSurrenderContext.Surrender = RSA_GeneralSurrenderFunction;
  generalSurrenderContext.handle = (POINTER)&generalFlag;
  generalSurrenderContext.reserved = NULL_PTR;

  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 ("RSA PKCS #1 Algorithm\n");
    RSA_PrintMessage ("=====================\n");
    RSA_PrintMessage ("Maximum allowable size for data to encrypt = %d bytes\n",
                      BLOCK_SIZE - 11);
    RSA_PrintBuf ("Data to Encrypt", dataToEncryptWithRSA, dataToEncryptLen);

    if ((status = RSA_CreateRandomAlgorithmObject (&randomAlgorithm)) != 0)
      break;

    /* The following function is in samples/pkalg/rsa/rsautil.c */
    if ((status = RSA_CreateRSAKeypair
                    (&publicKey, &privateKey, RSA_MODULUS_BITS,
                     randomAlgorithm)) != 0)
      break;

    RSA_PrintMessage ("\n   Distributing Your Public Key\n");
    RSA_PrintMessage ("   ============================\n");

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

    RSA_PrintMessage ("The public key DER-encoded as X.509\n");
    RSA_PrintBuf ("SubjectPublicKeyInfo type", myPublicKeyBER.data,
                  myPublicKeyBER.len);

    RSA_PrintMessage ("   Encrypting with the RSA Public Key\n");
    RSA_PrintMessage ("   ==================================\n");

    /*  Create an Algorithm Object */
    if ((status = B_CreateAlgorithmObject (&rsaEncryptor)) != 0)
      break;

    /*  Set the algorithm object to AI_PKCS_RSAPublic */
    if ((status = B_SetAlgorithmInfo (rsaEncryptor, AI_PKCS_RSAPublic,
                                      NULL_PTR)) != 0)
      break;

    /*  Init -- encrypt with the recipient's public key */
    if ((status = B_EncryptInit (rsaEncryptor, publicKey, RSA_SAMPLE_CHOOSER,
                                 (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Update */
    generalFlag = 0;
    if ((status = B_EncryptUpdate (rsaEncryptor, encryptedData,
                                   &outputLenUpdate, BLOCK_SIZE,
                                   dataToEncryptWithRSA, dataToEncryptLen,
                                   randomAlgorithm,
                                   &generalSurrenderContext)) != 0)
      break;

    /*  Final  */
    generalFlag = 0;
    if ((status = B_EncryptFinal (rsaEncryptor,
                                  encryptedData + outputLenUpdate,
                                  &outputLenFinal,
                                  BLOCK_SIZE - outputLenUpdate,
                                  randomAlgorithm,
                                  &generalSurrenderContext)) != 0)
      break;

    outputLenTotal = outputLenUpdate + outputLenFinal;
    RSA_PrintBuf ("Encrypted Data", encryptedData, outputLenTotal);

    RSA_PrintMessage ("   Decrypting with the RSA Private Key\n");
    RSA_PrintMessage ("   ===================================\n");

    if ((status = B_GetKeyInfo ((POINTER *)&getPrivateKey, privateKey,
                                KI_PKCS_RSAPrivateBER)) != 0)
      break;

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

    T_memcpy (privateKeyBER.data, getPrivateKey->data,
              privateKeyBER.len);

    RSA_PrintMessage ("The private key encoded as a PKCS #8\n");
    RSA_PrintBuf ("PrivateKeyInfo type", privateKeyBER.data,
                  privateKeyBER.len);

    /*  Create an Algorithm Object */
    if ((status = B_CreateAlgorithmObject (&rsaDecryptor)) != 0)
      break;

    /*  Set the algorithm object to AI_PKCS_RSAPrivate */
    if ((status = B_SetAlgorithmInfo (rsaDecryptor, AI_PKCS_RSAPrivate,
                                      NULL_PTR)) != 0)
      break;

    /*  Init -- Use the private key associated with the public
                key used to encrypt */
    if ((status = B_DecryptInit (rsaDecryptor, privateKey, RSA_SAMPLE_CHOOSER,
                                 (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Update */
    generalFlag = 0;
    if ((status = B_DecryptUpdate (rsaDecryptor, decryptedData,
                                   &outputLenUpdate, BLOCK_SIZE,
                                   encryptedData, outputLenTotal, NULL_PTR,
                                   &generalSurrenderContext)) != 0)
      break;

    /*  Final */
    generalFlag = 0;
    if ((status = B_DecryptFinal (rsaDecryptor,
                                  decryptedData + outputLenUpdate,
                                  &outputLenFinal,
                                  BLOCK_SIZE - outputLenUpdate, NULL_PTR,
                                  &generalSurrenderContext)) != 0)
      break;

    outputLenTotal = outputLenUpdate + outputLenFinal;

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

    if ((outputLenTotal == dataToEncryptLen) &&
        (T_memcmp (dataToEncryptWithRSA, decryptedData,
                   outputLenTotal)) == 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 ("rsapkcs", status);

  /*  Destroy the key and algorithm objects */
  B_DestroyAlgorithmObject (&randomAlgorithm);
  B_DestroyAlgorithmObject (&rsaEncryptor);
  B_DestroyAlgorithmObject (&rsaDecryptor);
  B_DestroyKeyObject (&privateKey);
  B_DestroyKeyObject (&publicKey);

  /*  Free up any memory allocated  */
  if (myPublicKeyBER.data != NULL_PTR)
    T_free (myPublicKeyBER.data);

  if (privateKeyBER.data != NULL_PTR)
    T_free (privateKeyBER.data);

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

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