| RSA BSAFE Micro Edition Suite |
Streamlined security for mobile and embedded devices |
 
![]() |
/* $Id: reqgen.c,v 1.63 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" /* The callback function called when the public key operation surrenders */ static int kg_surrender(R_SURRENDER * ctx, int p, int n); /* The function to create a subject name string */ static int get_subject_name_string(BIO *bio_err, unsigned int max_str_len, char *str, int no_in); /* The size of the issuer name string to hold the user input */ #define NAME_STR_LEN 512 /* The length of the input string for reading in a name entry value */ #define NAME_INPUT_STR_LENGTH 80 /* The number of items in the name to be created from user input */ #define NAME_REQ_NUM 5 /* * The mapping of long name version strings of the name item identifier to * the default value */ static char *name_req[NAME_REQ_NUM*3] = { LN_commonName, SN_commonName, "User One", LN_organizationName, SN_organizationName, "RSA Security", LN_localityName, SN_localityName, "Brisbane", LN_stateOrProvinceName, SN_stateOrProvinceName, "Qld", LN_countryName, SN_countryName, "AU", }; /* The usage help message */ static char *reqgen_usage[] = { "usage: reqgen [options]\n", "where options are:\n", " -out arg - The certificate request file name to write\n", #ifndef NO_PEM " -outform arg - The output format - one of BIN PEM", " (default is PEM)\n", #else /* !NO_PEM */ " -outform arg - The output format (BIN only)\n", #endif /* !NO_PEM */ " -signkey arg - The file name of private key to sign request with\n", #ifndef NO_PEM " -signkeyform arg - The format of key - one of BIN PEM", " (default is PEM)\n", #else /* !NO_PEM */ " -signkeyform arg - The format of key (BIN only)\n", #endif /* !NO_PEM */ #ifndef NO_DSA " -signkeytype arg - The type of key - one of RSA DSA (default is RSA)\n", #else /* NO_DSA */ " -signkeytype arg - The type of key - one of RSA (default is RSA)\n", #endif /* !NO_DSA */ #ifndef NO_DSA " -sign_type arg - The signature type to use - one of:\n", " RSA_MD2 RSA_MD5 RSA_SHA1 DSA_SHA1", " (default is RSA_SHA1)\n", #else /* NO_DSA */ " -sign_type arg - The signature type to use - one of:\n", " RSA_MD2 RSA_MD5 RSA_SHA1 (default is RSA_SHA1)\n", #endif /* !NO_DSA */ " -inkey arg - The public key file name to read\n", " -outkey arg - The public key file name to write\n", #ifndef NO_PEM " -keyform arg - The format of key - one of BIN PEM", " (default is PEM)\n", #else /* !NO_PEM */ " -keyform arg - The format of key (BIN only)\n", #endif /* !NO_PEM */ #ifndef NO_DSA " -keytype arg - The type of key - one of RSA DSA (default is RSA)\n", #else /* NO_DSA */ " -keytype arg - The type of key - one of RSA (default is RSA)\n", #endif /* !NO_DSA */ " -keysize arg - The key length in bits (default is 1024)\n", " -numprimes arg - The number of primes used when generating a key", " (default is 2)\n", " -cert arg - The name of certificate file\n", #ifndef NO_PEM " -certform arg - The format of certificate - one of BIN PEM", " (default is PEM)\n", #else /* !NO_PEM */ " -certform arg - The format of certificate (BIN only)\n", #endif /* !NO_PEM */ " -certtype arg - The type of certificate - one of X509", " (default is X509)\n", " -no_in - Indicates that no input is required for the", " creation of the name\n", " -eg - The example usage\n", NULL }; static char *reqgen_example_usage[] = { "Generates a certificate request and key pair\n", "reqgen -out req.out -signkey signer.key -outkey key.out\n", "\n", "Generates a certificate request using an existing key pair and", " certificate\n", "reqgen -out req.out -signkey signer.key -inkey key.in -cert cert.in\n", "\n", "Generates a certificate request using internal data for subject", " name etc\n", "reqgen -out req.out -signkey signer.key -outkey key.out -no_in\n", "\n", "where req.out = The certificate request created\n", " signer.key = The private key of the cert. req. signer\n", " key.out = The generated key pair\n", " key.in = An existing key pair used for the request\n", " cert.in = The existing certificate - details are used for", " the request\n", "\n", NULL }; /* * Main sample program entry point. * * @param argc [In] The number of arguments typed on the command line. * @param argv [In] The array of individual arguments from the command line. * @returns R_ERROR_NONE indicates success.<br> * See @ref R_ERROR_IDS for valid values. */ int main(int argc, char **argv) { int ret = R_ERROR_NONE; /* The return value */ BIO *bio_err = NULL; /* The standard error stream */ BIO *bio_out = NULL; /* The standard output stream */ BIO *bio_key = NULL; /* The public key output stream */ BIO *bio_req = NULL; /* The certificate request output stream */ R_LIB_CTX *lib_ctx = NULL; /* The library context */ R_CERT_REQ_CTX *req_ctx = NULL; /* The certificate request context */ R_CERT_REQ *req = NULL; /* The certificate request */ R_CERT_CTX *cert_ctx = NULL; /* The certificate context */ R_CERT *cert = NULL; /* The certificate */ R_CERT_NAME *name = NULL; /* The certificate name */ R_PKEY_CTX *pkey_ctx = NULL; /* The public key context */ R_PKEY *pkey = NULL; /* The public key */ R_PKEY *sign_key = NULL; /* The signing key - public key */ R_PKEY *s_pkey = NULL; /* The public key used */ R_SURRENDER *surr = NULL; /* The surrender function when generating * key */ unsigned char *buf = NULL; /* The data buffer */ R_FORMAT req_form; /* The format of the certificate request */ int key_bits; /* The number of bits in the new key */ int key_mod; /* The modifying parameter in the new * key */ int key_type; /* The type of public key */ R_FORMAT key_form; /* The format of public key */ int sign_key_type; /* The type of signing key */ R_FORMAT sign_key_form; /* The format of the signing key */ int sign_type; /* The signature type */ int cert_type; /* The type of certificate */ R_FORMAT cert_form; /* The format of the certificate */ char *inpkeyfile = NULL; /* The input public key file name */ char *signpkeyfile = NULL; /* The signing public key file name */ char *outpkeyfile = NULL; /* The output file name of public key */ char *certfile = NULL; /* The certificate file name */ char *reqfile = NULL; /* The certificate request file name */ int no_in = 0; /* Indicates that no input from the user * required */ int version = 1; /* The version of the certificate * request */ char name_str[NAME_STR_LEN]; /* The certificate name as a string */ int badop = 0; /* Indicates a bad command line option */ char *str; /* The character string */ int key_usage = R_CERT_KEY_USAGE_DIGITAL_SIGNATURE | R_CERT_KEY_USAGE_NON_REPUDIATION | R_CERT_KEY_USAGE_KEY_ENCIPHERMENT | R_CERT_KEY_USAGE_DATA_ENCIPHERMENT | R_CERT_KEY_USAGE_KEY_AGREEMENT | R_CERT_KEY_USAGE_KEY_CERT_SIGN | R_CERT_KEY_USAGE_CRL_SIGN | R_CERT_KEY_USAGE_ENCIPHER_ONLY | R_CERT_KEY_USAGE_DECIPHER_ONLY; /* Set the defaults */ #ifndef NO_PEM req_form = R_FORMAT_PEM; #else /* NO_PEM */ req_form = R_FORMAT_BINARY; #endif /* !NO_PEM */ key_bits = 1024; key_mod = 2; key_type = R_PKEY_TYPE_RSA; sign_key_type = R_PKEY_TYPE_RSA; #ifndef NO_PEM key_form = R_FORMAT_PEM; sign_key_form = R_FORMAT_PEM; #else /* NO_PEM */ key_form = R_FORMAT_BINARY; sign_key_form = R_FORMAT_BINARY; #endif /* !NO_PEM */ sign_type = R_CR_ID_SHA1_RSA; 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 */ /* * 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. */ bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); if (bio_err == NULL) { ret = R_ERROR_ALLOC_FAILURE; goto done; } bio_out = BIO_new_fp(stdout, BIO_NOCLOSE); if (bio_out == NULL) { ret = R_ERROR_ALLOC_FAILURE; goto done; } /* Parse the command line parameters */ /* Skip the program name */ argc--; argv++; /* Process all command line options */ while (argc >= 1) { if (Strcmp(*argv, "-out") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } reqfile = *argv; } else if (Strcmp(*argv, "-outform") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } str = *argv; if ((ret = R_FORMAT_from_string(str, &req_form)) != R_ERROR_NONE) { BIO_printf(bio_err, "Unknown request format: %s\n", str); goto bad; } } else if (Strcmp(*argv, "-sign_type") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } str = *argv; if (Strcmp(str, "RSA_MD2") == 0) { sign_type = R_CR_ID_MD2_RSA; } else if (Strcmp(str, "RSA_MD5") == 0) { sign_type = R_CR_ID_MD5_RSA; } else if (Strcmp(str, "RSA_SHA1") == 0) { sign_type = R_CR_ID_SHA1_RSA; } #ifndef NO_DSA else if (Strcmp(str, "DSA_SHA1") == 0) { sign_type = R_CR_ID_SHA1_DSA; } #endif /* NO_DSA */ else { BIO_printf(bio_err, "Unknown signature type type\n"); goto bad; } } else if (Strcmp(*argv, "-inkey") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } inpkeyfile = *argv; } else if (Strcmp(*argv, "-signkey") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } signpkeyfile = *argv; } else if (Strcmp(*argv, "-signkeyform") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } str = *argv; if (R_FORMAT_from_string(str, &sign_key_form) != R_ERROR_NONE) { BIO_printf(bio_err, "Unknown pkey format: %s\n", str); goto bad; } } else if (Strcmp(*argv, "-signkeytype") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } str = *argv; if (R_PKEY_TYPE_from_string(&sign_key_type, str) != R_ERROR_NONE) { goto bad; } if (key_type == R_PKEY_TYPE_UNKNOWN) { BIO_printf(bio_err, "Unknown pkey type: %s\n", str); goto bad; } } else if (Strcmp(*argv, "-outkey") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } outpkeyfile = *argv; } else if (Strcmp(*argv, "-keyform") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } str = *argv; if (R_FORMAT_from_string(str, &key_form) != R_ERROR_NONE) { BIO_printf(bio_err, "Unknown pkey format: %s\n", str); goto bad; } } else if (Strcmp(*argv, "-keytype") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } str = *argv; if (R_PKEY_TYPE_from_string(&key_type, str) != R_ERROR_NONE) { goto bad; } if (key_type == R_PKEY_TYPE_UNKNOWN) { BIO_printf(bio_err, "Unknown pkey type: %s\n", str); goto bad; } } else if (Strcmp(*argv, "-keysize") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } key_bits = atoi(*argv); } else if (Strcmp(*argv, "-numprimes") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } key_mod = atoi(*argv); } else if (Strcmp(*argv, "-cert") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } certfile = *argv; } else if (Strcmp(*argv, "-certform") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } str = *argv; if ((ret = R_FORMAT_from_string(str, &cert_form)) != R_ERROR_NONE) { BIO_printf(bio_err, "Unknown certificate format: %s\n", str); goto bad; } } else if (Strcmp(*argv, "-certtype") == 0) { if ((--argc < 1) || (Strncmp(*(++argv), "-", 1) == 0)) { goto bad; } str = *argv; 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; } } else if (Strcmp(*argv, "-no_in") == 0) { no_in = 1; } else if (Strcmp(*argv,"-eg") == 0) { char **egp; for (egp = reqgen_example_usage; (*egp) != NULL; egp++) { BIO_printf(bio_out, *egp); } goto done; } else { BIO_printf(bio_err, "Unknown option %s\n", *argv); badop = 1; break; } argc--; argv++; } /* Display the help menu if an invalid command line option was entered */ if (badop) { char **pp; bad: ; for (pp = reqgen_usage; (*pp != NULL); pp++) { BIO_printf(bio_err, *pp); } goto done; } /* Set up the surrender callback structure */ surr = (R_SURRENDER *)Malloc(sizeof(*surr)); if (surr == NULL) { BIO_printf(bio_err, "Failed to allocate the memory for surr\n"); ret = R_ERROR_ALLOC_FAILURE; goto done; } surr->callback = kg_surrender; surr->arg = (char *) bio_err; /* * 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 (PRODUCT_LIBRARY_NEW(PRODUCT_DEFAULT_RESOURCE_LIST(), 0, &lib_ctx) != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to create the library context\n"); ret = R_ERROR_ALLOC_FAILURE; goto done; } /* * Create a certificate request context and public key context. These * contexts are required if any R_CERT_REQ_* and R_PKEY_* routines * are used. */ ret = R_CERT_REQ_CTX_new(lib_ctx, R_RES_FLAG_DEF, R_CERT_REQ_TYPE_PKCS10, &req_ctx); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to create an R_CERT_REQ_CTX\n"); goto done; } ret = R_PKEY_CTX_new(lib_ctx, R_RES_FLAG_DEF, key_type, &pkey_ctx); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to create an R_PKEY_CTX\n"); ret = R_ERROR_ALLOC_FAILURE; goto done; } /* Load the PKEY from file */ /* * Obtain the PKEY. This is the key for the client certificate. If a PKEY * is provided then read it into a R_PKEY object.Otherwise generate the * key. */ if (inpkeyfile != NULL) { ret = R_PKEY_from_file(pkey_ctx, &pkey, inpkeyfile, key_type, key_form); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to open the key file: %s\n", inpkeyfile); goto done; } } else if (inpkeyfile == NULL) { ret = R_PKEY_generate_simple(pkey_ctx, &pkey, key_type, key_bits, key_mod, R_PKEY_FL_DEFAULT, surr); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to generate the key!\n"); goto done; } } /* * Obtain the signer PKEY. This is the Certification Authority (CA) * certificate's key. The CA key is used to sign the request. If no CA key * is provided use the client key. */ if (signpkeyfile != NULL) { ret = R_PKEY_from_file(pkey_ctx, &sign_key, signpkeyfile, sign_key_type, sign_key_form); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to open the key file: %s\n", signpkeyfile); goto done; } s_pkey = sign_key; } else { s_pkey = pkey; } /* * Create a certificate request. This involves: * - Creating a certificate request object (R_CERT_REQ). * - Gathering the certificate request details and setting them against * the object. * - Signing the certificate request. * There are two options available at this point (outlined below). */ if (certfile == NULL) { /* * Generate the certificate request. No pre-existing certificate on * which to base the request exists. The information in the various * fields of the certificate request is set against the certificate * request object. */ /* Create an empty certificate request */ ret = R_CERT_REQ_new(req_ctx, R_CERT_REQ_TYPE_PKCS10, &req); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to create the request\n"); goto done; } /* Enter the version of the certificate request structure */ ret = R_CERT_REQ_set_info(req, R_CERT_REQ_INFO_VERSION, &version); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to set the version\n"); goto done; } /* Retrieve the subject name as a string */ ret = get_subject_name_string(bio_err, NAME_STR_LEN, name_str, no_in); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to retrieve the subject name from user\n"); goto done; } /* Convert the string into an R_CERT_NAME structure */ ret = R_CERT_NAME_from_string(req_ctx, name_str, &name); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to create the name from string\n"); goto done; } /* Store the subject name */ ret = R_CERT_REQ_set_info(req, R_CERT_REQ_INFO_SUBJECT_R_CERT_NAME, name); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to set the subject name\n"); goto done; } /* Enter the public key for the certificate request */ ret = R_CERT_REQ_set_info(req, R_CERT_REQ_INFO_R_PKEY, pkey); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to set the public key\n"); goto done; } ret = R_CERT_REQ_set_info(req, R_CERT_REQ_INFO_KEY_USAGE_INT, &key_usage); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to set key usage values\n"); goto done; } /* Sign the certificate request */ ret = R_CERT_REQ_sign(req, s_pkey, sign_type); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to sign the request\n"); goto done; } } else { /* * Create a certificate request from an existing certificate. Obtain * the client certificate information from an existing certificate. * The existing certificate is loaded into the application and * converted to a request. The information in the various fields of * the certificate request is set against the certificate request * object. */ /* Create a certificate context from which to base the certificate */ ret = R_CERT_CTX_new(lib_ctx, R_RES_FLAG_DEF, cert_type, &cert_ctx); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to create an R_CERT_CTX\n"); goto done; } /* Create a certificate from the data in the file */ ret = R_CERT_read_file(cert_ctx, certfile, cert_type, cert_form, &cert); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Unable to load the certificate file: %s\n", certfile); goto done; } /* Create a certificate request from a certificate */ ret = R_CERT_to_R_CERT_REQ(cert, req_ctx, R_CERT_REQ_TYPE_PKCS10, &req); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to generate the request from a certfificate\n"); goto done; } /* * In the previous step the PKEY from the existing certificate was * stored in the new certificate request. However, if a new key was * generated earlier (specifically for this certificate request) then * store the key in the request. */ if ((inpkeyfile == NULL) || (!R_CERT_is_matching_private_key(cert, pkey))) { /* Enter the public key for the certificate request */ ret = R_CERT_REQ_set_info(req, R_CERT_REQ_INFO_R_PKEY, pkey); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to set the public key\n"); goto done; } } /* Sign the certificate request */ ret = R_CERT_REQ_sign(req, s_pkey, sign_type); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to sign the request\n"); goto done; } } /* Output the key if requested */ if (outpkeyfile != NULL) { /* Create an output stream to write the key to */ bio_key = BIO_new_file(outpkeyfile, "wb"); if (bio_key == NULL) { BIO_printf(bio_err, "Unable to open the file: %s\n", outpkeyfile); ret = R_ERROR_ALLOC_FAILURE; goto done; } /* Write the public key to the output stream */ ret = R_PKEY_to_bio(bio_key, pkey, key_form, NULL); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to write the key\n"); goto done; } } /* * Write the certificate request to file. Open the output stream and print * the request into the stream. */ /* Open the certificate request BIO */ if (reqfile != NULL) { bio_req = BIO_new_file(reqfile, "wb"); if (bio_req == NULL) { BIO_printf(bio_err, "Unable to open the file: %s\n", reqfile); ret = R_ERROR_ALLOC_FAILURE; goto done; } } else { bio_req = bio_out; bio_out = NULL; } /* Print the PEM format only to stdout */ if (!((req_form == R_FORMAT_BINARY) && (reqfile == NULL))) { ret = R_CERT_REQ_write(req, bio_req, req_form, NULL); if (ret != R_ERROR_NONE) { BIO_printf(bio_err, "Failed to write the request\n"); } } done: /* * 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)); } /* Clean up */ if (surr != NULL) { Free(surr); } if (sign_key != NULL) { R_PKEY_free(sign_key); } if (pkey != NULL) { R_PKEY_free(pkey); } if (cert != NULL) { R_CERT_free(cert); } if (buf != NULL) { Free(buf); } if (name != NULL) { R_CERT_NAME_free(name); } if (req != NULL) { R_CERT_REQ_free(req); } if (cert_ctx != NULL) { R_CERT_CTX_free(cert_ctx); } if (pkey_ctx != NULL) { R_PKEY_CTX_free(pkey_ctx); } if (req_ctx != NULL) { R_CERT_REQ_CTX_free(req_ctx); } if (bio_req != NULL) { BIO_free(bio_req); } if (bio_key != NULL) { BIO_free(bio_key); } if (lib_ctx != NULL) { R_LIB_CTX_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)); } /* * Indicates the public key pair generation surrender callback function. * * @param surr [In] The surrender structure. * @param p [In] The phase. * @param n [In] The number. * * @returns 0 indicates success. */ static int kg_surrender(R_SURRENDER * surr, int p, int n) { char c = '*'; /* Status character to write out */ /* Use a different character for each status */ if (p == 0) { c = '.'; } if (p == 1) { c = '+'; } if (p == 2) { c = '*'; } if (p == 3) { c = '\n'; } /* * Write out the character and flush to ensure it appears * as soon as possible */ BIO_write((BIO *) surr->arg, &c, 1); BIO_flush((BIO *) surr->arg); /* Continue calculation */ return (0); } /* * Obtains the details of the subject name from the user and places it in a * string. * * @param bio_err [In] The BIO for error messages. * @param max_str_len [In] The amount of memory allocated to string. * @param str [In] The subject name. * @param no_in [In] The default value. * * @returns R_ERROR_NONE indicates success.<br> * See @ref R_ERROR_IDS for valid values. */ static int get_subject_name_string(BIO *bio_err, unsigned int max_str_len, char *str, int no_in) { int ret = R_ERROR_NONE; /* The return value */ BIO *bio_in = NULL; /* The standard input * stream */ MS_STATIC char in_str[NAME_INPUT_STR_LENGTH]; /* The input string */ int i; /* The iterator over * string */ char *p; /* A pointer into string */ if ((bio_in = BIO_new_fp(stdin, BIO_NOCLOSE)) == NULL) { ret = R_ERROR_ALLOC_FAILURE; BIO_printf(bio_err, "Failed to open the standard input stream\n"); } else { /* Ensure the subject name string is empty */ str[0] = '\0'; /* Create a subject name string with each of the entries completed */ for (i=0;i<NAME_REQ_NUM;i++) { /* Enter the separator between successive entries */ if (i != 0) { Strcat(str, ", "); } /* Enter the long name of the entry type */ Strcat(str, name_req[i*3+1]); Strcat(str, "="); p=name_req[i*3+2]; if (no_in == 0) { /* Print the prompt */ BIO_printf(bio_err, "Enter %s [default %s]: ", name_req[i*3], p); /* Empty the string and retrieve the user's input */ in_str[0]=0; BIO_gets(bio_in, in_str, sizeof(in_str)); /* Remove the trailing carriage return(s)/line feed(s) */ while (in_str[Strlen(in_str)-1] == '\n' || in_str[Strlen(in_str)-1] == '\r') { in_str[Strlen(in_str)-1] = '\0'; } /* Use the entered string if applicable */ if (in_str[0] != '\0') { p=in_str; } } /* Enter the entry value */ Strcat(str, p); } } if (bio_in != NULL) { BIO_free(bio_in); } /* The return error value */ return(ret); }