RSA BSAFE Micro Edition Suite

Streamlined security for mobile and embedded devices

Search  Print

ocsp_req_create.c

/* $Id: ocsp_req_create.c,v 1.1.2.15 2005/11/16 00:18:03 patrick Exp $ */
/*
 * Copyright (C) 1998-2005 RSA Security Inc.
 *
 * This file shall only be used to demonstrate how to interface to an
 * RSA Security Inc. licensed development product.
 *
 * You have a royalty-free right to use, reproduce and distribute this
 * demonstration file, provided that you agree that RSA Security Inc.
 * has no warranty, implied or otherwise, or liability for this
 * demonstration file (including any modified version).  This software
 * is provided "as is" without warranties or representations of any
 * kind. RSA Security disclaims all conditions and warranties, statutory
 * and otherwise, both express and implied, with respect to the software,
 * its quality and performance, including but not limited to, all
 * implied warranties of merchantability, fitness for a particular
 * purpose, title and noninfringement of third party rights. Without
 * limiting the foregoing, RSA Security does not warrant that the
 * software is error-free or that errors in the product will be
 * corrected. You agree that RSA Security shall not be liable for any
 * direct, indirect, incidental, special, consequential, punitive or
 * other damages whatsoever resulting from your use of this software
 * or any modified version.
 *
 *
 */

/*
 * @file ocsp_req_create.c
 * This sample demonstrates how to create and sign an OCSP request.
 *
 * For example, to:
 *
 * Create an unsigned OCSP request:
 *   ocsp_req_create -check_certs certToCheck1.bin:certToCheck2.bin
 *     -issuer_certs issuerCert1.bin:issuerCert2.bin -req_out request.bin
 *
 * Create a signed OCSP request using an RSA key, add the options:
 *      -req_cert requestorCert.bin -key key.bin -key_type RSA
 *
 * Create an OCSP request with unknown requestExtensions and
 *   unknown singleRequestExtensions, add the options:
 *      -add_single_ext -add_ext
 *
 * Create an OCSP request with acceptable response types extension
 *   and no nonce extension, add the options:
 *     -add_acceptable_response_types -omit_nonce
 *
 * where: certToCheck1.bin:certToCheck2.bin = The filenames of the certificates
 *                                            to check the status for
 *                                            (colon-separated)
 *        issuerCert1.bin:issuerCert2.bin   = The filenames of the issuer
 *                                            certificates of the certificates
 *                                            to check the status for
 *                                            (colon-separated, 
 *                                             one issuer cert for each
 *                                             certificate to check)
 *        request.bin       = The OCSP request file (binary).
 *        requestorCert.bin = The requestor's certificate file (binary).
 *        key.bin           = The requestor's private key file (binary)
 *                            (PKCS #1 format for RSA keys).
 */

#include "r_prod.h"
#include "ocsp_com.h"

/* Usage help message. */
static char *ocsp_req_create_usage[] =
{
    "usage: ocsp_req_create [options]\n",
    "where options are:\n",
    " -check_certs files       - Colon-separated list of certificates \n",
    "                            whose revocation status will be \n",
    "                            checked. (required)\n",
    " -issuer_certs files      - Colon seperated list of certificates \n",
    "                            of issuers of certificates to be \n",
    "                            checked. (required)\n",
    " -req_cert file           - Requestor certificate. (required for \
signing) \n",
    " -key file                - Requestor's private key. If specified, \n",
    "                            the request will be signed. \n",
    " -key_type string         - Type of requestor’s private key. \n",
    "                            RSA or DSA. (required if key supplied) \n",
    " -verify_certs            - Colon-separated list of certificates \n",
    "                            that verify the request signer. \n",
    " -omit_nonce              - Omit nonce extension from request\n",
    "                            (nonce is included by default). \n",
    " -add_acceptable_response_type\n",
    "                          - Add acceptable response types extension\n",
    "                            to request. \n",
    " -add_ext                 - Add unknown extensions to \n",
    "                            requestExtensions in the request. \n",
    " -add_single_ext          - Add unknown extensions to \n",
    "                            singleRequestExtensions in the request. \n",
    " -req_out file            - File to output request.\n",
    " -help                    - Print help message.\n",
    " -eg                      - Print some example usages.\n",
    NULL
};

static char *ocsp_req_create_example_usage[] =
{
    "This sample demonstrates how to create and sign an OCSP request.\n",
    " For example, to:\n",
    "\n",
    " Create an unsigned OCSP request:\n",
    "   ocsp_req_create -check_certs certToCheck1.bin:certToCheck2.bin\n",
    "    -issuer_certs issuerCert1.bin:issuerCert2.bin -req_out request.bin\n",
    "\n",
    " Create a signed OCSP request using an RSA key, add the options:\n",
    "      -req_cert requestorCert.bin -key key.bin -key_type RSA\n",
    "\n",
    " Create an OCSP request with unknown requestExtensions and\n",
    "   unknown singleRequestExtensions, add the options:\n",
    "      -add_single_ext -add_ext\n",
    "\n",
    " Create an OCSP request with acceptable response types extension\n",
    "   and no nonce extension, add the options:\n",
    "     -add_acceptable_response_types -omit_nonce\n",
    "\n",
    " where: certToCheck1.bin:certToCheck2.bin = The filenames of the",
    " certificates\n",
    "                                            to check the status for\n",
    "                                            (colon-separated)\n",
    "        issuerCert1.bin:issuerCert2.bin   = The filenames of the issuer",
    "\n",
    "                                            certificates of the"
    " certificates\n",
    "                                            to check the status for\n",
    "                                            (colon-separated,\n",
    "                                             one issuer cert for each\n",
    "                                             certificate to check)\n",
    "        request.bin       = The OCSP request file (binary).\n",
    "        requestorCert.bin = The requestor's certificate file (binary).\n",
    "        key.bin           = The requestor's private key file (binary)\n",
    "                            (PKCS #1 format for RSA keys).\n",
    "\n",
    NULL
};

/*
 * Main sample program entry point.
 *
 * @param argc  [In]  The number of arguments typed on the command line.
 * @param argv  [In]  The array of individual arguments from the command line.
 *
 * @returns  R_ERROR_NONE indicates success.
 *           See @ref R_ERROR_IDS for valid values.
 */
int main(int argc, char **argv)
{
    int                 ret                     = R_ERROR_NONE;
    R_LIB_CTX           *lib_ctx                = NULL;
    R_OCSP_CTX          *ocsp_ctx               = NULL;
    R_OCSP_REQ          *req                    = NULL;
    R_OCSP_REQ_ENTRY    *req_entry              = NULL;
    R_CERT_CTX          *cert_ctx               = NULL;
    R_CERT              *check_cert             = NULL;
    R_CERT              *issuer_cert            = NULL;
    R_CERT              *verify_cert            = NULL;
    R_CERT              *req_cert               = NULL;
    BIO                 *bio_std_out            = NULL;
    BIO                 *bio_file_out           = NULL;
    char                *check_cert_files       = NULL;
    char                *issuer_cert_files      = NULL;
    int                 check_cert_file_len     = 0;
    int                 issuer_cert_file_len    = 0;
    char                *verify_cert_files      = NULL;
    int                 verify_cert_file_len    = 0;
    char                *req_cert_file          = NULL;
    char                *req_out_file           = NULL;
    R_CERT_TYPE         certtype                = R_CERT_TYPE_X509;
    R_FORMAT            certform                = R_FORMAT_BINARY;
    char                *check_cert_file        = NULL;
    char                *issuer_cert_file       = NULL;
    char                *verify_cert_file       = NULL;
    R_INDEXED_INFO indexed_info;
    unsigned int        version                 = 0;
    R_OCSP_CERT_ID      cert_id;
    R_TITEM             req_cert_titem;
    int                 omit_nonce              = 0; /* FALSE */
    int                 add_response_types      = 0; /* FALSE */
    int                 add_single_ext = 0; /* FALSE */
    int                 add_ext = 0; /* FALSE */
    R_EXT               *nonce_ext              = NULL;
    R_EXT               *response_types_ext     = NULL;
    int                 responses               = 0;
    R_OCSP_REQ_FLAG     req_flags               = 0;
    char                *key_file               = NULL;
    char                *key_type_str           = NULL;
    int                 key_type                = 0;
    R_CR_ALG_ID         signature_alg_id        = 0;
    R_PKEY              *key                    = NULL;
    R_PKEY_CTX          *pkey_ctx               = NULL;
    int                 print_usage             = 0;

    /* BER-encoded Extensions, which is a SEQUENCE containing one unknown
       Extension (OID: 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09).
     */
    unsigned char EXAMPLE_UNKNOWN_EXTENSIONS_DATA[] =
    {
        0x30, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x01, 0x02, 0x03, 0x04,
        0x05, 0x06, 0x07, 0x08, 0x09, 0x04, 0x10, 0x9F, 0x56, 0x17,
        0xC6, 0xF8, 0x57, 0xA5, 0x9E, 0x9E, 0x59, 0x8A, 0x9E, 0x1A,
        0x41, 0xB0, 0xD4
    };
    /* Typed item that will be used to set unknown extensions. */
    R_TITEM ext_r_titem;

    /* Initialize ITEM data to NULL. */
    req_cert_titem.data = NULL;
    ext_r_titem.data = NULL;
    /* Initialize the cert_id */
    Memset(&cert_id, 0, sizeof(cert_id));

    /*
     * Create a BIO to stdout. BIOs are the Basic Input/Output mechanism
     * provided by RSA. These are recommended for all input and output
     * from applications.
     */
    if ((bio_std_out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL)
    {
        ret = R_ERROR_ALLOC_FAILURE;
        goto end;
    }

    /* Skip the program name. */
    argc--;
    argv++;

    /*
     * Parse the command line parameters.
     */
    while (argc >= 1)
    {
        if (Strcmp(*argv, "-check_certs") == 0)
        {
            if (--argc < 1)
            {
                print_usage = 1;
                goto end;
            }
            check_cert_files = *(++argv);
        }
        else if (Strcmp(*argv, "-issuer_certs") == 0)
        {
            if (--argc < 1)
            {
                print_usage = 1;
                goto end;
            }
            issuer_cert_files = *(++argv);
        }
        else if (Strcmp(*argv, "-verify_certs") == 0)
        {
            if (--argc < 1)
            {
                print_usage = 1;
                goto end;
            }
            verify_cert_files = *(++argv);
        }
        else if (Strcmp(*argv, "-req_cert") == 0)
        {
            if (--argc < 1)
            {
                print_usage = 1;
                goto end;
            }
            req_cert_file = *(++argv);
        }
        else if (Strcmp(*argv, "-req_out") == 0)
        {
            if (--argc < 1)
            {
                print_usage = 1;
                goto end;
            }
            req_out_file = *(++argv);
        }
        else if (Strcmp(*argv, "-key") == 0)
        {
            if (--argc < 1)
            {
                print_usage = 1;
                goto end;
            }
            key_file = *(++argv);
        }
        else if (Strcmp(*argv, "-key_type") == 0)
        {
            if (--argc < 1)
            {
                print_usage = 1;
                goto end;
            }
            key_type_str = *(++argv);
        }
        else if (Strcmp(*argv, "-omit_nonce") == 0)
        {
            omit_nonce = 1;
        }
        else if (Strcmp(*argv, "-add_acceptable_response_types") == 0)
        {
            add_response_types = 1;
        }
        /* Add unknown extensions to singleRequestExtensions. */
        else if (Strcmp(*argv, "-add_single_ext") == 0)
        {
            add_single_ext = 1;
        }
        /* Add unknown extensions to requestExtensions. */
        else if (Strcmp(*argv, "-add_ext") == 0)
        {
            add_ext = 1;
        }
        /* Display the usage information. */
        else if (Strcmp(*argv, "-help") == 0)
        {
            print_usage = 1;
            goto end;
        }
        /* Print the example usage. */
        else if (Strcmp(*argv,"-eg") == 0)
        {
            char **egp;
            for (egp = ocsp_req_create_example_usage; (*egp) != NULL; egp++)
            {
                BIO_printf(bio_std_out, *egp);
            }
            goto end;
        }
        /* Unknown option. */
        else
        {
            BIO_printf(bio_std_out, "Unknown option %s\n", *argv);
            print_usage = 1;
            goto end;
        }
        argc--;
        argv++;
    } /* end while (argc >= 1) */

    /* Check that the parameters provide all the data needed for performing
     * verification operations.
     */
    if (check_cert_files == NULL)
    {
        BIO_printf(bio_std_out, "Certificates to check required\n");
        print_usage = 1;
        goto end;
    }
    if (issuer_cert_files == NULL)
    {
        BIO_printf(bio_std_out, "Issuer certificates required\n");
        print_usage = 1;
        goto end;
    }

    if (req_out_file != NULL)
    {
        if ((bio_file_out = BIO_new_file(req_out_file, "wb")) == NULL)
        {
            BIO_printf(bio_std_out, "Could not open file %s\n", req_out_file);
            ret = R_ERROR_ALLOC_FAILURE;
            goto end;
        }
    }
    if (key_file != NULL)
    {
        if (Strcmp(key_type_str, "RSA") == 0)
        {
            signature_alg_id = R_CR_ID_SHA1_RSA ;
            key_type = R_PKEY_TYPE_RSA;
        }
        else if (Strcmp(key_type_str, "DSA") == 0)
        {
            signature_alg_id = R_CR_ID_SHA1_DSA ;
            key_type = R_PKEY_TYPE_DSA;
        }
        else
        {
           BIO_printf(bio_std_out, "Valid key type required\n");
           print_usage = 1;
           goto end;
        }

        if (req_cert_file == NULL)
        {
            BIO_printf(bio_std_out, "Request certificate required for \
signing\n");
            print_usage = 1;
            goto end;
        }

    }


    /*************************************************************************
     * Step 1. Create the library context.
     * Retrieve the default resource list to provide access to all
     * configurable aspects of the library.
     *************************************************************************/
    if ((ret = PRODUCT_LIBRARY_NEW(PRODUCT_DEFAULT_RESOURCE_LIST(),
        R_RES_FLAG_DEF, &lib_ctx)) != R_ERROR_NONE)
    {
        BIO_printf(bio_std_out, "Library new failure\n");
        goto end;
    }

    /*************************************************************************
     * Step 2. Create a new OCSP context.
     * Create an R_OCSP_CTX with which to create the OCSP request object.
     *************************************************************************/
    if (((ret = R_OCSP_CTX_new(lib_ctx, R_RES_FLAG_DEF, &ocsp_ctx))
        != R_ERROR_NONE) || ocsp_ctx == NULL)
    {
        BIO_printf(bio_std_out, "R_OCSP_CTX_new failure\n");
        goto end;
    }

    /*************************************************************************
     * Step 3. Create a new certificate context.
     *************************************************************************/
    if ((ret = R_CERT_CTX_new(lib_ctx, R_RES_FLAG_DEF, R_CERT_TYPE_X509,
        &cert_ctx)) != R_ERROR_NONE)
    {
        BIO_printf(bio_std_out, "R_CERT_CTX_new failure\n");
        goto end;
    }

    /*************************************************************************
     * The following is the structure of an OCSP request.

       OCSPRequest     ::=     SEQUENCE {
           tbsRequest                  TBSRequest,
           optionalSignature   [0]     EXPLICIT Signature OPTIONAL }

       TBSRequest      ::=     SEQUENCE {
           version             [0]     EXPLICIT Version DEFAULT v1,
           requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
           requestList                 SEQUENCE OF Request,
           requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }

       Signature       ::=     SEQUENCE {
           signatureAlgorithm      AlgorithmIdentifier,
           signature               BIT STRING,
           certs               [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL}

       Version         ::=             INTEGER  {  v1(0) }

       Request         ::=     SEQUENCE {
           reqCert                     CertID,
           singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }

       CertID          ::=     SEQUENCE {
           hashAlgorithm       AlgorithmIdentifier,
           issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
           issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
           serialNumber        CertificateSerialNumber }
     *************************************************************************/

    /*************************************************************************
     * Step 4. Create an OCSP request object from the input data.
     *************************************************************************/
    if ((ret = R_OCSP_REQ_new(ocsp_ctx, R_RES_FLAG_DEF, &req))
        != R_ERROR_NONE)
    {
        BIO_printf(bio_std_out, "R_OCSP_REQ_new failure: \n");
        goto end;
    }

    /* -------------------------------------------------------------------
     * --- TBS Request ---------------------------------------------------
     * -------------------------------------------------------------------
     */

    /* ### version */
    version = 0;
    ret = R_OCSP_REQ_set_info(req, R_OCSP_REQ_INFO_VERSION, &version);

    /* ### requestorName */
    if (req_cert_file != NULL)
    {
        /* Read req_cert in from the file. */
        if (((ret = R_CERT_read_file(cert_ctx, req_cert_file,
            certtype, certform, &req_cert)) != R_ERROR_NONE)
            || req_cert == NULL)
        {
            BIO_printf(bio_std_out, "Certificate from file failure: %s\n",
                req_cert_file);
            goto end;
        }

        /* Get requestor name in a R_TITEM struct. */
        if ((ret = R_CERT_get_info(req_cert, R_CERT_INFO_SUBJECT,
            &req_cert_titem)) != R_ERROR_NONE)
        {
            BIO_printf(bio_std_out, "R_CERT_get_info failure getting \
R_CERT_INFO_SUBJECT\n");
            goto end;
        }
        req_cert_titem.type = R_OCSP_REQUESTOR_NAME_TYPE_BINARY;

        /* Put data into the request object. */
        if ((ret = R_OCSP_REQ_set_info(req, R_OCSP_REQ_INFO_REQUESTOR_NAME,
            &req_cert_titem)) != R_ERROR_NONE)
        {
            BIO_printf(bio_std_out, "R_OCSP_REQ_set_info failure\n");
            BIO_printf(bio_std_out, "req_cert_titem.type = %d\n",
                req_cert_titem.type);
            goto end;
        }
    } /* end if (req_cert_file != NULL) */

    /* ### requestList */

    /* Each request in the requestList is represented by an
       R_OCSP_REQ_ENTRY. Create a new entry for each certificate to be
       checked. */

     /* Get the length of the next file name in the check_certs and
        issuer_certs command line parameters. */
    check_cert_file_len = R_STR_token(&check_cert_files, ':', NULL);
    issuer_cert_file_len = R_STR_token(&issuer_cert_files, ':', NULL);

    while (check_cert_file_len > 0 && issuer_cert_file_len > 0)
    {
        /* ### Request */
        ret = R_OCSP_REQ_ENTRY_new(ocsp_ctx, R_RES_FLAG_DEF, &req_entry);

        /* ### reqCert */

        /* Retrieve the next certificate file name. */
        if ((check_cert_file =
            (char *)Malloc(check_cert_file_len + 1)) == NULL)
        {
            ret = R_ERROR_ALLOC_FAILURE;
            goto end;
        }
        R_STR_token(&check_cert_files, ':', check_cert_file);
        if ((issuer_cert_file =
            (char *)Malloc(issuer_cert_file_len + 1)) == NULL)
        {
            ret = R_ERROR_ALLOC_FAILURE;
            goto end;
        }
        R_STR_token(&issuer_cert_files, ':', issuer_cert_file);

        /* Read in the certificates from the files. */
        if (((ret = R_CERT_read_file(cert_ctx, check_cert_file,
            certtype, certform, &check_cert)) != R_ERROR_NONE)
            || check_cert == NULL)
        {
            BIO_printf(bio_std_out, "Certificate from file failure: %s\n",
                check_cert_file);
            goto end;
        }
        if (((ret = R_CERT_read_file(cert_ctx, issuer_cert_file,
            certtype, certform, &issuer_cert)) != R_ERROR_NONE)
            || issuer_cert == NULL)
        {
            BIO_printf(bio_std_out, "Certificate from file failure: %s\n",
                issuer_cert_file);
            goto end;
        }

        /* Create cert_id from check_cert and issuer_cert. */
        if ((ret = R_OCSP_CERT_ID_from_certs (ocsp_ctx, check_cert,
            issuer_cert, &cert_id)) != R_ERROR_NONE)
        {
            BIO_printf(bio_std_out, "R_OCSP_CERT_ID_from_certs failure\n");
            BIO_printf(bio_std_out, "check_cert_file: %s\n",
                check_cert_file);
            BIO_printf(bio_std_out, "issuer_cert_file: %s\n",
                issuer_cert_file);
             goto end;
        }

        /* Set the certificate ID of the request. */
        if ((ret = R_OCSP_REQ_ENTRY_set_info(req_entry,
            R_OCSP_REQ_ENTRY_INFO_CERT_ID, &cert_id)) != R_ERROR_NONE)
        {
            BIO_printf(bio_std_out, "R_OCSP_REQ_ENTRY_set_info failure\n");
            goto end;
        }
        /* set_info has copied the cert_id data, so it needs be freed */
        R_OCSP_CERT_ID_free(&cert_id);

        /* ### singleRequestExtensions */

        /* Add unknown extensions to singleRequestExtensions, if
           the option is specified on the command line. */
        if (add_single_ext)
        {
            ext_r_titem.type = BER_SEQUENCE;
            ext_r_titem.len = sizeof(EXAMPLE_UNKNOWN_EXTENSIONS_DATA);
            if ((ext_r_titem.data = (unsigned char *)Malloc(ext_r_titem.len
                * sizeof(unsigned char))) == NULL)
            {
                ret = R_ERROR_ALLOC_FAILURE;
                goto end;
            }
            Memcpy(ext_r_titem.data, EXAMPLE_UNKNOWN_EXTENSIONS_DATA,
                ext_r_titem.len);

            if ((ret = R_OCSP_REQ_ENTRY_set_info(req_entry,
                R_OCSP_REQ_ENTRY_INFO_EXTENSIONS,
                &ext_r_titem)) != R_ERROR_NONE)
            {
                BIO_printf(bio_std_out, "R_OCSP_REQ_ENTRY_set_info \
ure setting R_OCSP_REQ_ENTRY_INFO_EXTENSIONS: \n");
                goto end;
            }
            BIO_printf(bio_std_out, "Added singleRequestExtensions ");
            BIO_printf(bio_std_out, "(%d bytes): \n", ext_r_titem.len);
            BIO_dump_format(bio_std_out, ext_r_titem.data, ext_r_titem.len,
                BIO_DUMP_FORMAT_HEX, ':', 2, 16);

        } /* end if (add_single_ext) */
 
        /* Add the Request to the requestList of the TBSRequest. */
        if ((ret = R_OCSP_REQ_add_entry(req, req_entry)) != R_ERROR_NONE)
        {
            BIO_printf(bio_std_out, "R_OCSP_REQ_add_entry failure: \n");
            goto end;
        }

        /* Clean up. */
        if (ext_r_titem.data != NULL)
        {
            Free(ext_r_titem.data);
            ext_r_titem.data = NULL;
        }
        if (check_cert != NULL)
        {
            R_CERT_free(check_cert);
            check_cert = NULL;
        }
        if (issuer_cert != NULL)
        {
            R_CERT_free(issuer_cert);
            issuer_cert = NULL;
        }
        if (check_cert_file != NULL)
        {
            Free(check_cert_file);
            check_cert_file = NULL;
        }
        if (issuer_cert_file != NULL)
        {
            Free(issuer_cert_file);
            issuer_cert_file = NULL;
        }
        if (req_entry != NULL)
        {
            R_OCSP_REQ_ENTRY_free(req_entry);
            req_entry = NULL;
        }

        /* Get the length of the next file name in the check_certs and
           issuer_certs command line parameters. */
        check_cert_file_len = R_STR_token(&check_cert_files, ':', NULL);
        issuer_cert_file_len = R_STR_token(&check_cert_files, ':', NULL);
    } /* end while (check_cert_file_len > 0 && issuer_cert_file_len > 0)*/

    /* ### requestExtensions */

    if (omit_nonce == 1)
    {
        /* Omit nonce extension. */
        req_flags = R_OCSP_REQ_FLAG_DISABLE_NONCE;
        ret = R_OCSP_REQ_set_info(req, R_OCSP_REQ_INFO_FLAGS, &req_flags);
    }

    if (add_ext == 1)
    {
        /* Add unknown extensions to requestExtensions, if the option
           is specified on the command line. */
        ext_r_titem.type = BER_SEQUENCE;
        ext_r_titem.len = sizeof(EXAMPLE_UNKNOWN_EXTENSIONS_DATA);
        if ((ext_r_titem.data = (unsigned char *)Malloc(ext_r_titem.len
            * sizeof(unsigned char))) == NULL)
        {
            ret = R_ERROR_ALLOC_FAILURE;
            goto end;
        }
        Memcpy(ext_r_titem.data, EXAMPLE_UNKNOWN_EXTENSIONS_DATA,
        ext_r_titem.len);
        if ((ret = R_OCSP_REQ_set_info(req,
            R_OCSP_REQ_INFO_EXTENSIONS,
            &ext_r_titem)) != R_ERROR_NONE)
        {
            BIO_printf(bio_std_out, "R_OCSP_REQ_set_info failure \
ing R_OCSP_REQ_INFO_EXTENSIONS: \n");
            goto end;
        }
        BIO_printf(bio_std_out, "Added requestExtensions ");
        BIO_printf(bio_std_out, "(%d bytes): \n", ext_r_titem.len);
        BIO_dump_format(bio_std_out, ext_r_titem.data, ext_r_titem.len,
            BIO_DUMP_FORMAT_HEX, ':', 2, 16);
    } /* end if (add_ext) */

    if (add_response_types == 1)
    {
        /* Add the acceptable response types extension. */
        ret = R_EXT_new(lib_ctx, 0, &response_types_ext);
        responses = R_EXT_OCSP_RESPONSE_BASIC;

        /* Set the acceptable response types extension to contain
           the basic response type. */
        ret = R_EXT_set_info(response_types_ext,
            R_EXT_INFO_OCSP_RESPONSES, &responses);
        ret = R_OCSP_REQ_set_info(req,
            R_OCSP_REQ_INFO_EXTENSION_ADD_BY_OID, response_types_ext);
    }

    /* -------------------------------------------------------------------
     * end TBS Request ---------------------------------------------------
     * -------------------------------------------------------------------
     */

    /*************************************************************************
     * Step 5. Sign the OCSP request.
     *************************************************************************/
    if (key_file != NULL)
    {
        /* Check for verification certificates. */
        if (verify_cert_files != NULL)
        {
            verify_cert_file_len = R_STR_token(&verify_cert_files, ':', NULL);
            while (verify_cert_file_len > 0)
            {
                /* Retrieve the next certificate file name from the list. */
                if ((verify_cert_file =
                    (char *)Malloc(verify_cert_file_len + 1)) == NULL)
                {
                    ret = R_ERROR_ALLOC_FAILURE;
                    goto end;
                }
                R_STR_token(&verify_cert_files, ':', verify_cert_file);

                /* Read in the certificates from the files. */
                if (((ret = R_CERT_read_file(cert_ctx, verify_cert_file,
                    certtype, certform, &verify_cert)) != R_ERROR_NONE)
                    || verify_cert == NULL)
                {
                    BIO_printf(bio_std_out,
                        "Certificate from file failure: %s\n",
                        verify_cert_file);
                    goto end;
                }

                indexed_info.index = R_OCSP_CERT_ADD_LOCATION_LAST;
                indexed_info.data = verify_cert;

                if ((ret = R_OCSP_REQ_set_info(req,
                    R_OCSP_REQ_INFO_CERTIFICATE_ADD,
                    &indexed_info)) != R_ERROR_NONE)
                {
                    BIO_printf(bio_std_out, "R_OCSP_REQ_set_info failure \
while setting R_OCSP_REQ_INFO_CERTIFICATE_ADD: \n");
                    goto end;
                }

                if (verify_cert != NULL)
                {
                    R_CERT_free(verify_cert);
                    verify_cert = NULL;
                }
                if (verify_cert_file != NULL)
                {
                    Free(verify_cert_file);
                    verify_cert_file = NULL;
                }

                verify_cert_file_len = R_STR_token(&verify_cert_files, ':',
                    NULL);
            } /* end while (verify_cert_file_len > 0) */
        } /* end if (verify_cert_files != NULL) */

        if ((ret = R_PKEY_CTX_new(lib_ctx, R_RES_FLAG_DEF, key_type,
            &pkey_ctx)) != R_ERROR_NONE)
        {
            BIO_printf(bio_std_out, "Failed to create key context\n");
            goto end;
        }

        if ((ret = R_PKEY_from_file(pkey_ctx, &key, key_file, key_type,
            R_FORMAT_BINARY)) != R_ERROR_NONE)
        {
            BIO_printf(bio_std_out, "Failed to create key from file\n");
            goto end;
        }

        if ((ret = R_OCSP_REQ_sign (req, req_cert, key,
            signature_alg_id)) != R_ERROR_NONE)
        {
            BIO_printf(bio_std_out, "Failed to sign request\n");
            goto end;
        }
    }

    /*************************************************************************
     * Step 6. Print out the OCSP request information, and save to a file.
     *************************************************************************/
    /* Write out to the console. */
    if ((ret = R_OCSP_REQ_write(req, bio_std_out, R_FORMAT_TEXT,
        NULL)) != R_ERROR_NONE)
    {
        BIO_printf(bio_std_out, "R_OCSP_REQ_write failure\n");
        goto end;
    }
    /* If specified, write the request out to a file. */
    if (req_out_file != NULL)
    {
        if ((ret = R_OCSP_REQ_write(req, bio_file_out, R_FORMAT_BINARY,
            NULL)) != R_ERROR_NONE)
        {
            BIO_printf(bio_std_out, "R_OCSP_REQ_write (file) failure\n");
            goto end;
        }
    }

end:
    /* Display the help menu if an invalid command line option was entered. */
    if (print_usage)
    {
        char **pp;

        for (pp = ocsp_req_create_usage; (*pp != NULL); pp++)
        {
            BIO_printf(bio_std_out, *pp);
        }
    }

    /*************************************************************************
     * Step 7. Clean up.
     * Report errors using both the error number and the string
     * representation. Destroy the dynamically allocated
     * objects, and return an exit code.
     *************************************************************************/
    if ((ret != R_ERROR_NONE) && (bio_std_out != NULL))
    {
        BIO_printf(bio_std_out, "ERROR: (%d) %s\n", ret,
            R_LIB_CTX_get_error_string(lib_ctx, R_RES_MOD_ID_LIBRARY, ret));
    }
    if (key != NULL)
    {
        R_PKEY_free(key);
    }
    if (pkey_ctx != NULL)
    {
        R_PKEY_CTX_free(pkey_ctx);
    }
    if (verify_cert != NULL)
    {
        R_CERT_free(verify_cert);
        verify_cert = NULL;
    }
    if (verify_cert_file != NULL)
    {
        Free(verify_cert_file);
    }
    if (nonce_ext != NULL)
    {
        R_EXT_free(nonce_ext);
    }
    if (response_types_ext != NULL)
    {
        R_EXT_free(response_types_ext);
    }
    if (ext_r_titem.data != NULL)
    {
        Free(ext_r_titem.data);
    }
    if (check_cert != NULL)
    {
        R_CERT_free(check_cert);
    }
    if (issuer_cert != NULL)
    {
        R_CERT_free(issuer_cert);
    }
    if (check_cert_file != NULL)
    {
        Free(check_cert_file);
    }
    if (issuer_cert_file != NULL)
    {
        Free(issuer_cert_file);
    }
    if (req_entry != NULL)
    {
        R_OCSP_REQ_ENTRY_free(req_entry);
    }
    if (req != NULL)
    {
        R_OCSP_REQ_free(req);
    }
    if (req_cert != NULL)
    {
        R_CERT_free(req_cert);
    }
    if (cert_ctx!= NULL)
    {
        R_CERT_CTX_free(cert_ctx);
    }
    if (ocsp_ctx != NULL)
    {
        R_OCSP_CTX_free(ocsp_ctx);
    }
    if (lib_ctx != NULL)
    {
        PRODUCT_LIBRARY_FREE(lib_ctx);
    }
    if (bio_file_out != NULL)
    {
        BIO_free(bio_file_out);
    }
    if (bio_std_out != NULL)
    {
        BIO_free(bio_std_out);
    }
    R_OCSP_CERT_ID_free(&cert_id);

    return(R_ERROR_EXIT_CODE(ret));
}

Copyright (c) 1999-2005 RSA Security Inc. All rights reserved. 072-001001-2100-001-000 - 2.1