RSA BSAFE Cert-C

Certificate Components for C

Crypto-C 6.2.1 Developer's Guide
Search

crl.c

Parses, manipulates and generates CRLs.

/* $Id: crl.c,v 1.7 2004/03/02 05:18:39 gsingh Exp $ */
/* crl.c
** Copyright (c) 1999-2003, RSA Security Inc.
**
** This file is used to demonstrate how to interface to an RSA Security
** licensed development product.  You have a royalty-free right to use,
** modify, reproduce and distribute this demonstration file (including
** any modified version), provided that you agree that RSA Security has
** no warranty, implied or otherwise, or liability for this demonstration
** file or any modified version.
**
** Demonstrate how to parse or generate CRLs.
**
** When compiling, define the macro RSA_REQUIRE_FILE_LOG (-D compile
** option, or equivelent) to force the program to return an error code
** if file logging cannot be initialized.  For example, if the file
** containing the log message format strings cannot be located (certc.msg
** or equivalent).
*/

#include "certc.h"
#include "filelog.h"
#include "rsacsp.h"
#include "demoutil.h"
#include "crlutil.h"

#ifdef _MSC_VER
# pragma warning (disable: 171)
#endif

/*  The number of service providers used in this example.  Here, we must
 *  register a crypto service provider.
 */
#define SP_COUNT 1

/*  DisplayCRLObj reads in the BER encoding of a CRL from a file and 
 *  prints out its fields.  A properly initialized CERTC_CTX must be
 *  passed in.
 */
static int DisplayCrlObj (CERTC_CTX ctx);

/*  GenerateCRLObj creats a CRL and obtains user input to populate
 *  the crl fields.  A properly initialized CERTC_CTX must be 
 *  passed in.
 */
static int GenerateCrlObj (CERTC_CTX ctx);

/*  VerifyCrlSignature reads in the BER encoding of a CRL from a file
 *  and verifies the CRL signature.  A BER-encoded public key is obtained
 *  from a file and used to verify the signature.  A properly initialized 
 *  CERTC_CTX must be passed in.
 */
static int VerifyCrlSignature (CERTC_CTX ctx);

/*  GetCrlInnerDer reads in the BER encoding of a CRL from a file and
 *  then obtains the DER encoding of the data to be signed.  This data
 *  is then stored in a file.  A properly initialized CERTC_CTX must
 *  be passed in.
 */
static int GetCrlInnerDer (CERTC_CTX ctx);

/*  SignCrlInnerDER reads in the BER encoded portion of the CRL to be signed
 *  This function also reads in a BER encoded private key.  The private key
 *  is then used to sign the CRL data.  The CRL is then saved in DER
 *  format in a file.  A properly initialized CERTC_CTX must be passed in.
 */
static int SignCrlInnerDer (CERTC_CTX ctx);

/*  FindCertInCrl reads in a BER encoded CRL from a file and a BER-encoded
 *  certificate from a file.  The crl is then searched to see if the 
 *  certificate is listed in the CRL.  The result of this search is then
 *  printed out.  A properly initialized CERTC_CTX must be passed in.
 */
static int FindCertInCrl (CERTC_CTX ctx);

/*  ExtractObjsFromCRL reads in a BER encoded crl from a file and extracts
 *  fields from this object.  The fields are then saved to user specified
 *  files.  A properly initialized CERTC_CTX must be passed in.
 */
static int ExtractObjsFromCrl (CERTC_CTX ctx);

/*  RemoveCRLEntry reads in a BER-encoded CRL from a file.  Then it asks the
 *  user to select a CRL entry to be removed and then saves the new CRL in a
 *  user-specified file.  A properly-initialized CERTC_CTX must be passed in.
 */
static int RemoveCRLEntry (CERTC_CTX ctx);

int main (int argc, char *argv[])
{
  int status = 0;
  char command[RSA_DEMO_MAX_LINE_LEN];

  CERTC_CTX ctx = NULL;
  SERVICE_HANDLER spTable[SP_COUNT];
  POINTER spParams[SP_COUNT];

  FILE_LOG_PARAMS logParams = {NULL, NULL};
  SERVICE_HANDLER logHandler = {
    SPT_LOG, "Default File Log", S_InitializeFileLog
  };

  /* Since we are going to be performing operations using Crypto-C, we need
     to register an instance of the crypto provider. */
  spTable[0].type = SPT_CRYPTO;
  spTable[0].name = "BSAFE Crypto-C";
  spTable[0].Initialize = S_InitializeDefaultCSP;

  spParams[0] = NULL;

  status = RSA_SetOptions (&logParams, argc, argv);
  if (status != 0)
    goto CLEANUP;

  status = C_InitializeCertC (spTable, spParams, SP_COUNT, &ctx);
  if (status != 0)
    goto CLEANUP;

  /* Attempt to initialize file logging, but unless RSA_REQUIRE_FILE_LOG is
   * defined, treat it as a non-fatal condition.
   */
  status = C_RegisterService (ctx, &logHandler, (POINTER)&logParams,
                              SERVICE_ORDER_FIRST);
#ifdef RSA_REQUIRE_FILE_LOG
  if (status != 0)
    goto CLEANUP;
#endif
  
  RSA_PrintMessage ("CRL Object Demonstration\n");
  RSA_PrintMessage ("========================\n");

  for (;;) {
    RSA_PrintMessage ("\nCRL Object Operations\n");
    RSA_PrintMessage ("  A - Display CRL object from a file\n");
    RSA_PrintMessage ("  B - Generate CRL object\n");
    RSA_PrintMessage ("  C - Verify CRL signature\n");
    RSA_PrintMessage ("  D - Get Inner DER of CRL\n");
    RSA_PrintMessage ("  E - Sign Inner DER\n");
    RSA_PrintMessage ("  F - Check whether a cert is listed in a CRL\n");
    RSA_PrintMessage ("  G - Extract objects from CRL\n");
    RSA_PrintMessage ("  H - Remove a CRL Entry\n");

    status = RSA_GetCommand (command, sizeof (command),
                             "Enter choice (blank to quit)");
    if (status != 0)
      goto CLEANUP;

    switch (command[0]) {
      case 'a':
      case 'A':
        status = DisplayCrlObj (ctx);
        break;
      case 'b':
      case 'B':
        status = GenerateCrlObj (ctx);
        break;
      case 'c':
      case 'C':
        status = VerifyCrlSignature (ctx);
        break;
      case 'd':
      case 'D':
        status = GetCrlInnerDer (ctx);
        break;
      case 'e':
      case 'E':
        status = SignCrlInnerDer (ctx);
        break;
      case 'f':
      case 'F':
        status = FindCertInCrl (ctx);
        break;
      case 'g':
      case 'G':
        status = ExtractObjsFromCrl(ctx);
        break;
      case 'h':
      case 'H':
        status = RemoveCRLEntry(ctx);
        break;
      case '\0':
      case 'q':
      case 'Q':
        goto CLEANUP;
      default:
        RSA_PrintMessage ("Unrecognized Option: %c\n", command[0]);
        status = RSA_DEMO_E_INVALID_PARAMETER;
    }

    if (status != 0)
      RSA_PrintMessage ("Operation not completed.\n");
    else
      RSA_PrintMessage ("Operation successful!\n");
  }
    
CLEANUP:
  if (status != 0)
    RSA_PrintError ("crl.c", status);

  C_FinalizeCertC (&ctx);

  return status;
}  /* end main */

/* See function declaration at the top for a description */
static int DisplayCrlObj (CERTC_CTX ctx)
{
  int status = 0;
  
  unsigned char *crlBer = NULL;
  unsigned int crlBerLen = 0;
  
  CRL_OBJ crlObj = NULL;
  ITEM output;

  status = RSA_GetFileToAllocBuffer (&crlBer, &crlBerLen,
                                     "Enter name of CRL object binary");
  if (status != 0)
    goto CLEANUP;

  status = C_CreateCRLObject (&crlObj, ctx);
  if (status != 0)
    goto CLEANUP;

  status = C_SetCRLBER (crlObj, crlBer, crlBerLen);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("\nCRL Object Contents\n");

  /* RSA_PrintCrlObject is described in samples/common/include/crlutil.h */
  status = RSA_PrintCrlObject (crlObj);
  if (status != 0)
    goto CLEANUP;

  /* Check the CRL for any inconsistencies.  Cert-C is lenient in allowing
     CRLs with abnormalities to be imported using C_SetCRLBER, but will not
     allow the export of CRLs with incorrect encodings to be exported using
     C_GetCRLDER. */
  status = C_GetCRLDER (crlObj, &output.data, &output.len);
  if (status != 0) {
    RSA_PrintMessage ("Please examine the CRL binary ");
    RSA_PrintMessage ("for problems with the encoding.\n");
    RSA_PrintMessage ("C_SetCRLBER passed but C_GetCRLDER fails.\n");
    goto CLEANUP;
  }

CLEANUP:
  if (status != 0)
    RSA_PrintError ("DisplayCrlObj", status);

  C_DestroyCRLObject (&crlObj);
  T_free (crlBer);

  return status;
}  /* end DisplayCrlObj */

/* See function declaration at the top for a description */
static int GenerateCrlObj (CERTC_CTX ctx)
{
  int status = 0;

  CRL_OBJ crlObj = NULL;

  unsigned char *crlBer = NULL;
  unsigned int crlBerLen = 0;

  status = C_CreateCRLObject (&crlObj, ctx);
  if (status != 0)
    goto CLEANUP;

  /* RSA_GetInputToCrlObject is described in
     samples/common/include/crlutil.h */
  status = RSA_GetInputToCrlObject (ctx, crlObj);
  if (status != 0)
    goto CLEANUP;

  status = C_GetCRLDER (crlObj, &crlBer, &crlBerLen);
  if (status != 0)
    goto CLEANUP;

  status = RSA_WriteDataToFile
           (crlBer, crlBerLen,
            "Enter file name to store CRL object binary");
  if (status != 0)
    goto CLEANUP;
  
CLEANUP:
  if (status != 0)
    RSA_PrintError ("GenerateCrlObj", status);

  C_DestroyCRLObject (&crlObj);
  
  return status;
}  /* end GenerateCrlObj */

/* See function declaration at the top for a description */
static int VerifyCrlSignature (CERTC_CTX ctx)
{
  int status = 0;

  unsigned char *crlBer = NULL;
  unsigned int crlBerLen = 0;

  B_KEY_OBJ publicKey = NULL;
  CRL_OBJ crlObj = NULL;

  status = RSA_GetFileToAllocBuffer (&crlBer, &crlBerLen,
                                     "Enter name of CRL binary");
  if (status != 0)
    goto CLEANUP;

  status = C_CreateCRLObject (&crlObj, ctx);
  if (status != 0)
    goto CLEANUP;

  status = C_SetCRLBER (crlObj, crlBer, crlBerLen);
  if (status != 0)
    goto CLEANUP;

  /* RSA_GetKeyObjFromFile is described in samples/common/include/keyutil.h */
  status = RSA_GetKeyObjFromFile (RSA_DEMO_PUBLIC_KEY, &publicKey);
  if (status != 0)
    goto CLEANUP;

  status = C_VerifyCRLSignature (crlObj, publicKey);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("Signature verified!\n");

CLEANUP:
  if (status != 0)
    RSA_PrintError ("VerifyCrlSignature", status);

  C_DestroyCRLObject (&crlObj);
  B_DestroyKeyObject (&publicKey);
  T_free (crlBer);

  return status;
}  /* end VerifyCrlSignature */

/* See function declaration at the top for a description */
static int GetCrlInnerDer (CERTC_CTX ctx)
{
  int status = 0;
  
  unsigned char *crlBer = NULL, *innerDer = NULL;
  unsigned int crlBerLen = 0, innerDerLen = 0;
  
  CRL_OBJ crlObj = NULL;

  status = RSA_GetFileToAllocBuffer (&crlBer, &crlBerLen,
                                     "Enter name of CRL object binary");
  if (status != 0)
    goto CLEANUP;

  status = C_CreateCRLObject (&crlObj, ctx);
  if (status != 0)
    goto CLEANUP;

  status = C_SetCRLBER (crlObj, crlBer, crlBerLen);
  if (status != 0)
    goto CLEANUP;

  status = C_GetCRLInnerDER (crlObj, &innerDer, &innerDerLen);
  if (status != 0)
    goto CLEANUP;

  status = RSA_WriteDataToFile
           (innerDer, innerDerLen,
            "Enter name of file to store CRL inner DER binary");
  if (status != 0)
    goto CLEANUP;

CLEANUP:
  if (status != 0)
    RSA_PrintError ("GetCrlInnerDer", status);

  T_free (crlBer);
  C_DestroyCRLObject (&crlObj);

  return status;
}  /* end GetCrlInnerDer */

/* See function declaration at the top for a description */
static int SignCrlInnerDer (CERTC_CTX ctx)
{
  int status = 0;
  
  unsigned char *innerDer = NULL, *crlBer = NULL;
  unsigned int innerDerLen = 0, crlBerLen = 0;
  
  B_KEY_OBJ privateKey = NULL;
  CRL_OBJ crlObj = NULL;

  status = RSA_GetFileToAllocBuffer
           (&innerDer, &innerDerLen, "Enter name of CRL inner DER binary");
  if (status != 0)
    goto CLEANUP;

  status = C_CreateCRLObject (&crlObj, ctx);
  if (status != 0)
    goto CLEANUP;

  status = C_SetCRLInnerBER (crlObj, innerDer, innerDerLen);
  if (status != 0)
    goto CLEANUP;

  /* RSA_GetKeyObjFromFile is described in samples/common/include/keyutil.h */
  status = RSA_GetKeyObjFromFile (RSA_DEMO_PRIVATE_KEY, &privateKey);
  if (status != 0)
    goto CLEANUP;
  
  status = C_SignCRL (crlObj, privateKey);
  if (status != 0)
    goto CLEANUP;

  status = C_GetCRLDER (crlObj, &crlBer, &crlBerLen);
  if (status != 0)
    goto CLEANUP;

  status = RSA_WriteDataToFile
           (crlBer, crlBerLen,
            "Enter file name to store CRL object binary");
  if (status != 0)
    goto CLEANUP;

CLEANUP:
  if (status != 0)
    RSA_PrintError ("SignCrlInnerDer", status);

  T_free (innerDer);
  C_DestroyCRLObject (&crlObj);

  return status;
}  /* end SignCrlInnerDer */

/* See function declaration at the top for a description */
static int FindCertInCrl (CERTC_CTX ctx)
{
  int status = 0;
  
  unsigned char *crlBer = NULL, *certBer = NULL;
  unsigned int crlBerLen = 0, certBerLen = 0;
  
  CRL_OBJ crlObj = NULL;
  CERT_OBJ certObj = NULL;

  CERT_FIELDS certFields;
  CRL_FIELDS crlFields;

  unsigned int temp = 0;

  status = RSA_GetFileToAllocBuffer (&crlBer, &crlBerLen,
                                     "Enter name of CRL object binary");
  if (status != 0)
    goto CLEANUP;

  status = C_CreateCRLObject (&crlObj, ctx);
  if (status != 0)
    goto CLEANUP;

  status = C_SetCRLBER (crlObj, crlBer, crlBerLen);
  if (status != 0)
    goto CLEANUP;

  status = C_GetCRLFields (crlObj, &crlFields);
  if (status != 0)
    goto CLEANUP;

  status = RSA_GetFileToAllocBuffer (&certBer, &certBerLen,
                                     "Enter name of cert object binary");
  if (status != 0)
    goto CLEANUP;

  status = C_CreateCertObject (&certObj, ctx);
  if (status != 0)
    goto CLEANUP;

  status = C_SetCertBER (certObj, certBer, certBerLen);
  if (status != 0)
    goto CLEANUP;

  status = C_GetCertFields (certObj, &certFields);
  if (status != 0)
    goto CLEANUP;

  /* We use this method because we are checking for the presence of a cert in
   * an isolated CRL.  For more sophisticated checking involving verification
   * of the CRL (need CRL issuer's cert for example), use C_CheckCertRevocation
   * or C_BuildCertPath.
   */
  status = C_CompareName (certFields.issuerName, crlFields.issuerName);
  if (status != 0) {
    RSA_PrintMessage ("***The certificate and CRL issuers do not match.\n");
    status = 0;
    goto CLEANUP;
  }
  
  status = C_FindCRLEntryBySerialNumber
           (crlFields.crlEntries, certFields.serialNumber.data,
            certFields.serialNumber.len, &temp);
  if (status == E_NOT_FOUND) {
    RSA_PrintMessage ("***Certificate not listed in CRL!\n");
    status = 0;
  }
  else if (status == 0)
    RSA_PrintMessage ("***Certificate listed among CRL Entries!\n");
  else
    goto CLEANUP;

CLEANUP:
  if (status != 0)
    RSA_PrintError ("FindCertInCrl", status);

  T_free (crlBer);
  T_free (certBer);
  C_DestroyCRLObject (&crlObj);
  C_DestroyCertObject (&certObj);

  return status;
}  /* end FindCertInCrl */

/* See function declaration at the top for a description */
static int ExtractObjsFromCrl (CERTC_CTX ctx)
{
  int status = 0;
  unsigned int crlEntryCount, i = 0;
  unsigned int skipEntries = 0;
  unsigned char *crlBer = NULL, *ber = NULL;
  unsigned int crlBerLen, berLen = 0;

  char command[RSA_DEMO_MAX_LINE_LEN];

  CRL_OBJ crlObj = (CRL_OBJ)NULL_PTR;
  CRL_FIELDS crlFields;
  CRL_ENTRY_INFO crlEntryInfo;

  /* Obtain the CRL binary */
  status = RSA_GetFileToAllocBuffer (&crlBer, &crlBerLen,
                                     "Enter name of CRL object binary");
  if (status != 0)
    goto CLEANUP;

  status = C_CreateCRLObject (&crlObj, ctx);
  if (status != 0)
    goto CLEANUP;

  status = C_SetCRLBER (crlObj, crlBer, crlBerLen);
  if (status != 0)
    goto CLEANUP;

  /* Extract the fields from the CRL object, which we will modify */
  status = C_GetCRLFields (crlObj, &crlFields);
  if (status != 0)
    goto CLEANUP;

  /* Print out the CRL fields, except for the CRL entries */
  switch (crlFields.version) {
    case CRL_VERSION_1:
      RSA_PrintMessage ("Version 1 CRL\n");
      break;
    case CRL_VERSION_2:
      RSA_PrintMessage ("Version 2 CRL\n");
      break;
    default:
      RSA_PrintMessage ("Unknown version: %u\n", crlFields.version);
  }

  RSA_PrintSignatureAlgorithm (crlFields.signatureAlgorithm);
  RSA_PrintUint4Time ("Last Update", crlFields.lastUpdate);
  RSA_PrintUint4Time ("Next Update", crlFields.nextUpdate);

  /* Save the issuer name */
  RSA_PrintNameObject ("Issuer Name", crlFields.issuerName);
  status = C_GetNameDER (crlFields.issuerName, &ber, &berLen);
  if (status != 0)
    goto CLEANUP;

  status = RSA_WriteDataToFile
             (ber, berLen, "Enter name of file to store issuer name binary");
  if (status == RSA_DEMO_E_CANCEL)
    status = 0; /* you don't have to save if you don't want to */
  else if (status != 0)
    goto CLEANUP;

  /* Save the CRL extensions (if they exist) */
  if (crlFields.crlExtensions != NULL) {
    status = RSA_PrintExtensionsObject (crlFields.crlExtensions);
    if (status != 0)
      goto CLEANUP;

    status = C_GetExtensionsObjectDER (crlFields.crlExtensions, &ber,
                                       &berLen);
    if (status != 0)
      goto CLEANUP;

    status = RSA_WriteDataToFile
               (ber, berLen,
                "Enter name of file to store CRL extensions binary");
    if (status == RSA_DEMO_E_CANCEL)
      status = 0; /* you don't have to save if you don't want to */
    else if (status != 0)
      goto CLEANUP;
  }

  /*  Getting the number of entries in the crl */
  status = C_GetCRLEntriesCount (crlFields.crlEntries, &crlEntryCount);
  if (status != 0)
    goto CLEANUP;
 
  if (crlEntryCount != 0) {
    RSA_PrintMessage ("\nThere are %d CRL Entries.  Would ", crlEntryCount);
    RSA_PrintMessage ("you like to recurse \nthrough the Entries to save ");
    RSA_PrintMessage ("the extensions objects");
    status = RSA_GetCommand (command, sizeof (command), "(y/n)? ");
    if (status != 0)
      goto CLEANUP;

    switch (command[0]) {
      case 'y':
      case 'Y':
        skipEntries = 0;
        break;
      default:
        skipEntries = 1;
        RSA_PrintMessage ("Skipping the CRL Entries\n");
    }

    if (skipEntries == 0) {
      /* Print out information about each entry */
      for (i = 0; i < crlEntryCount; i++) {
        status = C_GetCRLEntry (crlFields.crlEntries, &crlEntryInfo, i);
        if (status != 0)
          goto CLEANUP;

        RSA_PrintMessage ("\nEntry Number %d\n\n", i+1);
        RSA_PrintBuf ("Serial Number ", crlEntryInfo.serialNumber.data, 
                      crlEntryInfo.serialNumber.len);
        RSA_PrintUint4Time ("Revoked at time: ", crlEntryInfo.actionTime);

        /* Save the CRL entry extensions (if they exist) */
        if (crlEntryInfo.crlEntryExtensions != NULL) {
          status = C_GetExtensionsObjectDER (crlEntryInfo.crlEntryExtensions,
                                             &ber, &berLen);
          if (status != 0)
            goto CLEANUP;

          status = RSA_WriteDataToFile (ber, berLen,
                    "Enter name of file to store CRL entry extensions binary");
          if (status == RSA_DEMO_E_CANCEL)
            status = 0; /* you don't have to save if you don't want to */
          else if (status != 0)
            goto CLEANUP;
        } /* end save CRL entry extensions option */
      } /* end for loop to save individual CRL entry information */
    } /* end condition to save CRL entries */
  } /* end condition if CRL entries exist */

CLEANUP:
  if (status != 0)
    RSA_PrintError ("ExtractObjsFromCrl", status);

  T_free (crlBer);
  C_DestroyCRLObject (&crlObj);

  return status;
}  /* end ExtractObjsFromCrl */

/* See function declaration at the top for a description */
static int RemoveCRLEntry (CERTC_CTX ctx)
{
  int status = 0;
  unsigned int crlEntryToDelete = 0;
  unsigned int crlEntryCount = 0;
  unsigned int index, temp = 0;
  unsigned int signCRL = 0;

  unsigned char *crlBer = NULL, *ber = NULL;
  unsigned int crlBerLen = 0, berLen = 0;

  CRL_OBJ crlObj = (CRL_OBJ)NULL_PTR;
  CRL_FIELDS crlFields;
  CRL_ENTRY_INFO crlEntryInfo;
  B_KEY_OBJ privateKey = (B_KEY_OBJ)NULL_PTR;

  /* Obtain the CRL binary */
  status = RSA_GetFileToAllocBuffer (&crlBer, &crlBerLen,
                                     "Enter name of CRL object binary");
  if (status != 0)
    goto CLEANUP;

  status = C_CreateCRLObject (&crlObj, ctx);
  if (status != 0)
    goto CLEANUP;

  status = C_SetCRLBER (crlObj, crlBer, crlBerLen);
  if (status != 0)
    goto CLEANUP;

  status = C_GetCRLFields (crlObj, &crlFields);
  if (status != 0)
    goto CLEANUP;

  /* Print out the serial numbers of all the entries */
  status = C_GetCRLEntriesCount (crlFields.crlEntries, &crlEntryCount);
  if (status != 0)
    goto CLEANUP;

  if (crlEntryCount == 0) {
    RSA_PrintMessage ("\nThere are no CRL Entries to Delete\n");
    goto CLEANUP;  /* at this point, we're finished */
  }

  /* prompt the user for CRL entries to delete and remove those entries from
     the CRL contents */
  while (crlEntryCount != 0) {
    RSA_PrintMessage ("\nThe following are the serial numbers of ");
    RSA_PrintMessage ("the CRL entries\n");

    /* print the serial numbers of the CRL entries */
    for (index = 0; index < crlEntryCount; index++) {
      status = C_GetCRLEntry (crlFields.crlEntries, &crlEntryInfo, index);
      if (status != 0)
        goto CLEANUP;

      /* print the choice number */
      RSA_PrintMessage ("  %d -", index);

      /* print the hex-ascii serial number */
      for (temp = 0; temp < crlEntryInfo.serialNumber.len; temp++) {
        /* remember the current character, if it's a printable ascii char */
        RSA_PrintMessage (" %02x", crlEntryInfo.serialNumber.data[temp]);
      }

      RSA_PrintMessage ("\n");
    } /* end printing all of the CRL entries' serial numbers */

    RSA_PrintMessage ("Enter the number of the entry you want to delete ");
    status = RSA_GetInteger ((int *)&crlEntryToDelete, "(blank to exit)");
    if (status == RSA_DEMO_E_CANCEL) {
      status = 0;
      break;
    }

    if (crlEntryToDelete < crlEntryCount) {
      /* mark the fact that the CRL needs to be re-signed since we've modified
         its contents */
      signCRL = 1;

      /*  Deleting the CRL entry */
      status = C_DeleteCRLEntry (crlFields.crlEntries, crlEntryToDelete);
      if (status != 0)
        goto CLEANUP;

      /*  Re-setting the crlObj with the new crl */
      status = C_SetCRLFields (crlObj, &crlFields);
      if (status != 0)
        goto CLEANUP;
    }

    /* recompute the total number of CRL entries available */
    status = C_GetCRLEntriesCount (crlFields.crlEntries, &crlEntryCount);
    if (status != 0)
      goto CLEANUP;
  } /* end loop allowing users to remove CRL entries */
  
  /* if any contents of the CRL were modified, we need to re-sign it */
  if (signCRL != 0) {
    RSA_PrintMessage ("Supply private key to sign CRL.\n");
    status = RSA_GetKeyObjFromFile (RSA_DEMO_PRIVATE_KEY, &privateKey);
    if (status != 0)
      goto CLEANUP;
  
    status = C_SignCRL (crlObj, privateKey);
    if (status != 0)
      goto CLEANUP;
    
    /* Save the new CRL */
    status = C_GetCRLDER (crlObj, &ber, &berLen);
    if (status != 0)
      goto CLEANUP;

    status = RSA_WriteDataToFile
               (ber, berLen,
                "Enter file name to store new CRL object binary");
    if (status != 0)
      goto CLEANUP;
  }

CLEANUP:
  if (status != 0)
    RSA_PrintError ("RemoveCRLEntry", status);

  T_free (crlBer);
  B_DestroyKeyObject (&privateKey);
  C_DestroyCRLObject (&crlObj);

  return status;
} /* end RemoveCRLEntry */

Copyright (c) 1999-2005 RSA Security Inc. All rights reserved. 067-001001-2720-001-000 - 2.7.2