| RSA BSAFE Micro Edition Suite |
Streamlined security for mobile and embedded devices |
 
![]() |
/* $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); }