RSA BSAFE Micro Edition Suite

Streamlined security for mobile and embedded devices

Search  Print

Get R_CERT Certificate from SSLCERT

This sample demonstrates how to shows how to obtain certificates in R_CERT format from certificates in SSLCERT format.

Sample Description:
-------------------
This sample shows how to obtain certificates in R_CERT format from 
certificates in SSLCERT format.

Procedure:
----------
 1) Initialize the library.
 2) Create the R_PKEY and R_CERT contexts.
 3) Load and create a certificate (SSLCERT) - supplied via
    builtin_cert_pkey.h.
 4) Get and print the subject and issuer name.
 5) Load and create a private key (EVP_KEY) - also supplied
    via builtin_cert_pkey.h.
 6) Confirm the private key and certificate are a matching pair.
 7) Convert the SSLCERT certificate to binary.
 8) Convert the binary certificate to an R_CERT certificate.
 9) Print the subject and issuer name of the new R_CERT.
10) Convert the EVP_KEY private key to binary.
11) Convert the binary private key to an R_PKEY private key.
12) Confirm the new R_PKEY private key and the new R_CERT
    certificate are a matching pair - this confirms the
    conversion was successful.

/* $Id: sslcert2rcert.c,v 1.12 2005/08/09 11:06:02 hfrancis Exp $ */

/*
 * Copyright (C) 1999-2003 RSA Security Inc. All rights reserved.
 *
 * This work contains proprietary information of RSA Security.
 * Distribution is limited to authorized licensees of RSA
 * Security. Any unauthorized reproduction, distribution or
 * modification of this work is strictly prohibited.
 */

#include "r_prod.h"
#include "builtin_cert_pkey.h"      /* Built-in certificate and private key */

#define  CERT_NAME_BUF_LEN 256

/* Global BIO for output to standard error */
BIO *bio_err;

int main(int argc, char *argv[])
{
    int ret = R_ERROR_FAILED;                /* Function return value */
    BIO *bio_out = NULL;
    R_LIB_CTX *lib_ctx = NULL;          /* Pointer to library context */
    SSLCERT *sslcert = NULL;                /* Pointer to certificate */
    SSLCERT_NAME *xn;
    SSLCERT_NAME *sn;
    EVP_PKEY *pkey = NULL;                  /* Pointer to private key */
    R_CERT_CTX       *cert_ctx  = NULL;
    R_CERT           *rcert     = NULL;
    R_PKEY_CTX       *key_ctx   = NULL;
    R_CERT_TYPE       certtype;
    R_FORMAT          certform;
    R_PKEY_TYPE       keytype;
    R_FORMAT          keyform;
    R_PKEY           *rpkey = NULL;
    int               cert_length = 0;
    unsigned int      consumed_len;
    unsigned char    *cert_buffer = NULL;
    unsigned char    *cert_bufptr = NULL;
    char buf[CERT_NAME_BUF_LEN] = {'\0'};
    unsigned char    *key_buffer = NULL;
    unsigned char    *key_bufptr = NULL;
    int               key_length = 0;
    char             *issuerName = NULL;
    char             *subjectName = NULL;

    certtype     = R_CERT_TYPE_X509;
    certform     = R_FORMAT_BINARY;
    keytype      = R_PKEY_TYPE_RSA;
    keyform      = R_FORMAT_BINARY;

    /* Create an output channel */
    if ((bio_err = BIO_new_fp(stderr, BIO_NOCLOSE)) == NULL)
    {
        goto end;
    }
    BIO_set_flags(bio_err, BIO_FLAGS_FLUSH_ON_WRITE);

    /* Create an output channel */
    if ((bio_out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL)
    {
        goto end;
    }
    BIO_set_flags(bio_out, BIO_FLAGS_FLUSH_ON_WRITE);

    /* Initialize the SSL library using the default resources */
    if (PRODUCT_LIBRARY_NEW(PRODUCT_DEFAULT_RESOURCE_LIST(), R_RES_FLAG_DEF,
        &lib_ctx) != R_ERROR_NONE)
    {
        BIO_printf(bio_err, "Unable to create library context\n");
        goto end;
    }

    /* Create a new key context */
    if ((ret = R_PKEY_CTX_new(lib_ctx, R_RES_FLAG_DEF, keytype, &key_ctx)) !=
        R_ERROR_NONE)
    {
        BIO_printf(bio_out, "Key context new failure\n");
        goto end;
    }

    /* Create a new certificate context */
    if ((ret = R_CERT_CTX_new(lib_ctx, R_RES_FLAG_DEF, certtype, &cert_ctx)) !=
        R_ERROR_NONE)
    {
        BIO_printf(bio_out, "Certificate context new failure\n");
        goto end;
    }

#ifndef SSLC_SMALL_CODE
    SSL_load_error_strings();
#endif /* !SSLC_SMALL_CODE */

    /* Load the built-in server certificate */
    BIO_printf(bio_out, "Loading the built-in SSLCERT certificate\n");
    sslcert = sslcert_get_certificate();
    if (sslcert == NULL)
    {
        BIO_printf(bio_err, "Unable to get built-in server certificate\n");
        goto end;
    }

    /* Print the issuer and subject name */
    xn = SSLCERT_get_issuer_name(sslcert);
    issuerName = SSLCERT_NAME_oneline(xn,buf,CERT_NAME_BUF_LEN);
    if (issuerName == NULL)
    {
        BIO_printf(bio_err, "Unable to get issuer name\n");
        goto end;
    }
    BIO_printf(bio_out, "\nIssuer: %s\n", issuerName);

    sn = SSLCERT_get_subject_name(sslcert);
    subjectName = SSLCERT_NAME_oneline(sn,buf, CERT_NAME_BUF_LEN);
    if (subjectName == NULL)
    {
        BIO_printf(bio_err, "Unable to get subject name\n");
        goto end;
    }
    BIO_printf(bio_out, "Subject: %s\n", subjectName);

    /* Load the built-in server private key */
    BIO_printf(bio_out, "\nLoading the builtin RSA key\n");
    pkey = get_rsa512_priv_server();
    if (pkey == NULL)
    {
        BIO_printf(bio_err, "Unable to get built-in server private key\n");
        goto end;
    }

    /* Check the private key against the certificate */
    if (!SSLCERT_check_private_key(sslcert, pkey ))
    {
        BIO_printf(bio_err, "Private key check failed\n");
        goto end;
    }
    else
    {
        BIO_printf(bio_out, "Private key check PASSED - SSLCERT\n");
    }

    /* Convert SSLCERT to R_CERT */
    BIO_printf(bio_out, "\n\nConvert SSLC to R_CERT\n\n");

    /* Allocate a temporary buffer for the server's certificate */
    cert_length = SSLCERT_to_binary(sslcert, NULL);

    cert_buffer = (unsigned char *)Malloc((unsigned int)cert_length);
    if (cert_buffer == NULL)
    {
        /* The buffer cannot be allocated so exit immediately */
        SSLerr(SSL_F_REQUEST_CERTIFICATE, ERR_R_MALLOC_FAILURE);
        goto end;
    }

    /* Keep a copy of the start of the buffer before calling SSLCERT_to_binary
     * because function call SSLCERT_to_binary will move the buffer pointer
     * to the end of the certificate
     */
    cert_bufptr = cert_buffer;
    /* Output the certificate data to the tmp buffer in ASN.1 format */
    cert_length = SSLCERT_to_binary(sslcert, &cert_buffer);
    /* Bring the buffer pointer back to its initial position  */
    cert_buffer = cert_bufptr;

    BIO_printf(bio_out, "Length of SSLCERT binary representation %d\n", 
                         cert_length);
    /*
     * Create a certificate object. Read the binary representation of the
     * certificate and convert it to an R_CERT object. If the object
     * does not exist (that is, cert==NULL), an R_CERT object is created.
     */
    if ((ret = R_CERT_from_binary(cert_ctx, R_FLAG_SHARE_DATA,
                                  R_CERT_TYPE_X509, cert_length,
                                  (const unsigned char *)cert_buffer,
                                  (unsigned int *)&consumed_len, &rcert))
                 != R_ERROR_NONE)
    {
        BIO_printf(bio_err, "R_CERT_from_binary failure for certificate\n");
        goto end;
    }

    if ((ret = R_CERT_subject_name_to_string(rcert, sizeof(buf),
                                                 (char *)buf)) == R_ERROR_NONE)
    {
        BIO_printf(bio_out, "subject: %s\n", buf);
    }

    if ((ret = R_CERT_issuer_name_to_string(rcert, sizeof(buf),
                                        (char *)buf)) == R_ERROR_NONE)
    {
        BIO_printf(bio_out, "issuer: %s\n", buf);
        fflush(stdout);
    }

    /* Allocate a temporary buffer for the server's certificate */
    key_length = SSLCERT_PKEY_to_binary(pkey, NULL);

    key_buffer = (unsigned char *)Malloc((unsigned int)key_length);
    if (key_buffer == NULL)
    {
        /* The buffer cannot be allocated so exit immediately */
        SSLerr(SSLCERT_F_PKEY_FROM_BINARY, ERR_R_MALLOC_FAILURE);
        goto end;
    }
    key_bufptr = key_buffer;

    /* Output the certificate data to the tmp buffer in ASN.1 format */
    key_length = SSLCERT_PKEY_to_binary(pkey, &key_buffer);
    BIO_printf(bio_out, "Key length of binary representation is %d\n\n", 
                         key_length);
    key_buffer = key_bufptr;

    /*
     * Create the public key object and load the key. Creating a private key
     * object enables the private key to be read from memory and converted into
     * an R_PKEY object. 
     */
    if ((ret = R_PKEY_from_binary( key_ctx, R_PKEY_FL_DEFAULT, R_PKEY_TYPE_RSA,
        key_length, key_buffer, &consumed_len, &rpkey)) != R_ERROR_NONE)
    {
        BIO_printf(bio_out, "R_PKEY_from_binary failure\n");
        goto end;
    }

    if (R_CERT_is_matching_private_key(rcert, rpkey))
    {
        BIO_printf(bio_out, "R_CERT and R_PKEY match!\n");
    }
    else
    {
        BIO_printf(bio_err, "Failed: R_CERT / R_PKEY match\n");
        goto end;
    }

    /* Process the data read from the client */
    BIO_printf(bio_out, "Done\n");

    /* Set program success */
    ret = R_ERROR_NONE;

end:

    /* On error output the error stack */
    if ((ret != R_ERROR_NONE) && (bio_err != NULL))
    {
        ERR_print_errors(bio_err);
    }

    if (cert_bufptr)
    {
        Free (cert_bufptr);
    }

    if (key_bufptr)
    {
        Free (key_bufptr);
    }

    /*
     * The private key and certificate were generated as structures in memory
     * before being associated with the SSL. The application therefore still
     * has a reference to the private key and certificate which must be freed
     * now.
     */
    if (pkey != NULL)
    {
        SSLCERT_PKEY_free(pkey);
    }

    if (sslcert != NULL)
    {
        SSLCERT_free(sslcert);
    }

    if (rcert != NULL)
    {
        R_CERT_free(rcert);
    }

    if (rpkey != NULL)
    {
        R_PKEY_free(rpkey);
    }

    if (key_ctx != NULL)
    {
        R_PKEY_CTX_free(key_ctx);
    }

    if (cert_ctx != NULL)
    {
        R_CERT_CTX_free(cert_ctx);
    }

    /* Free the SSL library context */
    if (lib_ctx != NULL)
    {
        PRODUCT_LIBRARY_FREE(lib_ctx);
    }

    /* Free the BIOs for standard out and error */
    if (bio_out != NULL)
    {
        BIO_free(bio_out);
    }

    if (bio_err != NULL)
    {
        BIO_free(bio_err);
        bio_err = NULL;
    }

    return(R_ERROR_EXIT_CODE(ret));
}


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