RSA BSAFE Cert-C

Certificate Components for C

Crypto-C 6.2.1 Developer's Guide
Search

pkcs10.c

Displays PKCS #10 object from a file. Generates PKCS #10 object. Verifies PKCS #10 signature. Extracts objects from PKCS #10. Verifies PKCS #10 signature using alternate method. Converts PKCS #10 to X.509 Certificate.

/* $Id: pkcs10.c,v 1.6 2004/04/15 02:40:38 itaylor Exp $ */
/* pkcs10.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 certificate requests.
**
** 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 "demoutil.h"
#include "p10util.h"
#include "certutil.h"
#include "rsacsp.h"
#include "filelog.h"
#include "attributil.h"

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

static int DisplayPkcs10Obj (CERTC_CTX ctx);
static int GeneratePkcs10Obj (CERTC_CTX ctx);
static int VerifyPkcs10Signature (CERTC_CTX ctx);
static int ExtractObjsFromPkcs10 (CERTC_CTX ctx);
static int VerifyPkcs10Signature2 (CERTC_CTX ctx);
static int CryptoCVerifySignature (ITEM *dataToSign, ITEM *signature,
                                   ITEM *signatureAlgId, B_KEY_OBJ publicKey);
static int PKCS10ObjToCertObj (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
  };

  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 ("PKCS #10 Cert Request Object Demonstration\n");
  RSA_PrintMessage ("==========================================\n");

  for (;;) {
    RSA_PrintMessage ("\nPKCS #10 Object Operations\n");
    RSA_PrintMessage ("  A - Display PKCS #10 object from a file\n");
    RSA_PrintMessage ("  B - Generate PKCS #10 object\n");
    RSA_PrintMessage ("  C - Verify PKCS #10 signature\n");
    RSA_PrintMessage ("  D - Extract objects from PKCS #10\n");
    RSA_PrintMessage ("  E - Verify PKCS #10 signature (alternate method)\n");
    RSA_PrintMessage ("  F - Convert PKCS #10 to X.509 Cert\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 = DisplayPkcs10Obj (ctx);
        break;
      case 'b':
      case 'B':
        status = GeneratePkcs10Obj (ctx);
        break;
      case 'c':
      case 'C':
        status = VerifyPkcs10Signature (ctx);
        break;
      case'd':
      case'D':
        status = ExtractObjsFromPkcs10 (ctx);
        break;
      case 'e':
      case 'E':
        status = VerifyPkcs10Signature2 (ctx);
        break;
      case 'f':
      case 'F':
        status = PKCS10ObjToCertObj (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 ("pkcs10.c", status);

  C_FinalizeCertC (&ctx);

  return status;
}  /* end main */

static int DisplayPkcs10Obj (CERTC_CTX ctx)
{
  int status = 0;
  
  unsigned char *pkcs10Ber = NULL;
  unsigned int pkcs10BerLen = 0;
  
  PKCS10_OBJ pkcs10Obj = NULL;

  status = RSA_GetFileToAllocBuffer
           (&pkcs10Ber, &pkcs10BerLen,
            "Enter name of PKCS #10 object binary");
  if (status != 0)
    goto CLEANUP;

  status = C_CreatePKCS10Object (ctx, &pkcs10Obj);
  if (status != 0)
    goto CLEANUP;

  status = C_SetPKCS10BER (pkcs10Obj, pkcs10Ber, pkcs10BerLen);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("\nPKCS #10 Object Contents\n");
  status = RSA_PrintPkcs10Object (pkcs10Obj);
  if (status != 0)
    goto CLEANUP;

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

  C_DestroyPKCS10Object (&pkcs10Obj);
  T_free (pkcs10Ber);

  return status;
}  /* end DisplayPkcs10Obj */

static int GeneratePkcs10Obj (CERTC_CTX ctx)
{
  int status = 0;

  PKCS10_OBJ pkcs10Obj = NULL;

  unsigned char *pkcs10Ber = NULL;
  unsigned int pkcs10BerLen = 0;

  status = C_CreatePKCS10Object (ctx, &pkcs10Obj);
  if (status != 0)
    goto CLEANUP;

  status = RSA_GetInputToPkcs10Object (pkcs10Obj, ctx);
  if (status != 0)
    goto CLEANUP;

  status = C_GetPKCS10DER (pkcs10Obj, &pkcs10Ber, &pkcs10BerLen);
  if (status != 0)
    goto CLEANUP;

  status = RSA_WriteDataToFile
           (pkcs10Ber, pkcs10BerLen,
            "Enter file name to store PKCS #10 object binary");
  if (status != 0)
    goto CLEANUP;
  
CLEANUP:
  if (status != 0)
    RSA_PrintError ("GeneratePkcs10Obj", status);

  C_DestroyPKCS10Object (&pkcs10Obj);
  
  return status;
}  /* end GeneratePkcs10Obj */

static int VerifyPkcs10Signature (CERTC_CTX ctx)
{
  int status = 0;

  unsigned char *pkcs10Ber = NULL_PTR;
  unsigned int pkcs10BerLen = 0;
  
  PKCS10_OBJ pkcs10Obj = NULL;

  status = RSA_GetFileToAllocBuffer
           (&pkcs10Ber, &pkcs10BerLen,
            "Enter name of PKCS #10 object binary");
  if (status != 0)
    goto CLEANUP;

  status = C_CreatePKCS10Object (ctx, &pkcs10Obj);
  if (status != 0)
    goto CLEANUP;

  status = C_SetPKCS10BER (pkcs10Obj, pkcs10Ber, pkcs10BerLen);
  if (status != 0)
    goto CLEANUP;

  status = C_VerifyPKCS10Signature (pkcs10Obj);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("PKCS #10 signature verified successfully!\n");

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

  T_free (pkcs10Ber);
  C_DestroyPKCS10Object (&pkcs10Obj);
  
  return status;
}  /* end VerifyPkcs10Signature */

static int ExtractObjsFromPkcs10 (CERTC_CTX ctx)
{
  int status = 0;

  unsigned char *pkcs10Ber = NULL_PTR;
  unsigned int pkcs10BerLen = 0;
  
  PKCS10_OBJ pkcs10Obj = NULL;
  PKCS10_FIELDS pkcs10Fields;

  char *nameString = NULL;
  ITEM nameDer = {NULL, 0}, attributesDer = {NULL, 0};

  status = RSA_GetFileToAllocBuffer
           (&pkcs10Ber, &pkcs10BerLen,
            "Enter name of PKCS #10 object binary");
  if (status != 0)
    goto CLEANUP;

  status = C_CreatePKCS10Object (ctx, &pkcs10Obj);
  if (status != 0)
    goto CLEANUP;

  status = C_SetPKCS10BER (pkcs10Obj, pkcs10Ber, pkcs10BerLen);
  if (status != 0)
    goto CLEANUP;

  status = C_GetPKCS10Fields (pkcs10Obj, &pkcs10Fields);
  if (status != 0)
    goto CLEANUP;

  status = C_GetNameStringReverse (pkcs10Fields.subjectName, &nameString);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("Subject Name: %s\n", nameString);

  status = C_GetNameDER (pkcs10Fields.subjectName, &nameDer.data,
                         &nameDer.len);
  if (status != 0)
    goto CLEANUP;

  status = RSA_WriteDataToFile 
             (nameDer.data, nameDer.len,
              "Enter name of file to store subject name binary");
  if (status != 0)
    goto CLEANUP;

  status = RSA_WriteDataToFile
             (pkcs10Fields.publicKey.data, pkcs10Fields.publicKey.len,
              "Enter name of file to store public key binary");
  if (status != 0)
    goto CLEANUP;

  if (pkcs10Fields.attribute != NULL) {
    status = C_GetAttributesDER (pkcs10Fields.attribute, &attributesDer.data,
                                 &attributesDer.len);
    if (status != 0)
      goto CLEANUP;

    status = RSA_WriteDataToFile
               (attributesDer.data, attributesDer.len,
                "Enter name of file to store attributes object binary");
    if (status != 0)
      goto CLEANUP;
  }

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

  C_DestroyPKCS10Object (&pkcs10Obj);
  
  return status;
} /* end ExtractObjsFromPkcs10 */

/* This is an example demonstrating how to use the ASN.1 APIs to pull apart
 * a PKCS 10 request and verify the signature.
 */
static int VerifyPkcs10Signature2 (CERTC_CTX ctx)
{
  int status = 0;

  unsigned char *pkcs10Ber = NULL_PTR;
  unsigned int pkcs10BerLen = 0;
  
  PKCS10_OBJ pkcs10Obj = NULL;
  LIST_OBJ contents = NULL;

  int tag;
  unsigned int tagClass, count;

  ITEM *dataToSign = NULL, *signatureAlgId = NULL, *bitString = NULL;
  ITEM signatureItem = {NULL, 0};
  BIT_STRING signature = {NULL, 0, 0};

  B_KEY_OBJ publicKey = NULL;

  status = RSA_GetFileToAllocBuffer
           (&pkcs10Ber, &pkcs10BerLen,
            "Enter name of PKCS #10 object binary");
  if (status != 0)
    goto CLEANUP;

  status = C_CreatePKCS10Object (ctx, &pkcs10Obj);
  if (status != 0)
    goto CLEANUP;

  status = C_SetPKCS10BER (pkcs10Obj, pkcs10Ber, pkcs10BerLen);
  if (status != 0)
    goto CLEANUP;

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

  /* We want to get the portion of the PKCS #10 that was signed, the signature
     algorithm ID, and the signature.  We will then use this information with
     Crypto-C calls to verify the signature. */
  status = C_BERDecodeList (ctx, pkcs10Ber, pkcs10BerLen, &tag, &tagClass,
                            contents);
  if (status != 0)
    goto CLEANUP;

  /* The PKCS #10 Certification Request is supposed to be a SEQUENCE */
  if (tag != VT_SEQUENCE) {
    status = RSA_DEMO_E_INVALID_TAG;
    goto CLEANUP;
  }

  status = C_GetListObjectCount (contents, &count);
  if (status != 0)
    goto CLEANUP;

  if (count != 3) {
    status = RSA_DEMO_E_INVALID_MESSAGE;
    goto CLEANUP;
  }

  status = C_GetListObjectEntry (contents, 0, (POINTER *)&dataToSign);
  if (status != 0)
    goto CLEANUP;

  status = C_GetListObjectEntry (contents, 1, (POINTER *)&signatureAlgId);
  if (status != 0)
    goto CLEANUP;

  status = C_GetListObjectEntry (contents, 2, (POINTER *)&bitString);
  if (status != 0)
    goto CLEANUP;

  status = C_BERDecodeBitString (ctx, bitString->data, bitString->len, &tag,
                                 &tagClass, &signature);
  if (status != 0)
    goto CLEANUP;

  if (tag != VT_BIT_STRING) {
    status = RSA_DEMO_E_INVALID_TAG;
    goto CLEANUP;
  }

  /* Handle the case where unused bits is 0. */
  if (signature.unusedBits != 0) {
    status = RSA_DEMO_E_NOT_IMPLEMENTED;
    goto CLEANUP;
  }

  signatureItem.data = signature.data;
  signatureItem.len = signature.len;

  status = RSA_GetKeyFromPkcs10 (pkcs10Obj, &publicKey);
  if (status != 0)
    goto CLEANUP;

  status = CryptoCVerifySignature (dataToSign, &signatureItem,
                                   signatureAlgId, publicKey);

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

  B_DestroyKeyObject (&publicKey);
  C_DestroyListObject (&contents);
  C_DestroyPKCS10Object (&pkcs10Obj);
  
  return status;
} /* end VerifyPkcs10Signature2 */

static int CryptoCVerifySignature (ITEM *dataToSign, ITEM *signature,
                                   ITEM *signatureAlgId, B_KEY_OBJ publicKey)
{
  int status = 0, i;
  B_ALGORITHM_OBJ verifyObj = NULL;

  B_INFO_TYPE algorithmInfos[] = {
    AI_MD2WithRSAEncryptionBER,
    AI_MD5WithRSAEncryptionBER,
    AI_SHA1WithRSAEncryptionBER,
    AI_DSAWithSHA1_BER
  };

  B_ALGORITHM_METHOD *chooser[] = {
    &AM_MD2,
    &AM_MD5,
    &AM_SHA,
    &AM_RSA_DECRYPT,
    &AM_DSA_VERIFY,
    NULL
  };

  unsigned char x957DsaWithSha1Oid[] = {
    0x30, 0x09, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE,
    0x38, 0x04, 0x03
  };

  status = B_CreateAlgorithmObject (&verifyObj);
  if (status != 0)
    goto CLEANUP;

  for (i = 0; i < sizeof (algorithmInfos) / sizeof (algorithmInfos[0]); i++) {
    status = B_SetAlgorithmInfo (verifyObj, algorithmInfos[i],
                                 (POINTER)signatureAlgId);
    if (status == 0)
      break;
  }

  /* Check the X9.57 DSA with SHA1 OID, since AI_DSAWithSHA1_BER doesn't
     accept it.  (Crypto-C bug #13474) */
  if (signatureAlgId->len == sizeof (x957DsaWithSha1Oid) &&
      T_memcmp (signatureAlgId->data, x957DsaWithSha1Oid,
                sizeof (x957DsaWithSha1Oid)) == 0)
    status = B_SetAlgorithmInfo (verifyObj, AI_DSAWithSHA1, NULL);

  /* if none of the AIs in algorithmInfos worked, return an error code */
  if (status != 0)
    goto CLEANUP;

  status = B_VerifyInit (verifyObj, publicKey, chooser, NULL);
  if (status != 0)
    goto CLEANUP;

  status = B_VerifyUpdate (verifyObj, dataToSign->data, dataToSign->len,
                           NULL);
  if (status != 0)
    goto CLEANUP;

  status = B_VerifyFinal (verifyObj, signature->data, signature->len,
                          NULL, NULL);

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

  B_DestroyAlgorithmObject (&verifyObj);

  return status;
} /* end CryptoCVerifySignature */

static int PKCS10ObjToCertObj (CERTC_CTX ctx)
{
  int status;

  unsigned char *pkcs10Ber = NULL;
  unsigned int pkcs10BerLen = 0;
  
  PKCS10_OBJ pkcs10Obj = NULL;
  PKCS10_FIELDS pkcs10Fields = {0};

  CERT_OBJ newCert = NULL;
  CERT_FIELDS newCertFields = {0};

  CERT_OBJ issuerCert = NULL;
  CERT_FIELDS issuerCertFields = {0};
  B_KEY_OBJ privateKey = NULL;
  ITEM issuerCertBer = {0}, privateKeyBer = {0};

  ALGORITHM_IDENTIFIER signatureAlg = {0};
  ITEM subjectNameBer, issuerNameBer;

  EXTENSIONS_OBJ certExt = NULL;
  ITEM certExtBer = {0};

  status = RSA_GetFileToAllocBuffer
           (&pkcs10Ber, &pkcs10BerLen,
            "Enter name of PKCS #10 object binary");
  if (status != 0)
    goto CLEANUP;

  status = C_CreatePKCS10Object (ctx, &pkcs10Obj);
  if (status != 0)
    goto CLEANUP;

  status = C_SetPKCS10BER (pkcs10Obj, pkcs10Ber, pkcs10BerLen);
  if (status != 0)
    goto CLEANUP;

  status = C_GetPKCS10Fields (pkcs10Obj, &pkcs10Fields);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("Creating new cert object...\n");
  status = C_CreateCertObject (&newCert, ctx);
  if (status != 0)
    goto CLEANUP;

  /* initialize blank cert fields */
  status = C_GetCertFields (newCert, &newCertFields);
  if (status != 0)
    goto CLEANUP;

  /* newCertFields.version defaults to 1 */
  newCertFields.version = CERT_VERSION_1;

  status = RSA_GetItem (&newCertFields.serialNumber,
                        "Enter hex-ascii serial number (blank to quit)");
  if (status != 0)
    goto CLEANUP;

  status = RSA_ChooseSignatureAlgorithmPrompt (&signatureAlg);
  if (status != 0)
    goto CLEANUP;

  newCertFields.signatureAlgorithm = signatureAlg.algorithmId;

  status = RSA_GetInputToUint4Time (&newCertFields.validity.start,
                                    "Enter validity start");
  if (status != 0)
    goto CLEANUP;

  status = RSA_GetInputToUint4Time (&newCertFields.validity.end,
                                    "Enter validity end");
  if (status != 0)
    goto CLEANUP;

  /* Prompt user to supply issuer cert and private key.  If none is
     supplied, this will be a self-signed cert */
  RSA_PrintMessage ("Supply the signer's cert and private key, or enter ");
  RSA_PrintMessage ("a blank\nto self-sign the cert.\n");
  status = RSA_GetFileToAllocBuffer
             (&issuerCertBer.data, &issuerCertBer.len,
              "Enter file containing issuer cert binary (blank to self-sign)");
  if (status == 0) {
    /* setting issuerCert to non-NULL value means that we don't have a
       self-signed cert */
    status = C_CreateCertObject (&issuerCert, ctx);
    if (status != 0)
      goto CLEANUP;

    status = C_SetCertBER (issuerCert, issuerCertBer.data, issuerCertBer.len);
    if (status != 0)
      goto CLEANUP;

    status = C_GetCertFields (issuerCert, &issuerCertFields);
    if (status != 0)
      goto CLEANUP;

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

    status = C_SetNameBER (newCertFields.issuerName, issuerNameBer.data,
                           issuerNameBer.len);
    if (status != 0)
      goto CLEANUP;
  } else if (status != 0 && status != RSA_DEMO_E_CANCEL)
    goto CLEANUP;

  if (status == 0)
    RSA_PrintMessage ("Supply private key corresponding to issuer cert.\n");
  else
    RSA_PrintMessage ("Supply private key for self-signing certificate.\n");

  status = RSA_GetFileToAllocBuffer
             (&privateKeyBer.data, &privateKeyBer.len,
              "Enter file containing private key binary for signing cert");
  if (status != 0)
    goto CLEANUP;

  status = B_CreateKeyObject (&privateKey);
  if (status != 0)
    goto CLEANUP;

  status = RSA_SetKeyBer (RSA_DEMO_PRIVATE_KEY, privateKey, privateKeyBer);
  if (status != 0)
    goto CLEANUP;

  /* copy name in PKCS #10 request to new cert */
  status = C_GetNameDER (pkcs10Fields.subjectName, &subjectNameBer.data,
                         &subjectNameBer.len);
  if (status != 0)
    goto CLEANUP;

  /* our blank cert fields contains an already-created name object */
  status = C_SetNameBER (newCertFields.subjectName, subjectNameBer.data,
                         subjectNameBer.len);
  if (status != 0)
    goto CLEANUP;

  /* if the user requests a self signed cert, issuerCert is NULL */
  if (issuerCert == NULL) {
    status = C_SetNameBER (newCertFields.issuerName, subjectNameBer.data,
                           subjectNameBer.len);
    if (status != 0)
      goto CLEANUP;
  }

  newCertFields.publicKey.data = pkcs10Fields.publicKey.data;
  newCertFields.publicKey.len = pkcs10Fields.publicKey.len;

  /* give option to "upgrade" to a v2 cert */
  status = RSA_GetBitString
           (&newCertFields.issuerUniqueID,
            "Enter optional unique ID of cert issuer (blank to omit)");
  if (status != 0 && status != RSA_DEMO_E_CANCEL)
    goto CLEANUP;
  else if (status == 0)
    newCertFields.version = CERT_VERSION_2;

  status = RSA_GetBitString
           (&newCertFields.subjectUniqueID,
            "Enter optional unique ID of cert subject (blank to omit)");
  if (status != 0 && status != RSA_DEMO_E_CANCEL)
    goto CLEANUP;
  else if (status == 0)
    newCertFields.version = CERT_VERSION_2;

  /* give option to "upgrade" to a v3 cert */
  status = C_CreateExtensionsObject (&certExt, CERT_EXTENSIONS_OBJ, ctx);
  if (status != 0)
    goto CLEANUP;

  status = C_GetExtensionsInAttributesObj (certExt, pkcs10Fields.attribute);
  if (status == 0) {
    RSA_PrintMessage ("Extracting extensions from PKCS #10...\n");
    newCertFields.version = CERT_VERSION_3;
    
    status = C_GetExtensionsObjectDER (certExt, &certExtBer.data,
                                       &certExtBer.len);
    if (status != 0)
      goto CLEANUP;

    status = C_SetExtensionsObjectBER
               (newCertFields.certExtensions, certExtBer.data, certExtBer.len);
    if (status != 0)
      goto CLEANUP;
  } else if (status != 0) {
    /* optionally specify extensions */
    status = RSA_GetFileToExtensionsObject
               (ctx, &newCertFields.certExtensions);
    if (status != 0 && status != RSA_DEMO_E_CANCEL)
      goto CLEANUP;

    if (status == 0)
      newCertFields.version = CERT_VERSION_3;
  }

  status = C_SetCertFields (newCert, &newCertFields);
  if (status != 0)
    goto CLEANUP;

  status = C_SignCert (newCert, privateKey);
  if (status != 0)
    goto CLEANUP;

  RSA_PrintMessage ("New Certificate:\n");
  status = RSA_PrintCertObject (newCert);
  if (status != 0)
    goto CLEANUP;

  status = RSA_SaveCertObjToFile (newCert);

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

  T_memset (privateKeyBer.data, 0, privateKeyBer.len);
  T_free (privateKeyBer.data);

  T_free (newCertFields.serialNumber.data);
  T_free (issuerCertBer.data);

  B_DestroyKeyObject (&privateKey);
  C_DestroyCertObject (&issuerCert);
  C_DestroyCertObject (&newCert);

  return status;
} /* end PKCS10ObjToCertObj */

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