RSA BSAFE Crypto-C

Cryptographic Components for C

Search

rsaoaep.c

/* $Id: rsaoaep.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 using
 * AI_PKCS_OAEP_RSAPublic and AI_PKCS_OAEP_RSAPrivate to encrypt and
 * decrypt randomly generated data using OAEP as defined in PKCS #1 v2.
 *
 * The Optimal Asymmetric Encryption Padding (OAEP) scheme is used as a
 * superior padding scheme to thrwart certain attacks against the protocols
 * using digital envelopes.
 *
 * 19NOV98 JAG v4.1.1
 */

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

#define RSA_MODULUS_BITS 1024

/* PKCS #1 OAEP has 42 bytes of padding */
#define BLOCK_OVERHEAD 42

B_ALGORITHM_METHOD *DEMO_ALGORITHM_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
};



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

int MAIN(int argc, char *argv[])
{
  /* Random algorithm objects. */
  B_ALGORITHM_OBJ randomAlgorithm = (B_ALGORITHM_OBJ)NULL_PTR;

  /* Public and private key objects. */
  B_KEY_OBJ publicKey = (B_KEY_OBJ)NULL_PTR;
  B_KEY_OBJ privateKey = (B_KEY_OBJ)NULL_PTR;

  /* Encryption and decryption objects. */
  B_ALGORITHM_OBJ rsaEncryptor = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ rsaDecryptor = (B_ALGORITHM_OBJ)NULL_PTR;

  unsigned char *dataToEncrypt = NULL_PTR;
  unsigned int dataToEncryptLen = 0;
  unsigned char *encryptedData = NULL_PTR, *decryptedData = NULL_PTR;
  unsigned char *updateBuffer = NULL_PTR;
  unsigned int encryptedDataLen = 0, decryptedDataLen = 0;
  unsigned int updateBufferLen = 0;
  unsigned int blockSize = 0, blockPayload = 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 ("RSA PKCS #1 V2 Encryption With OAEP Example\n");
    RSA_PrintMessage ("===========================================\n");

    /* Determine the encryption block size, and the payload (data) that we
     * can encrypt in each block.
     */
    blockSize = (RSA_MODULUS_BITS + 7) / 8;
    blockPayload = blockSize - BLOCK_OVERHEAD;

    /* Encrypted data is allocated to the max message size.
     */
    dataToEncrypt = T_malloc (blockPayload);
    dataToEncryptLen = blockPayload;

    encryptedData = T_malloc (blockSize);
    updateBuffer = T_malloc (blockSize);

    /* Decrypted data is allocated to the padded max message size.
     */
    decryptedData = T_malloc (blockPayload);

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

    /* For more information on generating RSA keypairs, see the following
     * function in samples/pkalg/rsa/rsautil.c
     */
    if ((status = RSA_CreateRSAKeypair
                    (&publicKey, &privateKey, RSA_MODULUS_BITS,
                     randomAlgorithm)) != 0)
      break;

    /* For this example, we'll envelope some randomly generated bytes.
     */
    if ((status = B_GenerateRandomBytes (randomAlgorithm, dataToEncrypt,
                                         dataToEncryptLen,
                                         (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    RSA_PrintBuf ("Data to Encrypt and Pad", dataToEncrypt, dataToEncryptLen);

    RSA_PrintMessage ("\nPerforming PKCS V2 Encryption\n");
    RSA_PrintMessage ("=============================\n");

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

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

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

    /*  Update */
    if ((status = B_EncryptUpdate (rsaEncryptor, encryptedData,
                                   &updateBufferLen, blockSize,
                                   dataToEncrypt, dataToEncryptLen,
                                   randomAlgorithm,
                                   (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Final */
    if ((status = B_EncryptFinal (rsaEncryptor, encryptedData,
                                  &encryptedDataLen, blockSize,
                                  randomAlgorithm,
                                  (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    encryptedDataLen += updateBufferLen;

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

    RSA_PrintMessage ("\nPerforming PKCS V2 Decryption\n");
    RSA_PrintMessage ("=============================\n");

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

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

    /*  Init  */
    if ((status = B_DecryptInit (rsaDecryptor, privateKey,
                                 DEMO_ALGORITHM_CHOOSER,
                                 (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Update */
    updateBufferLen = 0;
    if ((status = B_DecryptUpdate (rsaDecryptor, updateBuffer,
                                   &updateBufferLen, blockPayload,
                                   encryptedData, encryptedDataLen,
                                   randomAlgorithm,
                                   (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Final */
    if ((status = B_DecryptFinal (rsaDecryptor, decryptedData,
                                  &decryptedDataLen, blockPayload,
                                  randomAlgorithm,
                                  (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    decryptedDataLen += updateBufferLen;

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

    /* The decrypted data should match the plaintext data that was
     * originally generated.  If they match, the envelope verified
     * correctly.
     */
    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 ("rsaoaep", status);

  /*  Destroy  */
  B_DestroyAlgorithmObject (&randomAlgorithm);
  B_DestroyKeyObject (&privateKey);
  B_DestroyKeyObject (&publicKey);
  B_DestroyAlgorithmObject (&rsaDecryptor);
  B_DestroyAlgorithmObject (&rsaEncryptor);

  /* Free the memory used by these objects.  The T_ functions are
   * defined in tstdlib.c included in the samples/common/source
   * directory with Crypto-C.  Also zero out the sensitive data for
   * security precautions.
   */

  if (dataToEncrypt != NULL_PTR) {
    T_memset(dataToEncrypt, 0, dataToEncryptLen);
    T_free(dataToEncrypt);
  }

  if (encryptedData != NULL_PTR)
    T_free(encryptedData);

  if (updateBuffer != NULL_PTR)
    T_free(updateBuffer);

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

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

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