| RSA BSAFE Micro Edition Suite |
Streamlined security for mobile and embedded devices |
 
![]() |
/* $Id: ext.c,v 1.1.2.3 2005/10/27 01:19:25 sparki 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" /* Usage statement for this program */ static char *cert_usage[] = { "usage: cert [options]\n", "where options are:\n", " -in arg - The input certificate file\n", #ifdef NO_PEM " -inform arg - The input format (BIN only)\n", #else " -inform arg - The input format - one of BIN PEM", " (default is PEM)\n", #endif /* NO_PEM */ #ifndef NO_WTLSCERT " -intype arg - The input type - one of WTLS X509 \n", " (default is X509)\n", #else /* NO_WTLSCERT */ " -intype arg - The input type - X509 \n", #endif /* !NO_WTLSCERT */ " -hex - Print the certificate extensions in hexadecimal " "format\n", " -validity - Output the validity of the certificate's " "extensions\n", " -key_usage - Output the key usage of the certificate\n", " -ext_key_usage - Output the extended key usage of the " "certificate\n", " -aia - Output the authority information access of the " "certificate\n", " -oid - Retrieve extension by OID and print value\n", #ifdef NO_SOFTWARE_CRYPTO " -no_fips140 - Use non FIPS140 crypto implementations\n", #endif /* NO_SOFTWARE_CRYPTO */ " -eg - Example Usage\n", NULL }; /* Example usages statement for this program */ static char *cert_example_usage[] = { "Print the certificate extensions in hexadecimal form\n", "ext -in cert.in -hex\n", "\n", "Print the key usage extension and extended key usage extension\n", "ext -in cert.in -key_usage -ext_key_usage\n", "\n", "Retrieve an extension by OID and print the value\n", "ext -int cert.in -oid 6086480186f842010d\n", "\n", "Validate the certificate's extensions\n", "ext -in cert.in -validate\n", "\n", "where: cert.in = The certificate upon which to perform operations\n", "\n", NULL }; /* * Demonstrates how to use the most common operations performed on * certificate extensions. * * @param argc [In] The number of command line arguments. * @param argv [In] An array of command line argument strings. * * @returns R_ERROR_NONE indicates success.<br> * See @ref R_ERROR_IDS for valid values. * * @note If an error occurs, the error value is displayed where possible. */ int main(int argc, char **argv) { int ret = R_ERROR_NONE; /* The return value */ BIO *bio_out = NULL; /* The BIO that represents stdout */ BIO *bio_err; /* The BIO that represents stderr */ BIO *in = NULL; /* The BIO to read from for input */ R_RES_LIST *res_list; /* The resource list */ R_LIB_CTX *lib_ctx = NULL; /* The library context */ int badop = 0; /* Indicates a bad option on the command * line */ char *infile = NULL; /* The name of the file from which to read */ int cert_type; /* The type of certificate */ R_FORMAT cert_form; /* The format of certificate */ R_CERT *cert = NULL; /* The certificate object */ int do_hex; /* The hexadecimal version to display */ int do_validity; /* Display the validity of the certificate * extensions */ int do_key_usage; /* Display the key usage of the certificate */ int do_ext_key_usage; /* Display the extended key usage of the * certificate */ int do_aia; /* Display the authority information access of * the certificate */ int do_oid; /* Retrieve an extension by OID and display * the value */ R_ITEM oid; /* OID data and length */ char *str; /* A character string */ R_CERT_CTX *cert_ctx = NULL; /* The certificate context */ R_TITEM titem; /* An item of data with a type */ R_ITEM item; /* An item of data with length */ R_EXT *ext = NULL; /* An extension object */ /* Initialize to defaults */ cert_type = R_CERT_TYPE_X509; #ifndef NO_PEM cert_form = R_FORMAT_PEM; #else /* !NO_PEM */ cert_form = R_FORMAT_BINARY; #endif /* !NO_PEM */ do_hex = 0; do_validity = 0; do_key_usage = 0; do_ext_key_usage = 0; do_aia = 0; do_oid = 0; oid.data = NULL; res_list = PRODUCT_DEFAULT_RESOURCE_LIST(); /* * Create BIOs to stderr and stdout. 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 end; } if ((bio_out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL) { ret = R_ERROR_ALLOC_FAILURE; goto end; } /* Parse the command line parameters */ /* Skip over the program name command line argument */ argc--; argv++; /* Check to ensure there are command line arguments supplied */ if (argc < 1) { goto bad; } /* Process the command line arguments */ while (argc >= 1) { /* The name of the input file */ if ((Strcmp(*argv, "-in") == 0) || (Strcmp(*argv, "-cert") == 0)) { /* * Obtain the next argument if it does not start with a dash. * A dash is probably another option. */ if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } infile = *argv; } /* The type of certificate that will be read in */ else if ((Strcmp(*argv, "-certtype") == 0) || (Strcmp(*argv, "-intype") == 0)) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } str = *argv; /* * Convert the string to a value. If the string is not recognized * (UNKNOWN) then report an error. */ if ((ret = R_CERT_TYPE_from_string(str, &cert_type)) != R_ERROR_NONE) { BIO_printf(bio_err, "Unknown certificate type: %s\n", str); goto bad; } } /* The format of the certificate that will be read in */ else if ((Strcmp(*argv, "-certform") == 0) || (Strcmp(*argv, "-inform") == 0) ) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } str = *argv; /* * Convert the string to a value. If the string is not recognized * (UNKNOWN) then report an error. */ if ((ret = R_FORMAT_from_string(str, &cert_form)) != R_ERROR_NONE) { BIO_printf(bio_err, "Unknown certificate format: %s\n", str); goto bad; } } /* The hexadecimal version to display */ else if (Strcmp(*argv, "-hex") == 0) { do_hex = 1; } /* The validity of the certificate's extensions to display */ else if (Strcmp(*argv, "-validity") == 0) { do_validity = 1; } /* The key usage to display */ else if (Strcmp(*argv, "-key_usage") == 0) { do_key_usage = 1; } /* The extended key usage to display */ else if (Strcmp(*argv, "-ext_key_usage") == 0) { do_ext_key_usage = 1; } /* The authority information access to display */ else if (Strcmp(*argv, "-aia") == 0) { do_aia = 1; } /* The OID to look up an extension with */ else if (Strcmp(*argv, "-oid") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } str = *argv; /* Ensure there an even number of digits in the OID */ if ((Strlen(str) & 1) != 0) { BIO_printf(bio_err, "Bad OID data: %s", str); goto bad; } /* Calculate the length of the OID and allocate space for it */ oid.len = Strlen(str) / 2; oid.data = (unsigned char *)Malloc(oid.len); if (oid.data == NULL) { ret = R_ERROR_ALLOC_FAILURE; BIO_printf(bio_err, "Unable to allocate memory: %d\n", oid.len); goto end; } ret = R_hexstr_to_bin(str, Strlen(str), oid.data); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Bad OID data: %s", str); goto bad; } do_oid = 1; } #ifdef NO_SOFTWARE_CRYPTO else if (Strcmp(*argv, "-no_fips140") == 0) { res_list = PRODUCT_NON_FIPS_140_MODE_RESOURCE_LIST(); } #endif /* NO_SOFTWARE_CRYPTO */ /* The usage information to display */ else if (Strcmp(*argv, "-help") == 0) { goto bad; } else if (Strcmp(*argv,"-eg") == 0) { char **egp; for (egp = cert_example_usage; (*egp) != NULL; egp++) { BIO_printf(bio_out, *egp); } goto end; } /* The option on the command line was not recognized */ else { BIO_printf(bio_err, "unknown option %s\n", *argv); badop = 1; break; } /* Move onto the next command line argument */ argc--; argv++; } /* Ensure a certificate is available for processing */ if (infile == NULL) { badop = 1; BIO_printf(bio_err, "No certificate supplied (-in option)\n"); } /* Enter the usage if there was a bad option */ if (badop) { char **pp; bad: ; for (pp = cert_usage; (*pp != NULL); pp++) { BIO_printf(bio_err, *pp); } goto end; } /* * Create the library context to provide access to all configurable aspects * of the library. */ if ((ret = PRODUCT_LIBRARY_NEW(res_list, 0, &lib_ctx)) != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to create the library context\n"); goto end; } /* * Create a certificate context. All certificate operations require a * certificate context, which provides access to the certificate * functionality. */ ret = R_CERT_CTX_new(lib_ctx, R_RES_FLAG_DEF, cert_type, &cert_ctx); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "The new certificate context failed\n"); goto end; } /* * Read the certificate into a new certificate object that stores all the * certificate information. */ /* Open the input file - this is the certificate file */ if ((in = BIO_new_file(infile, "rb")) == NULL) { ret = R_ERROR_NOT_FOUND; BIO_printf(bio_err, "Unable to open the input file %s\n", infile); goto end; } /* Read the certificate into a certificate object */ ret = R_CERT_read(cert_ctx, in, cert_type, cert_form, &cert); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to load the certificate\n"); goto end; } /* Display the validity of the certificate's extensions */ if (do_validity) { /* Check that all critical extensions are recognized */ ret = R_CERT_check(cert, R_CERT_CHECK_FLAG_EXTENSIONS); if (ret != R_ERROR_NONE) { BIO_printf(bio_out, "Certificate's extensions are not valid\n"); } else { BIO_printf(bio_out, "Certificate's extensions are valid\n"); } } /* Display the key usage as a string */ if (do_key_usage) { static char str[256]; /* The character string */ /* Get a string representing the key usage */ ret = R_CERT_key_usage_to_string(cert, NULL, sizeof(str), str); if (ret == R_ERROR_NOT_FOUND) { BIO_printf(bio_out, "No Key Usage extension in certificate\n"); ret = R_ERROR_NONE; } else if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to extract the key usage from the certificate\n"); goto end; } else { BIO_printf(bio_out, "Key Usage = %s\n", str); } } /* Display the extended key usage as a string */ if (do_ext_key_usage) { static char str[256]; /* The character string */ /* Get a string representing the extended key usage */ ret = R_CERT_extended_key_usage_to_string(cert, NULL, sizeof(str), str); if (ret == R_ERROR_NOT_FOUND) { BIO_printf(bio_out, "No Extended Key Usage extension in " "certificate\n"); ret = R_ERROR_NONE; } else if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to extract the key usage from the certificate\n"); goto end; } else { BIO_printf(bio_out, "Extended Key Usage = %s\n", str); } } /* Display the extended key usage as a string */ if (do_aia) { static char str[256]; /* The character string */ /* Get a string representing the authority information access */ ret = R_CERT_authority_info_access_to_string(cert, "\n ", sizeof(str), str); if (ret == R_ERROR_NOT_FOUND) { BIO_printf(bio_out, "No Authority Info Access extension in " "certificate\n"); ret = R_ERROR_NONE; } else if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to extract the authority information access from the " "certificate\n"); goto end; } else { BIO_printf(bio_out, "Authority Info Access:\n %s\n", str); } } /* Retrieve an extension by OID and print the value */ if (do_oid) { /* Display the OID that will be used */ BIO_printf(bio_out, "OID: "); BIO_dump_format(bio_out, oid.data, oid.len, BIO_DUMP_FORMAT_HEX, ':', 0, 16); /* Create a new extension object */ ret = R_EXT_new(lib_ctx, R_RES_FLAG_DEF, &ext); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to create a new extension object\n"); goto end; } /* Set the OID data into the extension */ ret = R_EXT_set_info(ext, R_EXT_INFO_OID, &oid); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to set OID data into extension\n"); goto end; } /* Search for an extension with the OID that has been set */ ret = R_CERT_get_info(cert, R_CERT_INFO_EXTENSION_BY_OID, ext); if (ret == R_ERROR_NOT_FOUND) { BIO_printf(bio_out, "Unable to find extension in certificate\n"); ret = R_ERROR_NONE; } else if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to get extension by OID\n"); goto end; } /* Get the data for the extenstion */ ret = R_EXT_get_info(ext, R_EXT_INFO_DATA, &item); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to get OID data from extension\n"); goto end; } /* Dump out the extension data as hexadecimal bytes. */ BIO_dump_format(bio_out, item.data, item.len, BIO_DUMP_FORMAT_HEX, ':', 4, 16); } /* Display the certificate extensions in plain hexadecimal Bytes format */ if (do_hex) { /* Get the raw extension bytes */ ret = R_CERT_get_info(cert, R_CERT_INFO_EXTENSIONS, &titem); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to display the hexadecimal format" " of the certificate extensions\n"); goto end; } /* Dump out the extension data in hexadecimal format */ BIO_printf(bio_out, "Extensions in hexadecimal format:\n"); BIO_dump_format(bio_out, titem.data, titem.len, BIO_DUMP_FORMAT_HEX, ':', 4, 16); } end: /* * 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)) { if (lib_ctx != NULL) { BIO_printf(bio_err, "Error: (%d) %s\n", ret, R_LIB_CTX_get_error_string(lib_ctx, R_RES_MOD_ID_LIBRARY, ret)); } else { BIO_printf(bio_err, "Error: %d\n", ret); } } if (ext != NULL) { R_EXT_free(ext); } if (cert != NULL) { R_CERT_free(cert); } if (cert_ctx != NULL) { R_CERT_CTX_free(cert_ctx); } if (in != NULL) { BIO_free(in); } if (lib_ctx != NULL) { PRODUCT_LIBRARY_FREE(lib_ctx); } if (oid.data != NULL) { Free(oid.data); } if (bio_err != NULL) { BIO_free(bio_err); } if (bio_out != NULL) { BIO_free(bio_out); } return(R_ERROR_EXIT_CODE(ret)); }