| RSA BSAFE Micro Edition Suite |
Streamlined security for mobile and embedded devices |
 
![]() |
/* $Id: s_crl_verify.c,v 1.18 2005/03/28 00:29:41 hfrancis Exp $ */ /* * Copyright (C) 1998-2005 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. * */ /* * For example, to: * * Verify a basic CRL: * s_crl_verify -in crl.pem -cert ca_cert.pem * * Verify a Basic Encoding Rule (BER)-encoded CRL: * s_crl_verify -in crl.ber -inform BIN -cert ca_cert.ber -certform BIN */ #include "r_prod.h" #include "s_crl_shr.h" #define MAX_BUF_SIZE 256 static char *crl_verify_usage[] = { "usage: crl_verify [options]\n", "where options are:\n", " -in crl - The input Certificate Revocation List (CRL)\n", " -inform encoding - Encoding of the CRL one of BIN (default)\n", " -cert - The issuer certificate to verify with\n", " -certform - Certificate encoding - one of BIN (default), PEM\n", " -certtype - The certificate type - X.509 (default)\n", " -no_fips140 - Do not use FIPS 140 crypto resources\n", " -help - Print this menu\n", NULL }; int main(int argc, char **argv) { int ret = R_ERROR_FAILED; int result = 1; R_LIB_CTX *lib_ctx = NULL; SSLCERT *cert = NULL; R_CRL *crl = NULL; BIO *bio_out = NULL; BIO *bio_err = NULL; char *infile = NULL; char *certfile = NULL; char *str = NULL; unsigned char *binary_buffer = NULL; unsigned char *temp_buffer = NULL; unsigned int buffer_length; R_FORMAT inform = R_FORMAT_BINARY; R_FORMAT certform = R_FORMAT_BINARY; SSLCERT_NAME *name = NULL; SSLCERT_NAME *cert_subject_name = NULL; char buf[MAX_BUF_SIZE]; R_ITEM item; int mode = R_LIB_CTX_FIPS140_MODE; /* Create an output channel */ if ((bio_err = BIO_new_fp(stderr, BIO_NOCLOSE)) == NULL) { goto end; } BIO_set_flags(bio_err, BIO_FLAGS_FLUSH_ON_WRITE); /* Create an output channel */ if ((bio_out = BIO_new_fp(stdout, BIO_NOCLOSE)) == NULL) { goto end; } BIO_set_flags(bio_out, BIO_FLAGS_FLUSH_ON_WRITE); /* Skip the program name */ argc--; argv++; /* Process all command line options */ while (argc >= 1) { if (Strcmp(*argv, "-in") == 0) { if (--argc < 1) { goto bad; } infile = *(++argv); } else if (Strcmp(*argv, "-inform") == 0) { if (--argc < 1) { goto bad; } str = *(++argv); if (R_FORMAT_from_string(str, &inform) != R_ERROR_NONE) { BIO_printf(bio_err, "Unknown input format %s\n", str); goto bad; } } else if (Strcmp(*argv, "-cert") == 0) { if (--argc < 1) { goto bad; } certfile = *(++argv); } else if (Strcmp(*argv, "-certform") == 0) { if (--argc < 1) { goto bad; } str = *(++argv); if (R_FORMAT_from_string(str, &certform) != R_ERROR_NONE) { BIO_printf(bio_err, "Unknown certificate format %s\n", str); goto bad; } } else if (Strcmp(*argv, "-certtype") == 0) { if (--argc < 1) { goto bad; } str = *(++argv); if (Strcmp(str, "X509") != 0) { BIO_printf(bio_err, "Unknown certificate type %s\n", str); goto bad; } } else if (Strcmp(*argv, "-no_fips140") == 0) { mode = R_LIB_CTX_STANDARD_MODE; } else if (Strcmp(*argv, "-help") == 0) { goto bad; } else { BIO_printf(bio_err, "Unknown option %s\n", *argv); goto bad; } argc--; argv++; } /* Simple checks first */ if (infile == NULL) { BIO_printf(bio_err, "Input file required\n"); goto bad; } if (certfile == NULL) { BIO_printf(bio_err, "Issuer certificate required\n"); goto bad; } /* Display the help menu if an invalid command line option was entered */ if (0) { char **pp; bad: for (pp = crl_verify_usage; (*pp) != NULL; pp++) { BIO_printf(bio_err, *pp); } goto end; } /* * Create the library context. Retrieve the default (or non-FIPS 140) * resource list and create a library context providing access to all * configurable aspects of the library. */ if (PRODUCT_LIBRARY_NEW(PRODUCT_DEFAULT_RESOURCE_LIST(), R_RES_FLAG_DEF, &lib_ctx) != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to create library context\n"); goto end; } /* * Set the mode of operation of the library. * * Note this is only applicable to libraries that support FIPS/non-FIPS * modes of operations. */ (void)R_LIB_CTX_set_info(lib_ctx, R_LIB_CTX_INFO_ID_MODE, &mode); /* Read the CRL and parse into an R_CRL object for processing */ if (R_CRL_read_file(lib_ctx, infile, inform, NULL, &crl) != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to read CRL from file\n"); goto end; } /* Read the Certification Authority (CA) certificate */ if (load_file_to_buffer(certfile, &binary_buffer, &buffer_length) != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to read certificate data from file\n"); goto end; } /* * Take a copy of binary_buffer as the following call progresses * the pointer */ temp_buffer = binary_buffer; if ((cert = SSLCERT_from_binary(NULL, &temp_buffer, buffer_length)) == NULL) { BIO_printf(bio_err, "Unable to parse certificate data\n"); goto end; } /* * Verify that the CRL issuer and CA certificate subject are the same. * Note that this step is included to show the use of some CRL APIs in a * typical case. The functionality of this step is part of * R_CRL_verify(). */ if ((cert_subject_name = SSLCERT_get_subject_name(cert))== NULL) { BIO_printf(bio_err, "Unable to get certificate subject name\n"); goto end; } if (SSLCERT_NAME_oneline(cert_subject_name, buf, sizeof(buf)) != NULL) { BIO_printf(bio_out, "Certificate subject: %s\n", buf); } else { BIO_printf(bio_err, "Unable to generate certificate name oneline\n"); goto end; } /* Retrieve the CRL issuer */ if (R_CRL_get_info(crl, R_CRL_INFO_ISSUER, &item) == R_ERROR_NONE) { if (SSLCERT_NAME_from_binary(&name, &item.data, item.len) != NULL) { if (SSLCERT_NAME_oneline(name, buf, sizeof(buf)) != NULL) { BIO_printf(bio_out, "CRL issuer: %s\n", buf); } } } /* Compare the CRL issuer name and the certificate subject name */ if (SSLCERT_NAME_cmp(name, cert_subject_name) == 0) { BIO_printf(bio_out, "The CRL issuer and certificate subject are the same.\n"); } else { ret = R_ERROR_FAILED; BIO_printf(bio_err, "The CRL issuer and certificate subject do not match.\n"); goto end; } /* * Verify the signature of the CRL. The signature of the CRL was created * with the CA's private key, and verified with the CA's public key * (obtained from the CA's certificate). All the CRL data and signature is * stored in the R_CRL object that is passed to R_CRL_verify(). */ BIO_printf(bio_out, "Verify the Certificate Revocation List (CRL) signature\n"); if (R_CRL_SSLCERT_verify(crl, cert, &result) != R_ERROR_NONE) { BIO_printf(bio_err, "R_CRL_SSLCERT_verify failed\n"); goto end; } if (result == 0) { BIO_printf(bio_out, "CRL verification PASSED\n"); } else { BIO_printf(bio_out, "CRL verification FAILED\n"); } ret = R_ERROR_NONE; end: /* * Clean up. Report the error number if there is an output stream. * Destroy dynamically allocated objects and return an exit code. */ if ((bio_err != NULL) && (ret != R_ERROR_NONE)) { BIO_printf(bio_err, "ERROR: (%d) \n", ret); } /* Clean up all objects and contexts */ if (name != NULL) { SSLCERT_NAME_free(name); } if (cert != NULL) { SSLCERT_free(cert); } if (binary_buffer != NULL) { Free(binary_buffer); } if (crl != NULL) { R_CRL_free(crl); } if (lib_ctx != NULL) { PRODUCT_LIBRARY_FREE(lib_ctx); } if (bio_out != NULL) { BIO_free(bio_out); } if (bio_err != NULL) { BIO_free(bio_err); } return(R_ERROR_EXIT_CODE(ret)); }