| RSA BSAFE Micro Edition Suite |
Streamlined security for mobile and embedded devices |
 
![]() |
/* $Id: store.c,v 1.48 2005/08/08 05:33:32 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 char *store_usage[]={ "usage: store [options]\n", "where options are:\n", " -certs list - The List of certificates (colon separated)\n", #ifndef NO_WTLSCERT " -certenc encoding - Encode the certificates - one of X509 (default),", " WTLS\n", #else /* NO_WTLSCERT */ " -certenc encoding - Encode the certificates - one of X509 (default)\n", #endif /* !NO_WTLSCERT */ #ifdef NO_PEM " -certform format - The format of the certificates (BIN only)\n", #else " -certform format - The format of the certificates", " - one of BIN (default), PEM\n", #endif /* NO_PEM */ " -certtype type - The type of the certificate - one of CM, CVC or CA\n", " -certstatus status - The status of the certificates", " - one of TRUST, UNTRUST, CHAIN\n", " -lookup cert - The certificate to look up\n", #ifdef NO_PEM " -lookupform format - The format of the certificate (BIN only)\n", #else " -lookupform format - The format of the certificate", " - one of BIN (default), PEM\n", #endif /* NO_PEM */ " -lookuptype type - The type of the certificate to look up", " - one of CM, CVC or CA\n", " -lookupstatus status - The new status of the certificate to look up", " - one of TRUST,UNTRUST, CHAIN\n", #ifdef NO_SOFTWARE_CRYPTO " -no_fips140 - Use non FIPS140 crypto implementations\n", #endif /* NO_SOFTWARE_CRYPTO */ NULL }; int main(int argc, char **argv) { int ret = R_ERROR_NONE; R_RES_LIST *res_list; R_LIB_CTX *lib_ctx = NULL; R_CERT_STORE_CTX *ctx = NULL; R_CERT_CTX *cert_ctx = NULL; R_CERT_STORE *obj = NULL; R_CERT *cert = NULL, *lookup = NULL; R_PKEY *pubkey = NULL; R_CERT_NAME *name = NULL; BIO *bio_out = NULL; char *certfile, *lookupfile, *str; R_CERT_TYPE certenc; int certtype; R_FORMAT certform; int certstatus, lookuptype; R_FORMAT lookupform; int lookupstatus, state; /* Set the defaults */ certfile = NULL; lookupfile = NULL; certenc = R_CERT_TYPE_X509; certform = R_FORMAT_BINARY; certtype = R_CERT_STORE_ANY_CERTIFICATE; certstatus = R_CERT_STORE_STATE_TRUSTED_CERTIFICATE; lookupform = R_FORMAT_BINARY; lookuptype = R_CERT_STORE_ANY_CERTIFICATE; lookupstatus = R_CERT_STORE_STATE_TRUSTED_CERTIFICATE; res_list = PRODUCT_DEFAULT_RESOURCE_LIST(); /* * Create BIO to stdout. BIOs are the Basic Input/Output mechanism provided * by RSA and are recommended for all input and output from applications. */ bio_out = BIO_new_fp(stdout, BIO_NOCLOSE); if (bio_out == NULL) { ret = R_ERROR_ALLOC_FAILURE; goto end; } /* Parse the command line parameters */ /* Skip the program name */ argc--; argv++; /* Process all command line options */ while (argc >= 1) { if (Strcmp(*argv,"-certs") == 0) { if (--argc < 1) { goto bad; } certfile = *(++argv); } else if (Strcmp(*argv,"-certenc") == 0) { if (--argc < 1) { goto bad; } str = *(++argv); /* * Convert the certificate's encoding string to its integer value */ if ((ret = R_CERT_TYPE_from_string(str, &certenc)) != R_ERROR_NONE) { BIO_printf(bio_out, "Unknown encoding %s\n", str); goto bad; } } else if (Strcmp(*argv,"-certform") == 0) { if (--argc < 1) { goto bad; } str = *(++argv); /* Convert the certificate's format string to its integer value */ if ((ret = R_FORMAT_from_string(str, &certform)) != R_ERROR_NONE) { BIO_printf(bio_out, "Unknown format %s\n", str); goto bad; } } else if (Strcmp(*argv,"-certtype") == 0) { if (--argc < 1) { goto bad; } str = *(++argv); /* Convert the certificate's type string to its integer value */ if ((ret = R_CERT_STORE_cert_type_from_string(str, &certtype)) != R_ERROR_NONE) { BIO_printf(bio_out, "Unknown type %s\n", str); goto bad; } } else if (Strcmp(*argv,"-certstatus") == 0) { if (--argc < 1) { goto bad; } str = *(++argv); /* Convert the certificate's status string to its integer value */ if ((R_CERT_STORE_STATE_from_string(str, &certstatus)) != R_ERROR_NONE) { BIO_printf(bio_out, "Unknown status %s\n", str); goto bad; } } else if (Strcmp(*argv,"-lookup") == 0) { if (--argc < 1) { goto bad; } lookupfile = *(++argv); } else if (Strcmp(*argv,"-lookupform") == 0) { if (--argc < 1) { goto bad; } str = *(++argv); /* * Convert the lookup certificate's format string to its integer * value */ if ((ret = R_FORMAT_from_string(str, &lookupform)) != R_ERROR_NONE) { BIO_printf(bio_out, "Unknown format %s\n", str); goto bad; } } else if (Strcmp(*argv,"-lookuptype") == 0) { if (--argc < 1) { goto bad; } str = *(++argv); /* * Convert the lookup certificate's type string to its integer * value */ if ((ret = R_CERT_STORE_cert_type_from_string(str, &lookuptype)) != R_ERROR_NONE) { BIO_printf(bio_out, "Unknown type %s\n", str); goto bad; } } else if (Strcmp(*argv,"-lookupstatus") == 0) { if (--argc < 1) { goto bad; } str = *(++argv); /* * Convert the lookup certificate's status string to its integer * value */ if ((R_CERT_STORE_STATE_from_string(str, &lookupstatus)) != R_ERROR_NONE) { BIO_printf(bio_out, "Unknown status %s\n", str); goto bad; } } #ifdef NO_SOFTWARE_CRYPTO else if (Strcmp(*argv, "-no_fips140") == 0) { res_list = PRODUCT_NON_FIPS_140_MODE_RESOURCE_LIST(); } #endif /* NO_SOFTWARE_CRYPTO */ else { BIO_printf(bio_out, "Unknown option %s\n", *argv); goto bad; } argc--; argv++; } /* Perform simple checks first */ if ((certfile == NULL) || (lookupfile == NULL)) { BIO_printf(bio_out, "Both -certs and -lookup are required\n"); goto bad; } /* Display the help menu if an invalid command line option was entered */ if (0) { char **pp; bad: for (pp = store_usage; (*pp) != NULL; pp++) { BIO_printf(bio_out, *pp); } goto end; } /* * 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(res_list, R_RES_FLAG_DEF, &lib_ctx)) != R_ERROR_NONE) { BIO_printf(bio_out, "Library new failure\n"); goto end; } /* * Create a new certificate store context. The certificate store context * contains the repository that holds the certificates that are added to * the store. */ if ((ret = R_CERT_STORE_CTX_new(lib_ctx, R_RES_FLAG_DEF, &ctx)) != R_ERROR_NONE) { BIO_printf(bio_out, "Store context new failure\n"); goto end; } /* * Create a certificate context. All certificate operations require a * certificate context (#R_CERT_CTX). This context provides access to the * certificate functionality. */ if ((ret = R_CERT_CTX_new(lib_ctx, R_RES_FLAG_DEF, certenc, &cert_ctx)) != R_ERROR_NONE) { BIO_printf(bio_out, "Certificate context new failure\n"); goto end; } /* * Create a new store object. The store object can be used to interact with * the certificate store. For example, the store object is used to add * certificates to the store. */ if ((ret = R_CERT_STORE_new(ctx, &obj)) != R_ERROR_NONE) { BIO_printf(bio_out, "Store object new failure\n"); goto end; } /* * Process all certificates. The following loop reads in all the * certificates, sets their trust level and type, and adds them to the * store repository using the certificate store object created above. */ str = strtok(certfile, ":"); while (str != NULL) { /* Read the certificate from file */ if ((ret = R_CERT_read_file(cert_ctx, str, certenc, certform, &cert)) != R_ERROR_NONE) { BIO_printf(bio_out, "Certificate from file failure: %s\n", str); goto end; } /* Sets the certificate into the store object */ if ((ret = R_CERT_STORE_set_cert(obj, cert, NULL)) != R_ERROR_NONE) { BIO_printf(bio_out, "Add certificate failure\n"); goto end; } /* * The store object now owns the certificate and therefore the * application does not need to free it */ cert = NULL; /* Set the trust level of the certificate */ if ((ret = R_CERT_STORE_set_cert_state(obj, certstatus)) != R_ERROR_NONE) { BIO_printf(bio_out, "Set trust failure\n"); goto end; } /* Set the class of the certificate */ if ((ret = R_CERT_STORE_set_cert_class(obj, certtype)) != R_ERROR_NONE) { BIO_printf(bio_out, "Set class failure\n"); goto end; } /* Add the certificate into the store repository */ if ((ret = R_CERT_STORE_add(obj)) != R_ERROR_NONE) { BIO_printf(bio_out, "Add certificate failure\n"); goto end; } /* Initialize the store object for the next certificate */ if ((ret = R_CERT_STORE_init(obj)) != R_ERROR_NONE) { BIO_printf(bio_out, "Initializing store object failure\n"); goto end; } /* Retrieve the next file */ str = strtok(NULL, ":"); } /* Read the certificate to look up */ if ((ret = R_CERT_read_file(cert_ctx, lookupfile, certenc, lookupform, &lookup)) != R_ERROR_NONE) { BIO_printf(bio_out, "Certificate from file failure: %s\n", lookupfile); goto end; } /* * Search the store repository by issuer name. Extract the issuer name from * the certificate being searched for. */ BIO_printf(bio_out, "Finding certificate by issuer name..."); /* Access the issuer name in order to do the find operation */ ret = R_CERT_issuer_name_to_R_CERT_NAME(lookup, R_FLAG_SHARE_DATA, &name); if (ret == R_ERROR_NONE) { ret = R_CERT_STORE_find_entry_by_issuer(obj, name, lookuptype); } /* As the data is by reference, free the R_CERT_NAME structure */ R_CERT_NAME_free(name); name = NULL; if (ret == R_ERROR_NONE) { BIO_printf(bio_out, " found\n"); } else { BIO_printf(bio_out," not found\n"); } /* * Search the store repository by subject name. Extract the subject name * from the certificate being searched for. */ BIO_printf(bio_out, "Finding certificate by subject name..."); /* Access the subject name in order to do the find operation */ ret = R_CERT_subject_name_to_R_CERT_NAME(lookup, R_FLAG_SHARE_DATA, &name); if (ret == R_ERROR_NONE) { ret = R_CERT_STORE_find_entry_by_subject(obj, name, lookuptype); } /* As the data is by reference, free the R_CERT_NAME structure */ R_CERT_NAME_free(name); name = NULL; if (ret == R_ERROR_NONE) { BIO_printf(bio_out, " found\n"); } else { BIO_printf(bio_out, " not found\n"); } /* * Search the store repository by public key. Extract the public key from * the certificate being searched for. */ BIO_printf(bio_out, "Finding certificate by public key..."); /* Access the public key in order to do the find operation */ ret = R_CERT_public_key_to_R_PKEY(lookup, R_FLAG_SHARE_DATA, &pubkey); if (ret == R_ERROR_NONE) { ret = R_CERT_STORE_find_entry_by_pubkey(obj, pubkey, lookuptype); } if (ret == R_ERROR_NONE) { BIO_printf(bio_out, " found\n"); } else { BIO_printf(bio_out, " not found\n"); } /* * Change the state of a certificate in the store. This part of the sample * demonstrates how to manipulate the state of a certificate in the store * repository. This sample: * - Retrieves the state of the certificate that was found previously. * - Sets a new state for the certificate. * - Updates the new state for the certificate in the store repository. * - Retrieves the state of the certificate from the repository. * - Checks that the status has changed. */ BIO_printf(bio_out, "Retrieving the current state..."); if ((ret = R_CERT_STORE_get_cert_state(obj, &state)) != R_ERROR_NONE) { BIO_printf(bio_out, "\nRetrieve state failure\n"); goto end; } BIO_printf(bio_out, "found %d\n", state); /* Set a new state */ if ((ret = R_CERT_STORE_set_cert_state(obj, lookupstatus)) != R_ERROR_NONE) { BIO_printf(bio_out, "Set state failure\n"); goto end; } /* Update the new state into the store context */ if ((ret = R_CERT_STORE_update(obj)) != R_ERROR_NONE) { BIO_printf(bio_out, "Update failure\n"); goto end; } BIO_printf(bio_out, "Retrieving new state..."); /* * Retrieve the store object again from the context and check that * the state has changed */ if ((ret = R_CERT_STORE_find_entry_by_pubkey(obj, pubkey, lookuptype)) != R_ERROR_NONE) { BIO_printf(bio_out, "Failed to look up the certificate in store\n"); goto end; } /* Retrieve the state from the store and check it has been updated */ if ((ret = R_CERT_STORE_get_cert_state(obj, &state)) != R_ERROR_NONE) { BIO_printf(bio_out, "\nRetrieve state failure\n"); goto end; } BIO_printf(bio_out, "found %d\n", state); if (state != lookupstatus) { ret = R_ERROR_FAILED; BIO_printf(bio_out, "Failed to update store context state\n"); goto end; } /* * Delete the certificate object from the store context. Confirm that the * certificate was deleted by looking it up again and confirming that it * was not found. */ if ((ret = R_CERT_STORE_delete(obj)) != R_ERROR_NONE) { BIO_printf(bio_out,"Remove certificate failure\n"); goto end; } /* Attempt to retrieve the removed object from the store context */ ret = R_CERT_STORE_find_entry_by_pubkey(obj, pubkey, lookuptype); if (ret != R_ERROR_NOT_FOUND) { ret = R_ERROR_FAILED; BIO_printf(bio_out, "Failed to delete object from store context\n"); } else { ret = R_ERROR_NONE; } 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_out != NULL)) { BIO_printf(bio_out, "ERROR: (%d) %s\n", ret, R_LIB_CTX_get_error_string(lib_ctx, R_RES_MOD_ID_LIBRARY, ret)); } /* Clean up all objects and contexts */ if (pubkey != NULL) { R_PKEY_free(pubkey); } if (name != NULL) { R_CERT_NAME_free(name); } if (cert != NULL) { R_CERT_free(cert); } if (lookup != NULL) { R_CERT_free(lookup); } if (obj != NULL) { R_CERT_STORE_free(obj); } if (ctx != NULL) { R_CERT_STORE_CTX_free(ctx); } /* * The certificate context cannot be freed until the store has been emptied * as the certificates in the store hold a reference back to the * certificate context */ if (cert_ctx != NULL) { R_CERT_CTX_free(cert_ctx); } if (lib_ctx != NULL) { PRODUCT_LIBRARY_FREE(lib_ctx); } if (bio_out != NULL) { BIO_free(bio_out); } return(R_ERROR_EXIT_CODE(ret)); }