RSA BSAFE Cert-C

Certificate Components for C

Crypto-C 6.2.1 Developer's Guide
Search

genreq.c

Utilities to generate RSA key pairs, generate certificate requests for a default subject, and sign requests

/* $Id: genreq.c,v 1.3 2004/03/02 05:18:34 gsingh Exp $ */
/* genreq.c
** Copyright (c) 1995-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.
*/

#include <stdio.h>
#include "aglobal.h"
#include "bsafe.h"
#include "demo.h"
#include "bcert.h"
#include "dutil.h"
#include "dchooser.h"
#include "myprint.h" 
#include "genreq.h"
#include "inoutcl.h"

static unsigned char FERMAT_4[] = {1, 0, 1};

/* Here's an example of attribute BER encoding */
static unsigned char ATTRIBUTE_BER[] = {
  0x31, 0x1e, 0x30, 0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
  0x09, 0x05, 0x31, 0x0f, 0x17, 0x0d, 0x39, 0x32, 0x30, 0x31, 0x32, 0x32, 0x31,
  0x39, 0x31, 0x34, 0x32, 0x35, 0x5a
};

#ifdef _BCERT_API_
static int AddSubjectInfo PROTO_LIST ((CERT_REQUEST_OBJ, B_KEY_OBJ));
#else
static int AddSubjectInfo PROTO_LIST ((PKCS10_OBJ, B_KEY_OBJ));
#endif /* _BCERT_API_ */

static int GenerateRSAKeyPair PROTO_LIST 
  ((B_KEY_OBJ *, B_KEY_OBJ *, unsigned int, B_ALGORITHM_OBJ,
    A_SURRENDER_CTX *));

/* Create a certificate request object. Fill it with the subject's information.
     Sign the request with the subject's private key, then write the BER
     encoding of the request to file in binary mode.
 */   
int GenerateCertRequest (sessionContext)
SESSION_CTX *sessionContext;
{
  B_KEY_OBJ privateKey = (B_KEY_OBJ)NULL_PTR, publicKey = (B_KEY_OBJ)NULL_PTR;

#ifdef _BCERT_API_
  CERT_REQUEST_OBJ certRequestObject = NULL_PTR;
#else
  PKCS10_OBJ pkcs10Object = NULL;
  B_ALGORITHM_CHOOSER chooser = NULL;
  B_ALGORITHM_OBJ randomAlgorithm = NULL;
  A_SURRENDER_CTX *surrenderCtx = NULL;
#endif /* _BCERT_API_ */

  ITEM ber; 
  char buffer[80];
  int status;
  unsigned int modulusBits;

  do {
#ifdef _BCERT_API_
    if ((status = C_CreateCertRequestObject (&certRequestObject)) != 0)
      break;
#else
    if ((status = C_CreatePKCS10Object (sessionContext->certcContext,
                                        &pkcs10Object)) != 0)
      break;
#endif /* _BCERT_API_ */
                                  
    GetCommandLine 
      (buffer, sizeof (buffer), 
       "Please enter a key size between 512 and 2048: ",
       &sessionContext->ioContext);
    sscanf (buffer, "%d", &modulusBits);
    if (modulusBits < 512 || modulusBits > 2048) {
      PrintMessage 
        ("Invalid value!  Key size must be between 512 and 2048.",
         0, IO_CTX_PROMPT, &sessionContext->ioContext);
      status = D_KEY_LEN;
      break;
    }
    else {
      PrintMessage
        ("Generating RSA key pair (might take a while!)",
         0, IO_CTX_PROMPT, &sessionContext->ioContext);

#ifdef _BCERT_API_
      if ((status = GenerateRSAKeyPair 
           (&publicKey, &privateKey, modulusBits, sessionContext->randomObject, 
            &sessionContext->surrender)) != 0)
        break;
#else
      if ((status = C_GetRandomObject (sessionContext->certcContext,
                                       &randomAlgorithm)) != 0)
        break;

      surrenderCtx = C_GetSurrenderCtx (sessionContext->certcContext);

      if ((status = C_GetChooser (sessionContext->certcContext,
                                  &chooser)) != 0)
        break;

      if ((status = GenerateRSAKeyPair 
           (&publicKey, &privateKey, modulusBits, randomAlgorithm,
            surrenderCtx)) != 0)
        break;
#endif /* _BCERT_API_ */
    } 

#ifdef _BCERT_API_
    if ((status = AddSubjectInfo (certRequestObject, publicKey)) != 0)
      break;
#else
    if ((status = AddSubjectInfo (pkcs10Object, publicKey)) != 0)
      break;
#endif /* _BCERT_API_ */
     
    PrintMessage 
      ("\nSigning the certificate request", 0, IO_CTX_PROMPT, 
       &sessionContext->ioContext);
    /* Sign the certificate request with the subject's private key */
#ifdef _BCERT_API_
    if ((status = C_SignCertRequest 
         (certRequestObject, privateKey, sessionContext->randomObject, 
          SA_MD2_WITH_RSA_ENCRYPTION, (unsigned char *)NULL_PTR, 
          (unsigned int *)NULL_PTR, 0, &sessionContext->surrender)) != 0)
      break;
#else
    if ((status = C_SignPKCS10 (pkcs10Object, privateKey,
                                SA_SHA1_WITH_RSA_ENCRYPTION)) != 0)
      break;
#endif /* _BCERT_API_ */
    
    /* Get the BER encoding of the cert request */
#ifdef _BCERT_API_
    if ((status = C_GetCertRequestDER
         (certRequestObject, &ber.data, &ber.len)) != 0)
      break;

    PrintCertRequestObject
      (certRequestObject, "\n\nCertificate Request information:\n");
#else
    if ((status = C_GetPKCS10DER 
         (pkcs10Object, &ber.data, &ber.len)) != 0)
      break;

    PrintPKCS10Object
      (pkcs10Object, "\n\nCertificate Request information:\n");
#endif /* _BCERT_API_ */

    /* Write to a file */
    if ((status = WriteToFile 
         (&ber, "certificate request", &sessionContext->ioContext)) != 0)
      break; 
  } while (0); 
  B_DestroyKeyObject (&publicKey);
  B_DestroyKeyObject (&privateKey);
#ifdef _BCERT_API_
  C_DestroyCertRequestObject (&certRequestObject);
#else
  C_DestroyPKCS10Object (&pkcs10Object);
#endif /* _BCERT_API_ */
  return (status);
}

/* Fill the certificate request object with the user's info */
#ifdef _BCERT_API_
static int AddSubjectInfo (certRequestObject, publicKey)
CERT_REQUEST_OBJ certRequestObject;
B_KEY_OBJ publicKey;
#else
static int AddSubjectInfo (pkcs10Object, publicKey)
PKCS10_OBJ pkcs10Object;
B_KEY_OBJ publicKey;
#endif /* _BCERT_API_ */
{
#ifdef _BCERT_API_
  CERT_REQUEST_FIELDS certRequestFields;  
#else
  PKCS10_FIELDS pkcs10Fields;
#endif /* _BCERT_API_ */
  ITEM *publicKeyBER;
  int status;

#ifdef _BCERT_API_
  T_memset ((POINTER)&certRequestFields, 0, sizeof (certRequestFields));
#else
  T_memset ((POINTER)&pkcs10Fields, 0, sizeof (pkcs10Fields));
#endif /* _BCERT_API_ */

  do {
#ifdef _BCERT_API_
    /* Create name and attributes object for the cert request fields */
    if ((status = C_CreateAttributesObject
         (&certRequestFields.attribute)) != 0)
      break;

    if ((status = C_CreateNameObject (&certRequestFields.subjectName)) != 0)
      break;

    /* Fill in the cert request fields with the subject's information */
    certRequestFields.version = CERT_REQUEST_VERSION_1;

    /* Set the subject name field */
    if ((status = MakeNameObject 
         (certRequestFields.subjectName,
          (unsigned char *)"Test User 1", sizeof ("Test User 1") - 1)) != 0)
        break;

    /* Set the attribute field */
    if ((status = C_SetAttributesBER
         (certRequestFields.attribute, ATTRIBUTE_BER,
          sizeof (ATTRIBUTE_BER))) != 0)
      break;      
#else
    /* Create name and attributes object for the cert request fields */
    if ((status = C_CreateAttributesObject
         (&pkcs10Fields.attribute)) != 0)
      break;

    if ((status = C_CreateNameObject (&pkcs10Fields.subjectName)) != 0)
      break;

    /* Fill in the cert request fields with the subject's information */
    pkcs10Fields.version = PKCS10_VERSION_1;

    /* Set the subject name field */
    if ((status = MakeNameObject 
         (pkcs10Fields.subjectName,
          (unsigned char *)"Test User 1", sizeof ("Test User 1") - 1)) != 0)
        break;

    /* Set the attribute field */
    if ((status = C_SetAttributesBER
         (pkcs10Fields.attribute, ATTRIBUTE_BER,
          sizeof (ATTRIBUTE_BER))) != 0)
      break;  
#endif /* _BCERT_API_ */
    
    /* Put the public key BER into the cert request fields */
    if ((status = B_GetKeyInfo 
         ((POINTER *)&publicKeyBER, publicKey, KI_RSAPublicBER)) != 0)
      break;
    
#ifdef _BCERT_API_
    certRequestFields.publicKey = *publicKeyBER;
    /* Set the certRequestObject with data in the certRequestFields */
    if ((status = C_SetCertRequestFields 
         (certRequestObject, &certRequestFields)) != 0)
      break;
#else
    pkcs10Fields.publicKey = *publicKeyBER;
    /* Set the certRequestObject with data in the certRequestFields */
    if ((status = C_SetPKCS10Fields 
          (pkcs10Object, &pkcs10Fields)) != 0)
      break;
#endif /* _BCERT_API_ */
  } while (0);

  /* Clean up */ 
#ifdef _BCERT_API_
  C_DestroyNameObject (&certRequestFields.subjectName);
  C_DestroyAttributesObject (&certRequestFields.attribute);
#else
  C_DestroyNameObject (&pkcs10Fields.subjectName);
  C_DestroyAttributesObject (&pkcs10Fields.attribute);
#endif /* _BCERT_API_ */
  return (status);
}
  
static int GenerateRSAKeyPair 
  (publicKey, privateKey, modulusBits, randomObject, surrender)
B_KEY_OBJ *publicKey;
B_KEY_OBJ *privateKey;
unsigned int modulusBits;
B_ALGORITHM_OBJ randomObject;
A_SURRENDER_CTX *surrender;
{ 
  A_RSA_KEY_GEN_PARAMS parameters;
  B_ALGORITHM_OBJ keyGenAlgorithm = (B_ALGORITHM_OBJ)NULL_PTR; 
  int status;
  
  do {
    if ((status = B_CreateKeyObject (publicKey)) != 0)
      break;
    if ((status = B_CreateKeyObject (privateKey)) != 0)
      break;
    if ((status = B_CreateAlgorithmObject (&keyGenAlgorithm)) != 0)
      break;

    parameters.modulusBits = modulusBits;
    parameters.publicExponent.data = FERMAT_4;
    parameters.publicExponent.len =  sizeof (FERMAT_4);
    if ((status = B_SetAlgorithmInfo
         (keyGenAlgorithm, AI_RSAKeyGen, (POINTER)&parameters)) != 0)
      break;

    if ((status = B_GenerateInit
         (keyGenAlgorithm, DEMO_CHOOSER, surrender)) != 0) {
      if (status == BE_MODULUS_LEN)
        /* Explicitly preserve BE_MODULUS_LEN */
        status = D_KEY_LEN;
      break;
    }
    if ((status = B_GenerateKeypair
         (keyGenAlgorithm, *publicKey, *privateKey, randomObject, surrender))
         != 0)
      break; 
  } while (0);
  B_DestroyAlgorithmObject (&keyGenAlgorithm);
  return (status);  
}  


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