RSA BSAFE Micro Edition Suite

Streamlined security for mobile and embedded devices

Search  Print

Storing/Reading Certificates from Memory

This sample demonstrates how certificates can be stored in the application code itself, and then read from memory for use. The sample contains Privacy Enhanced Mail (PEM) certificate data in char * structures.

Sample Description:
-------------------
This sample shows how certificates can be stored in the 
application code itself, and then read from memory for use.
The sample contains PEM certificate data in char * 
structures.

Procedure:
----------
 1) Create the library context and BIOs.
 2) Create the certificate context.
 3) Read the certificate from memory BIO.
 4) Process the certificate.
 5) Clean up.


/* $Id: frombuf.c,v 1.33 2005/06/30 06:55:42 gsingh 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"
#ifndef NO_PEM
#include "r_passwd.h"

char *test_wtls_certificate[] =
{
    "-----BEGIN WTLS CERTIFICATE-----",
    "AQIBAAQGQyA9IEFVOG36jDpPgmwBAAQGQyA9IEFVAgAAAwEAAQBAvcooR53q6/Mg",
    "sqbHNtb7nXWHX5N53U2e3WhfPFuMMdtyZCMB9WxxUebOR3r1QzrsbY38+eTOgPg9",
    "oa3x+bKYJQBAU6OLA5BfD07DYkgylNk2lO6wznGGR/+25Br9kZSYXlXuiMAd9Qm1",
    "qEP/yJzl9cryA+fOd08IKkNPnCGztN5DoQ == ",
    "-----END WTLS CERTIFICATE-----"
};
#define N_test_wtls_certificate \
    (int)(sizeof(test_wtls_certificate)/sizeof(test_wtls_certificate[0]))

char *test_x509_certificate[] =
{
    "-----BEGIN CERTIFICATE-----",
    "MIIBiDCB8gIBADANBgkqhkiG9w0BAQQFADANMQswCQYDVQQGEwJBVTAeFw0wMTA1",
    "MDkwMTA1MTFaFw0wMTA2MDgwMTA1MTFaMA0xCzAJBgNVBAYTAkFVMIGfMA0GCSqG",
    "SIb3DQEBAQUAA4GNADCBiQKBgQDzPHX6E45JKbotHyLJHmkRY4mV/uzuvO8HucUm",
    "2wi3IrZ4Cpx/rLK78P9cizDZD2mH3pjASZAWgsGRJKvnGgiFTGg54FDppV1GFlee",
    "KLVSUVYuMFHt/n3jKjvLQ1GEDuFKpMeStTsskDbDQ7gKlsa6dc7dK7h+vIRfnFez",
    "c9g1/wIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAAyhL6kFrsxRO1mSAByeyTMkMesz",
    "r9cPPfwE1aTFa+nNTDVR4NWXN/ccrKi7+FO/Rged6hJB5Unk8L5be6u0/SToyeZa",
    "iY3amp48RgbMEbylRVUq5fsMKn3yKhfbzc567B/234ljaDQQU0ohA3FlpHc65CDw",
    "wYnfeslJ0MZyppqK",
    "-----END CERTIFICATE-----"
};

#define N_test_x509_certificate \
    (int)(sizeof(test_x509_certificate)/sizeof(test_x509_certificate[0]))

char *test_privatekey[] =
{
    "-----BEGIN RSA PRIVATE KEY-----",
    "MIIBOgIBAAJBAL3KKEed6uvzILKmxzbW+511h1+Ted1Nnt1oXzxbjDHbcmQjAfVs",
    "cVHmzkd69UM67G2N/PnkzoD4PaGt8fmymCUCAwEAAQJAbfmuzZEciA0ibWNnHMgG",
    "lX99Kkzy2OIZpILObNM/scNP/obP45hKPLp7T0ryzRTDdtEizRLJcCmHn4Cc0+YC",
    "AQIhAOhXx0iKwq6oBixUH/TReQpkxnB+nIPAdkkwCotbu/d1AiEA0R0xL2WJ5zGH",
    "z8czFI9CZD+KRlUQKYMQDwYaSN8yt/ECIFB7x66bUqEJ10mXwpId1d4B1rO1SCZj",
    "jxX/LEfl+RDZAiBwwkgCYcNRylCMhsKRhIptWiHquPWlHMos/8JupwRHUQIhANXY",
    "60ZidPu9cYtYba2+oydEj0BE77gMr3Buxxo+aLha",
    "-----END RSA PRIVATE KEY-----"
};
#define N_test_privatekey \
    (int)(sizeof(test_privatekey)/sizeof(test_privatekey[0]))

char *test_encrypted_privatekey[] =
{
    "-----BEGIN RSA PRIVATE KEY-----",
    "Proc-Type: 4,ENCRYPTED",
    "DEK-Info: DES-EDE3-CBC,1E533F0A0A00D90B",
    "",
    "p2asbIUd6CSAf+N87jxKc1/Cxvmv2u/SIJkdcQUGMntGKT02IRS97sxqqBntYr1m",
    "UW+9pJBmCLDPJTheO9X7gYJhr/QUVboo44KxO2XMhC4nBiao46MJ9uRG5H6WOMg1",
    "j0FwM9XZN/qUmZAxzZ3GGckw16XOUVUKgGLqb0H3y9+nGniuLSJLaE/FehUwJwFA",
    "BnTbS9YEzpY+NYal7MIGpUKxqKs6QdQY86zJZDoxPg4WRBQ2oMrx2Ux+qnyPkHju",
    "vz6urBFcBYoneYv+D8A22EEtF5RPiatMDOc5h3TlUPx0Mjn3beL5IkMWXHKPpqrb",
    "0N8P+ppwvgG8LrO7/hDii0RDvGdtDkgY+6bRDrKIqU3vqjgkGdqetolf2XxziFIC",
    "RCKOhIXmcmZTLKOGYi7KjPbhTQv1MsYSN2Bx/wzZ8JM=",
    "-----END RSA PRIVATE KEY-----"
};
#define N_test_encrypted_privatekey \
    (int)(sizeof(test_encrypted_privatekey)/sizeof(test_encrypted_privatekey[0]))

int passphrase_cb(char *buf, int len, char *prompt, int verify);
int print_cert_info(BIO *bio, R_CERT *cert);

/*
 * 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.
 * @return  0 indicates success.<br>
 *          1 indicates error.
 *
 * @note    If there was an error, the error value is displayed where possible.
 */
int main(int argc, char **argv)
{
    R_LIB_CTX  *lib_ctx       = NULL;
    R_CERT_CTX *wtls_cert_ctx = NULL;
    R_CERT_CTX *x509_cert_ctx = NULL;
    R_CERT     *wtls_cert     = NULL;
    R_CERT     *x509_cert     = NULL;
    R_PKEY_CTX *pkey_ctx      = NULL;
    R_PKEY     *pkey          = NULL;
    R_PKEY     *enc_pkey      = NULL;
    BIO        *bio_err       = NULL;
    BIO        *mem           = NULL;
    int         ret = R_ERROR_FAILED;
    int         i;

    /*
     * 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.
     */
    if ((ret = PRODUCT_LIBRARY_NEW(PRODUCT_NON_FIPS_140_MODE_RESOURCE_LIST(), 0,
        &lib_ctx)) != R_ERROR_NONE)
    {
        goto err;
    }

    /* Create a memory buffer BIO */
    if ((mem = BIO_new_mem()) == NULL)
    {
        ret = R_ERROR_ALLOC_FAILURE;
        goto err;
    }

#ifndef NO_WTLSCERT
    /*
     * Load and print a WTLS certificate from a buffer:
     *     - Create the specific certificate context.
     *     - Copy the certificate into the memory BIO.
     *     - Read the certificate from the memory BIO to a certificate object.
     *     - Print the certificate by writing it in text format.
     */

    /* Create a new WLTS certificate context */
    if ((ret = R_CERT_CTX_new(lib_ctx, R_RES_FLAG_DEF, R_CERT_TYPE_WTLS,
        &wtls_cert_ctx)) != R_ERROR_NONE)
    {
        goto err;
    }

    /* Print the certificate into the memory buffer BIO */
    for (i = 0; i < N_test_wtls_certificate; i++)
    {
        BIO_printf(mem, "%s\n", test_wtls_certificate[i]);
    }

    /* Load the certificate from the memory buffer */
    ret = R_CERT_read(wtls_cert_ctx, mem, R_CERT_TYPE_WTLS,
                R_FORMAT_PEM, &wtls_cert);

    /* Print the certificate */
    if ((ret == R_ERROR_NONE) && (wtls_cert != NULL))
    {
        R_CERT_write(wtls_cert, bio_err, R_FORMAT_TEXT, NULL);
    }
    else
    {
        BIO_printf(bio_err, "Failed to load the certificate - exiting\n");
        goto err;
    }

    /* Reuse the memory buffer BIO */
    BIO_reset(mem);
#endif /* NO_WTLSCERT */

#ifndef NO_X509CERT
    /*
     * Load and print an X.509 certificate from a buffer:
     *     - Create the specific certificate context.
     *     - Copy the certificate into the memory BIO.
     *     - Read the certificate from the memory BIO to a certificate object.
     *     - Print the certificate by writing it in text format.
     */

   /* Create a new X.509 certificate context */
    if ((ret = R_CERT_CTX_new(lib_ctx, R_RES_FLAG_DEF, R_CERT_TYPE_X509,
        &x509_cert_ctx)) != R_ERROR_NONE)
    {
        goto err;
    }

    /* Print the certificate into the memory buffer BIO */
    for (i = 0; i < N_test_x509_certificate; i++)
    {
        BIO_printf(mem, "%s\n", test_x509_certificate[i]);
    }

    /* Load the certificate from the memory buffer */
    ret = R_CERT_read(x509_cert_ctx, mem, R_CERT_TYPE_X509,
        R_FORMAT_PEM, &x509_cert);

    /* Print the certificate */
    if ((ret == R_ERROR_NONE) && (x509_cert != NULL))
    {
        R_CERT_write(x509_cert, bio_err, R_FORMAT_TEXT, NULL);
    }
    else
    {
        BIO_printf(bio_err, "Failed to load the certificate - exiting\n");
        goto err;
    }

    /* Reuse the memory buffer BIO */
    BIO_reset(mem);

#endif /* NO_X509CERT */

    /*
     * Load and print a private key from a buffer:
     *     - Create the key context.
     *     - Copy the key into the memory BIO.
     *     - Read the key from the memory BIO to a key object.
     *     - Print the key by writing it in text format.
     */

    /* Create a new key context */
    if ((ret = R_PKEY_CTX_new(lib_ctx, R_RES_FLAG_DEF, R_PKEY_TYPE_RSA,
        &pkey_ctx)) != R_ERROR_NONE)
    {
        goto err;
    }

    /* Print the private key into the memory buffer BIO */
    for (i = 0; i < N_test_privatekey; i++)
    {
        BIO_printf(mem, "%s\n", test_privatekey[i]);
    }

    /* Load the private key from the memory buffer */
    ret = R_PKEY_from_bio(mem, pkey_ctx, &pkey, R_PKEY_TYPE_RSA, R_FORMAT_PEM);

    /* Print the private key */
    if ((ret == R_ERROR_NONE) && (pkey != NULL))
    {
        BIO_printf(bio_err, "Read the private key\n");
        R_PKEY_print(bio_err, pkey, R_FORMAT_TEXT, NULL);
    }
    else
    {
        BIO_printf(bio_err, "Failed to load the private key - exiting\n");
        goto err;
    }

    /* Reuse the memory buffer BIO */
    BIO_reset(mem);

    /*
     * Load and print an encrypted private key from a buffer:
     *     - Use the existing key context.
     *     - Set up the password callback.
     *     - Copy the key into the memory BIO.
     *     - Read the key from the memory BIO to a key object.
     *     - Print the key by writing it in text format.
     */

    /* Print the encrypted private key into the memory buffer BIO */
    for (i = 0; i < N_test_encrypted_privatekey; i++)
    {
        BIO_printf(mem, "%s\n", test_encrypted_privatekey[i]);
    }

    /* Set the application-specific password callback function */
    R_passwd_set_cb(passphrase_cb);

    /* Load the encrypted private key from the memory buffer */
    ret = R_PKEY_from_bio(mem, pkey_ctx, &enc_pkey, R_PKEY_TYPE_RSA,
        R_FORMAT_PEM);

    /* Print the encrypted private key */
    if ((ret == R_ERROR_NONE) && (enc_pkey != NULL))
    {
        BIO_printf(bio_err, "Read the encrypted private key\n");
        R_PKEY_print(bio_err, enc_pkey, R_FORMAT_TEXT, NULL);
    }
    else
    {
        BIO_printf(bio_err, "Failed to load the encrypted private key - exiting\n");
        goto 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.
     */
err:

    if ((bio_err != NULL) && (ret != R_ERROR_NONE))
    {
        BIO_printf(bio_err, "Error: (%d) %s\n", ret,
            R_LIB_CTX_get_error_string(lib_ctx, R_RES_MOD_ID_LIBRARY, ret));
    }

    if (bio_err != NULL)
    {
        BIO_free(bio_err);
    }
    if (mem != NULL)
    {
        BIO_free(mem);
    }
    if (wtls_cert != NULL)
    {
        R_CERT_free(wtls_cert);
    }
    if (x509_cert != NULL)
    {
        R_CERT_free(x509_cert);
    }
    if (pkey != NULL)
    {
        R_PKEY_free(pkey);
    }
    if (enc_pkey != NULL)
    {
        R_PKEY_free(enc_pkey);
    }
    if (wtls_cert_ctx != NULL)
    {
        R_CERT_CTX_free(wtls_cert_ctx);
    }
    if (x509_cert_ctx != NULL)
    {
        R_CERT_CTX_free(x509_cert_ctx);
    }
    if (pkey_ctx != NULL)
    {
        R_PKEY_CTX_free(pkey_ctx);
    }

    if (lib_ctx != NULL)
    {
        PRODUCT_LIBRARY_FREE(lib_ctx);
    }

    return(R_ERROR_EXIT_CODE(ret));
}

/*
 * Provides a passphrase for decryption. In this case, a hard-coded passphrase
 * of "test1234" is used.
 *
 * @param  buf       [Out] The returned passphrase buffer.
 * @param  len       [In]  The size of the passphrase buffer.
 * @param  prompt    [In]  The unused prompt string.
 * @param  verify    [In]  The unused verify flag.
 *
 * @returns  R_ERROR_NONE indicates success.<br>
 *           See @ref R_ERROR_IDS for valid values.
 */
int passphrase_cb(char *buf, int len, char *prompt, int verify)
{
    char *passphrase = "test1234";
    int   passphrase_len;

    passphrase_len = Strlen(passphrase);

    /*
     * Check that there is sufficient space for the passphrase including a
     * NULL terminator in the buffer, otherwise truncate
     */
    if (passphrase_len > (len - 1))
    {
        passphrase_len = (len - 1);
    }

    Memcpy(buf, passphrase, passphrase_len + 1);

    return (R_ERROR_NONE);
}
#else /* !NO_PEM */
/*
 * Main sample program entry point when NO_PEM is defined.
 *
 * @param argc  [In]  The number of arguments typed on the command line.
 * @param argv  [In]  The array of individual arguments from the command line.
 * @return
 *          0 indicates success.<br>
 *          1 indicates error.
 *
 * @note    This sample if not useful if NO_PEM is defined.
 */
int main(int argc, char **argv)
{
    return (0);
}
#endif /* !NO_PEM */

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