RSA BSAFE Crypto-C

Cryptographic Components for C

Search

ecdsa.c

/* $Id: ecdsa.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 demonstrates raw DSA signing and verifying.  This
 *  method is usually used to sign the result of a digest operation.
 *  Here we just sign an arbitrary 32 byte value.  If you want to
 *  digest a message and sign it using DSA, AI_EC_DSAWithDigest may
 *  be what you want to use.  See ecdsadig.c for an example.
 *
 *  This program will generate an EC keypair, sign data with the
 *  private key, and then verify using the public key.
 */

#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_DSA_CHOOSER[] = {
  &AM_ECFP_DSA_SIGN,
  &AM_ECF2POLY_DSA_SIGN,
  &AM_ECFP_DSA_VERIFY,
  &AM_ECF2POLY_DSA_VERIFY,
  (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 ecdsaMain
#else
#define MAIN main
#endif

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

  /*  dataToSign must be between 16 and 32 bytes inclusive  */
  unsigned char dataToSign[] = {
    0x53, 0x69, 0x67, 0x6E, 0x20, 0x74, 0x68, 0x69,
    0x73, 0x20, 0x33, 0x32, 0x20, 0x62, 0x79, 0x74,
    0x65, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6D,
    0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x3F, 0x21
  };
  unsigned int dataToSignLen = sizeof(dataToSign);

  B_ALGORITHM_OBJ randomAlgorithm = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ ecParamsObj = (B_ALGORITHM_OBJ)NULL_PTR;

  A_EC_PARAMS *ecParamInfo;
  unsigned int orderLen;

  ITEM aTableItem = {NULL, 0};
  ITEM pubKeyAccelTableItem = {NULL, 0};

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

  B_ALGORITHM_OBJ ecDSASign = (B_ALGORITHM_OBJ)NULL_PTR;
  B_ALGORITHM_OBJ ecDSAVerify = (B_ALGORITHM_OBJ)NULL_PTR;

  unsigned char *signature = NULL_PTR;
  unsigned int maxSignatureLen;
  unsigned int signatureLen;  /*  actual length of the signature  */

  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 ("Raw EC DSA Signing Example\n");
    RSA_PrintMessage ("==========================\n");

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

    if ((status = RSA_GetCommand (userInput, sizeof (userInput),
                                  "Generate new parameters (y/n)")) != 0)
      break;

    if ((userInput[0] == 'y') || (userInput[0] == 'Y')) {
      if ((status = RSA_CreateECParamsObject (&ecParamsObj,
                                              randomAlgorithm)) != 0)
        break;
    } else {
      if ((status = RSA_CreateECParamsObject (&ecParamsObj,
                                              NULL)) != 0)
        break;
    }

    if ((status = RSA_PrintECParamInfo (ecParamsObj, AI_ECParameters)) != 0)
      break;

    /*  Retrieve useful information from the EC Parameters  */
    if ((status = B_GetAlgorithmInfo ((POINTER *)&ecParamInfo, ecParamsObj,
                                      AI_ECParameters)) != 0)
      break;

    orderLen = ecParamInfo->order.len;
    RSA_PrintMessage ("EC Parameters:  Order length = %u bytes\n", orderLen);

    if ((status = RSA_GetCommand (userInput, sizeof (userInput),
                                  "Generate accelerator tables (y/n)")) != 0)
      break;

    if ((userInput[0] == 'y') || (userInput[0] == 'Y')) {
      if ((status = RSA_BuildAccelTable (&aTableItem, ecParamsObj)) != 0)
        break;
    }

    if ((status = RSA_CreateECKeys (&publicKey, &privateKey, ecParamsObj,
                                    randomAlgorithm, &aTableItem)) != 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;

    /*  Create the algorithm object  */
    if ((status = B_CreateAlgorithmObject (&ecDSASign)) != 0)
      break;

    /*  Set the algorithm info  */
    if ((status = B_SetAlgorithmInfo (ecDSASign, AI_EC_DSA,
                                      (POINTER)NULL_PTR)) != 0)
      break;

    if (aTableItem.data != NULL) {
      RSA_PrintMessage ("Using accelerator table for signing...\n");

      if ((status = B_SetAlgorithmInfo (ecDSASign, AI_ECAcceleratorTable,
                                        (POINTER)&aTableItem)) != 0)
        break;
    }

    /*  Init  */
    if ((status = B_SignInit (ecDSASign, privateKey, EC_DSA_CHOOSER,
                              (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Update  */
    RSA_PrintBuf ("Data to Sign", dataToSign, dataToSignLen);

    if ((status = B_SignUpdate (ecDSASign, dataToSign, dataToSignLen,
                                (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Final  */
    /*  Allocate space for the signature  */
    maxSignatureLen = 2 * orderLen;
    RSA_PrintMessage ("Max signature length = %u bytes\n", maxSignatureLen);

    signature = T_malloc (maxSignatureLen);
    if (signature == NULL_PTR) {
      status = RSA_DEMO_E_ALLOC;
      break;
    }

    if ((status = B_SignFinal (ecDSASign, signature, &signatureLen,
                               maxSignatureLen, randomAlgorithm,
                               (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    RSA_PrintBuf ("Signature", signature, signatureLen);

    RSA_PrintMessage ("\nVerifying Signature...\n");

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

    /*  Set  */
    if ((status = B_SetAlgorithmInfo (ecDSAVerify, AI_EC_DSA,
                                      (POINTER)NULL_PTR)) != 0)
      break;

    if ((status = RSA_GetCommand
                    (userInput, sizeof (userInput),
                     "Generate public key accelerator tables (y/n)")) != 0)
      break;

    if ((userInput[0] == 'y') || (userInput[0] == 'Y')) {
      if ((status = RSA_BuildPubKeyAccelTable (&pubKeyAccelTableItem,
                                               publicKey)) != 0)
        break;

      RSA_PrintMessage
        ("Using public key accelerator table for ECDSA verififcation...\n");

      if ((status = B_SetAlgorithmInfo (ecDSAVerify, AI_ECAcceleratorTable,
                                        (POINTER)&pubKeyAccelTableItem)) != 0)
      break;
    } else if (aTableItem.data != NULL) {
      RSA_PrintMessage
        ("Using EC parameter accelerator table for ECDSA verification...\n");

      if ((status = B_SetAlgorithmInfo (ecDSAVerify, AI_ECAcceleratorTable,
                                        (POINTER)&aTableItem)) != 0)
        break;
    }

    /*  Init  */
    if ((status = B_VerifyInit (ecDSAVerify, publicKey, EC_DSA_CHOOSER,
                                (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Update  */
    if ((status = B_VerifyUpdate (ecDSAVerify, dataToSign, dataToSignLen,
                                  (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    /*  Final  */
    if ((status = B_VerifyFinal (ecDSAVerify, signature, signatureLen,
                                 (B_ALGORITHM_OBJ)NULL_PTR,
                                 (A_SURRENDER_CTX *)NULL_PTR)) != 0)
      break;

    RSA_PrintMessage ("Success!  The signature verified.\n");
  } while(0);

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

  /* Destroy key and algorithm objects and free memory */
  if (aTableItem.data != NULL)
  {
    T_memset (aTableItem.data, 0, aTableItem.len);
    T_free (aTableItem.data);
  }

  if (pubKeyAccelTableItem.data != NULL)
  {
    T_memset (pubKeyAccelTableItem.data, 0, pubKeyAccelTableItem.len);
    T_free (pubKeyAccelTableItem.data);
  }

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

  B_DestroyAlgorithmObject (&randomAlgorithm);
  B_DestroyAlgorithmObject (&ecParamsObj);
  B_DestroyAlgorithmObject (&ecDSASign);
  B_DestroyAlgorithmObject (&ecDSAVerify);
  B_DestroyKeyObject (&publicKey);
  B_DestroyKeyObject (&privateKey);

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

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