RSA BSAFE Crypto-C

Cryptographic Components for C

Search

Performing ECDSA with X9.62-Compliant BER

This sample demonstrates how to perform ECDSA in compliance with the ANSI X9.62 standard. BER-encoding is used to initialize the parameters.

/* $Id: x962.c,v 1.7 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.
 * 
 *
 */

/*  This program demonstrates raw DSA signing and verifying in compliance
 *  with the ANSI X9.62 standard.  This method is usually used to sign the
 *  result of a digest operation.  Here we just sign an arbitrary 32 byte
 *  value.
 *
 *  This program will generate an EC keypair, sign data with the
 *  private key, and then verify using the public key in accordance to the
 *  X9.62 standard.
 *
 *  If you wish to use the acceleration tables, please refer to the sample
 *  sample/pkalg/ecc/ecdsa.c, sample/pkalg/ecc/ecutil.h, and
 *  sample/pkalg/ecutil.c.
 */

#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 x962Main
#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;

  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 ("X9.62 ANSI Compliant EC DSA Signature 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;

    RSA_PrintMessage ("\nBER-encoded EC Parameters:\n");
    if ((status = RSA_PrintECParamInfo (ecParamsObj, AI_ECParametersBER)) != 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);

    /*  We pass in NULL as the final argument, since we are not using
        accelerator tables  */
    if ((status = RSA_CreateECKeys (&publicKey, &privateKey, ecParamsObj,
                                    randomAlgorithm, NULL)) != 0)
      break;

    /*  Print out key information */
    RSA_PrintMessage ("\nBER-encoded keypair containing only the public or ");
    RSA_PrintMessage ("private components:\n");
    if ((status = RSA_PrintECKeyInfo ("publicKeyBER", KI_ECPublicComponentBER,
                                      publicKey, 1)) != 0)
      break;

    if ((status = RSA_PrintECKeyInfo ("privateKeyBER",
                                      KI_ECPrivateComponentBER,
                                      privateKey, 1)) != 0)
      break;

    RSA_PrintMessage ("\nBER-encoded keypair containing corresponding ");
    RSA_PrintMessage ("parameters:\n");
    if ((status = RSA_PrintECKeyInfo ("publicKeyBER", KI_ECPublicBER,
                                      publicKey, 1)) != 0)
      break;

    if ((status = RSA_PrintECKeyInfo ("privateKeyBER", KI_ECPrivateBER,
                                      privateKey, 1)) != 0)
      break;

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

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

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

    /*  Update  */
    RSA_PrintBuf ("\nData 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;

    /*  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 ("x962", status);

  /* Dstroy key and algorithm objects and free memory */
  B_DestroyAlgorithmObject (&randomAlgorithm);
  B_DestroyAlgorithmObject (&ecParamsObj);
  B_DestroyAlgorithmObject (&ecDSASign);
  B_DestroyAlgorithmObject (&ecDSAVerify);
  B_DestroyKeyObject (&publicKey);
  B_DestroyKeyObject (&privateKey);

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

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

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