RSA BSAFE Cert-C

Certificate Components for C

Crypto-C 6.2.1 Developer's Guide
Search

crmf.c

Prompts user for information to create a CRMF message and saves the BER-encoded message to a file

/* $Id: crmf.c,v 1.4 2004/03/02 05:18:39 gsingh Exp $ */
/* crmf.c
** Copyright (c) 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.
**
** This sample program prompts the user for information to create a CRMF
** message and saves the BER-encoded message to a file.
**
** 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 "demoutil.h"
#include "keyutil.h"
#include "nameutil.h"
#include "filelog.h"
#include "rsacsp.h"
#include "crmfi.h"
#include "pkicrmsg.h"

/*  This routine takes a PKI_MSG_OBJ that is supposed to contain messages of
 *  type PKI_MSGTYPE_CERT_REQ and adds a PKI_CERT_REQ_OBJ to the given PKI
 *  message object.  The index populated by this function specifies the index
 *  for the request that was just added to the PKI message object.
 */
static int AddPkiCertRequestPrompt (CERTC_CTX ctx, PKI_MSG_OBJ pkiMsgObj);

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

#define CRMF_PROVIDER_NAME "CRMF Provider"

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

  CERTC_CTX ctx = NULL;
  SERVICE_HANDLER spTable[SP_COUNT] = {
    {SPT_PKI, CRMF_PROVIDER_NAME, S_InitializeCRMF},
    {SPT_CRYPTO, "Default CSP", S_InitializeDefaultCSP}
  };
  
  POINTER spParams[SP_COUNT] = {0};

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

  PKI_MSG_OBJ pkiMsgObj = (PKI_MSG_OBJ)NULL_PTR;
  ITEM crmfDer = {0};

  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 ("CRMF Example\n");
  RSA_PrintMessage ("============\n");

  /* Create the container for the request messages */
  status = C_CreatePKIMsgObject (ctx, &pkiMsgObj);
  if (status != 0)
    goto CLEANUP;

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

  status = AddPkiCertRequestPrompt (ctx, pkiMsgObj);
  if (status != 0)
    goto CLEANUP;

  status = C_GetPKIMsgDER (ctx, CRMF_PROVIDER_NAME, pkiMsgObj,
                           (PKI_PROTECT_INFO *)NULL_PTR, &crmfDer);
  if (status != 0)
    goto CLEANUP;

  status = RSA_WriteDataToFile (crmfDer.data, crmfDer.len,
                                "Enter name of file to store CRMF DER");
  
CLEANUP:
  if (status != 0)
    RSA_PrintError ("crmf.c", status);
  else
    RSA_PrintMessage ("Done!\n");

  C_DestroyPKIMsgObject (&pkiMsgObj);
  C_FinalizeCertC (&ctx);

  return status;
}  /* end main */

int AddPkiCertRequestPrompt (CERTC_CTX ctx, PKI_MSG_OBJ pkiMsgObj)
{
  int status;
  unsigned int index;
  
  PKI_CERT_REQ_OBJ certReqObj = (PKI_CERT_REQ_OBJ)NULL_PTR;
  PKI_CERT_TEMPLATE_OBJ certTemplateObj = (PKI_CERT_TEMPLATE_OBJ)NULL_PTR;

  ALGORITHM_IDENTIFIER sigAlg;

  B_KEY_OBJ publicKey = (B_KEY_OBJ)NULL_PTR, privateKey = (B_KEY_OBJ)NULL_PTR;
  ITEM publicKeyBer = {0};

  NAME_OBJ subjectName = (NAME_OBJ)NULL_PTR;

  PKI_POP_GEN_INFO pkiPopGenInfo = {0};

  /* Create a request message */
  status = C_CreatePKICertReqObject (ctx, &certReqObj);
  if (status != 0)
    goto CLEANUP;

  /* Create a template with information that we desire in our issued cert */
  status = C_CreatePKICertTemplateObject (ctx, &certTemplateObj);
  if (status != 0)
    goto CLEANUP;

  /* Technically, all of the fields in the cert template object are optional,
     but our example sets the signature algorithm, public key, and subject
     name. */
  RSA_PrintMessage ("Optionally specify a signature algorithm ");
  RSA_PrintMessage ("(blank to omit)\n");
  status = RSA_ChooseSignatureAlgorithmPrompt (&sigAlg);
  if (status != 0 && status != RSA_DEMO_E_CANCEL)
    goto CLEANUP;

  status = C_SetCertTemplateSignatureAlgorithm (certTemplateObj,
                                                sigAlg.algorithmId);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("Supply keypair to be certified.\n");
  status = RSA_GetKeypair (ctx, &publicKey, &privateKey);
  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 (stat