RSA BSAFE Cert-C

Certificate Components for C

Crypto-C 6.2.1 Developer's Guide
Search

kcscrs.c

End-entity to CRS PKI sample. An end-entity submits a key pair direcly to a KCS CA.

/* $Id: kcscrs.c,v 1.4 2004/03/02 05:18:39 gsingh Exp $ */
/* kcscrs.c
** Copyright (c) 2000-2002, 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.
**
** IMPORTANT NOTES (Please read before attempting to build/run)
** ===============
** Before running this program, users must put the appropriate information in
** kcscrs.cfg specifying the URL of the server.  The CRS_PROV_CFG_URL macro
** below should be set to the location of the kcscrs.cfg file.
**
** In addition, the proper jurisdiction information must be filled in the
** regInfoFields array below for "corp_company" and "org_unit".
**
** You must also be prepared to supply the CRS signer binary BER-encoded X.509
** certificate.  This may be obtained from the KCS 5.5 Subscriber Services web
** page.  Go to the appropriate jurisdiction and obtain the base-64 encoded
** CRS trusted root.  For the purposes of this demo, use the b64 sample to
** convert the base-64 X.509 to a binary X.509.
**
** 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 "imdb.h"
#include "crlstat.h"
#include "pkixpath.h"
#include "crs.h"
#include "demoutil.h"
#include "pkiutil.h"
#include "certutil.h"
#include "crlutil.h"
#include "nameutil.h"
#include "keyutil.h"
#include "p12util.h"
#include "pkiutil.h"

/*  Used to locate configuration information  */
#define CRS_PROV_CFG_URL "file:

/*  Name of PKI service provider  */
#define PKI_SP_NAME "KCS CRS Transaction Provider"

/*  Name of database associated with cert path context.  */
#define EE_DB_NAME "Requestor's Database"

#define SP_COUNT 5

/*  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 of the CRS signer
 *
 *  The caller must also supply the requestor's keypair and name object.
 *  Since this is an end-entity to CA CRS transaction, the requestor's keypair
 *  will be used to secure the CRS 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 name-value pairs specified by the RA for certificate enrollment.
 *  The Verisign documentation (CRS Profile Specification) specifies the info
 *  needed.
 */
static int SetRegInfo (ATTRIBUTES_OBJ regInfo);

int main (int argc, char *argv[])
{
  int status = 0;
  CERTC_CTX ctx = NULL;
  
  char temp[RSA_DEMO_MAX_LINE_LEN];

  PKI_MSG_OBJ certReq = NULL, certResp = NULL;
  PKI_MSG_FIELDS msgFields;
  PKI_CERTREQ_FIELDS creqFields;
  PKI_CERTRESP_FIELDS certRespFields;
  
  NAME_OBJ requestorName = NULL;
  B_KEY_OBJ publicKey = NULL, privateKey = NULL;
  ITEM publicBer = {NULL, 0}, certDer = {NULL, 0};
  PKI_PROTECT_INFO pkiProtectInfo = {{NULL}};

  EXTENSIONS_OBJ certExtensions = NULL;
  
  SERVICE_HANDLER spTable[SP_COUNT] = {
    {SPT_CRYPTO, "Default CSP", S_InitializeDefaultCSP},
    {SPT_CERT_STATUS, "Cert Status Provider", S_InitializeCRLStatus},
    {SPT_CERT_PATH, "Path Provider", S_InitializePKIXPath},
    {SPT_PKI, PKI_SP_NAME, S_InitializeCRS},
    {SPT_DATABASE, EE_DB_NAME, S_InitializeMemoryDB}
  };
  POINTER spParams[SP_COUNT];

  PKI_CRS_INIT_PARAMS crsInitParams = {(unsigned char *)CRS_PROV_CFG_URL};  

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

  spParams[0] = NULL;
  spParams[1] = NULL;
  spParams[2] = NULL;
  spParams[3] = (POINTER)&crsInitParams;
  spParams[4] = NULL;

  /* To guarantee unused fields are set to 0, and to facilitate cleanup */
  T_memset ((POINTER)&creqFields, 0, sizeof (PKI_CERTREQ_FIELDS));

  status = RSA_SetOptions (&logParams, argc, argv);
  if (status != 0)
    goto CLEANUP;
  
  RSA_PrintMessage ("KCS CRS Provider Demonstration\n");
  RSA_PrintMessage ("==============================\n");

  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

  status = C_CreatePKIMsgObject (ctx, &certReq);
  if (status != 0)
    goto CLEANUP;

  status = C_GetPKIMsgFields (certReq, &msgFields);
  if (status != 0)
    goto CLEANUP;

  /* just to be absolutely sure... */
  IgnoreAll (msgFields.flags);

  msgFields.msgType = PKI_MSGTYPE_CERTREQ;
  ClearIgnoreFlag (msgFields.flags, PKI_MSGFLAGS_IGNORE_MSGTYPE);

  SetMsgWrapType (msgFields.flags, PKI_MSGFLAGS_WRAP_ENVELOPE_THEN_SIGN);

  status = RSA_GetRequestorInfo (ctx, &requestorName, &publicKey, &privateKey);
  if (status != 0)
    goto CLEANUP;

  status = C_SetPKIMsgFields (certReq, &msgFields);
  if (status != 0)
    goto CLEANUP;

  /* Set certReq sender and recipient.  Also, obtain pkiProtectInfo. */
  status = InitializePkiProtectInfo (ctx, certReq, requestorName, publicKey,
                                     privateKey, &pkiProtectInfo);
  if (status != 0)
    goto CLEANUP;

  status = C_GetPKICertRequestFields (certReq, &creqFields);
  if (status != 0)
    goto CLEANUP;

  IgnoreAll (creqFields.flags);

  /* following LRM p.212, for an EE to CA transaction */
  creqFields.certTemplate.serialNumber.data = T_malloc (1);
  creqFields.certTemplate.serialNumber.len = 1;
  T_memset (creqFields.certTemplate.serialNumber.data, 0, 1);

  ClearIgnoreFlag (creqFields.flags, PKI_CERTREQFLAGS_IGNORE_TEMPLATE_SERIAL);
  
  creqFields.certTemplate.subjectName = requestorName;

  ClearIgnoreFlag (creqFields.flags,
                   PKI_CERTREQFLAGS_IGNORE_TEMPLATE_SUBJECTNAME);

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

  creqFields.certTemplate.publicKey.data = publicBer.data;
  creqFields.certTemplate.publicKey.len = publicBer.len;
  ClearIgnoreFlag (creqFields.flags,
                   PKI_CERTREQFLAGS_IGNORE_TEMPLATE_PUBLICKEY);

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

  RSA_PrintMessage ("\nOptionally supply desired cert extensions.  ");
  RSA_PrintMessage ("Enter blank to omit.\n");
  status = RSA_GetFileToExtensionsObject (ctx, &certExtensions);
  if (status == 0) {
    creqFields.certTemplate.certExtensions = certExtensions;
    ClearIgnoreFlag (creqFields.flags,
                     PKI_CERTREQFLAGS_IGNORE_TEMPLATE_CERTEXTS);
  } else if (status != 0 && status != RSA_DEMO_E_CANCEL)
    goto CLEANUP;

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

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

  ClearIgnoreFlag (creqFields.flags, PKI_CERTREQFLAGS_IGNORE_REGINFO);

  status = C_SetPKICertRequestFields (certReq, &creqFields);
  if (status != 0)
    goto CLEANUP;

  status = C_GeneratePKIProofOfPossession (ctx, PKI_SP_NAME, certReq,
                                           privateKey, NULL);
  if (status != 0)
    goto CLEANUP;

  /* Save self-signed cert and private key to open enveloped messages from
     CRS responder. */
  status = C_GetPKIMsgFields (certReq, &msgFields);
  if (status != 0)
    goto CLEANUP;

  if (!(msgFields.flags & PKI_MSGFLAGS_IGNORE_EXTRACERTS)) {
    RSA_PrintMessage ("Adding certs to database...\n");
    status = RSA_PrintCertList (msgFields.extraCerts);
    if (status != 0)
      goto CLEANUP;

    /* Put the temporary self-signed cert in the database */
    status = C_InsertCertList (pkiProtectInfo.info.protectionCtx->database,
                               msgFields.extraCerts);
    if (status != 0)
      goto CLEANUP;

    status = C_InsertPrivateKeyBySPKI (pkiProtectInfo.info.protectionCtx->database,
                                       &publicBer, privateKey);
    if (status != 0)
      goto CLEANUP;
  } else 
    RSA_PrintMessage ("No self-signed cert available!\n");
  
  status = C_CreatePKIMsgObject (ctx, &certResp);
  if (status != 0)
    goto CLEANUP;

  for (;;) {
    /*  Write and send the request and read in the response.  */
    RSA_PrintMessage ("Constructing and sending request.  Please wait.\n");
    status = C_RequestPKICert (ctx, PKI_SP_NAME, certReq, &pkiProtectInfo,
                               NULL, certResp);
    if (status != 0)
      goto CLEANUP;

    status = C_GetPKICertResponseFields (certResp, &certRespFields);
    if (status != 0)
      goto CLEANUP;

    RSA_PrintMessage ("Certificate Request Status\n");
    status = RSA_PrintPkiStatusInfo (&certRespFields.statusInfo);
    if (status != 0)
      goto CLEANUP;

    if (certRespFields.statusInfo.status != PKI_STATUS_WAITING)
      break;

    /*  We don't care about what this RSA_GetCommand call does, we just use it
     *  as a blocking mechanism so that we wait to send our duplicate request once
     *  we know it has a chance of succeeding.
     */
    RSA_GetCommand (temp, sizeof (temp), "Hit enter when cert has been approved");
  }

  /*  In the case of C_WritePKICertRequestMsg, C_SendPKIMsg, and 
   *  C_ReadPKICertResponseMsg being used in place of C_RequestPKICert, the PKI
   *  providers currently place all of the returned certs in the
   *  certRespFields.extraCerts list and it is the application's responsibility to
   *  filter these certs to find the one containing the public key for which
   *  certification was requested.
   */
  if (certRespFields.flags & PKI_CERTRESPFLAGS_IGNORE_CERT) {
    RSA_PrintMessage ("Certificate not returned.\n");
    status = RSA_DEMO_E_INVALID_PARAMETER;
    goto CLEANUP;
  }

  RSA_PrintMessage ("Resulting Certificate\n");
  status = RSA_PrintCertObject (certRespFields.cert);

  status = C_GetCertDER (certRespFields.cert, &certDer.data, &certDer.len);
  if (status != 0)
    goto CLEANUP;

  status = RSA_WriteDataToFile (certDer.data, certDer.len,
                                "Enter name of file to store cert binary");

CLEANUP:
  if (status != 0)
    RSA_PrintError ("kcscrs.c", status);

  T_free (publicBer.data);
  T_free (creqFields.certTemplate.serialNumber.data);

  DestroyPkiProtectInfo (&pkiProtectInfo);

  B_DestroyKeyObject (&publicKey);
  B_DestroyKeyObject (&privateKey);
  C_DestroyAttributesObject (&creqFields.regInfo);
  C_DestroyExtensionsObject (&certExtensions);
  C_DestroyNameObject (&requestorName);
  C_DestroyPKIMsgObject (&certReq);
  C_DestroyPKIMsgObject (&certResp);
  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;

  CERT_OBJ rootCert = NULL;
  CERT_FIELDS rootCertFields;
  ITEM rootCertBer = {NULL, 0}, publicKeyBer = {NULL, 0};

  SERVICE db = NULL;
  LIST_OBJ trustedRoots = NULL, certList = NULL;

  PKI_SENDER_INFO senderInfo;
  PKI_RECIPIENT_INFO recipientInfo;

  NAME_OBJ requestorCopy = NULL, recipientCopy = NULL;
  ITEM nameBer = {NULL, 0};
  unsigned char *tmpSerialNumber = NULL, *serialNumber = 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 = RSA_GetFileToAllocBuffer
           (&rootCertBer.data, &rootCertBer.len,
            "Enter name of file containing CRS root certificate binary");
  if (status != 0)
    goto CLEANUP;

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

  status = C_SetCertBER (rootCert, rootCertBer.data, rootCertBer.len);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("Root Certificate\n");
  RSA_PrintCertInfo (rootCert);

  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;

  status = C_AddCertToList (trustedRoots, rootCert, NULL);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("\nOptionally supply other 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;

  status = C_InsertCertList (db, 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");
  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, 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;

  pkiProtectInfo->info.protectionCtx->pathAlgorithm = PA_X509_V1;
  pkiProtectInfo->info.protectionCtx->pathOptions = PF_IGNORE_REVOCATION;
  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 CRS 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;

  /* make a copy of the root issuer name */
  status = C_CreateNameObject (&requestorCopy);
  if (status != 0)
    goto CLEANUP;

  status = C_GetNameDER (requestor, &nameBer.data, &nameBer.len);
  if (status != 0)
    goto CLEANUP;

  status = C_SetNameBER (requestorCopy, nameBer.data, nameBer.len);
  if (status != 0)
    goto CLEANUP;

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

  /* 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;

  /* hard-coded for simplicity */
  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 (rootCert, &rootCertFields);
  if (status != 0)
    goto CLEANUP;

  /* make a copy of the root issuer name */
  status = C_CreateNameObject (&recipientCopy);
  if (status != 0)
    goto CLEANUP;

  status = C_GetNameDER (rootCertFields.issuerName, &nameBer.data, &nameBer.len);
  if (status != 0)
    goto CLEANUP;

  status = C_SetNameBER (recipientCopy, nameBer.data, nameBer.len);
  if (status != 0)
    goto CLEANUP;

  /* make a copy of the CRS root serial number */
  serialNumber = T_malloc (rootCertFields.serialNumber.len);
  if (serialNumber == NULL) {
    status = RSA_DEMO_E_ALLOC;
    goto CLEANUP;
  }

  T_memcpy (serialNumber, rootCertFields.serialNumber.data,
            rootCertFields.serialNumber.len);

  recipientInfo.type = PKI_RECIPIENT_KEY_TRANSPORT;

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

  recipientInfo.info.keyTrans.recipientId.type = PKI_ENTITY_ISSUER_SERIAL;
  recipientInfo.info.keyTrans.recipientId.id.issuerSerialNumber.
    issuerName = recipientCopy;
  recipientInfo.info.keyTrans.recipientId.id.issuerSerialNumber.
    serialNumber.data = serialNumber;
  recipientInfo.info.keyTrans.recipientId.id.issuerSerialNumber.
    serialNumber.len = rootCertFields.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 (serialNumber);
  T_free (rootCertBer.data);
  T_free (publicKeyBer.data);
  C_DestroyNameObject (&requestorCopy);
  C_DestroyNameObject (&recipientCopy);
  C_DestroyCertObject (&rootCert);
  C_DestroyListObject (&certList);

  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;

  RSA_DEMO_REG_INFO_ENTRY regInfoFields[] = {
    {"common_name", NULL, VT_UTF8_STRING},
    {"mail_email", NULL, VT_UTF8_STRING},
    {"mail_firstName", NULL, VT_UTF8_STRING},
    {"mail_lastName", NULL, VT_UTF8_STRING},
    {"corp_company", "legacy-certc", VT_UTF8_STRING},
    {"org_unit", "test", VT_UTF8_STRING},
    {"cert_type", "end-user", VT_UTF8_STRING},
    {"authenticate", "YES", VT_UTF8_STRING},
    {"embed_email", "yes", VT_UTF8_STRING},
    {"challenge", "password", VT_UTF8_STRING}
  };

  status = RSA_RegInfoPrompt
           (regInfo, regInfoFields,
            sizeof (regInfoFields) / sizeof (RSA_DEMO_REG_INFO_ENTRY));
  if (status != 0)
    RSA_PrintError ("CreateRegInfo", status);

  return status;
}  /* end CreateRegInfo */

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