RSA BSAFE Cert-C

Certificate Components for C

Crypto-C 6.2.1 Developer's Guide
Search

scepreq.c

Requests a certificate from a CA that supports SCEP

/* $Id: scepreq.c,v 1.4 2004/03/02 05:18:42 gsingh Exp $ */
/* scepreq.c
** Copyright (c) 2002-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.
**
** This program can be used to request a certificate from a CA that supports
** SCEP.
**
** 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 "rsacsp.h"
#include "imdb.h"
#include "scep.h"
#include "pkixpath.h"
#include "filelog.h"
#include "demoutil.h"
#include "pkiutil.h"
#include "certutil.h"
#include "crlutil.h"
#include "keyutil.h"
#include "nameutil.h"
#include "extnutil.h"

#ifdef _MSC_VER
# pragma warning (disable: 171) /* invalid type conversion (often of very similar ptrs) */
#endif

/*  The number of service providers registered when the context is
 *  initialized.
 */
#define SP_COUNT 3

#define DEFAULT_SCEP_URL "http://century.rsa.com:80/cgi-bin/pkiclient.exe/CertCTest/pkiclient.exe"
#define SCEP_PROVIDER_NAME "RSA SCEP PKI Provider"
#define EE_DB_NAME "Requestor's Database"

/*  For this example, we have the EE sending messages to the CA in order to
 *  get an immediate response.  Therefore, we use this procedure to associate
 *  a requestor's database with the given ctx, containing the credentials
 *  necessary to communicate the CA.
 *
 *  In this example, we use enveloped and signed messages.  Therefore, this
 *  routine must be given the root certificate which the CA uses for SCEP.
 *  You can use the scepdb sample (samples/db/scepdb.c) to obtain the CA cert.
 *
 *  The caller must also supply the requestor's keypair and name object.
 *  Since this is an end-entity to CA SCEP transaction, the requestor's keypair
 *  will be used to secure the SCEP messages.  In addition, the name object
 *  describing the sender must be identical to the subject name in the cert
 *  template, telling Cert-C to generate a self-signed certificate for the
 *  end-entity to use in the transaction to request an actual certificate
 *  issued by the CA.
 *
 *  This function calls C_SetPKIMsgSender and C_SetPKIMsgRecipient to modify
 *  the information in the given certReq.
 *
 *  DestroyPkiProtectInfo must be called when pkiProtectInfo is no longer
 *  needed.
 */
static int InitializePkiProtectInfo (CERTC_CTX ctx, PKI_MSG_OBJ certReq,
                                     NAME_OBJ requestor, B_KEY_OBJ publicKey,
                                     B_KEY_OBJ privateKey,
                                     PKI_PROTECT_INFO *pkiProtectInfo);

static void DestroyPkiProtectInfo (PKI_PROTECT_INFO *pkiProtectInfo);

/*  Collect regInfo for SCEP request.  This must contain the challenge
 *  password attribute.
 */
static int SetRegInfo (ATTRIBUTES_OBJ regInfo);

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

  CERTC_CTX ctx = NULL;
  SERVICE_HANDLER spTable[SP_COUNT] = {
    {SPT_CRYPTO, "Default CSP", S_InitializeDefaultCSP},
    {SPT_DATABASE, EE_DB_NAME, S_InitializeMemoryDB},
    {SPT_CERT_PATH, "Cert Path Processing Provider", S_InitializePKIXPath}
  };

  POINTER spParams[SP_COUNT] = {0};

  SERVICE db = (SERVICE)NULL_PTR;

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

  PKI_SCEP_INIT_PARAMS scepInitParams = {0};
  SERVICE_HANDLER scepHandler = {
    SPT_PKI, SCEP_PROVIDER_NAME, S_InitializeSCEPPKI
  };

  PKI_MSG_OBJ pkiMsgObj = (PKI_MSG_OBJ)NULL_PTR;
  PKI_PROTECT_INFO protectInfo = {0};

  PKI_CERT_REQ_OBJ certReqObj = (PKI_CERT_REQ_OBJ)NULL_PTR;
  PKI_CERT_TEMPLATE_OBJ certTemplateObj = (PKI_CERT_TEMPLATE_OBJ)NULL_PTR;

  NAME_OBJ requestor = (NAME_OBJ)NULL_PTR;
  EXTENSIONS_OBJ certExtensions = (EXTENSIONS_OBJ)NULL_PTR;
  B_KEY_OBJ publicKey = (B_KEY_OBJ)NULL_PTR, privateKey = (B_KEY_OBJ)NULL_PTR;
  ITEM publicKeyBer = {0};

  ATTRIBUTES_OBJ regInfo = (ATTRIBUTES_OBJ)NULL_PTR;
  LIST_OBJ extraCerts = (LIST_OBJ)NULL_PTR;

  unsigned int reqIndex;

  PKI_POP_GEN_INFO popGenInfo = {0};

  CERT_OBJ certObj;
  unsigned int count, i;

  PKI_MSG_OBJ pkiMsgRespObj = (PKI_MSG_OBJ)NULL_PTR;

  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 failure to register 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 ("SCEP Certificate Request Example\n");
  RSA_PrintMessage ("================================\n");

  /* Used to hold results and to hold CA cert */
  status = C_BindService (ctx, SPT_DATABASE, EE_DB_NAME, &db);
  if (status != 0)
    goto CLEANUP;

  /* Step 1: Register SCEP Provider */
  scepInitParams.initChoice = PKI_SCEP_INIT_METHOD_STRUCT;
  
  status = RSA_CreateTransportInfoFieldsPrompt
             (&scepInitParams.method.initStruct.transport, DEFAULT_SCEP_URL);
  if (status != 0)
    goto CLEANUP;

  status = RSA_ScepProfilePrompt (&scepInitParams.method.initStruct.profile);
  if (status != 0)
    goto CLEANUP;

  status = C_RegisterService (ctx, &scepHandler, (POINTER)&scepInitParams,
                              SERVICE_ORDER_LAST);
  if (status != 0)
    goto CLEANUP;

  /* Step 2: Create PKI message object */
  status = C_CreatePKIMsgObject (ctx, &pkiMsgObj);
  if (status != 0)
    goto CLEANUP;

  status = C_SetPKIMsgType (pkiMsgObj, PKI_MSGTYPE_CERT_REQ);
  if (status != 0)
    goto CLEANUP;

  /* The private key will be used later to generate the proof of possession */
  status = RSA_GetRequestorInfo (ctx, &requestor, &publicKey, &privateKey);
  if (status != 0)
    goto CLEANUP;

  /* Set Message Protection:
   * The protectInfo will be used when we call C_RequestPKIMsg.
   * Since we are using a CERT_PATH_CTX, we need to register a provider
   * of type SPT_CERT_PATH with the current CERTC_CTX.  That was done
   * in this sample during the call to C_InitializeCertC.
   */
  status = InitializePkiProtectInfo (ctx, pkiMsgObj, requestor, publicKey,
                                     privateKey, &protectInfo);
  if (status != 0)
    goto CLEANUP;

  /* Because we have set PKI_MSG_PROTECTION_SIGN, note that we must add the
     SCEP Signer's cert (CA cert) to the senderDb and a valid chain must exist
     from the SCEP Signer's cert to a cert in the trustedCerts list. */
  status = C_SetPKIMsgProtectionType (pkiMsgObj,
                                      PKI_MSG_PROTECTION_ENVELOPE_THEN_SIGN);
  if (status != 0)
    goto CLEANUP;

  /* Step 3: Create Certificate Request Object */
  status = C_CreatePKICertReqObject (ctx, &certReqObj);
  if (status != 0)
    goto CLEANUP;

  /* We must supply the signature algorithm, subject name, public key, and
     cert extensions in the cert template */
  status = C_CreatePKICertTemplateObject (ctx, &certTemplateObj);
  if (status != 0)
    goto CLEANUP;

  /* Could modify to use the menuutil helper routines to give the user a
     choice, if desired */
  status = C_SetCertTemplateSignatureAlgorithm (certTemplateObj,
                                                SA_MD5_WITH_RSA_ENCRYPTION);
  if (status != 0)
    goto CLEANUP;

  status = C_SetCertTemplateSubjectName (certTemplateObj, requestor);
  if (status != 0)
    goto CLEANUP;

  status = RSA_GetKeyBer (RSA_DEMO_PUBLIC_KEY, publicKey, &publicKeyBer);
  if (status != 0)
    goto CLEANUP;

  status = C_SetCertTemplatePublicKey (certTemplateObj, &publicKeyBer);
  if (status != 0)
    goto CLEANUP;

  status = C_CreateExtensionsObject (&certExtensions, CERT_EXTENSIONS_OBJ,
                                     ctx);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("Supply desired cert extensions.\n");
  status = RSA_GetExtensionsObject (certExtensions, CERT_EXTENSIONS_OBJ);
  if (status != 0)
    goto CLEANUP;

  status = C_SetCertTemplateExtensions (certTemplateObj, certExtensions);
  if (status != 0)
    goto CLEANUP;

  status = C_SetPKICertReqCertTemplate (certReqObj, certTemplateObj);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("Supply regInfo for certificate enrollment.\n");
  status = C_CreateAttributesObject (&regInfo);
  if (status != 0)
    goto CLEANUP;

  status = SetRegInfo (regInfo);
  if (status != 0)
    goto CLEANUP;

  status = C_SetPKICertReqRegInfo (certReqObj, regInfo);
  if (status != 0)
    goto CLEANUP;

  /* Specify an action for C_GeneratePKIMsgProofOfPossession */
  status = C_SetPKICertReqPOPType (certReqObj, PKI_POP_SIGNATURE);
  if (status != 0)
    goto CLEANUP;

  /* Step 4: Add cert request to PKI message object */
  status = C_AddPKIMsg (pkiMsgObj, (POINTER)certReqObj, &reqIndex);
  if (status != 0)
    goto CLEANUP;

  /* Step 5: Generate Proof of Possession of private key */
  popGenInfo.method = PKI_POP_METHOD_CHALLENGE;

  status = C_GeneratePKIMsgProofOfPossession (ctx, SCEP_PROVIDER_NAME,
                                              pkiMsgObj, reqIndex, privateKey,
                                              &popGenInfo);
  if (status != 0)
    goto CLEANUP;

  /* Retrieve our temporary self-signed cert to put in the database, so that
     enveloped messages from the server can be decrypted */
  status = C_GetPKIMsgExtraCerts (pkiMsgObj, &extraCerts);
  if (status != 0 && status != E_VALUE_NOT_SET)
    goto CLEANUP;

  if (status == E_VALUE_NOT_SET) {
    status = 0;  /* not a fatal error, yet */
    RSA_PrintMessage ("No temporary self-signed cert generated.\n");
  } else {
    RSA_PrintMessage ("Adding trusted certs to database...\n");
    status = RSA_PrintCertList (extraCerts);
    if (status != 0)
      goto CLEANUP;

    status = C_InsertCertList (protectInfo.info.protectionCtx->database,
                               extraCerts);
    if (status != 0)
      goto CLEANUP;

    /* Besides putting the temporary self-signed cert in the database,
       explicitly trust them too */
    status = C_GetListObjectCount (extraCerts, &count);
    if (status != 0)
      goto CLEANUP;

    for (i = 0; i < count; i++) {
      status = C_GetListObjectEntry (extraCerts, i, (POINTER *)&certObj);
      if (status != 0)
        goto CLEANUP;

      status = C_AddCertToList (protectInfo.info.protectionCtx->trustedCerts,
                                certObj, NULL);
      if (status != 0)
        goto CLEANUP;
    }
  }

  /* Step 6: Send Request Message */
  status = C_CreatePKIMsgObject (ctx, &pkiMsgRespObj);
  if (status != 0)
    goto CLEANUP;

  for (;;) {
    RSA_PrintMessage ("Sending Certificate Request...\n");
    status = C_RequestPKIMsg (ctx, SCEP_PROVIDER_NAME, pkiMsgObj, &protectInfo,
                              db, pkiMsgRespObj);
    if (status != 0)
      goto CLEANUP;

    /* Step 7: Process Response Message */
    status = RSA_ProcessPkiMsgResp (ctx, pkiMsgRespObj, pkiMsgObj,
                                    RSA_DEMO_SCEP, SCEP_PROVIDER_NAME,
                                    &protectInfo, db);
    if (status == 0)
      break;
    else if (status != 0 && status != RSA_DEMO_E_ACTION_PENDING)
      goto CLEANUP;

    /* You could also print the contents of the db SERVICE handle to see
       if any additional certs or CRLs were returned. */

    RSA_GetCommand (userInput, sizeof (userInput),
                    "Hit enter when cert has been approved");
  }

CLEANUP:
  if (status != 0)
    RSA_PrintError ("scepreq.c", status);
  else
    RSA_PrintMessage ("Done!\n");

  DestroyPkiProtectInfo (&protectInfo);

  RSA_DestroyTransportInfoFields (&scepInitParams.method.initStruct.transport);

  T_free (publicKeyBer.data);

  B_DestroyKeyObject (&publicKey);
  B_DestroyKeyObject (&privateKey);

  C_DestroyAttributesObject (&regInfo);
  C_DestroyExtensionsObject (&certExtensions);
  C_DestroyPKICertTemplateObject (&certTemplateObj);
  C_DestroyPKICertReqObject (&certReqObj);
  C_DestroyPKIMsgObject (&pkiMsgObj);
  C_DestroyPKIMsgObject (&pkiMsgRespObj);
  C_UnbindService (&db);
  C_FinalizeCertC (&ctx);

  return status;
}  /* end main */

static int InitializePkiProtectInfo (CERTC_CTX ctx, PKI_MSG_OBJ certReq,
                                     NAME_OBJ requestor, B_KEY_OBJ publicKey,
                                     B_KEY_OBJ privateKey,
                                     PKI_PROTECT_INFO *pkiProtectInfo)
{
  int status = 0;
  char userInput[RSA_DEMO_MAX_LINE_LEN];

  CERT_OBJ recipientCert = NULL;
  CERT_FIELDS recipientCertFields;
  ITEM recipientCertBer = {NULL, 0}, publicKeyBer = {NULL, 0};

  SERVICE db = NULL;
  DB_ITERATOR crlIterator = NULL;
  LIST_OBJ trustedRoots = NULL, certList = NULL, tmpList = NULL;

  PKI_SENDER_INFO senderInfo;
  PKI_RECIPIENT_INFO recipientInfo;

  unsigned char *tmpSerialNumber = NULL;

  T_memset ((POINTER)&senderInfo, 0, sizeof (senderInfo));
  T_memset ((POINTER)&recipientInfo, 0, sizeof (recipientInfo));

  pkiProtectInfo->info.protectionCtx =
    (CERT_PATH_CTX *)T_malloc (sizeof (CERT_PATH_CTX));
  if (pkiProtectInfo->info.protectionCtx == NULL) {
    status = RSA_DEMO_E_ALLOC;
    goto CLEANUP;
  }

  T_memset ((POINTER)pkiProtectInfo->info.protectionCtx, 0,
            sizeof (CERT_PATH_CTX));

  status = C_BindService (ctx, SPT_DATABASE, EE_DB_NAME, &db);
  if (status != 0)
    goto CLEANUP;

  status = C_CreateListObject (&trustedRoots);
  if (status != 0)
    goto CLEANUP;

  status = C_CreateListObject (&certList);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("You can use the scepdb sample to obtain the CA certs.\n");
  RSA_PrintMessage ("First supply the SCEP responder cert representing the ");
  RSA_PrintMessage ("recipient.\n");
  status = RSA_GetFileToAllocBuffer
           (&recipientCertBer.data, &recipientCertBer.len,
            "Enter name of file containing recipient certificate binary");
  if (status != 0)
    goto CLEANUP;

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

  status = C_SetCertBER (recipientCert, recipientCertBer.data,
                         recipientCertBer.len);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("SCEP Responder Cert (Recipient)\n");
  RSA_PrintCertInfo (recipientCert);

  status = C_InsertCert (db, recipientCert);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("Explicitly trust recipient cert (y/n)? ");
  status = RSA_GetCommand (userInput, sizeof (userInput), NULL);
  if (status != 0)
    goto CLEANUP;

  if (userInput[0] == 'y') {
    status = C_AddCertToList (trustedRoots, recipientCert, NULL);
    if (status != 0)
      goto CLEANUP;
  }

  RSA_PrintMessage ("\nSupply trusted root certificates.\n");
  status = RSA_AddCertsToListPrompt (ctx, trustedRoots);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("\nTrusted Roots\n");
  status = RSA_PrintCertList (trustedRoots);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("\nOptionally supply other relevant certificates, such ");
  RSA_PrintMessage ("as those needed to\nconstruct the certificate chain.\n");
  RSA_PrintMessage ("Other certs are those such as a CA signer cert that is");
  RSA_PrintMessage (" different from the\nrecipient certificate.\n");
  status = RSA_AddCertsToListPrompt (ctx, certList);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("\nOther certificates\n");
  status = RSA_PrintCertList (certList);
  if (status != 0)
    goto CLEANUP;

  status = C_InsertCertList (db, trustedRoots);
  if (status != 0)
    goto CLEANUP;

  status = C_InsertCertList (db, certList);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("\nOptionally supply additional CRLs for chaining.\n");
  status = RSA_AddCrlsToDbPrompt (ctx, db);
  if (status != 0)
    goto CLEANUP;

  /* if our database does not contain CRLs, turn off revocation checking */
  status = C_CreateListObject (&tmpList);
  if (status != 0)
    goto CLEANUP;

  C_SelectFirstCRL (db, &crlIterator, tmpList);
  if (crlIterator == NULL)
    /* no CRLs present */
    pkiProtectInfo->info.protectionCtx->pathOptions = PF_IGNORE_REVOCATION;
  else
    pkiProtectInfo->info.protectionCtx->pathOptions = 0;

  C_DestroyListObject (&tmpList);

  pkiProtectInfo->info.protectionCtx->pathAlgorithm = PA_X509_V1;
  pkiProtectInfo->info.protectionCtx->trustedCerts = trustedRoots;
  pkiProtectInfo->info.protectionCtx->policies = ANY_POLICY;
  pkiProtectInfo->info.protectionCtx->validationTime = PF_VALIDATION_TIME_NOW;
  pkiProtectInfo->info.protectionCtx->database = db;

  /*  Since we are an end-entity requesting a certificate, we use the keypair
   *  we want certified (along with a self-signed cert, generated internally
   *  by Cert-C) in the SCEP message exchanges.  Add the requestor's private
   *  key to the database (requestor is the sender).
   */
  status = RSA_GetKeyBer (RSA_DEMO_PUBLIC_KEY, publicKey, &publicKeyBer);
  if (status != 0)
    goto CLEANUP;

  status = C_InsertPrivateKeyBySPKI (db, &publicKeyBer, privateKey);
  if (status != 0)
    goto CLEANUP;

  /* Set sender information */
  senderInfo.senderId.type = PKI_ENTITY_ISSUER_SERIAL;

  senderInfo.senderId.id.issuerSerialNumber.issuerName = requestor;

  /* The sender (requestor) does not have a certificate.  Set these values to
     tell the provider to generate a temporary self-signed cert */
  tmpSerialNumber = T_malloc (1);
  T_memset (tmpSerialNumber, 0, 1);
  senderInfo.senderId.id.issuerSerialNumber.serialNumber.data = tmpSerialNumber;
  senderInfo.senderId.id.issuerSerialNumber.serialNumber.len = 1;

  /* For simplicity, we set RSA with MD5 as the signature algorithm.
     If desired, modify to use menuutil functions to prompt user. */
  senderInfo.digestAlgorithmId.algorithmId = DAI_MD5;
  senderInfo.digestAlgorithmId.algorithmParam = NULL;
  senderInfo.signatureAlgorithmId.algorithmId = SA_RSA_ENCRYPTION;
  senderInfo.signatureAlgorithmId.algorithmParam = NULL;

  status = C_SetPKIMsgSender (certReq, &senderInfo);
  if (status != 0)
    goto CLEANUP;

  /* Since this example uses enveloped and signed messages, we need to set
     the recipient appropriately. */
  status = C_GetCertFields (recipientCert, &recipientCertFields);
  if (status != 0)
    goto CLEANUP;

  recipientInfo.type = PKI_RECIPIENT_KEY_TRANSPORT;

  /* hard-coded for simplicity (and let Cert-C generate the IV) */
  recipientInfo.contentEncryptionAlgorithmId.algorithmId = EAI_DES;
  recipientInfo.contentEncryptionAlgorithmId.algorithmParam = NULL;

  recipientInfo.info.keyTrans.recipientId.type = PKI_ENTITY_ISSUER_SERIAL;
  recipientInfo.info.keyTrans.recipientId.id.issuerSerialNumber.
    issuerName = recipientCertFields.issuerName;
  recipientInfo.info.keyTrans.recipientId.id.issuerSerialNumber.
    serialNumber.data = recipientCertFields.serialNumber.data;
  recipientInfo.info.keyTrans.recipientId.id.issuerSerialNumber.
    serialNumber.len = recipientCertFields.serialNumber.len;

  /* Here's where we make the decision about which algorithm to use to encrypt
     the symmetric key.  For now, the only supported algorithm is
     KA_RSA_ENCRYPTION, or RSA PKCS #1 v1.5 block 02 padding.  In the future,
     other possiblilties could include PKCS #2 OAEP, or SET OAEP.  To be robust,
     a real application could examine the rootCertFields.publicKey to see what
     the possible algorithms are.  For example, a DSA certificate would not be
     suitable for enveloping at all whereas a cert with an OID indicating
     RSAEncryption would be valid for either PKCS #1 v1.5 block 02 padding or
     OAEP.  In addition, an application may want to examine the key usage
     extension in the rootCertFields.certExtensions. */
  recipientInfo.info.keyTrans.keyEncryptionAlgorithmId.algorithmId =
    KA_RSA_ENCRYPTION;
  recipientInfo.info.keyTrans.keyEncryptionAlgorithmId.algorithmParam =
    NULL;

  status = C_SetPKIMsgRecipient (certReq, &recipientInfo);

CLEANUP:
  if (status != 0) {
    DestroyPkiProtectInfo (pkiProtectInfo);
    RSA_PrintError ("InitializePkiProtectInfo", status);
  }

  T_free (tmpSerialNumber);
  T_free (recipientCertBer.data);
  T_free (publicKeyBer.data);
  C_FreeIterator (&crlIterator);
  C_DestroyCertObject (&recipientCert);
  C_DestroyListObject (&certList);
  C_DestroyListObject (&tmpList);

  return status;
}  /* end InitializePkiProtectInfo */

static void DestroyPkiProtectInfo (PKI_PROTECT_INFO *pkiProtectInfo)
{
  if (pkiProtectInfo->info.protectionCtx == NULL)
    return;

  if (pkiProtectInfo->info.protectionCtx->trustedCerts != NULL)
    C_DestroyListObject (&pkiProtectInfo->info.protectionCtx->trustedCerts);

  if (pkiProtectInfo->info.protectionCtx->policies != ANY_POLICY)
    C_DestroyListObject (&pkiProtectInfo->info.protectionCtx->policies);

  if (pkiProtectInfo->info.protectionCtx->database != NULL)
    C_UnbindService (&pkiProtectInfo->info.protectionCtx->database);

  if (pkiProtectInfo->info.protectionCtx != NULL)
    T_free ((POINTER)pkiProtectInfo->info.protectionCtx);

  pkiProtectInfo->info.protectionCtx = NULL;
}  /* end DestroyPkiProtectInfo */

static int SetRegInfo (ATTRIBUTES_OBJ regInfo)
{
  int status = 0;
  char userInput[RSA_DEMO_MAX_LINE_LEN];

  /* Set challenge password attribute */
  status = RSA_GetCommand (userInput, sizeof (userInput),
                           "Enter challenge password");
  if (status != 0)
    goto CLEANUP;

  status = C_SetChallengePasswordAttribute (regInfo, VT_T61_STRING,
                                            (POINTER)userInput,
                                            T_strlen (userInput));

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

  return status;
}  /* end SetRegInfo */

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