RSA BSAFE Crypto-C

Cryptographic Components for C

Search

bsliteds.c

/* $Id: bsliteds.c,v 1.4 2004/12/03 02:08:36 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.
 *
 *
 */

#include <stdio.h>
#include "aglobal.h"
#include "bsafe.h"
#include "bsafe.h"
#include "bsliteds.h"
#include "fileio.h"
#include "demochos.h"

int BSL_MakeDSAKeyPairFromSeed(unsigned char *publicKey,
  unsigned int *publicKeyLen, unsigned char *ppPrivateKey,
  unsigned int *ppPrivateKeyLen, unsigned int maxPrivateKeyLen,
  unsigned char *pbeParams, unsigned int *pbeParamsLen,
  unsigned int keySizeBits, unsigned char *seed, unsigned int seedLen,
  unsigned char *password, unsigned int passwordLen)
{
  B_DSA_PARAM_GEN_PARAMS parameters;
  B_ALGORITHM_OBJ keyGenAlgorithmObj = NULL_PTR;
  B_ALGORITHM_OBJ paramGenAlgorithmObj = NULL_PTR;
  B_ALGORITHM_OBJ pbEncryptionAlgorithmObj = NULL_PTR;
  B_ALGORITHM_OBJ randomAlgorithmObj = NULL_PTR;
  B_ALGORITHM_OBJ saltDigestAlgorithmObj = NULL_PTR;
  B_KEY_OBJ passwordKeyObj = NULL_PTR;
  B_KEY_OBJ privateKeyObj = NULL_PTR;
  B_KEY_OBJ publicKeyObj = NULL_PTR;
  B_PBE_PARAMS pbeParamsStruct;
  ITEM passwordItem, *keyItemPtr, *pbeBERItemPtr;
  int status;
  unsigned char pbeSaltBuf[20];
  unsigned int digestLen, outputLen;
  
  /* do {} while(0); provides convenient way to ensure cleanup upon error */
  do {

    /* create random algorithm objects and set algorithm info */
    status = B_CreateAlgorithmObject (&randomAlgorithmObj);
    if (status != 0)
      break;

    status = B_SetAlgorithmInfo (randomAlgorithmObj, AI_MD2Random, NULL_PTR);
    if (status != 0)
      break;

    /* call random init, update with supplied seed bytes */
    status = B_RandomInit
      (randomAlgorithmObj, DEMO_ALGORITHM_CHOOSER,
       (A_SURRENDER_CTX *)NULL_PTR);
    if (status != 0)
      break;

    status = B_RandomUpdate
      (randomAlgorithmObj, seed, seedLen, (A_SURRENDER_CTX *)NULL_PTR);
    if (status != 0)
      break;

    /* create param and key gen algorithm object */
    status = B_CreateAlgorithmObject (&paramGenAlgorithmObj);
    if (status != 0)
      break;
    status = B_CreateAlgorithmObject (&keyGenAlgorithmObj);
    if (status != 0)
      break;

    /* set up  parameters generation DSA parameter */
    parameters.primeBits = keySizeBits;
    status = B_SetAlgorithmInfo
      (paramGenAlgorithmObj, AI_DSAParamGen, (POINTER)&parameters);
    if (status != 0)
      break;

    status = B_GenerateInit
      (paramGenAlgorithmObj, DEMO_ALGORITHM_CHOOSER, 
       (A_SURRENDER_CTX *)NULL_PTR);
    if (status != 0)
      break;
    
    status = B_GenerateParameters
      (paramGenAlgorithmObj, keyGenAlgorithmObj, randomAlgorithmObj,
       (A_SURRENDER_CTX *)NULL_PTR);
    if (status != 0)
      break;

    /* init the dsa key gen algorithm */
    status = B_GenerateInit
      (keyGenAlgorithmObj, DEMO_ALGORITHM_CHOOSER,
       (A_SURRENDER_CTX *)NULL_PTR);
    if (status != 0)
      break;

    /* create private and public key objects */
    status = B_CreateKeyObject (&privateKeyObj);
    if (status != 0)
      break;

    status = B_CreateKeyObject (&publicKeyObj);
    if (status != 0)
      break;

    /* generate keys and store in key objects (may take a few moments) */
    status = B_GenerateKeypair
      (keyGenAlgorithmObj, publicKeyObj, privateKeyObj,
       randomAlgorithmObj, (A_SURRENDER_CTX *)NULL_PTR);
    if (status != 0)
      break;

    /* request the Distinguished Encoding (DER) of the public key
     */
    status = B_GetKeyInfo
      ((POINTER *)&keyItemPtr, publicKeyObj, KI_DSAPublicBER);
    if (status != 0)
      break;

    T_memcpy ((POINTER)publicKey, (POINTER)keyItemPtr->data, keyItemPtr->len);
    *publicKeyLen = keyItemPtr->len;

    /* request the Distinguished Encoding (DER) of the private key info
     */
    status = B_GetKeyInfo
      ((POINTER *)&keyItemPtr, privateKeyObj, KI_DSAPrivateBER);
    if (status != 0)
      break;

    /* if supplied password is NULL, copy unencrypted private key info
       to the supplied buffer
     */
    if (password == (unsigned char *)NULL_PTR) {
      T_memcpy
        ((POINTER)ppPrivateKey, (POINTER)keyItemPtr->data, keyItemPtr->len);
      *ppPrivateKeyLen = keyItemPtr->len;
    }
    /* otherwise; encrypt the private key under the supplied password */
    else {
      /* first, generate a password-based encryption salt value by
         digesting the private key and the supplied password
       */
      status = B_CreateAlgorithmObject (&saltDigestAlgorithmObj);
      if (status != 0)
        break;

      status = B_SetAlgorithmInfo (saltDigestAlgorithmObj, AI_SHA1, NULL_PTR);
      if (status != 0)
        break;

      status = B_DigestInit
        (saltDigestAlgorithmObj, NULL_PTR, DEMO_ALGORITHM_CHOOSER,
         (A_SURRENDER_CTX *)NULL_PTR);
      if (status != 0)
        break;

      status = B_DigestUpdate
        (saltDigestAlgorithmObj, password, passwordLen,
         (A_SURRENDER_CTX *)NULL_PTR);
      if (status != 0)
        break;
  
      status = B_DigestUpdate
        (saltDigestAlgorithmObj, keyItemPtr->data, keyItemPtr->len,
         (A_SURRENDER_CTX *)NULL_PTR);
      if (status != 0)
        break;

      status = B_DigestFinal
        (saltDigestAlgorithmObj, pbeSaltBuf, &digestLen, sizeof(pbeSaltBuf),
         (A_SURRENDER_CTX *)NULL_PTR);
      if (status != 0)
        break;

      /* create password-based encryption algorithm object */
      status = B_CreateAlgorithmObject (&pbEncryptionAlgorithmObj);
      if (status != 0)
        break;

      /* setup password-based encryption parameters */
      pbeParamsStruct.salt = pbeSaltBuf;
      pbeParamsStruct.iterationCount = 1;

      /* set algorithm object */
      status = B_SetAlgorithmInfo
        (pbEncryptionAlgorithmObj, AI_SHA1WithDES_CBCPad,
         (POINTER)&pbeParamsStruct);
      if (status != 0)
        break;

      /* get the PBE parameters in their BER encoded form */
      status = B_GetAlgorithmInfo
        ((POINTER *)&pbeBERItemPtr, pbEncryptionAlgorithmObj,
         AI_SHA1WithDES_CBCPadBER);
      if (status != 0)
        break;

      /* return encoded pbe parameters and length to the caller in the
         supplied args.
       */
      T_memcpy
        ((POINTER)pbeParams, (POINTER)pbeBERItemPtr->data, pbeBERItemPtr->len);
      *pbeParamsLen = pbeBERItemPtr->len;

      /* create key object */
      status = B_CreateKeyObject (&passwordKeyObj);
      if (status != 0)
        break;

      /* setup password item and set key info */
      passwordItem.data = password;
      passwordItem.len = passwordLen;
      status = B_SetKeyInfo (passwordKeyObj, KI_Item, (POINTER)&passwordItem);
      if (status != 0)
        break;

      /* encrypt the private key DER */
      status = B_EncryptInit
        (pbEncryptionAlgorithmObj, passwordKeyObj,
         DEMO_ALGORITHM_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR);
      if (status != 0)
        break;

      status = B_EncryptUpdate
        (pbEncryptionAlgorithmObj, ppPrivateKey, &outputLen,
         maxPrivateKeyLen, keyItemPtr->data, keyItemPtr->len,
         (B_ALGORITHM_OBJ)NULL_PTR, (A_SURRENDER_CTX *)NULL_PTR);
      if (status != 0)
        break;

      *ppPrivateKeyLen = outputLen;
      status = B_EncryptFinal
        (pbEncryptionAlgorithmObj, ppPrivateKey + *ppPrivateKeyLen,
         &outputLen, maxPrivateKeyLen - *ppPrivateKeyLen,
         (B_ALGORITHM_OBJ)NULL_PTR, (A_SURRENDER_CTX *)NULL_PTR);
      if (status != 0)
        break;

      *ppPrivateKeyLen += outputLen;
    }
  } while (0);

  /* cleanup objects */
  B_DestroyAlgorithmObject (&paramGenAlgorithmObj);
  B_DestroyAlgorithmObject (&keyGenAlgorithmObj);
  B_DestroyAlgorithmObject (&pbEncryptionAlgorithmObj);
  B_DestroyAlgorithmObject (&randomAlgorithmObj);
  B_DestroyAlgorithmObject (&saltDigestAlgorithmObj);
  B_DestroyKeyObject (&passwordKeyObj);
  B_DestroyKeyObject (&privateKeyObj);
  B_DestroyKeyObject (&publicKeyObj);

  return (status);
}

/*****************************************************************************
 *
 * BSL_SHAWithDSASignFile
 * ----------------------
 * Creates a DSA Digital Signature on a data file using the SHA message
 * digest algorithm and the supplied private key.  If the value of the
 * password is NULL_PTR, the private key should be supplied in its
 * unprotected form.  The signature is then stored in the specified file.
 *
 *****************************************************************************/

/* unsigned char *ppPrivateKey: input: buffer of private key bytes */
/* unsigned int ppPrivateKeyLen: input: number of private key bytes */
/* unsigned char *password: input: buffer of private key protection */
 /* password bytes */
/* unsigned int passwordLen: input: number of password bytes */
/* unsigned char *pbeParams: input: buffer of password-based */
 /* encryption algorithm parameters */
 /* bytes */
/* unsigned int pbeParamsLen: input: number of PBE params bytes */
/* unsigned char *seed: input: random seed for DSA signature */
int BSL_SHAWithDSASignFile(char *signatureOutFilename, char *dataInFilename,
  unsigned char *ppPrivateKey, unsigned int ppPrivateKeyLen,
  unsigned char *password, unsigned int passwordLen, unsigned char *pbeParams,
   unsigned int pbeParamsLen, unsigned char *seed, unsigned int seedLen)
{
  B_ALGORITHM_OBJ algorithmObject = NULL_PTR;
  B_ALGORITHM_OBJ randomAlgorithmObj = NULL_PTR;
  int status;
  unsigned char inputBuffer[1024], signature[512];
  unsigned int inputLen, signatureLen;
  FILE *inputFile = (FILE *) NULL_PTR;
  do {
    /* Open the data file to be signed */
    if ((inputFile = fopen (dataInFilename, "rb")) == NULL) {
      return (BE_DATA);
    }

    /* create and set random algorithm that is needed for DSA signature */
    status = B_CreateAlgorithmObject (&randomAlgorithmObj);
    if (status != 0)
      break;

    status = B_SetAlgorithmInfo (randomAlgorithmObj, AI_MD2Random, NULL_PTR);
    if (status != 0)
      break;

    /* call random init, update with supplied seed bytes */
    status = B_RandomInit
      (randomAlgorithmObj, DEMO_ALGORITHM_CHOOSER,
       (A_SURRENDER_CTX *)NULL_PTR);
    if (status != 0)
      break;

    status = B_RandomUpdate
      (randomAlgorithmObj, seed, seedLen, (A_SURRENDER_CTX *)NULL_PTR);
    if (status != 0)
      break;

    /* Initializate algorithm objects used to calculate signatures */
    if ((status = BSL_SHAWithDSASignInit
         (&algorithmObject, ppPrivateKey, ppPrivateKeyLen, password,
          passwordLen, pbeParams, pbeParamsLen)) != 0)
      break;
    
    /* Create signature by iteratively processing contents of inputFile */
    do {
      inputLen = fread (inputBuffer, 1, 1024, inputFile);
      if ((status = BSL_SHAWithDSASignUpdate
          (&algorithmObject, inputBuffer, inputLen)) != 0)
        break;
    } while (inputLen == 1024);
    if (status != 0)
      break;
    /* Finalizes the signature computation */
    if ((status = BSL_SHAWithDSASignFinal
         (&algorithmObject, signature, &signatureLen, 512,
          randomAlgorithmObj)) != 0)
      break;

    /* Write the signature to the specified file */
    if ((status = RSA_WriteFile
         (signatureOutFilename, signature, signatureLen)) != 0)
      break;
  } while (0);

  if (inputFile != NULL)
    fclose (inputFile);
  B_DestroyAlgorithmObject (&randomAlgorithmObj);
  return (status);
}        
      
/*****************************************************************************
 *
 * BSL_SHAWithDSAVerifyFile
 * ------------------------
 * Verifies a DSA Digital Signature on a data file using the SHA message
 * digest algorithm and the supplied public key.  A zero is returned if
 * the signature is successfully verified, a non-zero error value is
 * returned otherwise.
 *
 *****************************************************************************/

/* unsigned char *publicKey: input: buffer of public key bytes */
/* unsigned int publicKeyLen: input: number of public key bytes */
int BSL_SHAWithDSAVerifyFile(char *signatureInFilename, char *dataInFilename,
  unsigned char *publicKey, unsigned int publicKeyLen)
{
  B_ALGORITHM_OBJ algorithmObject = NULL_PTR;
  int status;
  unsigned char inputBuffer[1024], signature[512];
  unsigned int inputLen, signatureLen;
  FILE *inputFile = (FILE *) NULL_PTR;
  
  do {
    /* Open the input file to be verified. */
    if ((inputFile = fopen (dataInFilename, "rb")) == NULL) {
      return (BE_DATA);
      break;
    }
    /* Read the signature that is used to verify the inputBuffer */
    if ((status = RSA_ReadFile
          (signatureInFilename, signature, &signatureLen, 512)) != 0)
      break;


    /* Initializate algorithm objects used to verify signatures */
    if ((status = BSL_SHAWithDSAVerifyInit
         (&algorithmObject, publicKey, publicKeyLen)) != 0)
        break;

    /* Iteratively process data in inputFile to verify it against the
       signature */
    do {
      inputLen = fread (inputBuffer, 1, 1024, inputFile);
      if ((status = BSL_SHAWithDSAVerifyUpdate
         (&algorithmObject, inputBuffer, inputLen)) != 0)
        break;
    } while (inputLen == 1024);
    /* Finalizes signature verification using the supplied signature */
    if ((status = BSL_SHAWithDSAVerifyFinal
         (&algorithmObject, signature, signatureLen)) != 0)
        break;
  
  } while (0);

  if (inputFile != NULL)
    fclose (inputFile);
  /* A zero return status means signature verification was successful */
  return (status);
}

/***********************************************************************/

int BSL_SHAWithDSASignInit(B_ALGORITHM_OBJ *algorithmObject,
  unsigned char *ppPrivateKey, unsigned int ppPrivateKeyLen,
  unsigned char *password, unsigned int passwordLen, unsigned char *pbeParams,
   unsigned int pbeParamsLen)
{
  B_ALGORITHM_OBJ pbEncryptionAlgorithmObj = NULL_PTR;
  B_KEY_OBJ passwordKeyObj = NULL_PTR;
  B_KEY_OBJ privateKeyObj = NULL_PTR;
  ITEM passwordItem, privateKeyItem, pbEncryptionInfoItem;
  int status;
  unsigned char *privateKeyBuf = NULL_PTR;
  unsigned int outputLen, privateKeyBufLen;

  /* initialize algorithm object to NULL pointer */
  *algorithmObject = NULL_PTR;

  /* do {} while(0); provides convenient way to ensure cleanup upon error */
  do {
    
    /* set up an algorithm to create signature */
    status = B_CreateAlgorithmObject (algorithmObject);
    if (status != 0)
      break;

    /* set algorithm info to make signature with SHA and DSA */
    status = B_SetAlgorithmInfo
      (*algorithmObject, AI_DSAWithSHA1, NULL_PTR);
    if (status != 0)
      break;

    /* create a key object for the private key */
    status = B_CreateKeyObject (&privateKeyObj);
    if (status != 0)
      break;

    /* if supplied password is NULL, use the private key data supplied
     */
    if (password == (unsigned char *)NULL_PTR) {
      privateKeyItem.data = ppPrivateKey;
      privateKeyItem.len = ppPrivateKeyLen;
    }
    else {
      /* otherwise, a password is supplied, so decrypt the private key with the
           password and set the key info with the result
       */
      /* create password-based encryption algorithm object */
      status = B_CreateAlgorithmObject (&pbEncryptionAlgorithmObj);
      if (status != 0)
        break;

      /* set up the ITEM which supplies the password-based encryption
         algorithm info.  This contains the salt and iteration count
         which were specified when the private key was password-encrypted.
       */
      pbEncryptionInfoItem.data = pbeParams;
      pbEncryptionInfoItem.len = pbeParamsLen;

      /* set algorithm object */
      status = B_SetAlgorithmInfo
        (pbEncryptionAlgorithmObj, AI_SHA1WithDES_CBCPadBER,
         (POINTER)&pbEncryptionInfoItem);
      if (status != 0)
        break;

      /* create key object */
      status = B_CreateKeyObject (&passwordKeyObj);
      if (status != 0)
        break;

      /* setup password item and set key info */
      passwordItem.data = password;
      passwordItem.len = passwordLen;
      status = B_SetKeyInfo (passwordKeyObj, KI_Item, (POINTER)&passwordItem);
      if (status != 0)
        break;

      /* allocate a buffer to hold the decrypted private key.
         Since the decrypted size will be smaller than the encrypted size,
           we can allocate a buffer of the size of the encrypted key. */
      if ((privateKeyBuf = (unsigned char *)T_malloc (ppPrivateKeyLen))
          == (unsigned char *)NULL_PTR) {
        status = BE_ALLOC;
        break;
      }

      /* decrypt the private key DER */
      status = B_DecryptInit
        (pbEncryptionAlgorithmObj, passwordKeyObj, DEMO_ALGORITHM_CHOOSER,
         (A_SURRENDER_CTX *)NULL_PTR);
      if (status != 0)
        break;

      status = B_DecryptUpdate
        (pbEncryptionAlgorithmObj, privateKeyBuf, &outputLen, ppPrivateKeyLen,
         ppPrivateKey, ppPrivateKeyLen, (B_ALGORITHM_OBJ)NULL_PTR,
         (A_SURRENDER_CTX *)NULL_PTR);
      if (status != 0)
        break;

      privateKeyBufLen = outputLen;
      status = B_DecryptFinal
        (pbEncryptionAlgorithmObj, privateKeyBuf + privateKeyBufLen,
         &outputLen, ppPrivateKeyLen - privateKeyBufLen,
         (B_ALGORITHM_OBJ)NULL_PTR, (A_SURRENDER_CTX *)NULL_PTR);
      if (status != 0)
        break;

      privateKeyBufLen += outputLen;

      /* use the decrypted private key bytes */
      privateKeyItem.data = privateKeyBuf;
      privateKeyItem.len = privateKeyBufLen;
    }

    /* set the private key info */
    status = B_SetKeyInfo
      (privateKeyObj, KI_DSAPrivateBER, (POINTER)&privateKeyItem);
    if (status != 0)
      break;

    /* call the signature init */
    status = B_SignInit
      (*algorithmObject, privateKeyObj, DEMO_ALGORITHM_CHOOSER,
       (A_SURRENDER_CTX *)NULL_PTR);
    if (status != 0)
        break;

  } while (0);

  /* cleanup only if an error occurred */
  if (status != 0)
    B_DestroyAlgorithmObject (algorithmObject);

  /* cleanup objects */
  B_DestroyAlgorithmObject (&pbEncryptionAlgorithmObj);
  B_DestroyKeyObject (&passwordKeyObj);
  B_DestroyKeyObject (&privateKeyObj);
  
  /* if privateKeyBuf is not NULL, zeroize and free memory */
  if (privateKeyBuf != (unsigned char *)NULL_PTR) {
    T_memset ((POINTER)privateKeyBuf, 0, ppPrivateKeyLen);
    T_free ((POINTER)privateKeyBuf);
  }

  return (status);
}

/***********************************************************************/

int BSL_SHAWithDSASignUpdate(B_ALGORITHM_OBJ *algorithmObject,
  unsigned char *input, unsigned int inputLen)
{
  int status;

  /* call sign update to process input data */
  status = B_SignUpdate
    (*algorithmObject, input, inputLen, (A_SURRENDER_CTX *)NULL_PTR);

  /* cleanup only if an error occurred */
  if (status != 0)
    B_DestroyAlgorithmObject (algorithmObject);

  return (status);
}

/***********************************************************************/

int BSL_SHAWithDSASignFinal(B_ALGORITHM_OBJ *algorithmObject,
  unsigned char *signature, unsigned int *signatureLen,
  unsigned int maxSignatureLen, B_ALGORITHM_OBJ randomObject)
{
  int status;

  status = B_SignFinal
    (*algorithmObject, signature, signatureLen, maxSignatureLen,
     randomObject, (A_SURRENDER_CTX *)NULL_PTR);

  /* cleanup object */
  B_DestroyAlgorithmObject (algorithmObject);

  return (status);
}

/***********************************************************************/

int BSL_SHAWithDSAVerifyInit(B_ALGORITHM_OBJ *algorithmObject,
  unsigned char *publicKey, unsigned int publicKeyLen)
{
  B_KEY_OBJ publicKeyObj = NULL_PTR;
  ITEM publicKeyItem;
  int status;

  /* initialize algorithm object to NULL pointer */
  *algorithmObject = NULL_PTR;

  /* do {} while(0); provides convenient way to ensure cleanup upon error */
  do {
    
    /* create algorithm object for verifying signature */
    status = B_CreateAlgorithmObject (algorithmObject);
    if (status != 0)
      break;

    /* set algorithm object to SHA with DSA signature */
    status = B_SetAlgorithmInfo
      (*algorithmObject, AI_DSAWithSHA1, NULL_PTR);
    if (status != 0)
      break;

    /* create and set up a key object for public key decryption */
    status = B_CreateKeyObject (&publicKeyObj);
    if (status != 0)
      break;

    publicKeyItem.data = publicKey;
    publicKeyItem.len = publicKeyLen;
    status = B_SetKeyInfo
      (publicKeyObj, KI_DSAPublicBER, (POINTER)&publicKeyItem);
    if (status != 0)
      break;

    /* call the verify init */
    status = B_VerifyInit
      (*algorithmObject, publicKeyObj,
       DEMO_ALGORITHM_CHOOSER, (A_SURRENDER_CTX *)NULL_PTR);
    if (status != 0)
      break;

  } while (0);

  /* cleanup only if an error occurred */
  if (status != 0)
    B_DestroyAlgorithmObject (algorithmObject);
  
  /* cleanup object */
  B_DestroyKeyObject (&publicKeyObj);

  return (status);
}

/***********************************************************************/

int BSL_SHAWithDSAVerifyUpdate(B_ALGORITHM_OBJ *algorithmObject,
  unsigned char *input, unsigned int inputLen)
{
  int status;

  /* call the verify update */
  status = B_VerifyUpdate
    (*algorithmObject, input, inputLen, (A_SURRENDER_CTX *)NULL_PTR);

  /* cleanup only if an error occurred */
  if (status != 0)
    B_DestroyAlgorithmObject (algorithmObject);
  
  return (status);
}

/***********************************************************************/

int BSL_SHAWithDSAVerifyFinal(B_ALGORITHM_OBJ *algorithmObject,
  unsigned char *signature, unsigned int signatureLen)
{
  int status;

  /* call the verify final */
  status = B_VerifyFinal
    (*algorithmObject, signature, signatureLen,
     (B_ALGORITHM_OBJ)NULL_PTR, (A_SURRENDER_CTX *)NULL_PTR);

  /* cleanup object */
  B_DestroyAlgorithmObject (algorithmObject);
  
  return (status);
}

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