common.c revision fa60c371cd00bdca17de2ff18fe3e64d051ae61b
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * CDDL HEADER START
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * The contents of this file are subject to the terms of the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Common Development and Distribution License (the "License").
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * You may not use this file except in compliance with the License.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * See the License for the specific language governing permissions
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * and limitations under the License.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * When distributing Covered Code, include this CDDL HEADER in each
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If applicable, add the following below this CDDL HEADER, with the
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * fields enclosed by brackets "[]" replaced with your own identifying
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * information: Portions Copyright [yyyy] [name of copyright owner]
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * CDDL HEADER END
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Use is subject to license terms.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma ident "%Z%%M% %I% %E% SMI"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This file contains the functions that are shared among
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the various services this tool will ultimately provide.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The functions in this file return PKCS#11 CK_RV errors.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Only one session and one login per token is supported
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * at this time.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Local status variables. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/* Supporting structures and global variables for getopt_av(). */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct av_opts_s {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int _save_numopts = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Perform PKCS#11 setup here. Currently only C_Initialize is required,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * along with setting/resetting state variables.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* If C_Initialize() already called, nothing to do here. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Reset state variables because C_Initialize() not yet done. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Initialize PKCS#11 library. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Finalize PKCS#11 library and reset state variables. Open sessions,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if any, are closed, and thereby any logins are logged out also.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* If the library wasn't initialized, nothing to do here. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Make sure the sesion is closed first. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Close PKCS#11 session and reset state variables. Any logins are
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * logged out.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* If session is already closed, nothing to do here. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Make sure user is logged out of token. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Log user out of token and reset status variable.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* If already logged out, nothing to do here. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Gets PIN from user. Caller needs to free the returned PIN when done.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If two prompts are given, the PIN is confirmed with second prompt.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Note that getphassphrase() may return data in static memory area.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinget_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Prompt user for a PIN. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Duplicate 1st PIN in separate chunk of memory. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* If second prompt given, PIN confirmation is requested. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Gets yes/no response from user. If either no prompt is supplied, a
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * default prompt is used. If not message for invalid input is supplied,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * a default will not be provided. If the user provides no response,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the input default B_TRUE == yes, B_FALSE == no is returned.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Otherwise, B_TRUE is returned for yes, and B_FALSE for no.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Prompt user. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Get the response. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((response = fgets(buf, sizeof (buf), stdin)) == NULL)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break; /* go to default response */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Skip any leading white space. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break; /* go to default response */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (ans == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Indicate invalid input, and try again. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Gets the list of slots which have tokens in them. Keeps adjusting
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the size of the slot list buffer until the call is successful or an
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * irrecoverable error occurs.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinget_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Get the slot count first because we don't know how many
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * slots there are and how many of those slots even have tokens.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Don't specify an arbitrary buffer size for the slot list;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * it may be too small (see section 11.5 of PKCS#11 spec).
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Also select only those slots that have tokens in them,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * because this tool has no need to know about empty slots.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Allocate initial space for the slot list. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Then get the slot list itself. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* If the number of slots grew, try again. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Breaks out the getopt-style option string into a structure that can be
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * traversed later for calls to getopt_av(). Option string is NOT altered,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * but the struct fields point to locations within option string.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * This tries to imitate getopt(3c) Each option must conform to:
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * <short name char> [ ':' ] [ '(' <long name string> ')' ]
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If long name is missing, the short name is used for long name.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* use short name option character */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * getopt_av() is very similar to getopt(3c) in that the takes an option
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * string, compares command line arguments for matches, and returns a single
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * letter option when a match is found. However, getopt_av() differs from
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * getopt(3c) by requiring that only longname options and values be found
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * on the command line and all leading dashes are omitted. In other words,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * it tries to enforce only longname "option=value" arguments on the command
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * line. Boolean options are not allowed either.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chingetopt_av(int argc, char * const *argv, const char *optstring)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* First time or when optstring changes from previous one */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i < _save_numopts; i++) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (len == opts_av[i].longnm_len && strncmp(cur_option,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* matched */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* needs optarg */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return ((int)'?');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinStr2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin /* default to 1 year lifetime */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return (-1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return (-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char *c = NULL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c != NULL) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else /* unrecognized option */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *c = '\0';
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return (-1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin } else if (strcasecmp(objclass, "private") == 0) {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return (-1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return (-1);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin /* return all keys */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Only return public keys */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Only return private keys */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (formstr == NULL || strcasecmp(formstr, "der") == 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinselect_token(void *kmfhandle, char *token, int readonly)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int i = 0;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int i = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Get the password to use for the PK12 encryption.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define COUNTRY_PROMPT gettext("Country Name (2 letter code) [US]:")
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define STATE_PROMPT gettext("State or Province Name (full name) " \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "[Some-State]:")
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define LOCALITY_PROMPT gettext("Locality Name (eg, city) []:")
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define ORG_PROMPT gettext("Organization Name (eg, company) []:")
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin#define UNIT_PROMPT gettext("Organizational Unit Name (eg, section) []:")
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define NAME_PROMPT gettext("Common Name (eg, YOUR name) []:")
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define SERNO_PROMPT gettext("Serial Number (hex value, example: " \
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin "0x01020304):")
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define LABEL_PROMPT gettext("Enter a label for the certificate:")
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define INVALID_INPUT gettext("Invalid input; please re-enter ...")
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic char *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinget_input_string(char *prompt, char *default_str, int min_len, int max_len)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Skip any leading white space. */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin (void) printf("Entering following fields for subject (a DN) ...\n");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Now create a subject name from the input strings */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (-1);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return (0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Parse a string of KeyUsage values and convert
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * them to the correct KU Bits.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The field may be marked "critical" by prepending
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * "critical:" to the list.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * EX: critical:digitialSignature,keyEncipherment
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinverify_keyusage(char *kustr, uint16_t *kubits, int *critical)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* Check to see if this is critical */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (strncasecmp(kustr, "critical:", strlen("critical:")) == 0) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (k != NULL) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (kuval == 0) {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * Verify the alternate subject label is real or invalid.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * The field may be marked "critical" by prepending
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * "critical:" to the list.
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin * EX: "critical:IP=1.2.3.4"
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chinverify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin /* Check to see if this is critical */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (strncasecmp(arg, "critical:", strlen("critical:")) == 0) {
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin /* Make sure there is an "=" sign */
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin p[0] = '\0';
return (rv);
char *p = NULL;
if (p != NULL)
return (KMF_OK);
int fd;
return (KMF_ERR_OPEN_FILE);
return (ret);
static KMF_RETURN
return (KMF_ERR_MEMORY);
return (KMF_ERR_MEMORY);
return (KMF_OK);
static KMF_RETURN
int critical;
return (rv);
if (p == NULL) {
while (p != NULL) {
return (rv);
*auth = 0;
return (rv);
return (KMF_ERR_INTERNAL);
return (KMF_OK);