RSA BSAFE Crypto-C

Cryptographic Components for C

Search

ecspecial.c

/* $Id: ecspecial.c,v 1.7 2004/12/03 02:08:37 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 create an EC keypair from a given curve, encrypt a
 *  block of data with the public key and decrypt with the private key,
 *  using the Elliptic Curve Encryption Scheme.
 */

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

B_ALGORITHM_METHOD *EC_CHOOSER[] = {
  &AM_ECFP_KEY_GEN,
  &AM_ECF2POLY_KEY_GEN,
  &AM_ECFP_ENCRYPT,
  &AM_ECFP_DECRYPT,
  &AM_ECF2POLY_ENCRYPT,
  &AM_ECF2POLY_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 ecesMain
#else
#define MAIN main
#endif

int MAIN(int argc, char *argv[])
{
  int status;

  B_ALGORITHM_OBJ randomAlgorithm = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ ecKeyGen = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ ecesEncrypt = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ ecesDecrypt = (B_ALGORITHM_OBJ)NULL_PTR;

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

  /*  We don't need a B_ALGORITHM_OBJ for the parameters since we
   *  are using pre-defined curves.  However, we still need the
   *  information for these curves */
  B_EC_PARAMS paramInfo;
  B_EC_SPECIAL_CURVE specialCurve;

  int fieldElementLen;

  unsigned char dataToEncrypt[] = {
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  };
  unsigned int dataToEncryptLen = sizeof(dataToEncrypt);

  unsigned char *encryptedData = NULL_PTR;
  unsigned char *decryptedData = NULL_PTR;
  unsigned int maxEncryptedDataLen, maxDecryptedDataLen;
  unsigned int outputLenUpdate, outputLenFinal, outputLenTotal;

  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 ("EC Special Curve encryption and decryption example\n");
    RSA_PrintMessage ("==================================================\n");

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

    RSA_PrintMessage("\nGenerating an EC Key Pair using a Special Curve\n");

    /*  Create.  */
    if ((status = B_CreateAlgorithmObject (&ecKeyGen)) != 0)
      break;
    if ((status = B_CreateKeyObject (&publicKey)) != 0)
      break;
    if ((status = B_CreateKeyObject (&privateKey)) != 0)
      break;

    /*  Set.  */
    /*  Here is where you will define what curve you want to use. */
    specialCurve.definedCurve = NIST_P192;
    fieldElementLen = 192;

    paramInfo.parameterInfoType = AI_ECSpecialCurve;
    paramInfo.parameterInfoValue = (POINTER)&specialCurve;

    if ((status = B_SetAlgorithmInfo (ecKeyGen, AI_ECKeyGen,
                                      (POINTER)&paramInfo)) != 0)
      break;

    /*  Init.  */
    if ((status = B_GenerateInit (ecKeyGen, EC_CHOOSER,
                                  (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Generate.  */
    if ((status = B_GenerateKeypair (ecKeyGen, publicKey, privateKey,
                                     randomAlgorithm,
                                     (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;


    /*  Print out key information  */
    if ((status = RSA_PrintECKeyInfo ("Public Key", KI_ECPublicComponent,
                                      publicKey, 0)) != 0)
      break;
    if ((status = RSA_PrintECKeyInfo ("Private Key", KI_ECPrivateComponent,
                                      privateKey, 0)) != 0)
      break;

    /* EC encryption */
    RSA_PrintMessage ("\nEncrypting Data...\n");
    RSA_PrintBuf ("Data to Encrypt", dataToEncrypt, dataToEncryptLen);

    /* Create. */
    if ((status = B_CreateAlgorithmObject (&ecesEncrypt)) != 0)
      break;

    /* Set.  */
    if ((status = B_SetAlgorithmInfo (ecesEncrypt, AI_EC_ES, NULL_PTR)) != 0)
      break;

    /* Init.  */
    if ((status = B_EncryptInit (ecesEncrypt, publicKey, EC_CHOOSER,
                                 (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Update.  */
    /*  Allocate space to hold encrypted data  */
    maxEncryptedDataLen = 21 + (2 * fieldElementLen) + dataToEncryptLen;
    RSA_PrintMessage ("Expected size of encrypted data = %u bytes\n",
                      maxEncryptedDataLen);

    encryptedData = T_malloc (maxEncryptedDataLen);
    if (encryptedData == NULL_PTR) {
      status = RSA_DEMO_E_ALLOC;
      break;
    }

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

    /* Final.  */
    if ((status = B_EncryptFinal (ecesEncrypt, encryptedData + outputLenUpdate,
                                  &outputLenFinal,
                                  maxEncryptedDataLen - outputLenUpdate,
                                  randomAlgorithm,
                                  (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    outputLenTotal = outputLenUpdate + outputLenFinal;

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

    /* EC decryption */
    RSA_PrintMessage("\nDecrypting Data...\n");

    /* Create. */
    if ((status = B_CreateAlgorithmObject (&ecesDecrypt)) != 0)
      break;

    /* Set.  */
    if ((status = B_SetAlgorithmInfo (ecesDecrypt, AI_EC_ES, NULL_PTR)) != 0)
      break;

    /* Init.  */
    if ((status = B_DecryptInit (ecesDecrypt, privateKey, EC_CHOOSER,
                                 (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Update.  */
    /*  Allocate space to hold decrypted data.
     *  The decrypted data will be smaller than the ciphertext. */
    maxDecryptedDataLen = outputLenTotal;
    RSA_PrintMessage ("Maximum size of decrypted data = %u bytes\n",
                      maxDecryptedDataLen);

    decryptedData = T_malloc (maxDecryptedDataLen);
    if (decryptedData == NULL_PTR) {
      status = RSA_DEMO_E_ALLOC;
      break;
    }

    if ((status = B_DecryptUpdate (ecesDecrypt, decryptedData,
                                   &outputLenUpdate, maxDecryptedDataLen,
                                   encryptedData, outputLenTotal,
                                   (B_ALGORITHM_OBJ)NULL_PTR,
                                   (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

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

    outputLenTotal = outputLenUpdate + outputLenFinal;

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

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

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

  /* Destroy all objects and free memory.  */
  B_DestroyAlgorithmObject (&ecesEncrypt);
  B_DestroyAlgorithmObject (&ecesDecrypt);
  B_DestroyKeyObject (&publicKey);
  B_DestroyKeyObject (&privateKey);

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

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

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

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