| RSA BSAFE Micro Edition Suite |
Streamlined security for mobile and embedded devices |
 
![]() |
stdin), and outputs to a specified file (default stdout) in a specified format.
Sample Description: ------------------- This sample loads, processes and outputs the required data for certificates. Because the input and output format can be specified, this sample can be used to convert certificate format types. The program inputs the certificate from a specified file (default stdin), and outputs to specified file (default stdout) in a specified format. Procedure: ---------- 1) Create the BIOs. 2) Read and parse the command line options. 3) Create the library context. 4) Open the Input, Output and CA file (if specified). 5) Create a certificate context and load the input certificate. 6) Process the certificate and output data as required. 7) Clean up.
/* $Id: cert.c,v 1.74 2005/08/08 05:33:30 jlevander 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 int display_modulus(BIO *bio_err, BIO *out, R_CERT *cert); static int display_pkey_text(BIO *bio_err, BIO *out, R_CERT *cert); static int display_hash(BIO *bio_err, BIO *out, R_CERT *cert); static int verify_cert(BIO *bio_err, BIO *bio_out, R_CERT *ca_cert, R_CERT *cert); static int display_fingerprint(BIO *bio_err, BIO *out, R_CERT *cert); static int display_thumbprint(BIO *bio_err, BIO *out, R_CERT *cert, R_CR_ALG_ID thumbprint_alg); /* 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 */ " -CAfile arg - The Certification Authority (CA) certificate\n", #ifdef NO_PEM /* NO_PEM */ " -CAform arg - The CA certificate format (BIN only)\n", #else " -CAform arg - The CA certificate format - one of BIN PEM", " (default is PEM)\n", #endif /* NO_PEM */ #ifndef NO_WTLSCERT " -CAtype arg - The CA certificate type - one of WTLS X509 \n", " (default is X509)\n", #else /* NO_WTLSCERT */ " -CAtype arg - The CA certificate type - X509 \n", #endif /* !NO_WTLSCERT */ " -out arg - The output file (default stdout)\n", #ifdef NO_PEM " -outform arg - The output format (BIN only)\n", #else " -outform arg - The output format - one of BIN PEM", " (default is PEM)\n", #endif /* NO_PEM */ " -outformarg arg - The output format for BASE64 - one of 0,1,2 or 3\n", " 0=EOL_NONE, 1=EOL_CR, 2=EOL_LF, 3=EOL_CR|LF\n", " -noout - Indicates no output\n", " -text - The output text format\n", " -C - Print the certificate in C format for inclusion", " in\n", " other code\n", #ifndef NO_CFUNC " -Cf - Print a function in C that will return the\n", " specified certificate\n", #endif /* NO_CFUNC */ " -hex - Print the certificate in hexadecimal format\n", " -codehex - Print the certificate in code hexadecimal\n", " certificate\n", " -verify - Verify the certificate.\n", " Pass in the certificate to verify with -in and \n", " the CA certificate, used to verify with -CAfile\n", " -serial - Output the serial number value (X509 only)\n", " -issuer - Output the issuer name\n", " -notBefore - Output the time when the certificate becomes\n", " valid\n", " -notAfter - Output the time when the certificate expires\n", " -dates - Output both valid and expiry date\n", " -validity - Output the validity of the certificate\n", " -subject - Output the subject name\n", " -MID_subject - Output the subject name in Mobile Information\n" " Device (MID) format\n", " -modulus - Output the RSA key modulus\n", " -pkey_text - Output the public key as text\n", " -hash - Output a hash of the certificate\n", " -fingerprint - Output the fingerprint of a certificate\n", " -thumbprint - Output the thumbprint of a certificate\n", " -thumbprint_alg arg - Digest of the thumbprint - one of MD5 SHA1 \n", " (default is SHA1)\n", #ifdef NO_SOFTWARE_CRYPTO " -no_fips140 - Use non FIPS140 crypto implementations\n", #endif /* NO_SOFTWARE_CRYPTO */ " -eg - Example Usage\n", NULL }; static char *cert_example_usage[] = { "Print the certificate details in text form\n", "cert -in cert.in -text\n", "\n", "Print before/after dates, current validity and subject\n", "cert -in cert.in -validity -subject -dates -noout\n", "\n", #ifndef NO_PEM "Convert the certificate between formats (inform defaults to PEM)\n", "cert -in cert.in -out certin.bin -outform BIN\n", "\n", #endif "Verify the certificate - CA cert has public key needed to verify", " signature\n", "cert -in cert.in -CAfile ca.cert -verify -noout\n", "\n", "where: cert.in = The certificate to perform operations on\n", " certin.bin = The binary version of cert.in\n", " ca.cert = The certificate of CA that signed cert.in\n", "\n", NULL }; /* * Demonstrates how to use the most common operations performed on * certificates. * * @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 */ BIO *out = NULL; /* The BIO to write output to */ BIO *ca = NULL; /* The BIO from which to read the CA * certificate */ 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 */ char *outfile = NULL; /* The name of file to write to */ char *cafile = NULL; /* The name of CA certificate file from * which to read */ int cert_type; /* The type of certificate */ R_FORMAT cert_form; /* The format of certificate */ R_FORMAT out_cert_form; /* The format of output certificate */ int outform_arg; /* Type of output format for the output form*/ void *format_arg; /* Pointer to outform_arg */ int ca_type; /* The type of CA certificate */ R_FORMAT ca_form; /* The format of the CA certificate */ int noout = 0; /* Indicates that no output is generated */ R_CERT *cert = NULL; /* The certificate object */ R_CERT *ca_cert = NULL; /* The CA certificate object */ int do_text; /* The text version to display */ int do_c; /* The C version to display */ int do_cf; /* The C fields version to display */ int do_hex; /* The hexadecimal version to display */ int do_codehex; /* The code version in hexadecimal to * display */ int do_serial; /* Display the serial number */ int do_issuer; /* Display the issuer name */ int do_subject; /* Display the subject name */ int do_MID_subject; /* Display the subject name in MID (JSR 118) format */ int do_modulus; /* Display the modulus of the subject * public key */ int do_hash; /* Display a hash of the subject name */ int do_not_after; /* Display the notAfter time */ int do_not_before; /* Display the notBefore time */ int do_validity; /* Display the time validity of the * certificate */ int do_fingerprint; /* Display a fingerprint of the certificate */ int do_thumbprint; /* Display a thumbprint of the certificate */ int do_verify; /* Verify the signature */ int do_pkey_text; /* Display the public key as text */ R_CR_ALG_ID thumbprint_alg; /* The hashing algorithm to use in * thumbprint */ char *str; /* A character string */ R_CERT_CTX *cert_ctx = NULL; /* The certificate context */ /* Initialize to defaults */ cert_type = R_CERT_TYPE_X509; ca_type = R_CERT_TYPE_X509; #ifndef NO_PEM cert_form = R_FORMAT_PEM; ca_form = R_FORMAT_PEM; out_cert_form = R_FORMAT_PEM; #else /* !NO_PEM */ cert_form = R_FORMAT_BINARY; ca_form = R_FORMAT_BINARY; out_cert_form = R_FORMAT_BINARY; #endif /* !NO_PEM */ do_text = 0; do_c = 0; do_cf = 0; do_hex = 0; do_codehex = 0; do_verify = 0; do_serial = 0; do_issuer = 0; do_not_after = 0; do_not_before = 0; do_validity = 0; do_subject = 0; do_MID_subject = 0; do_modulus = 0; do_hash = 0; do_fingerprint = 0; do_thumbprint = 0; do_pkey_text = 0; thumbprint_alg = R_CR_ID_SHA1; format_arg = 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) { /* * 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 name of the Certification Authority (CA) certificate file * to read */ else if (Strcmp(*argv, "-CAfile") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } cafile = *argv; } /* The type of the CA certificate to read */ else if (Strcmp(*argv, "-CAtype") == 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, &ca_type)) != R_ERROR_NONE) { BIO_printf(bio_err, "Unknown certificate type: %s\n", str); goto bad; } } /* The format of the CA certificate to read */ else if (Strcmp(*argv, "-CAform") == 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, &ca_form)) != R_ERROR_NONE) { BIO_printf(bio_err, "Unknown certificate format: %s\n", str); goto bad; } } /* The format of the certificate to write */ else if ( (Strcmp(*argv, "-outform") == 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, &out_cert_form)) != R_ERROR_NONE) { BIO_printf(bio_err, "Unknown certificate format: %s\n", str); goto bad; } } /* The format argument of the certificate to write */ else if ( (Strcmp(*argv, "-outformarg") == 0) ) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } outform_arg = atoi(*argv); format_arg = &outform_arg; } /* The name of the output file */ else if (Strcmp(*argv, "-out") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } outfile = *argv; } /* The text version to display */ else if (Strcmp(*argv, "-text") == 0) { do_text = 1; } /* The C code version to display */ else if (Strcmp(*argv, "-C") == 0) { do_c = 1; } #ifndef NO_CFUNC /* The C code version in fields to display */ else if (Strcmp(*argv, "-Cf") == 0) { do_cf = 1; } #endif /* !NO_CFUNC */ /* The hexadecimal version to display */ else if (Strcmp(*argv, "-hex") == 0) { do_hex = 1; } /* The C code version in hexadecimal to display */ else if (Strcmp(*argv, "-codehex") == 0) { do_codehex = 1; } /* The verification signature */ else if (Strcmp(*argv, "-verify") == 0) { do_verify = 1; } /* The serial number to display */ else if (Strcmp(*argv, "-serial") == 0) { do_serial = 1; } /* The issuer name to display */ else if (Strcmp(*argv, "-issuer") == 0) { do_issuer = 1; } /* The notBefore time to display */ else if ((Strcmp(*argv, "-notBefore") == 0) || ((Strcmp(*argv, "-notbefore") == 0))) { do_not_before = 1; } /* The notAfter time to display */ else if ((Strcmp(*argv, "-notAfter") == 0) || ((Strcmp(*argv, "-notafter") == 0))) { do_not_after = 1; } /* The notBefore and notAfter dates to display */ else if (Strcmp(*argv, "-dates") == 0) { do_not_before = 1; do_not_after = 1; } /* The statement of time validity to display */ else if (Strcmp(*argv, "-validity") == 0) { do_validity = 1; } /* The subject name to display */ else if (Strcmp(*argv, "-subject") == 0) { do_subject = 1; } /* The subject name to display in MID format */ else if (Strcmp(*argv, "-MID_subject") == 0) { do_MID_subject = 1; } /* The modulus of the subject public key to display */ else if (Strcmp(*argv, "-modulus") == 0) { do_modulus = 1; } /* The subject public key to display as text */ else if (Strcmp(*argv, "-pkey_text") == 0) { do_pkey_text = 1; } /* The hash of the subject name to display */ else if (Strcmp(*argv, "-hash") == 0) { do_hash = 1; } /* The fingerprint of the certificate (MD5 hash) to display */ else if (Strcmp(*argv, "-fingerprint") == 0) { do_fingerprint = 1; } /* The thumbprint of the certificate (default: SHA1 hash) to display */ else if (Strcmp(*argv, "-thumbprint") == 0) { do_thumbprint = 1; } /* The hashing algorithm used when generating the thumbprint */ else if (Strcmp(*argv, "-thumbprint_alg") == 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_NID_DIGEST_from_string(str, &thumbprint_alg)) != R_ERROR_NONE) { BIO_printf(bio_err, "Unknown digest: %s\n", str); goto bad; } } /* Do not display the certificate on output BIO */ else if (Strcmp(*argv, "-noout") == 0) { noout = 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"); } /* Ensure verification is available, if applicable */ if ((do_verify == 1) && (cafile == NULL)) { badop = 1; BIO_printf(bio_err, "No CA file specified for verify\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; } /* Open the output file (or stdout if none) */ if (outfile != NULL) { out = BIO_new_file(outfile, "wb"); if (out == NULL) { ret = R_ERROR_ALLOC_FAILURE; BIO_printf(bio_err, "Unable to create the output file %s\n", outfile); goto end; } } else { out = bio_out; } /* * 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; } /* * Read the CA certificate into a new certificate object. The CA * certificate is optional. It is used to verify the signature * of the input certificate. */ if (cafile != NULL) { /* Open the file */ ca = BIO_new_file(cafile, "rb"); if (ca == NULL) { ret = R_ERROR_NOT_FOUND; BIO_printf(bio_err, "Unable to open the CA file %s\n", cafile); goto end; } /* Read the certificate from the stream */ ret = R_CERT_read(cert_ctx, ca, ca_type, ca_form, &ca_cert); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to load the CA certificate\n"); goto end; } } /* * Find and display the requested certificate information. If printing a * WTLS certificate, do not include the steps that retrieve the serial * number. Command line options indicate the various certificate fields to * extract or calculate, and display. This is commented for each subsection * below. */ /* Display the serial number */ if (do_serial) { R_ITEM item; ret = R_CERT_get_info(cert, R_CERT_INFO_SERIAL_NUMBER, &item); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to extract the serial number from the certificate\n"); goto end; } BIO_printf(out, "serial="); BIO_dump_format(out, item.data, item.len, BIO_DUMP_FORMAT_HEX, '\0', 0, 0); } /* Display the issuer name as a string */ if (do_issuer) { static char str[256]; /* The character string */ ret = R_CERT_issuer_name_to_string(cert, sizeof(str), str); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to extract the issuer name from the certificate\n"); goto end; } BIO_printf(out, "issuer=%s\n", str); } /* Display the notBefore time as a string */ if (do_not_before) { static char buf[R_CERT_TIME_STRING_LENGTH]; /* The time as a string */ ret = R_CERT_not_before_to_string(cert, R_CERT_TIME_STRING_LENGTH, buf); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to extract notBefore time from the certificate\n"); goto end; } BIO_printf(out, "notBefore: %s\n", buf); } /* Display the notAfter time as a string */ if (do_not_after) { static char buf[R_CERT_TIME_STRING_LENGTH]; /* The time as a string */ ret = R_CERT_not_after_to_string(cert, R_CERT_TIME_STRING_LENGTH, buf); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to extract the notAfter time from the certificate\n "); goto end; } BIO_printf(out, "Not After : %s\n", buf); } /* Display a statement of time validity */ if (do_validity) { int validity; /* The time validity indicator */ char *str; /* The character string */ ret = R_CERT_time_validity(cert, &validity); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to determine the time validity of the certificate\n"); goto end; } if (validity == R_CERT_TIME_CURRENT) { str = "Current"; } else if (validity == R_CERT_TIME_NOT_YET_CURRENT) { str = "Not yet current"; } else { str = "Expired"; } BIO_printf(out, "Certificate is %s\n", str); } /* Display the subject name as a string */ if (do_subject) { static char str[256]; /* The character string */ ret = R_CERT_subject_name_to_string(cert, sizeof(str), str); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to extract the subject name from the certificate\n"); goto end; } BIO_printf(out, "subject=%s\n", str); } /* Display the subject name as a string in MID format */ if (do_MID_subject) { static char str[256]; /* The character string */ R_CERT_NAME *subject_name; /* Ensure that the certificate type is X.509 */ if (cert_type != R_CERT_TYPE_X509) { BIO_printf(bio_err, "MID subject name format is only available for X.509 certificates\n"); goto end; } ret = R_CERT_subject_name_to_R_CERT_NAME(cert, R_FLAG_SHARE_DATA, &subject_name); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to extract the subject name from the certificate\n"); goto end; } ret = R_CERT_NAME_to_MID_string(subject_name, sizeof(str), str); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to output the subject name in MID format\n"); R_CERT_NAME_free(subject_name); goto end; } BIO_printf(out, "MID subject=%s\n", str); R_CERT_NAME_free(subject_name); } /* Display the modulus of the subject public key */ if (do_modulus) { if ((ret = display_modulus(bio_err, out, cert)) != R_ERROR_NONE) { goto end; } } /* Display the subject public key as text */ if (do_pkey_text) { if ((ret = display_pkey_text(bio_err, out, cert)) != R_ERROR_NONE) { goto end; } } /* Display the unique hash value of the subject name */ if (do_hash) { if ((ret = display_hash(bio_err, out, cert)) != R_ERROR_NONE) { goto end; } } /* Verify the signature of the certificate using the CA certificate */ if (do_verify) { if ((ret = verify_cert(bio_err, bio_out, ca_cert, cert)) != R_ERROR_NONE) { goto end; } } /* Display the certificate in text format */ if (do_text) { ret = R_CERT_write(cert, out, R_FORMAT_TEXT, NULL); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to print the text format of the certificate\n"); goto end; } } /* Display the certificate in C code format */ if (do_c) { ret = R_CERT_write(cert, out, R_FORMAT_CODE_FIELDS, NULL); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to print the code format of the certificate\n"); goto end; } } #ifndef NO_CFUNC /* Display the certificate in C code fields format */ if (do_cf) { ret = R_CERT_write(cert, out, R_FORMAT_CODE_BINARY, NULL); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to print the code fields format of the certificate\n"); goto end; } } #endif /* !NO_CFUNC */ /* Display the certificate in plain hexadecimal Bytes format */ if (do_hex) { ret = R_CERT_write(cert, out, R_FORMAT_HEX, NULL); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to display the hexadecimal format" " of the certificate\n"); goto end; } } /* Display the certificate in a C code data format */ if (do_codehex) { ret = R_CERT_write(cert, out, R_FORMAT_CODE_HEX, NULL); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to print the hexadecimal format of the certificate\n"); goto end; } } /* Calculate and display the fingerprint of the certificate */ if (do_fingerprint) { if ((ret = display_fingerprint(bio_err, out, cert)) != R_ERROR_NONE) { goto end; } } /* Calculate and display the thumbprint of the certificate */ if (do_thumbprint) { if ((ret = display_thumbprint(bio_err, out, cert, thumbprint_alg)) != R_ERROR_NONE) { goto end; } } /* Output the certificate unless explicitly told otherwise and if not in * binary format */ if ((noout == 0) && (out_cert_form != R_FORMAT_BINARY)) { ret = R_CERT_write(cert, out, out_cert_form, format_arg); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to write out the certificate\n"); goto end; } } 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)) { BIO_printf(bio_err, "Error: (%d) %s\n", ret, R_LIB_CTX_get_error_string(lib_ctx, R_RES_MOD_ID_LIBRARY, ret)); } if (cert != NULL) { R_CERT_free(cert); } if (ca_cert != NULL) { R_CERT_free(ca_cert); } if (cert_ctx != NULL) { R_CERT_CTX_free(cert_ctx); } if (in != NULL) { BIO_free(in); } if ((out != NULL) && (out!=bio_out)) { BIO_free(out); } if (ca != NULL) { BIO_free(ca); } if (lib_ctx != NULL) { PRODUCT_LIBRARY_FREE(lib_ctx); } if (bio_err != NULL) { BIO_free(bio_err); } if (bio_out != NULL) { BIO_free(bio_out); } return(R_ERROR_EXIT_CODE(ret)); } /* * Displays the public modulus of the RSA key from a supplied certificate. * * @param bio_err [In] The BIO for the error messages. * @param out [In] The output stream for the modulus data. * @param cert [In] The certificate containing the modulus to display. * * @returns R_ERROR_NONE indicates success. * See @ref R_ERROR_IDS for valid values. */ static int display_modulus(BIO *bio_err, BIO *out, R_CERT *cert) { int ret = R_ERROR_NONE; R_PKEY *pkey = NULL; /* The public key object */ R_ITEM item; /* An item of data */ unsigned char *p; /* A pointer into the item data */ int len; /* The length of the modulus data */ ret = R_CERT_public_key_to_R_PKEY(cert, R_FLAG_SHARE_DATA, &pkey); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to obtain the public key object from the certificate\n"); goto end; } ret = R_PKEY_get_info(pkey, R_PKEY_INFO_ID_RSA_MOD, (void *)&item); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to obtain public key object from the certificate\n"); goto end; } /* Remove the leading zeros */ p = item.data; len = item.len; while ((*p) == 0) { p++; len--; } BIO_printf(out, "Modulus="); BIO_dump_format(out, p, len, BIO_DUMP_FORMAT_HEX, '\0', 0, 0); end: if (pkey != NULL) { R_PKEY_free(pkey); } return(ret); } /* * Displays the public key information from a supplied certificate. * * @param bio_err [In] The BIO for the error messages. * @param out [In] The output stream for the public key data. * @param cert [In] The certificate containing the public key to display. * * @returns R_ERROR_NONE indicates success. * See @ref R_ERROR_IDS for valid values. */ static int display_pkey_text(BIO *bio_err, BIO *out, R_CERT *cert) { int ret = R_ERROR_NONE; R_PKEY *pkey = NULL; /* The public key object */ ret = R_CERT_public_key_to_R_PKEY(cert, R_FLAG_SHARE_DATA, &pkey); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to obtain the public key object from the certificate\n"); goto end; } ret = R_PKEY_print(out, pkey, R_FORMAT_TEXT, NULL); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to print public key object from the certificate\n"); goto end; } end: if (pkey != NULL) { R_PKEY_free(pkey); } return(ret); } /* * Displays the hash information from a supplied certificate. * * @param bio_err [In] The BIO for the error messages. * @param out [In] The output stream for the hash data. * @param cert [In] The certificate containing the hash to display. * * @returns R_ERROR_NONE indicates success. * See @ref R_ERROR_IDS for valid values. */ static int display_hash(BIO *bio_err, BIO *out, R_CERT *cert) { int ret = R_ERROR_NONE; R_CERT_NAME *subject = NULL; /* The subject name object */ unsigned long hash; /* The hash value */ ret = R_CERT_subject_name_to_R_CERT_NAME(cert, R_FLAG_SHARE_DATA, &subject); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to obtain subject name object from certificate\n"); goto end; } ret = R_CERT_NAME_get_info(subject, R_CERT_NAME_INFO_HASH, &hash); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to hash subject name object\n"); goto end; } BIO_printf(out, "%08lx\n", hash); end: if (subject != NULL) { /* The R_CERT_NAME data is referenced. Free the structure. */ R_CERT_NAME_free(subject); } return(ret); } /* * Verifies a certificate. * * @param bio_err [In] The BIO for the error messages. * @param out [In] The BIO for the information messages. * @param ca_cert [In] The CA certificate that issued the certificate * being verified. * @param cert [In] The certificate to verify. * * @returns R_ERROR_NONE indicates success. * See @ref R_ERROR_IDS for valid values. */ static int verify_cert(BIO *bio_err, BIO *bio_out, R_CERT *ca_cert, R_CERT *cert) { int ret = R_ERROR_NONE; int verified; /* The signature verification status */ R_PKEY *pkey = NULL; /* The public key object */ ret = R_CERT_public_key_to_R_PKEY(ca_cert, R_FLAG_SHARE_DATA, &pkey); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to extract public key from the CA certificate\n"); goto end; } if ((ret = R_CERT_verify(cert, pkey, &verified)) != R_ERROR_NONE) { BIO_printf(bio_err, "R_CERT_verify failure\n"); goto end; } if (!verified) { ret = R_ERROR_FAILED; BIO_printf(bio_out, "The certificate verification failed\n"); } else { BIO_printf(bio_out, "The certificate verification was successful\n"); } end: if (pkey != NULL) { R_PKEY_free(pkey); } return(ret); } /* * Displays the fingerprint information from a supplied certificate. * * @param bio_err [In] The BIO for the error messages. * @param out [In] The output stream for the fingerprint data. * @param cert [In] The certificate containing the fingerprint to display. * * @returns R_ERROR_NONE indicates success. * See @ref R_ERROR_IDS for valid values. */ static int display_fingerprint(BIO *bio_err, BIO *out, R_CERT *cert) { int ret = R_ERROR_NONE; unsigned char *buf = NULL; /* The data buffer */ unsigned int blen; /* The length of the data buffer */ int i; /* The iterator over Bytes in the data * buffer */ R_CERT_fingerprint(cert, R_CR_ID_MD5, 0, NULL, &blen); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to calculate length of the fingerprint of the" " certificate\n"); goto end; } if ((buf = (unsigned char *)Malloc(blen)) == NULL) { BIO_printf(bio_err, "Unable to allocate memory for the fingerprint result\n"); ret = R_ERROR_ALLOC_FAILURE; goto end; } ret = R_CERT_fingerprint(cert, R_CR_ID_MD5, blen, buf, &blen); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to calculate the fingerprint of the certificate\n"); goto end; } BIO_printf(out, "MD5 fingerprint="); for (i = 0; i < (int)(blen); i++) { BIO_printf(out, "%02X%c", buf[i], (i+1 == (int)(blen))?('\n'):(':')); } end: if (buf != NULL) { Free(buf); } return(ret); } /* * Calculates the thumbprint information from a supplied certificate. * * @param bio_err [In] The BIO for the error messages. * @param out [In] The output stream for the thumbprint data. * @param cert [In] The certificate containing the thumbprint * to display. * @param thumbprint_alg [In] The thumbprint algorithm to use. * * @returns R_ERROR_NONE indicates success. * See @ref R_ERROR_IDS for valid values. */ static int display_thumbprint(BIO *bio_err, BIO *out, R_CERT *cert, R_CR_ALG_ID thumbprint_alg) { int ret = R_ERROR_NONE; unsigned char *buf = NULL; /* The data buffer */ unsigned int blen; /* The length of the data buffer */ int i; /* The iterator over Bytes in the data * buffer */ char *s[10]; ret = R_CERT_fingerprint(cert, thumbprint_alg, 0, NULL, &blen); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to calculate the length of the thumbprint of the" " certificate\n"); goto end; } if ((buf = (unsigned char *)Malloc(blen)) == NULL) { BIO_printf(bio_err, "Unable to allocate memory for the fingerprint result\n"); ret = R_ERROR_ALLOC_FAILURE; goto end; } ret = R_CERT_fingerprint(cert, thumbprint_alg, blen, buf, &blen); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to calculate the thumbprint of the certificate\n"); goto end; } if ((ret = R_NID_DIGEST_to_string(thumbprint_alg, sizeof(s), (char *)s)) != R_ERROR_NONE) { goto end; } BIO_printf(out, "Thumbprint Algorithm=%s", s); BIO_printf(out, "\nThumbprint="); for (i = 0; i < (int)(blen); i += 2) { BIO_printf(out, "%02X%02X%c", buf[i], buf[i+1], (i+2 == (int)(blen))?('\n'):(' ')); } end: if (buf != NULL) { Free(buf); } return(ret); }