RSA BSAFE Micro Edition Suite

Streamlined security for mobile and embedded devices

Search  Print

vfy_adv.c

/* $Id: vfy_adv.c,v 1.43 2005/02/07 07:46:49 hfrancis Exp $ */
/*
 * Copyright (C) 1998-2003 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.
 *
 *
 */

#include "r_prod.h"

static R_VERIFY_TIME_FUNC_T *get_vfy_time_func();
static R_VERIFY_DETAIL_FUNC_T *get_vfy_detail_func();

static int vfy_time_func(R_VERIFY_STATE *state, R_VERIFY_DETAILS *detail);
static int vfy_detail_func(R_VERIFY_STATE *state, R_VERIFY_DETAILS *detail,
    int index);

static int load_cert(R_CERT_CTX *cert_ctx, unsigned char *buf, long buf_len,
    char *name, BIO *bio, R_CERT **cert);

/*
 * The client certificate in binary form:
 *
 *  Version: 1 (0x0)
 *  Serial Number: 43:2e:
 *  Issuer: /C=AU/ST=Qld/L=Brisbane/O=RSA Security/OU=Engineering/CN=CA2
 *          certificate
 *  Validity:
 *       notBefore:  2001:01:01:00:00:00
 *       notAfter:   2010:01:01:00:00:00
 *  Subject: /C=AU/ST=Qld/L=Brisbane/O=RSA Security/OU=Engineering/CN=Leaf
 *           certificate
 */
static unsigned char client_x509_certificate[] =
{
    0x30, 0x82, 0x02, 0x5b, 0x30, 0x82, 0x01, 0xc4, 0x02, 0x02,
    0x43, 0x34, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
    0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x30, 0x75, 0x31,
    0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
    0x41, 0x55, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04,
    0x08, 0x13, 0x03, 0x51, 0x6c, 0x64, 0x31, 0x11, 0x30, 0x0f,
    0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x42, 0x72, 0x69,
    0x73, 0x62, 0x61, 0x6e, 0x65, 0x31, 0x15, 0x30, 0x13, 0x06,
    0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x52, 0x53, 0x41, 0x20,
    0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x31, 0x14,
    0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b, 0x45,
    0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67,
    0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
    0x0f, 0x43, 0x41, 0x32, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69,
    0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x1e, 0x17, 0x0d,
    0x30, 0x31, 0x30, 0x33, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
    0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x31, 0x30,
    0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x76,
    0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
    0x02, 0x41, 0x55, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55,
    0x04, 0x08, 0x13, 0x03, 0x51, 0x6c, 0x64, 0x31, 0x11, 0x30,
    0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x42, 0x72,
    0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x31, 0x15, 0x30, 0x13,
    0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x52, 0x53, 0x41,
    0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x31,
    0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b,
    0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e,
    0x67, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03,
    0x13, 0x10, 0x4c, 0x65, 0x61, 0x66, 0x20, 0x63, 0x65, 0x72,
    0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x81,
    0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
    0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
    0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xba, 0xc7, 0x7e,
    0x0b, 0x09, 0x2d, 0x9d, 0xbc, 0x04, 0x24, 0xca, 0x7c, 0x55,
    0x68, 0x72, 0xdc, 0x08, 0xac, 0x9f, 0xa7, 0x13, 0x24, 0x7c,
    0xa8, 0x09, 0x14, 0xcf, 0x38, 0xc5, 0x70, 0x42, 0x77, 0x76,
    0xc9, 0xcb, 0xc4, 0xfe, 0x10, 0x95, 0xde, 0x7c, 0x11, 0x1f,
    0x3e, 0xf2, 0x6c, 0x3d, 0xa5, 0xd5, 0x5c, 0xe3, 0x9b, 0xbf,
    0x06, 0x86, 0xf3, 0x58, 0x7a, 0xc2, 0x84, 0x7b, 0x86, 0xde,
    0xbf, 0xa1, 0x6c, 0xa8, 0x5a, 0xa4, 0xe9, 0x28, 0x32, 0x90,
    0xe2, 0x58, 0x98, 0x40, 0xc8, 0xb1, 0x7d, 0x32, 0xed, 0x53,
    0xbc, 0x5d, 0x0f, 0x23, 0x25, 0xa9, 0x97, 0x2a, 0x0a, 0x7e,
    0x66, 0x2b, 0x06, 0x10, 0x0f, 0xc8, 0xa4, 0x83, 0xc1, 0x2a,
    0x7c, 0x57, 0x9d, 0xd2, 0xb7, 0x99, 0xbc, 0xd8, 0xfd, 0x21,
    0x7a, 0x8c, 0xbd, 0x0e, 0xe8, 0x9f, 0xe3, 0x76, 0x0d, 0xdb,
    0xd8, 0xee, 0x24, 0xb2, 0x8b, 0x02, 0x03, 0x01, 0x00, 0x01,
    0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
    0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x5f,
    0x5f, 0xb6, 0x0b, 0x71, 0xce, 0xb3, 0x6f, 0x2e, 0x66, 0x8e,
    0x75, 0x1c, 0xba, 0x8c, 0x4e, 0xcb, 0xaf, 0x6b, 0x4a, 0x48,
    0xf7, 0x8e, 0xf4, 0x69, 0x61, 0xdf, 0xb2, 0x3e, 0x23, 0xab,
    0xd2, 0xa8, 0xc1, 0xae, 0xa4, 0x09, 0xb2, 0x69, 0x8a, 0xdf,
    0xa6, 0x45, 0xdd, 0x5b, 0x3e, 0x41, 0x43, 0xe1, 0xb5, 0x78,
    0xc2, 0x35, 0x80, 0x4e, 0xe5, 0x7b, 0xc2, 0xd4, 0x19, 0xdf,
    0x05, 0x32, 0x36, 0x1e, 0x46, 0x41, 0x7e, 0xc4, 0x11, 0x3e,
    0x8b, 0x36, 0x27, 0x9d, 0x2f, 0x60, 0x97, 0x5b, 0xef, 0xf6,
    0xd1, 0xcf, 0x05, 0xae, 0x6a, 0x83, 0x9d, 0x56, 0x92, 0xdd,
    0x3d, 0x33, 0x43, 0xc0, 0xa9, 0xea, 0x37, 0xae, 0xd3, 0xac,
    0x33, 0xfa, 0x06, 0xc0, 0x40, 0xba, 0xb3, 0xf7, 0xf3, 0x49,
    0x94, 0x4d, 0xd1, 0xb7, 0x4d, 0xee, 0xad, 0xb6, 0x59, 0xb1,
    0x50, 0xac, 0xc3, 0x22, 0x76, 0x97, 0x41,
};

/*
 * The second Certification Authority (CA) certificate, in binary form,
 * that can be used to verify the client certificate:
 *
 *  Version: 1 (0x0)
 *  Serial Number: 00:98:83:
 *  Issuer: /C=AU/ST=Qld/L=Brisbane/O=RSA Security/OU=Engineering/CN=CA1
 *          certificate
 *  Validity:
 *       notBefore:  2001:01:01:00:00:00
 *       notAfter:   2010:01:01:00:00:00
 *  Subject: /C=AU/ST=Qld/L=Brisbane/O=RSA Security/OU=Engineering/CN=CA2
 *           certificate
 */
static unsigned char ca2_x509_certificate[] =
{
    0x30, 0x82, 0x02, 0x5b, 0x30, 0x82, 0x01, 0xc4, 0x02, 0x03,
    0x00, 0x98, 0x89, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
    0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x30, 0x75,
    0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
    0x02, 0x41, 0x55, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55,
    0x04, 0x08, 0x13, 0x03, 0x51, 0x6c, 0x64, 0x31, 0x11, 0x30,
    0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x42, 0x72,
    0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x31, 0x15, 0x30, 0x13,
    0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x52, 0x53, 0x41,
    0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x31,
    0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b,
    0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e,
    0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03,
    0x13, 0x0f, 0x43, 0x41, 0x31, 0x20, 0x63, 0x65, 0x72, 0x74,
    0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x1e, 0x17,
    0x0d, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
    0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x31,
    0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
    0x75, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
    0x13, 0x02, 0x41, 0x55, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03,
    0x55, 0x04, 0x08, 0x13, 0x03, 0x51, 0x6c, 0x64, 0x31, 0x11,
    0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x42,
    0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x31, 0x15, 0x30,
    0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x52, 0x53,
    0x41, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
    0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13,
    0x0b, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69,
    0x6e, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04,
    0x03, 0x13, 0x0f, 0x43, 0x41, 0x32, 0x20, 0x63, 0x65, 0x72,
    0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x81,
    0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
    0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
    0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0x95, 0xc5, 0x3f,
    0x55, 0x22, 0xe7, 0xba, 0x78, 0x0c, 0xbf, 0xee, 0xce, 0x51,
    0x4f, 0xce, 0x7d, 0x8a, 0x5c, 0x9f, 0x69, 0xf2, 0x17, 0x64,
    0xa4, 0xc0, 0x95, 0x37, 0x03, 0x39, 0x4c, 0x85, 0xb4, 0x27,
    0x18, 0xb1, 0x67, 0xea, 0xd6, 0xbe, 0x85, 0x66, 0x9c, 0x66,
    0x9b, 0xbc, 0x87, 0xc8, 0x96, 0xea, 0xc0, 0x62, 0x69, 0x71,
    0x8e, 0x8d, 0x97, 0xba, 0x8a, 0x25, 0x35, 0x6a, 0x51, 0x1a,
    0xc5, 0x94, 0x6a, 0xa5, 0x1c, 0xc3, 0x7c, 0xda, 0xf1, 0xde,
    0x6f, 0x1d, 0x03, 0x6c, 0xd1, 0xaf, 0x47, 0xe6, 0x71, 0x5d,
    0x75, 0x87, 0xdc, 0xf8, 0x20, 0xd7, 0x79, 0x9b, 0x66, 0xff,
    0xaf, 0x5a, 0x48, 0xfc, 0xf3, 0xc2, 0x09, 0xda, 0x5f, 0x9a,
    0x8c, 0x60, 0xc6, 0x29, 0x98, 0x78, 0x0e, 0xda, 0x32, 0x0a,
    0xb5, 0xc8, 0xb7, 0xfd, 0x4c, 0x04, 0xa1, 0x56, 0x0f, 0x84,
    0x69, 0xb9, 0xe5, 0x75, 0x3b, 0x02, 0x03, 0x01, 0x00, 0x01,
    0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
    0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x2e,
    0x14, 0xac, 0x4b, 0x87, 0x46, 0xcf, 0x29, 0x70, 0x65, 0xe9,
    0xc9, 0x6d, 0x6d, 0xa6, 0xb4, 0xe7, 0x75, 0x87, 0x4e, 0xe0,
    0x76, 0xe2, 0xba, 0x6f, 0xcb, 0x1a, 0xf7, 0xf7, 0xe0, 0xe1,
    0x70, 0x6f, 0xf1, 0x86, 0x75, 0x56, 0x87, 0x18, 0x85, 0x68,
    0x8e, 0x6c, 0xa3, 0x16, 0x61, 0xa8, 0x3a, 0x7a, 0xd7, 0x9b,
    0x3d, 0x77, 0x29, 0xe4, 0x78, 0x51, 0x52, 0xdc, 0x93, 0x81,
    0x48, 0x89, 0xc9, 0x1f, 0xfc, 0x5b, 0xec, 0x06, 0x8f, 0x8a,
    0x95, 0x7d, 0xa1, 0x66, 0x02, 0x75, 0x4b, 0xe4, 0x0c, 0x29,
    0x52, 0x86, 0x5f, 0xf8, 0x32, 0xa5, 0xd5, 0x9b, 0x15, 0x69,
    0x3d, 0x7a, 0x4a, 0x4b, 0xda, 0xf4, 0x2b, 0xbb, 0xc4, 0x9b,
    0xdd, 0x6e, 0xc8, 0xf9, 0x1f, 0x79, 0x94, 0x60, 0xff, 0x26,
    0xfe, 0x6f, 0x8a, 0x07, 0xc7, 0xad, 0xdf, 0x05, 0x74, 0x90,
    0xfc, 0xe5, 0x27, 0xe1, 0xaa, 0x61, 0x60,
};

/*
 * The first CA certificate, in binary form, that can be used to verify
 * the second CA certificate:
 *
 *  Version: 1 (0x0)
 *  Serial Number: 67:96:
 *  Issuer: /C=AU/ST=Qld/L=Brisbane/O=RSA Security/OU=Engineering/CN=Root
 *          certificate
 *  Validity:
 *       notBefore:  2001:01:01:00:00:00
 *       notAfter:   2010:01:01:00:00:00
 *  Subject: /C=AU/ST=Qld/L=Brisbane/O=RSA Security/OU=Engineering/CN=CA1
 *           certificate
 */
static unsigned char ca1_x509_certificate[] =
{
    0x30, 0x82, 0x02, 0x5b, 0x30, 0x82, 0x01, 0xc4, 0x02, 0x02,
    0x67, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
    0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x30, 0x76, 0x31,
    0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
    0x41, 0x55, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04,
    0x08, 0x13, 0x03, 0x51, 0x6c, 0x64, 0x31, 0x11, 0x30, 0x0f,
    0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x42, 0x72, 0x69,
    0x73, 0x62, 0x61, 0x6e, 0x65, 0x31, 0x15, 0x30, 0x13, 0x06,
    0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x52, 0x53, 0x41, 0x20,
    0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x31, 0x14,
    0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b, 0x45,
    0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67,
    0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
    0x10, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x63, 0x65, 0x72, 0x74,
    0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x1e, 0x17,
    0x0d, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
    0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x31,
    0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
    0x75, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
    0x13, 0x02, 0x41, 0x55, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03,
    0x55, 0x04, 0x08, 0x13, 0x03, 0x51, 0x6c, 0x64, 0x31, 0x11,
    0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x42,
    0x72, 0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x31, 0x15, 0x30,
    0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x52, 0x53,
    0x41, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
    0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13,
    0x0b, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69,
    0x6e, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04,
    0x03, 0x13, 0x0f, 0x43, 0x41, 0x31, 0x20, 0x63, 0x65, 0x72,
    0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x81,
    0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
    0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
    0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xa5, 0x05, 0xad,
    0x0e, 0x21, 0x43, 0xdd, 0x2a, 0x02, 0x0f, 0xb6, 0x44, 0x16,
    0xb4, 0xba, 0x5e, 0x16, 0x1c, 0x79, 0x01, 0xe9, 0x50, 0xf9,
    0xa7, 0x44, 0x42, 0x9d, 0xa3, 0x3d, 0x7d, 0xd5, 0xd8, 0xe4,
    0xa5, 0x8c, 0x1f, 0x3c, 0xb7, 0x31, 0x24, 0x4b, 0xc4, 0xd1,
    0xd2, 0xd4, 0x3c, 0x68, 0x64, 0xc4, 0x52, 0x74, 0x66, 0x33,
    0x61, 0x4e, 0xd3, 0xc8, 0xaf, 0xb3, 0x5d, 0x03, 0x5b, 0x23,
    0x6a, 0x05, 0xf7, 0xb6, 0x45, 0x5c, 0x36, 0x4b, 0xfe, 0x81,
    0x4c, 0x22, 0x17, 0xfa, 0x6f, 0xa7, 0xfc, 0xe9, 0xc1, 0x74,
    0x56, 0x22, 0xb9, 0x55, 0x29, 0x6c, 0xb0, 0x9e, 0x0d, 0x1b,
    0xaf, 0x59, 0x65, 0x1a, 0x7f, 0xa8, 0x64, 0xc9, 0x88, 0x8d,
    0x2a, 0x5c, 0x77, 0xf5, 0xb1, 0x27, 0xe7, 0x76, 0x46, 0x50,
    0x73, 0x87, 0x6e, 0x14, 0xc7, 0xb9, 0xd4, 0x52, 0xa2, 0x06,
    0x9a, 0x1a, 0xdb, 0x75, 0x61, 0x02, 0x03, 0x01, 0x00, 0x01,
    0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
    0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x64,
    0x49, 0x93, 0x11, 0xd7, 0x5d, 0xb8, 0x1f, 0x48, 0xd4, 0x0d,
    0x53, 0x64, 0x53, 0x3b, 0xe6, 0x4e, 0xec, 0x8c, 0x1e, 0x68,
    0x3c, 0x09, 0xa2, 0xde, 0x71, 0xfb, 0xdb, 0x15, 0x1a, 0x6d,
    0xac, 0xe1, 0x1f, 0x21, 0x6f, 0xb7, 0xd0, 0xee, 0x12, 0x90,
    0xfb, 0x0c, 0x76, 0x2c, 0xc2, 0x34, 0x33, 0x9d, 0xc5, 0xac,
    0xdb, 0x3c, 0x79, 0x6e, 0x1f, 0xff, 0x90, 0x85, 0x31, 0x01,
    0x8d, 0xda, 0xf0, 0xfc, 0xf7, 0x48, 0x58, 0x97, 0xa9, 0x27,
    0xf4, 0x06, 0x7c, 0x3a, 0x7b, 0x3a, 0xe3, 0x10, 0x0b, 0xe2,
    0xc5, 0x0b, 0x73, 0x49, 0xc6, 0x9c, 0xb1, 0x33, 0x0c, 0xeb,
    0xf1, 0xf5, 0x96, 0x9c, 0x4b, 0xd4, 0xe8, 0xf3, 0x40, 0x4f,
    0x5a, 0xfa, 0x41, 0x24, 0x82, 0xf0, 0x18, 0x7a, 0x32, 0x8a,
    0x75, 0x45, 0x5f, 0x32, 0xa9, 0x21, 0x84, 0x8b, 0x4c, 0xef,
    0x51, 0xea, 0x2d, 0x07, 0x0c, 0x72, 0x74,
};

/*
 * The Root certificate, in binary form, that can be used to verify
 * the first CA certificate:
 *
 *  Version: 1 (0x0)
 *  Serial Number: 00:
 *  Issuer: /C=AU/ST=Qld/L=Brisbane/O=RSA Security/OU=Engineering/CN=Root
 *          certificate
 *  Validity:
 *       notBefore:  2001:01:01:00:00:00
 *  Validity:
 *       notBefore:  2001:01:01:00:00:00
 *       notAfter:   2010:01:01:00:00:00
 *  Subject: /C=AU/ST=Qld/L=Brisbane/O=RSA Security/OU=Engineering/CN=Root
 *           certificate
 */
static unsigned char root_x509_certificate[] =
{
    0x30, 0x82, 0x02, 0x5b, 0x30, 0x82, 0x01, 0xc4, 0x02, 0x01,
    0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
    0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x30, 0x76, 0x31, 0x0b,
    0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41,
    0x55, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x08,
    0x13, 0x03, 0x51, 0x6c, 0x64, 0x31, 0x11, 0x30, 0x0f, 0x06,
    0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x42, 0x72, 0x69, 0x73,
    0x62, 0x61, 0x6e, 0x65, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03,
    0x55, 0x04, 0x0a, 0x13, 0x0c, 0x52, 0x53, 0x41, 0x20, 0x53,
    0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x31, 0x14, 0x30,
    0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b, 0x45, 0x6e,
    0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x31,
    0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10,
    0x52, 0x6f, 0x6f, 0x74, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69,
    0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x1e, 0x17, 0x0d,
    0x30, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
    0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x31, 0x30,
    0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x76,
    0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
    0x02, 0x41, 0x55, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55,
    0x04, 0x08, 0x13, 0x03, 0x51, 0x6c, 0x64, 0x31, 0x11, 0x30,
    0x0f, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x42, 0x72,
    0x69, 0x73, 0x62, 0x61, 0x6e, 0x65, 0x31, 0x15, 0x30, 0x13,
    0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x52, 0x53, 0x41,
    0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x31,
    0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x0b,
    0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x65, 0x72, 0x69, 0x6e,
    0x67, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03,
    0x13, 0x10, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x63, 0x65, 0x72,
    0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x81,
    0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
    0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
    0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xe1, 0x77, 0xcd,
    0x40, 0x31, 0x78, 0xcd, 0x4c, 0x64, 0x9b, 0x73, 0x0f, 0xdc,
    0x82, 0x52, 0x5e, 0xe8, 0xbc, 0xfe, 0xba, 0xd2, 0xea, 0xd6,
    0xda, 0x4a, 0xfe, 0x9b, 0x6c, 0x6a, 0x11, 0xf0, 0xe0, 0xb1,
    0x69, 0x9a, 0x7b, 0xc1, 0xae, 0xfe, 0xa4, 0x2e, 0x1e, 0xfc,
    0xbb, 0xb7, 0x87, 0xb8, 0x0a, 0xe6, 0x61, 0x63, 0xa0, 0x47,
    0x66, 0x50, 0x21, 0x34, 0x05, 0xca, 0xc3, 0x66, 0x0e, 0xf3,
    0x54, 0x26, 0x0f, 0xa0, 0xb2, 0x5d, 0x77, 0x11, 0x38, 0x7d,
    0x27, 0x85, 0x8e, 0xa3, 0x21, 0xce, 0x35, 0xc5, 0xfc, 0x74,
    0xda, 0x8d, 0xd6, 0xbd, 0x3a, 0xd3, 0xff, 0x8d, 0x5e, 0x78,
    0x7b, 0x34, 0x87, 0x9e, 0xb7, 0x84, 0xd0, 0x32, 0x44, 0xcd,
    0x35, 0xa9, 0x8e, 0x29, 0x73, 0xfd, 0x5f, 0x2c, 0xc5, 0x98,
    0xe5, 0x04, 0xf2, 0x95, 0x7b, 0x4e, 0xef, 0x2c, 0xea, 0x27,
    0x98, 0x2a, 0x27, 0x90, 0xab, 0x02, 0x03, 0x01, 0x00, 0x01,
    0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
    0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x30,
    0x26, 0x5d, 0xb3, 0x05, 0x24, 0xac, 0x55, 0x46, 0x48, 0xfe,
    0x71, 0x4e, 0x61, 0x17, 0xee, 0xfb, 0x99, 0x70, 0xbf, 0x4c,
    0xc6, 0xc3, 0x5f, 0x92, 0x4d, 0xeb, 0xae, 0x29, 0xc1, 0x6d,
    0x43, 0x7c, 0x12, 0x2e, 0x68, 0x11, 0xe1, 0xd9, 0x22, 0xa7,
    0xfa, 0x40, 0x74, 0xba, 0x33, 0xe1, 0xfa, 0x08, 0x66, 0x00,
    0x04, 0x5e, 0x27, 0x57, 0x60, 0x2f, 0x2a, 0x48, 0x8d, 0x02,
    0x97, 0x4b, 0x84, 0xa4, 0x21, 0xee, 0xc5, 0xff, 0xa4, 0xd5,
    0x52, 0xad, 0x08, 0x11, 0x4e, 0x1c, 0x51, 0x51, 0x5c, 0xb5,
    0xf2, 0x89, 0x75, 0x1b, 0x26, 0x69, 0x6d, 0xa4, 0x6f, 0x76,
    0x2b, 0x94, 0x54, 0xf8, 0xe1, 0xb2, 0xa4, 0x90, 0x19, 0xa6,
    0xe9, 0xcd, 0xa9, 0x41, 0x76, 0x38, 0x57, 0x24, 0xe6, 0xa1,
    0xa6, 0x87, 0xdc, 0x4e, 0x6c, 0x2e, 0xc4, 0xa4, 0x6d, 0xaa,
    0x00, 0xb6, 0x70, 0x9c, 0x9d, 0xdf, 0xb9,
};

/*
 * Define the number of untrusted certificates. These are all the above
 * certificates except for the Root certificate. The Root certificate is
 * the only trusted certificate in this sample.
 */
#define NUM_UNTRUSTED_CERTS     3

/* The length of the reason string */
#define MAX_STR_LEN             30

/*
 * 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.<br>
 *           See @ref R_ERROR_IDS for valid values.
 */
int main(int argc, char **argv)
{
    int               ret = R_ERROR_NONE;     /* The return value           */
    int               res = R_VERIFY_R_NONE;  /* The verify reason code     */
    R_RES_LIST       *res_list = NULL;        /* The resource list          */
    R_LIB_CTX        *lib_ctx = NULL;         /* The library context        */
    R_VERIFY_CTX     *vfy_ctx = NULL;         /* The verification context   */
    R_VERIFY_STATE   *vfy_state = NULL;       /* The verify state           */
    R_CERT_STORE_CTX *store_ctx = NULL;       /* The certificate store
                                               * context */
    R_CERT_STORE     *store = NULL;           /* The certificate store      */
    R_CERT_CTX       *x509_cert_ctx = NULL;   /* The certificate context    */
                                              /* The certificate chain
                                               * array */
    R_CERT           *cert_chain[NUM_UNTRUSTED_CERTS];
    R_CERT           *root_cert = NULL;       /* The Root certificate       */
    R_CERT           *ca1_cert = NULL;        /* The first CA certificate   */
    R_CERT           *ca2_cert = NULL;        /* The second CA certificate  */
    R_CERT           *client_cert = NULL;     /* The client certificate     */
    BIO              *bio_err = NULL;         /* The standard error output  */
    int               verified;               /* The verified certificates  */
    char              str[MAX_STR_LEN];       /* The failure reason string  */

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

    /*
     * Create the library context. Retrieve the default resource list and
     * create a library context to provide access to all configurable aspects
     * of the library. The default list is updated with extra functions to
     * perform extended verification.
     */
#ifdef NO_SOFTWARE_CRYPTO
    res_list = PRODUCT_NON_FIPS_140_MODE_RESOURCE_LIST();
#else /* !NO_SOFTWARE_CRYPTO */
    res_list = PRODUCT_DEFAULT_RESOURCE_LIST();
#endif /* NO_SOFTWARE_CRYPTO */

    /*
     * Add the certificate time verification callback to the resource list
     * so the verification routines have access to the callback
     */
    if ((ret = R_VERIFY_set_time_verify_func(&res_list,
        (R_VERIFY_GET_TIME_VERIFY_FUNC_T *)get_vfy_time_func)) != R_ERROR_NONE)
    {
        goto err;
    }

    /*
     * Add the details verification callback to the resource list so the
     * verification routines have access to the callback
     */
    if ((ret = R_VERIFY_set_detail_verify_func(&res_list,
        (R_VERIFY_GET_DETAIL_VERIFY_FUNC_T *)get_vfy_detail_func))
             != R_ERROR_NONE)
    {
        goto err;
    }

    if ((ret = PRODUCT_LIBRARY_NEW(res_list, 0, &lib_ctx)) != R_ERROR_NONE)
    {
        goto err;
    }

    /*
     * Set up the verification related functionality, including:
     *      - Creating a verification context.
     *      - Setting the verification options.
     *      - Setting the application specific callback functions .
     */

    /* Create a new verification context */
    if ((ret = R_VERIFY_CTX_new(lib_ctx, R_RES_FLAG_DEF, &vfy_ctx)) !=
            R_ERROR_NONE)
    {
        goto err;
    }

    /* Set the default verification flags */
    if ((ret = R_VERIFY_CTX_set_flag(vfy_ctx,
        (R_VERIFY_FLAG_COMPLETE_CHAIN |
         R_VERIFY_FLAG_VERIFY_SIGNATURE |
         R_VERIFY_FLAG_VERIFY_FULL_CHAIN |
         R_VERIFY_FLAG_VERIFY_NOT_BEFORE |
         R_VERIFY_FLAG_VERIFY_NOT_AFTER))) != R_ERROR_NONE)
    {
        goto err;
    }

    /*
     * Set the BIO as the callback argument so any verification functions set
     * against the resource list have a means of printing
     */
    if ((ret = R_VERIFY_CTX_set_info(vfy_ctx, R_VERIFY_CTX_INFO_CALLBACK_ARG,
        bio_err)) != R_ERROR_NONE)
    {
        goto err;
    }

    /*
     * Create a new verification state. The state will hold the entire
     * verification process, including the certificates and the result.
     */
    if ((ret = R_VERIFY_STATE_new(vfy_ctx, R_RES_FLAG_DEF, &vfy_state)) !=
        R_ERROR_NONE)
    {
        goto err;
    }

    /*
     * Set the connection object allowing the verification state access to
     * the entities that own it. These objects can then be retrieved from
     * inside the verification code.
     *
     * For example:
     * PKCS7 verification
     * R_VERIFY_STATE_set_conn(vfy_state, R_VERIFY_CONN_TYPE_PKCS7, ctx, obj);
     *   - <i>ctx</i> has type R_CM_CTX.
     *   - <i>obj</i> has type R_CM.
     * These objects can then be accessed from inside any custom verification
     * routines via R_VERIFY_STATE_get_info().
     *
     * In this case there is no connection object so set the type to NONE.
     */
    if ((ret = R_VERIFY_STATE_set_conn(vfy_state, R_VERIFY_CONN_TYPE_NONE,
        NULL, NULL)) != R_ERROR_NONE)
    {
        goto err;
    }

    /*
     * Set up the certificate store related functionality, including:
     *    - Creating a store context.
     *    - Creating a store object.
     */
    if ((ret = R_CERT_STORE_CTX_new(lib_ctx, R_RES_FLAG_DEF, &store_ctx)) !=
        R_ERROR_NONE)
    {
        goto err;
    }

    if ((ret = R_CERT_STORE_new(store_ctx, &store)) != R_ERROR_NONE)
    {
        goto err;
    }

    /*
     * Create a certificate context. All certificate operations require a
     * certificate context (R_CERT_CTX). This context provides access to the
     * certificate functionality.
     */
    if ((ret = R_CERT_CTX_new(lib_ctx, R_RES_FLAG_DEF, R_CERT_TYPE_X509,
        &x509_cert_ctx)) != R_ERROR_NONE)
    {
        goto err;
    }

    /*
     * Set up the certificate-related functionality. For each certificate:
     *    - Read the certificate from file.
     *    - Set the certificate against the store object.
     *    - Set the certificate trust level.
     *    - Add the certificate to the store (using the store object).
     */
    if ((ret = load_cert(x509_cert_ctx, root_x509_certificate,
            sizeof(root_x509_certificate),   "Root",
            bio_err, &root_cert) != R_ERROR_NONE)        ||

        (ret = load_cert(x509_cert_ctx, ca1_x509_certificate,
            sizeof(ca1_x509_certificate),    "CA1",
            bio_err, &ca1_cert) != R_ERROR_NONE)         ||

        (ret = load_cert(x509_cert_ctx, ca2_x509_certificate,
            sizeof(ca2_x509_certificate),    "CA2",
            bio_err, &ca2_cert) != R_ERROR_NONE)         ||

        (ret = load_cert(x509_cert_ctx, client_x509_certificate,
            sizeof(client_x509_certificate), "Client",
            bio_err, &client_cert) != R_ERROR_NONE))
    {
        goto err;
    }

    /*
     * Add the Root certificate into the store. The store owns the
     * certificate so it does not need to be freed by the application.
     */
    if ((ret = R_CERT_STORE_set_cert(store, root_cert, NULL)) != R_ERROR_NONE)
    {
        BIO_printf(bio_err,
            "Failed to add the Root certificate to the store - exiting\n");
        goto err;
    }
    root_cert = NULL;

    /*
     * Set the trust level of the current certificate. For example, the Root
     * certificate is trusted and used for chain completion during chain
     * verification.
     */
    if ((ret = R_CERT_STORE_set_cert_state(store,
        R_CERT_STORE_STATE_TRUSTED_CERTIFICATE)) != R_ERROR_NONE)
    {
        BIO_printf(bio_err,
            "Failed to set the Root certificate trust - exiting\n");
        goto err;
    }

    if ((ret = R_CERT_STORE_add(store)) != R_ERROR_NONE)
    {
        BIO_printf(bio_err,
            "Failed to add the Root certificate to the store - exiting\n");
        goto err;
    }

    /*
     * Add the client certificate into the array followed by the CA
     * certificates. Ensure the chain is completed in the correct order.
     */
    cert_chain[0] = client_cert;      /* The client certificate signed
                                       * by the second CA */
    cert_chain[1] = ca2_cert;         /* The second CA certificate
                                       * signed by the first CA    */
    cert_chain[2] = ca1_cert;         /* The first CA certificate
                                       * signed by Root   */

    /* Populate the verification state object using the certificate chain */
    if ((ret = R_VERIFY_STATE_populate_with_R_CERT(vfy_state, store_ctx,
        cert_chain, NUM_UNTRUSTED_CERTS, R_VERIFY_STATE_NONE)) != R_ERROR_NONE)
    {
        goto err;
    }

    /* Verify the certificate chain */
    if ((ret = R_VERIFY_STATE_verify(vfy_state, &verified)) != R_ERROR_NONE)
    {
        goto err;
    }

    if (!verified)
    {
        /* Check for verification errors */
        if ((ret = R_VERIFY_STATE_get_reason(vfy_state, &res)) != R_ERROR_NONE)
        {
            BIO_printf(bio_err, "Verification error: reason unknown\n");
            goto err;
        }

        if ((ret = R_VERIFY_REASON_to_string(res, MAX_STR_LEN,
            str)) != R_ERROR_NONE)
        {
            BIO_printf(bio_err, "Verification error: reason unknown\n");
        }
        else
        {
            BIO_printf(bio_err, "Verification error: reason %d (%s)\n", res,
                str);
        }

        ret = R_ERROR_FAILED;
    }
    else
    {
        BIO_printf(bio_err, "\nSuccessfully verified certificate\n");
    }

err:
    /*
     * Clean up. Report errors if there is an output stream using both the
     * error and the string representation. Destroy the dynamically allocated
     * objects and return an exit code.
     */
    if ((ret != R_ERROR_NONE) && (bio_err != NULL))
    {
        BIO_printf(bio_err, "Error: (%d) %s\n", ret,
            R_LIB_CTX_get_error_string(lib_ctx, R_RES_MOD_ID_LIBRARY, ret));
    }

    if (client_cert != NULL)
    {
        R_CERT_free(client_cert);
    }
    if (ca2_cert != NULL)
    {
        R_CERT_free(ca2_cert);
    }
    if (ca1_cert != NULL)
    {
        R_CERT_free(ca1_cert);
    }
    if (root_cert != NULL)
    {
       R_CERT_free(root_cert);
    }
    if (store != NULL)
    {
        R_CERT_STORE_free(store);
    }
    if (store_ctx != NULL)
    {
        R_CERT_STORE_CTX_free(store_ctx);
    }
    if (vfy_state != NULL)
    {
        R_VERIFY_STATE_free(vfy_state);
    }
    /*
     * The certificate context cannot be freed until the store and state have
     * been emptied as certificates in the store and verification state hold
     * references back to the certificate context
     */
    if (x509_cert_ctx != NULL)
    {
        R_CERT_CTX_free(x509_cert_ctx);
    }
    if (vfy_ctx != NULL)
    {
        R_VERIFY_CTX_free(vfy_ctx);
    }
    if (lib_ctx != NULL)
    {
        PRODUCT_LIBRARY_FREE(lib_ctx);
    }
    if (bio_err != NULL)
    {
        BIO_free(bio_err);
    }

    return(R_ERROR_EXIT_CODE(ret));
}

/*
 * Returns the time verification function. This function is added into a
 * resource structure inside the resource list. It allows for replaceable
 * time verification routines to be used.
 *
 * @returns  The time verification function.
 */
static R_VERIFY_TIME_FUNC_T *get_vfy_time_func()
{
    return(&vfy_time_func);
}

/*
 * Returns the detail verification function. This function is added into a
 * resource structure inside the resource list. It allows for replaceable
 * detail verification routines to be used.
 *
 * @returns  The detail verification function.
 */
static R_VERIFY_DETAIL_FUNC_T *get_vfy_detail_func()
{
    return(&vfy_detail_func);
}

/*
 * An application-specific details time verification function that will be set
 * in the resource list.
 *
 * @param    state  [In] A reference to the certificate verification state.
 * @param    detail [In] A reference to the certificate verification details.
 *
 * @returns  #R_ERROR_NONE indicates success.
 *
 * @note     This example code extracts and prints the information required
 *           to perform a certificate time verification. No action is
 *           taken.
 *
 * @see      R_CERT_time_validity().
 */
static int vfy_time_func(R_VERIFY_STATE *state, R_VERIFY_DETAILS *detail)
{
    int            ret;
    R_VERIFY_CTX  *vfy_ctx;
    R_CERT        *cert;
    BIO           *bio_out;
    char           tbuf[20];

    /* Access the verification context */
    if ((ret = R_VERIFY_STATE_get_R_VERIFY_CTX(state,
        &vfy_ctx)) != R_ERROR_NONE)
    {
        goto done;
    }

    /* Extract the BIO for printing */
    if ((ret = R_VERIFY_CTX_get_info(vfy_ctx, R_VERIFY_CTX_INFO_CALLBACK_ARG,
        &bio_out)) != R_ERROR_NONE)
    {
        goto done;
    }

    /* Print something to indicate that verification time has been reached */
    BIO_printf(bio_out, "\n\t\t-----  REACHED VFY_TIME_FUNC  ----\n\n");

    /* Retrieve the certificate out of the details */
    if ((R_VERIFY_DETAILS_cert_to_R_CERT(detail,
        R_VERIFY_DETAIL_FLAG_BY_REFERENCE, &cert)) != R_ERROR_NONE)
    {
        goto done;
    }

    /* Retrieve and print the notBefore field */
    if (R_CERT_not_before_to_string(cert, sizeof(tbuf), tbuf) == R_ERROR_NONE)
    {
        BIO_printf(bio_out, "Not Before:\t%s\n", tbuf);
    }

    /* Retrieve and print the notAfter field */
    if (R_CERT_not_after_to_string(cert, sizeof(tbuf), tbuf) == R_ERROR_NONE)
    {
        BIO_printf(bio_out, "Not After:\t%s\n", tbuf);
    }

done:
    return(ret);
}

/*
 * An application-specific details verification function that will be set in
 * the resource list.
 *
 * @param    state  [In] A reference to the certificate verification state.
 * @param    detail [In] A reference to the certificate verification details.
 * @param    index  [In] The index of the certificate in the chain.
 *
 * @returns  #R_ERROR_NONE indicates success.
 *
 * @note     This example code extracts and prints some certificate
 *           information. No verification action is taken.
 */
static int vfy_detail_func(R_VERIFY_STATE *state, R_VERIFY_DETAILS *detail,
    int index)
{
    int           ret;
    R_VERIFY_CTX *vfy_ctx;
    R_CERT       *cert;
    BIO          *bio_out;
    int           ilen;
    char         *buf = NULL;
    R_ITEM        item;

    /* Access the verification context */
    if ((ret = R_VERIFY_STATE_get_R_VERIFY_CTX(state,
        &vfy_ctx)) != R_ERROR_NONE)
    {
        goto done;
    }

    /* Extract the BIO for printing */
    if ((ret = R_VERIFY_CTX_get_info(vfy_ctx, R_VERIFY_CTX_INFO_CALLBACK_ARG,
        &bio_out)) != R_ERROR_NONE)
    {
        goto done;
    }

    /*
     * Print something to indicate that the verification time has been reached
     */
    BIO_printf(bio_out, "\n\t\t-----  REACHED VFY_DETAIL_FUNC ----\n\n");
    BIO_printf(bio_out, "Index:\t\t%d\n", index);

    /* Retrieve the certificate out of the details */
    if ((R_VERIFY_DETAILS_cert_to_R_CERT(detail,
        R_VERIFY_DETAIL_FLAG_BY_REFERENCE, &cert)) != R_ERROR_NONE)
    {
        goto done;
    }

    /* Display the serial number of the certificate */
    if (R_CERT_get_info(cert, R_CERT_INFO_SERIAL_NUMBER,
        &item) == R_ERROR_NONE)
    {
        BIO_printf(bio_out, "Serial Number:\t");
        BIO_dump_format(bio_out, item.data, item.len,
            BIO_DUMP_FORMAT_HEX, ':', 0, 16);
    }

    /* Print the issuer and subject names */
    ilen = 256;
    if ((buf = Malloc(ilen)) != NULL)
    {
        if (R_CERT_issuer_name_to_string(cert, ilen, buf) == R_ERROR_NONE)
        {
            BIO_printf(bio_out, "Issuer:\t\t%s\n", buf);
        }

        if (R_CERT_subject_name_to_string(cert, ilen, buf) == R_ERROR_NONE)
        {
            BIO_printf(bio_out, "Subject:\t%s\n", buf);
        }

        Free(buf);
    }

done:
    return (ret);
}

/*
 * Loads an X.509 certificate from a buffer of binary data into an R_CERT
 * structure. This routine will also display the R_CERT object in text
 * format.
 *
 * @param    cert_ctx  [In]  The certificate context.
 * @param    buf       [In]  The buffer containing the binary data.
 * @param    buf_len   [In]  The length of the binary data buffer.
 * @param    name      [In]  The name of the cert (for display purposes only).
 * @param    bio       [In]  A reference to the output stream.
 * @param    cert      [Out] The created certificate structure.
 *
 * @returns  R_ERROR_NONE indicates success.<br>
 *           See @ref R_ERROR_IDS for valid values.
 *
 * @see      R_CERT_from_binary().
 */
static int load_cert(R_CERT_CTX *cert_ctx, unsigned char *buf, long buf_len,
    char *name, BIO *bio, R_CERT **cert)
{
    int ret;
    unsigned int consumed_len;

    if ((ret = R_CERT_from_binary(cert_ctx, R_FLAG_SHARE_DATA, R_CERT_TYPE_X509,
        buf_len, (const unsigned char *)buf, &consumed_len, cert)) !=
        R_ERROR_NONE)
    {
        BIO_printf(bio, "Failed to load %s certificate - exiting\n", name);
    }
    else
    {
        BIO_printf(bio, "Loaded %s certificate\n\n", name);
        R_CERT_write(*cert, bio, R_FORMAT_TEXT, NULL);
        BIO_printf(bio, "\n");
    }

    return(ret);
}


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