17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
599ebb4caSwyllys * Common Development and Distribution License (the "License").
699ebb4caSwyllys * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
202c9a247fSWyllys Ingersoll *
212c9a247fSWyllys Ingersoll * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
227c478bd9Sstevel@tonic-gate */
237c478bd9Sstevel@tonic-gate
247c478bd9Sstevel@tonic-gate /*
257c478bd9Sstevel@tonic-gate * This file contains the functions that are shared among
267c478bd9Sstevel@tonic-gate * the various services this tool will ultimately provide.
277711facfSdinak * The functions in this file return PKCS#11 CK_RV errors.
287711facfSdinak * Only one session and one login per token is supported
297711facfSdinak * at this time.
307c478bd9Sstevel@tonic-gate */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #include <stdio.h>
337c478bd9Sstevel@tonic-gate #include <stdlib.h>
347c478bd9Sstevel@tonic-gate #include <string.h>
357c478bd9Sstevel@tonic-gate #include <ctype.h>
3699ebb4caSwyllys #include <sys/types.h>
3799ebb4caSwyllys #include <sys/stat.h>
3899ebb4caSwyllys #include <fcntl.h>
3999ebb4caSwyllys #include <tzfile.h>
407c478bd9Sstevel@tonic-gate #include <cryptoutil.h>
417c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
4299ebb4caSwyllys #include <kmfapi.h>
437c478bd9Sstevel@tonic-gate
4499ebb4caSwyllys #include "common.h"
457711facfSdinak
467711facfSdinak /* Local status variables. */
477711facfSdinak static boolean_t initialized = B_FALSE;
487711facfSdinak static boolean_t session_opened = B_FALSE;
497711facfSdinak static boolean_t logged_in = B_FALSE;
507c478bd9Sstevel@tonic-gate
5149e21299Sdinak /* Supporting structures and global variables for getopt_av(). */
5249e21299Sdinak typedef struct av_opts_s {
5349e21299Sdinak int shortnm; /* short name character */
5449e21299Sdinak char *longnm; /* long name string, NOT terminated */
5549e21299Sdinak int longnm_len; /* length of long name string */
5649e21299Sdinak boolean_t has_arg; /* takes optional argument */
5749e21299Sdinak } av_opts;
5849e21299Sdinak static av_opts *opts_av = NULL;
5949e21299Sdinak static const char *_save_optstr = NULL;
6049e21299Sdinak static int _save_numopts = 0;
6149e21299Sdinak
6249e21299Sdinak int optind_av = 1;
6349e21299Sdinak char *optarg_av = NULL;
6449e21299Sdinak
6599ebb4caSwyllys static void close_sess(CK_SESSION_HANDLE);
6699ebb4caSwyllys static void logout_token(CK_SESSION_HANDLE);
6799ebb4caSwyllys
68e65e5c2dSWyllys Ingersoll struct oid_table_entry {
69e65e5c2dSWyllys Ingersoll const KMF_OID *oid;
70e65e5c2dSWyllys Ingersoll char *name;
71e65e5c2dSWyllys Ingersoll };
72e65e5c2dSWyllys Ingersoll
73e65e5c2dSWyllys Ingersoll struct oid_table_entry oid_table[] = {
74e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp112r1, "secp112r1"},
75e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp112r2, "secp112r2"},
76e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp128r1, "secp128r1"},
77e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp128r2, "secp128r2"},
78e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp160k1, "secp160k1"},
79e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp160r1, "secp160r1"},
80e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp160r2, "secp160r2"},
81e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp192k1, "secp192k1"},
82e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp192r1, "secp192r1"},
83e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp224k1, "secp224k1"},
84e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp224r1, "secp224r1"},
85e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp256k1, "secp256k1"},
86e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp256r1, "secp256r1"},
87e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp384r1, "secp384r1"},
88e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp521r1, "secp521r1"},
89e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect113r1, "sect113r1"},
90e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect113r2, "sect113r2"},
91e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect131r1, "sect131r1"},
92e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect131r2, "sect131r2"},
93e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect163k1, "sect163k1"},
94e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect163r1, "sect163r1"},
95e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect163r2, "sect163r2"},
96e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect193r1, "sect193r1"},
97e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect193r2, "sect193r2"},
98e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect233k1, "sect233k1"},
99e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect233r1, "sect233r1"},
100e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect239k1, "sect239k1"},
101e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect283k1, "sect283k1"},
102e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect283r1, "sect283r1"},
103e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect409k1, "sect409k1"},
104e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect409r1, "sect409r1"},
105e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect571k1, "sect571k1"},
106e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect571r1, "sect571r1"},
107e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb163v1, "c2pnb163v1"},
108e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb163v2, "c2pnb163v2"},
109e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb163v3, "c2pnb163v3"},
110e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb176v1, "c2pnb176v1"},
111e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb191v1, "c2tnb191v1"},
112e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb191v2, "c2tnb191v2"},
113e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb191v3, "c2tnb191v3"},
114e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb208w1, "c2pnb208w1"},
115e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb239v1, "c2tnb239v1"},
116e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb239v2, "c2tnb239v2"},
117e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb239v3, "c2tnb239v3"},
118e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb272w1, "c2pnb272w1"},
119e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb304w1, "c2pnb304w1"},
120e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb359v1, "c2tnb359v1"},
121e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb368w1, "c2pnb368w1"},
122e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb431r1, "c2tnb431r1"},
123e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_prime192v2, "prime192v2"},
124e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_prime192v3, "prime192v3"},
125e65e5c2dSWyllys Ingersoll { &KMFOID_MD5, "md5"},
126e65e5c2dSWyllys Ingersoll { &KMFOID_SHA1, "sha1"},
127e65e5c2dSWyllys Ingersoll { &KMFOID_SHA256, "sha256"},
128e65e5c2dSWyllys Ingersoll { &KMFOID_SHA384, "sha384"},
129e65e5c2dSWyllys Ingersoll { &KMFOID_SHA512, "sha512"}
130e65e5c2dSWyllys Ingersoll };
131e65e5c2dSWyllys Ingersoll int number_of_oids = sizeof (oid_table) / sizeof (struct oid_table_entry);
132e65e5c2dSWyllys Ingersoll #define number_of_curves (number_of_oids - 5)
133e65e5c2dSWyllys Ingersoll
1347c478bd9Sstevel@tonic-gate /*
1357711facfSdinak * Perform PKCS#11 setup here. Currently only C_Initialize is required,
1367711facfSdinak * along with setting/resetting state variables.
1377c478bd9Sstevel@tonic-gate */
138448b8615Swyllys static CK_RV
init_pkcs11(void)139448b8615Swyllys init_pkcs11(void)
1407c478bd9Sstevel@tonic-gate {
1417711facfSdinak CK_RV rv = CKR_OK;
1427711facfSdinak
1437711facfSdinak /* If C_Initialize() already called, nothing to do here. */
1447711facfSdinak if (initialized == B_TRUE)
1457711facfSdinak return (CKR_OK);
1467c478bd9Sstevel@tonic-gate
1477711facfSdinak /* Reset state variables because C_Initialize() not yet done. */
1487711facfSdinak session_opened = B_FALSE;
1497711facfSdinak logged_in = B_FALSE;
1507c478bd9Sstevel@tonic-gate
1517711facfSdinak /* Initialize PKCS#11 library. */
1527711facfSdinak if ((rv = C_Initialize(NULL_PTR)) != CKR_OK &&
1537711facfSdinak rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
1547711facfSdinak return (rv);
1557711facfSdinak }
1567c478bd9Sstevel@tonic-gate
1577711facfSdinak initialized = B_TRUE;
1587711facfSdinak return (CKR_OK);
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate /*
1627711facfSdinak * Finalize PKCS#11 library and reset state variables. Open sessions,
1637711facfSdinak * if any, are closed, and thereby any logins are logged out also.
1647c478bd9Sstevel@tonic-gate */
1657711facfSdinak void
final_pk11(CK_SESSION_HANDLE sess)1667711facfSdinak final_pk11(CK_SESSION_HANDLE sess)
1677c478bd9Sstevel@tonic-gate {
1687c478bd9Sstevel@tonic-gate
1697711facfSdinak /* If the library wasn't initialized, nothing to do here. */
1707711facfSdinak if (!initialized)
1717711facfSdinak return;
1727c478bd9Sstevel@tonic-gate
1737711facfSdinak /* Make sure the sesion is closed first. */
1747711facfSdinak close_sess(sess);
1757711facfSdinak
1767711facfSdinak (void) C_Finalize(NULL);
1777711facfSdinak initialized = B_FALSE;
1787711facfSdinak }
1797711facfSdinak
1807711facfSdinak /*
1817711facfSdinak * Close PKCS#11 session and reset state variables. Any logins are
1827711facfSdinak * logged out.
1837711facfSdinak */
18499ebb4caSwyllys static void
close_sess(CK_SESSION_HANDLE sess)1857711facfSdinak close_sess(CK_SESSION_HANDLE sess)
1867711facfSdinak {
1877711facfSdinak
188*6f2b04a2SToomas Soome if (sess == 0) {
1897711facfSdinak return;
1907711facfSdinak }
1917711facfSdinak
1927711facfSdinak /* If session is already closed, nothing to do here. */
1937711facfSdinak if (!session_opened)
1947711facfSdinak return;
1957711facfSdinak
1967711facfSdinak /* Make sure user is logged out of token. */
1977711facfSdinak logout_token(sess);
1987711facfSdinak
1997711facfSdinak (void) C_CloseSession(sess);
2007711facfSdinak session_opened = B_FALSE;
2017711facfSdinak }
2027711facfSdinak
2037711facfSdinak /*
2047711facfSdinak * Log user out of token and reset status variable.
2057711facfSdinak */
20699ebb4caSwyllys static void
logout_token(CK_SESSION_HANDLE sess)2077711facfSdinak logout_token(CK_SESSION_HANDLE sess)
2087711facfSdinak {
2097711facfSdinak
210*6f2b04a2SToomas Soome if (sess == 0) {
2117711facfSdinak return;
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate
2147711facfSdinak /* If already logged out, nothing to do here. */
2157711facfSdinak if (!logged_in)
2167711facfSdinak return;
2177711facfSdinak
2187711facfSdinak (void) C_Logout(sess);
2197711facfSdinak logged_in = B_FALSE;
2207711facfSdinak }
2217711facfSdinak
2227711facfSdinak /*
2237711facfSdinak * Gets PIN from user. Caller needs to free the returned PIN when done.
2247711facfSdinak * If two prompts are given, the PIN is confirmed with second prompt.
2257711facfSdinak * Note that getphassphrase() may return data in static memory area.
2267711facfSdinak */
2277711facfSdinak CK_RV
get_pin(char * prompt1,char * prompt2,CK_UTF8CHAR_PTR * pin,CK_ULONG * pinlen)2287711facfSdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen)
2297711facfSdinak {
230d00756ccSwyllys char *save_phrase, *phrase1, *phrase2;
2317711facfSdinak
2327711facfSdinak /* Prompt user for a PIN. */
2337711facfSdinak if (prompt1 == NULL) {
2347711facfSdinak return (CKR_ARGUMENTS_BAD);
2357711facfSdinak }
2367711facfSdinak if ((phrase1 = getpassphrase(prompt1)) == NULL) {
2377711facfSdinak return (CKR_FUNCTION_FAILED);
2387711facfSdinak }
2397711facfSdinak
2407711facfSdinak /* Duplicate 1st PIN in separate chunk of memory. */
2417711facfSdinak if ((save_phrase = strdup(phrase1)) == NULL)
2427711facfSdinak return (CKR_HOST_MEMORY);
2437711facfSdinak
2447711facfSdinak /* If second prompt given, PIN confirmation is requested. */
2457711facfSdinak if (prompt2 != NULL) {
2467711facfSdinak if ((phrase2 = getpassphrase(prompt2)) == NULL) {
2477711facfSdinak free(save_phrase);
2487711facfSdinak return (CKR_FUNCTION_FAILED);
2497711facfSdinak }
2507711facfSdinak if (strcmp(save_phrase, phrase2) != 0) {
2517711facfSdinak free(save_phrase);
2527711facfSdinak return (CKR_PIN_INCORRECT);
2537711facfSdinak }
2547711facfSdinak }
2557711facfSdinak
2567711facfSdinak *pin = (CK_UTF8CHAR_PTR)save_phrase;
2577711facfSdinak *pinlen = strlen(save_phrase);
2587711facfSdinak return (CKR_OK);
2597711facfSdinak }
2607711facfSdinak
261d00756ccSwyllys int
yn_to_int(char * ynstr)262d00756ccSwyllys yn_to_int(char *ynstr)
263d00756ccSwyllys {
264d00756ccSwyllys char *y = gettext("yes");
265d00756ccSwyllys char *n = gettext("no");
266d00756ccSwyllys if (ynstr == NULL)
267d00756ccSwyllys return (-1);
268d00756ccSwyllys
269d00756ccSwyllys if (strncasecmp(ynstr, y, 1) == 0)
270d00756ccSwyllys return (1);
271d00756ccSwyllys else if (strncasecmp(ynstr, n, 1) == 0)
272d00756ccSwyllys return (0);
273d00756ccSwyllys else
274d00756ccSwyllys return (-1);
275d00756ccSwyllys }
276d00756ccSwyllys
2777711facfSdinak /*
2787711facfSdinak * Gets yes/no response from user. If either no prompt is supplied, a
2797711facfSdinak * default prompt is used. If not message for invalid input is supplied,
2807711facfSdinak * a default will not be provided. If the user provides no response,
2817711facfSdinak * the input default B_TRUE == yes, B_FALSE == no is returned.
2827711facfSdinak * Otherwise, B_TRUE is returned for yes, and B_FALSE for no.
2837711facfSdinak */
2847711facfSdinak boolean_t
yesno(char * prompt,char * invalid,boolean_t dflt)2857711facfSdinak yesno(char *prompt, char *invalid, boolean_t dflt)
2867711facfSdinak {
287d00756ccSwyllys char *response, buf[1024];
288d00756ccSwyllys int ans;
2897711facfSdinak
2907711facfSdinak if (prompt == NULL)
2917711facfSdinak prompt = gettext("Enter (y)es or (n)o? ");
2927711facfSdinak
2937711facfSdinak for (;;) {
2947711facfSdinak /* Prompt user. */
2957711facfSdinak (void) printf("%s", prompt);
2967711facfSdinak (void) fflush(stdout);
2977711facfSdinak
2987711facfSdinak /* Get the response. */
2997711facfSdinak if ((response = fgets(buf, sizeof (buf), stdin)) == NULL)
3007711facfSdinak break; /* go to default response */
3017711facfSdinak
3027711facfSdinak /* Skip any leading white space. */
3037711facfSdinak while (isspace(*response))
3047711facfSdinak response++;
3057711facfSdinak if (*response == '\0')
3067711facfSdinak break; /* go to default response */
3077711facfSdinak
308d00756ccSwyllys ans = yn_to_int(response);
309d00756ccSwyllys if (ans == 1)
3107711facfSdinak return (B_TRUE);
311d00756ccSwyllys else if (ans == 0)
3127711facfSdinak return (B_FALSE);
3137711facfSdinak
3147711facfSdinak /* Indicate invalid input, and try again. */
3157711facfSdinak if (invalid != NULL)
31630a5e8faSwyllys (void) printf("%s", invalid);
3177711facfSdinak }
3187711facfSdinak return (dflt);
3197711facfSdinak }
3207711facfSdinak
3217711facfSdinak /*
3227711facfSdinak * Gets the list of slots which have tokens in them. Keeps adjusting
3237711facfSdinak * the size of the slot list buffer until the call is successful or an
3247711facfSdinak * irrecoverable error occurs.
3257711facfSdinak */
3267711facfSdinak CK_RV
get_token_slots(CK_SLOT_ID_PTR * slot_list,CK_ULONG * slot_count)3277711facfSdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count)
3287711facfSdinak {
3297711facfSdinak CK_ULONG tmp_count = 0;
3307711facfSdinak CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR;
3317711facfSdinak int rv = CKR_OK;
3327711facfSdinak
3337711facfSdinak if (!initialized)
334448b8615Swyllys if ((rv = init_pkcs11()) != CKR_OK)
3357711facfSdinak return (rv);
3367711facfSdinak
3377711facfSdinak /*
3387711facfSdinak * Get the slot count first because we don't know how many
3397711facfSdinak * slots there are and how many of those slots even have tokens.
3407711facfSdinak * Don't specify an arbitrary buffer size for the slot list;
3417711facfSdinak * it may be too small (see section 11.5 of PKCS#11 spec).
3427711facfSdinak * Also select only those slots that have tokens in them,
3437711facfSdinak * because this tool has no need to know about empty slots.
3447711facfSdinak */
3457711facfSdinak if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK)
3467711facfSdinak return (rv);
3477711facfSdinak
3487711facfSdinak if (tmp_count == 0) {
3497711facfSdinak *slot_list = NULL_PTR;
3507711facfSdinak *slot_count = 0;
3517711facfSdinak return (CKR_OK);
3527711facfSdinak }
3537711facfSdinak
3547711facfSdinak /* Allocate initial space for the slot list. */
3557711facfSdinak if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count *
3567711facfSdinak sizeof (CK_SLOT_ID))) == NULL)
3577711facfSdinak return (CKR_HOST_MEMORY);
3587711facfSdinak
3597711facfSdinak /* Then get the slot list itself. */
3607711facfSdinak for (;;) {
3617711facfSdinak if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) {
3627711facfSdinak *slot_list = tmp_list;
3637711facfSdinak *slot_count = tmp_count;
3647711facfSdinak break;
3657711facfSdinak }
3667711facfSdinak
3677711facfSdinak if (rv != CKR_BUFFER_TOO_SMALL) {
3687711facfSdinak free(tmp_list);
3697711facfSdinak break;
3707711facfSdinak }
3717711facfSdinak
3727711facfSdinak /* If the number of slots grew, try again. */
3737711facfSdinak if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list,
3747711facfSdinak tmp_count * sizeof (CK_SLOT_ID))) == NULL) {
3757711facfSdinak free(tmp_list);
3767711facfSdinak rv = CKR_HOST_MEMORY;
3777711facfSdinak break;
3787711facfSdinak }
3797711facfSdinak tmp_list = tmp2_list;
3807711facfSdinak }
3817711facfSdinak
3827711facfSdinak return (rv);
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate /*
38699ebb4caSwyllys * Breaks out the getopt-style option string into a structure that can be
38799ebb4caSwyllys * traversed later for calls to getopt_av(). Option string is NOT altered,
38899ebb4caSwyllys * but the struct fields point to locations within option string.
3897c478bd9Sstevel@tonic-gate */
3907c478bd9Sstevel@tonic-gate static int
populate_opts(char * optstring)39199ebb4caSwyllys populate_opts(char *optstring)
3927c478bd9Sstevel@tonic-gate {
39399ebb4caSwyllys int i;
39499ebb4caSwyllys av_opts *temp;
3957c478bd9Sstevel@tonic-gate char *marker;
3967c478bd9Sstevel@tonic-gate
39799ebb4caSwyllys if (optstring == NULL || *optstring == '\0')
39899ebb4caSwyllys return (0);
39999ebb4caSwyllys
40099ebb4caSwyllys /*
40199ebb4caSwyllys * This tries to imitate getopt(3c) Each option must conform to:
40299ebb4caSwyllys * <short name char> [ ':' ] [ '(' <long name string> ')' ]
40399ebb4caSwyllys * If long name is missing, the short name is used for long name.
40499ebb4caSwyllys */
40599ebb4caSwyllys for (i = 0; *optstring != '\0'; i++) {
40699ebb4caSwyllys if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) :
40799ebb4caSwyllys realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) {
40899ebb4caSwyllys if (opts_av != NULL)
40999ebb4caSwyllys free(opts_av);
41099ebb4caSwyllys opts_av = NULL;
41199ebb4caSwyllys return (0);
41299ebb4caSwyllys } else {
41399ebb4caSwyllys opts_av = (av_opts *)temp;
41499ebb4caSwyllys }
4157c478bd9Sstevel@tonic-gate
41699ebb4caSwyllys (void) memset(&opts_av[i], 0, sizeof (av_opts));
41799ebb4caSwyllys marker = optstring; /* may need optstring later */
4187c478bd9Sstevel@tonic-gate
41999ebb4caSwyllys opts_av[i].shortnm = *marker++; /* set short name */
42099ebb4caSwyllys
42199ebb4caSwyllys if (*marker == ':') { /* check for opt arg */
42299ebb4caSwyllys marker++;
42399ebb4caSwyllys opts_av[i].has_arg = B_TRUE;
42499ebb4caSwyllys }
42599ebb4caSwyllys
42699ebb4caSwyllys if (*marker == '(') { /* check and set long name */
42799ebb4caSwyllys marker++;
42899ebb4caSwyllys opts_av[i].longnm = marker;
42999ebb4caSwyllys opts_av[i].longnm_len = strcspn(marker, ")");
43099ebb4caSwyllys optstring = marker + opts_av[i].longnm_len + 1;
43199ebb4caSwyllys } else {
43299ebb4caSwyllys /* use short name option character */
43399ebb4caSwyllys opts_av[i].longnm = optstring;
43499ebb4caSwyllys opts_av[i].longnm_len = 1;
43599ebb4caSwyllys optstring = marker;
43699ebb4caSwyllys }
43799ebb4caSwyllys }
43899ebb4caSwyllys
43999ebb4caSwyllys return (i);
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate /*
44399ebb4caSwyllys * getopt_av() is very similar to getopt(3c) in that the takes an option
44499ebb4caSwyllys * string, compares command line arguments for matches, and returns a single
44599ebb4caSwyllys * letter option when a match is found. However, getopt_av() differs from
44699ebb4caSwyllys * getopt(3c) by requiring that only longname options and values be found
44799ebb4caSwyllys * on the command line and all leading dashes are omitted. In other words,
44899ebb4caSwyllys * it tries to enforce only longname "option=value" arguments on the command
44999ebb4caSwyllys * line. Boolean options are not allowed either.
4507c478bd9Sstevel@tonic-gate */
45199ebb4caSwyllys int
getopt_av(int argc,char * const * argv,const char * optstring)45299ebb4caSwyllys getopt_av(int argc, char * const *argv, const char *optstring)
4537c478bd9Sstevel@tonic-gate {
45499ebb4caSwyllys int i;
45599ebb4caSwyllys int len;
45699ebb4caSwyllys char *cur_option;
4577c478bd9Sstevel@tonic-gate
45899ebb4caSwyllys if (optind_av >= argc)
45999ebb4caSwyllys return (EOF);
4607c478bd9Sstevel@tonic-gate
46199ebb4caSwyllys /* First time or when optstring changes from previous one */
46299ebb4caSwyllys if (_save_optstr != optstring) {
46399ebb4caSwyllys if (opts_av != NULL)
46430a5e8faSwyllys free(opts_av);
46599ebb4caSwyllys opts_av = NULL;
46699ebb4caSwyllys _save_optstr = optstring;
46799ebb4caSwyllys _save_numopts = populate_opts((char *)optstring);
46899ebb4caSwyllys }
4697c478bd9Sstevel@tonic-gate
47099ebb4caSwyllys for (i = 0; i < _save_numopts; i++) {
47199ebb4caSwyllys cur_option = argv[optind_av];
4727c478bd9Sstevel@tonic-gate
47399ebb4caSwyllys if (strcmp(cur_option, "--") == 0) {
47499ebb4caSwyllys optind_av++;
47599ebb4caSwyllys break;
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate
47899ebb4caSwyllys if (cur_option[0] == '-' && strlen(cur_option) == 2) {
47999ebb4caSwyllys len = 1;
48099ebb4caSwyllys cur_option++; /* remove "-" */
48199ebb4caSwyllys } else {
48299ebb4caSwyllys len = strcspn(cur_option, "=");
48399ebb4caSwyllys }
4847c478bd9Sstevel@tonic-gate
48599ebb4caSwyllys if (len == opts_av[i].longnm_len && strncmp(cur_option,
48699ebb4caSwyllys opts_av[i].longnm, opts_av[i].longnm_len) == 0) {
48799ebb4caSwyllys /* matched */
48899ebb4caSwyllys if (!opts_av[i].has_arg) {
48999ebb4caSwyllys optind_av++;
49099ebb4caSwyllys return (opts_av[i].shortnm);
49199ebb4caSwyllys }
49299ebb4caSwyllys
49399ebb4caSwyllys /* needs optarg */
49499ebb4caSwyllys if (cur_option[len] == '=') {
49599ebb4caSwyllys optarg_av = &(cur_option[len+1]);
49699ebb4caSwyllys optind_av++;
49799ebb4caSwyllys return (opts_av[i].shortnm);
49899ebb4caSwyllys }
49999ebb4caSwyllys
50099ebb4caSwyllys optarg_av = NULL;
50199ebb4caSwyllys optind_av++;
50299ebb4caSwyllys return ((int)'?');
50399ebb4caSwyllys }
5047c478bd9Sstevel@tonic-gate }
5057c478bd9Sstevel@tonic-gate
50699ebb4caSwyllys return (EOF);
5077c478bd9Sstevel@tonic-gate }
5087c478bd9Sstevel@tonic-gate
50999ebb4caSwyllys KMF_KEYSTORE_TYPE
KS2Int(char * keystore_str)51099ebb4caSwyllys KS2Int(char *keystore_str)
51149e21299Sdinak {
51299ebb4caSwyllys if (keystore_str == NULL)
51399ebb4caSwyllys return (0);
514d00756ccSwyllys if (strcasecmp(keystore_str, "pkcs11") == 0)
51599ebb4caSwyllys return (KMF_KEYSTORE_PK11TOKEN);
516d00756ccSwyllys else if (strcasecmp(keystore_str, "nss") == 0)
51799ebb4caSwyllys return (KMF_KEYSTORE_NSS);
518d00756ccSwyllys else if (strcasecmp(keystore_str, "file") == 0)
51999ebb4caSwyllys return (KMF_KEYSTORE_OPENSSL);
52099ebb4caSwyllys else
52199ebb4caSwyllys return (0);
52299ebb4caSwyllys }
52349e21299Sdinak
524e65e5c2dSWyllys Ingersoll /*
525e65e5c2dSWyllys Ingersoll * compare_oids
526e65e5c2dSWyllys Ingersoll * return 1 if equal
527e65e5c2dSWyllys Ingersoll */
528e65e5c2dSWyllys Ingersoll boolean_t
compare_oids(KMF_OID * oid1,const KMF_OID * oid2)529e65e5c2dSWyllys Ingersoll compare_oids(KMF_OID *oid1, const KMF_OID *oid2)
530e65e5c2dSWyllys Ingersoll {
531e65e5c2dSWyllys Ingersoll return ((oid1->Length == oid2->Length) &&
532e65e5c2dSWyllys Ingersoll !memcmp(oid1->Data, oid2->Data, oid1->Length));
533e65e5c2dSWyllys Ingersoll }
53449e21299Sdinak
53599ebb4caSwyllys int
Str2KeyType(char * algm,KMF_OID * hashoid,KMF_KEY_ALG * ktype,KMF_ALGORITHM_INDEX * sigAlg)536e65e5c2dSWyllys Ingersoll Str2KeyType(char *algm, KMF_OID *hashoid, KMF_KEY_ALG *ktype,
537e65e5c2dSWyllys Ingersoll KMF_ALGORITHM_INDEX *sigAlg)
53899ebb4caSwyllys {
53999ebb4caSwyllys if (algm == NULL) {
540e65e5c2dSWyllys Ingersoll /* Default to SHA1+RSA */
5414165f465SWyllys Ingersoll *sigAlg = KMF_ALGID_SHA1WithRSA;
54299ebb4caSwyllys *ktype = KMF_RSA;
54399ebb4caSwyllys } else if (strcasecmp(algm, "DSA") == 0) {
544e65e5c2dSWyllys Ingersoll if (hashoid == NULL ||
545e65e5c2dSWyllys Ingersoll compare_oids(hashoid, &KMFOID_SHA1))
546e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA1WithDSA;
547e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA256))
548e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA256WithDSA;
549e65e5c2dSWyllys Ingersoll else
550e65e5c2dSWyllys Ingersoll return (-1); /* unsupported hash/key combo */
55199ebb4caSwyllys *ktype = KMF_DSA;
55299ebb4caSwyllys } else if (strcasecmp(algm, "RSA") == 0) {
553e65e5c2dSWyllys Ingersoll if (hashoid == NULL ||
554e65e5c2dSWyllys Ingersoll compare_oids(hashoid, &KMFOID_SHA1))
555e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA1WithRSA;
556e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA256))
557e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA256WithRSA;
558e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA384))
559e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA384WithRSA;
560e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA512))
561e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA512WithRSA;
562e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_MD5))
563e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_MD5WithRSA;
564e65e5c2dSWyllys Ingersoll else
565e65e5c2dSWyllys Ingersoll return (-1); /* unsupported hash/key combo */
56699ebb4caSwyllys *ktype = KMF_RSA;
567e65e5c2dSWyllys Ingersoll } else if (strcasecmp(algm, "EC") == 0) {
568e65e5c2dSWyllys Ingersoll /* EC keys may be used with some SHA2 hashes */
569e65e5c2dSWyllys Ingersoll if (hashoid == NULL ||
570e65e5c2dSWyllys Ingersoll compare_oids(hashoid, &KMFOID_SHA1))
571e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA1WithECDSA;
572e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA256))
573e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA256WithECDSA;
574e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA384))
575e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA384WithECDSA;
576e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA512))
577e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA512WithECDSA;
578e65e5c2dSWyllys Ingersoll else
579e65e5c2dSWyllys Ingersoll return (-1); /* unsupported hash/key combo */
580e65e5c2dSWyllys Ingersoll
581e65e5c2dSWyllys Ingersoll *ktype = KMF_ECDSA;
58299ebb4caSwyllys } else {
58399ebb4caSwyllys return (-1);
58449e21299Sdinak }
58599ebb4caSwyllys return (0);
58649e21299Sdinak }
58749e21299Sdinak
58899ebb4caSwyllys int
Str2SymKeyType(char * algm,KMF_KEY_ALG * ktype)58999ebb4caSwyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype)
59049e21299Sdinak {
59199ebb4caSwyllys if (algm == NULL)
59299ebb4caSwyllys *ktype = KMF_AES;
59399ebb4caSwyllys else if (strcasecmp(algm, "aes") == 0)
59499ebb4caSwyllys *ktype = KMF_AES;
59599ebb4caSwyllys else if (strcasecmp(algm, "arcfour") == 0)
59699ebb4caSwyllys *ktype = KMF_RC4;
59799ebb4caSwyllys else if (strcasecmp(algm, "des") == 0)
59899ebb4caSwyllys *ktype = KMF_DES;
59999ebb4caSwyllys else if (strcasecmp(algm, "3des") == 0)
60099ebb4caSwyllys *ktype = KMF_DES3;
601c197cb9dShylee else if (strcasecmp(algm, "generic") == 0)
602c197cb9dShylee *ktype = KMF_GENERIC_SECRET;
60399ebb4caSwyllys else
60499ebb4caSwyllys return (-1);
60549e21299Sdinak
60699ebb4caSwyllys return (0);
60749e21299Sdinak }
60849e21299Sdinak
60949e21299Sdinak int
Str2Lifetime(char * ltimestr,uint32_t * ltime)61099ebb4caSwyllys Str2Lifetime(char *ltimestr, uint32_t *ltime)
61149e21299Sdinak {
61299ebb4caSwyllys int num;
61399ebb4caSwyllys char timetok[6];
61449e21299Sdinak
615d00756ccSwyllys if (ltimestr == NULL || strlen(ltimestr) == 0) {
61699ebb4caSwyllys /* default to 1 year lifetime */
61799ebb4caSwyllys *ltime = SECSPERDAY * DAYSPERNYEAR;
61899ebb4caSwyllys return (0);
61949e21299Sdinak }
62049e21299Sdinak
62199ebb4caSwyllys (void) memset(timetok, 0, sizeof (timetok));
62299ebb4caSwyllys if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2)
62399ebb4caSwyllys return (-1);
62449e21299Sdinak
625d00756ccSwyllys if (strcasecmp(timetok, "day") == 0||
626d00756ccSwyllys strcasecmp(timetok, "days") == 0) {
62799ebb4caSwyllys *ltime = num * SECSPERDAY;
628d00756ccSwyllys } else if (strcasecmp(timetok, "hour") == 0||
629d00756ccSwyllys strcasecmp(timetok, "hours") == 0) {
63099ebb4caSwyllys *ltime = num * SECSPERHOUR;
631d00756ccSwyllys } else if (strcasecmp(timetok, "year") == 0 ||
632d00756ccSwyllys strcasecmp(timetok, "years") == 0) {
63399ebb4caSwyllys *ltime = num * SECSPERDAY * DAYSPERNYEAR;
63499ebb4caSwyllys } else {
63599ebb4caSwyllys *ltime = 0;
63649e21299Sdinak return (-1);
63749e21299Sdinak }
63849e21299Sdinak
63999ebb4caSwyllys return (0);
64099ebb4caSwyllys }
64149e21299Sdinak
64299ebb4caSwyllys int
OT2Int(char * objclass)64399ebb4caSwyllys OT2Int(char *objclass)
64499ebb4caSwyllys {
64599ebb4caSwyllys char *c = NULL;
64699ebb4caSwyllys int retval = 0;
64749e21299Sdinak
64899ebb4caSwyllys if (objclass == NULL)
64999ebb4caSwyllys return (-1);
65049e21299Sdinak
65199ebb4caSwyllys c = strchr(objclass, ':');
65299ebb4caSwyllys if (c != NULL) {
653d00756ccSwyllys if (strcasecmp(c, ":private") == 0)
65499ebb4caSwyllys retval = PK_PRIVATE_OBJ;
655d00756ccSwyllys else if (strcasecmp(c, ":public") == 0)
65699ebb4caSwyllys retval = PK_PUBLIC_OBJ;
657d00756ccSwyllys else if (strcasecmp(c, ":both") == 0)
65899ebb4caSwyllys retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ;
65999ebb4caSwyllys else /* unrecognized option */
66099ebb4caSwyllys return (-1);
66199ebb4caSwyllys
66299ebb4caSwyllys *c = '\0';
66399ebb4caSwyllys }
66499ebb4caSwyllys
665d00756ccSwyllys if (strcasecmp(objclass, "public") == 0) {
66699ebb4caSwyllys if (retval)
66799ebb4caSwyllys return (-1);
66830a5e8faSwyllys return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ);
669d00756ccSwyllys } else if (strcasecmp(objclass, "private") == 0) {
67099ebb4caSwyllys if (retval)
67199ebb4caSwyllys return (-1);
67299ebb4caSwyllys return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ);
673d00756ccSwyllys } else if (strcasecmp(objclass, "both") == 0) {
67499ebb4caSwyllys if (retval)
67599ebb4caSwyllys return (-1);
67699ebb4caSwyllys return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ);
677d00756ccSwyllys } else if (strcasecmp(objclass, "cert") == 0) {
67899ebb4caSwyllys return (retval | PK_CERT_OBJ);
679d00756ccSwyllys } else if (strcasecmp(objclass, "key") == 0) {
68099ebb4caSwyllys if (retval == 0) /* return all keys */
68199ebb4caSwyllys return (retval | PK_KEY_OBJ);
68299ebb4caSwyllys else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ))
68399ebb4caSwyllys /* return all keys */
68499ebb4caSwyllys return (retval | PK_KEY_OBJ);
68599ebb4caSwyllys else if (retval & PK_PUBLIC_OBJ)
68699ebb4caSwyllys /* Only return public keys */
68799ebb4caSwyllys return (retval | PK_PUBKEY_OBJ);
68899ebb4caSwyllys else if (retval & PK_PRIVATE_OBJ)
68999ebb4caSwyllys /* Only return private keys */
69099ebb4caSwyllys return (retval | PK_PRIKEY_OBJ);
691d00756ccSwyllys } else if (strcasecmp(objclass, "crl") == 0) {
69299ebb4caSwyllys if (retval)
69399ebb4caSwyllys return (-1);
69499ebb4caSwyllys return (retval | PK_CRL_OBJ);
69599ebb4caSwyllys }
69699ebb4caSwyllys
69799ebb4caSwyllys if (retval == 0) /* No matches found */
69899ebb4caSwyllys retval = -1;
69999ebb4caSwyllys return (retval);
70049e21299Sdinak }
70149e21299Sdinak
70299ebb4caSwyllys KMF_ENCODE_FORMAT
Str2Format(char * formstr)70399ebb4caSwyllys Str2Format(char *formstr)
7047c478bd9Sstevel@tonic-gate {
705d00756ccSwyllys if (formstr == NULL || strcasecmp(formstr, "der") == 0)
70699ebb4caSwyllys return (KMF_FORMAT_ASN1);
707d00756ccSwyllys if (strcasecmp(formstr, "pem") == 0)
70899ebb4caSwyllys return (KMF_FORMAT_PEM);
709d00756ccSwyllys if (strcasecmp(formstr, "pkcs12") == 0)
71099ebb4caSwyllys return (KMF_FORMAT_PKCS12);
711d00756ccSwyllys if (strcasecmp(formstr, "raw") == 0)
71230a5e8faSwyllys return (KMF_FORMAT_RAWKEY);
71399ebb4caSwyllys
71499ebb4caSwyllys return (KMF_FORMAT_UNDEF);
71599ebb4caSwyllys }
7167c478bd9Sstevel@tonic-gate
71799ebb4caSwyllys KMF_RETURN
select_token(void * kmfhandle,char * token,int readonly)718d00756ccSwyllys select_token(void *kmfhandle, char *token, int readonly)
71999ebb4caSwyllys {
72030a5e8faSwyllys KMF_ATTRIBUTE attlist[10];
72130a5e8faSwyllys int i = 0;
72230a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
72399ebb4caSwyllys KMF_RETURN rv = KMF_OK;
7247711facfSdinak
72599ebb4caSwyllys if (token == NULL)
72699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
7277c478bd9Sstevel@tonic-gate
72830a5e8faSwyllys kmf_set_attr_at_index(attlist, i,
72930a5e8faSwyllys KMF_KEYSTORE_TYPE_ATTR, &kstype,
73030a5e8faSwyllys sizeof (kstype));
73130a5e8faSwyllys i++;
7327711facfSdinak
73330a5e8faSwyllys if (token) {
73430a5e8faSwyllys kmf_set_attr_at_index(attlist, i,
73530a5e8faSwyllys KMF_TOKEN_LABEL_ATTR, token,
73630a5e8faSwyllys strlen(token));
73730a5e8faSwyllys i++;
73830a5e8faSwyllys }
73930a5e8faSwyllys
74030a5e8faSwyllys kmf_set_attr_at_index(attlist, i,
74130a5e8faSwyllys KMF_READONLY_ATTR, &readonly,
74230a5e8faSwyllys sizeof (readonly));
74330a5e8faSwyllys i++;
74430a5e8faSwyllys
74530a5e8faSwyllys rv = kmf_configure_keystore(kmfhandle, i, attlist);
74699ebb4caSwyllys if (rv == KMF_ERR_TOKEN_SELECTED)
74799ebb4caSwyllys rv = KMF_OK;
74899ebb4caSwyllys return (rv);
7497711facfSdinak }
7507711facfSdinak
75199ebb4caSwyllys KMF_RETURN
configure_nss(void * kmfhandle,char * dir,char * prefix)75299ebb4caSwyllys configure_nss(void *kmfhandle, char *dir, char *prefix)
7537711facfSdinak {
75430a5e8faSwyllys KMF_ATTRIBUTE attlist[10];
75530a5e8faSwyllys int i = 0;
75630a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
75799ebb4caSwyllys KMF_RETURN rv = KMF_OK;
7587711facfSdinak
75930a5e8faSwyllys kmf_set_attr_at_index(attlist, i,
76030a5e8faSwyllys KMF_KEYSTORE_TYPE_ATTR, &kstype,
76130a5e8faSwyllys sizeof (kstype));
76230a5e8faSwyllys i++;
76330a5e8faSwyllys
76430a5e8faSwyllys if (dir) {
76530a5e8faSwyllys kmf_set_attr_at_index(attlist, i,
76630a5e8faSwyllys KMF_DIRPATH_ATTR, dir,
76730a5e8faSwyllys strlen(dir));
76830a5e8faSwyllys i++;
76930a5e8faSwyllys }
77030a5e8faSwyllys
77130a5e8faSwyllys if (prefix) {
77230a5e8faSwyllys kmf_set_attr_at_index(attlist, i,
77330a5e8faSwyllys KMF_CERTPREFIX_ATTR, prefix,
77430a5e8faSwyllys strlen(prefix));
77530a5e8faSwyllys i++;
77630a5e8faSwyllys
77730a5e8faSwyllys kmf_set_attr_at_index(attlist, i,
77830a5e8faSwyllys KMF_KEYPREFIX_ATTR, prefix,
77930a5e8faSwyllys strlen(prefix));
78030a5e8faSwyllys i++;
78130a5e8faSwyllys }
7827711facfSdinak
78330a5e8faSwyllys rv = kmf_configure_keystore(kmfhandle, i, attlist);
78499ebb4caSwyllys if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED)
78599ebb4caSwyllys rv = KMF_OK;
7867c478bd9Sstevel@tonic-gate
78799ebb4caSwyllys return (rv);
78899ebb4caSwyllys }
7897711facfSdinak
79099ebb4caSwyllys KMF_RETURN
get_pk12_password(KMF_CREDENTIAL * cred)79199ebb4caSwyllys get_pk12_password(KMF_CREDENTIAL *cred)
79299ebb4caSwyllys {
79399ebb4caSwyllys KMF_RETURN rv = KMF_OK;
79499ebb4caSwyllys char prompt[1024];
7957711facfSdinak
7967711facfSdinak /*
79799ebb4caSwyllys * Get the password to use for the PK12 encryption.
7987711facfSdinak */
79999ebb4caSwyllys (void) strlcpy(prompt,
80030a5e8faSwyllys gettext("Enter password to use for "
80130a5e8faSwyllys "accessing the PKCS12 file: "), sizeof (prompt));
8027711facfSdinak
80399ebb4caSwyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
80430a5e8faSwyllys (ulong_t *)&cred->credlen) != CKR_OK) {
80599ebb4caSwyllys cred->cred = NULL;
80699ebb4caSwyllys cred->credlen = 0;
8077711facfSdinak }
8087711facfSdinak
8097711facfSdinak return (rv);
8107711facfSdinak }
8117711facfSdinak
8122cbed729Swyllys #define FILENAME_PROMPT gettext("Filename:")
8132cbed729Swyllys #define FILENAME_MINLEN 1
8142cbed729Swyllys #define FILENAME_MAXLEN MAXPATHLEN
8152cbed729Swyllys
8162cbed729Swyllys #define COUNTRY_PROMPT gettext("Country Name (2 letter code) [US]:")
8172cbed729Swyllys #define STATE_PROMPT gettext("State or Province Name (full name) " \
8182cbed729Swyllys "[Some-State]:")
8192cbed729Swyllys #define LOCALITY_PROMPT gettext("Locality Name (eg, city) []:")
8202cbed729Swyllys #define ORG_PROMPT gettext("Organization Name (eg, company) []:")
8212cbed729Swyllys #define UNIT_PROMPT gettext("Organizational Unit Name (eg, section) []:")
8222cbed729Swyllys #define NAME_PROMPT gettext("Common Name (eg, YOUR name) []:")
8232cbed729Swyllys #define EMAIL_PROMPT gettext("Email Address []:")
8242cbed729Swyllys
8252cbed729Swyllys #define SERNO_PROMPT gettext("Serial Number (hex value, example: " \
8262cbed729Swyllys "0x01020304):")
8272cbed729Swyllys #define SERNO_MINLEN 3
8282cbed729Swyllys #define SERNO_MAXLEN 42
8292cbed729Swyllys
8302cbed729Swyllys #define LABEL_PROMPT gettext("Enter a label for the certificate:")
8312cbed729Swyllys #define LABEL_MINLEN 1
8322cbed729Swyllys #define LABEL_MAXLEN 1024
8337711facfSdinak
83499ebb4caSwyllys #define COUNTRY_DEFAULT "US"
8352cbed729Swyllys #define STATE_DEFAULT NULL
836*6f2b04a2SToomas Soome #define INVALID_INPUT gettext("Invalid input; please re-enter ...")
8377711facfSdinak
83899ebb4caSwyllys #define SUBNAMESIZ 1024
83999ebb4caSwyllys #define RDN_MIN 1
84099ebb4caSwyllys #define RDN_MAX 64
84199ebb4caSwyllys #define COUNTRYNAME_MIN 2
84299ebb4caSwyllys #define COUNTRYNAME_MAX 2
8437711facfSdinak
84499ebb4caSwyllys static char *
get_input_string(char * prompt,char * default_str,int min_len,int max_len)84599ebb4caSwyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len)
84699ebb4caSwyllys {
84799ebb4caSwyllys char buf[1024];
84899ebb4caSwyllys char *response = NULL;
84999ebb4caSwyllys char *ret = NULL;
85099ebb4caSwyllys int len;
8517711facfSdinak
85299ebb4caSwyllys for (;;) {
85399ebb4caSwyllys (void) printf("\t%s", prompt);
85499ebb4caSwyllys (void) fflush(stdout);
85599ebb4caSwyllys
85699ebb4caSwyllys response = fgets(buf, sizeof (buf), stdin);
85799ebb4caSwyllys if (response == NULL) {
85899ebb4caSwyllys if (default_str != NULL) {
85999ebb4caSwyllys ret = strdup(default_str);
86099ebb4caSwyllys }
86199ebb4caSwyllys break;
86299ebb4caSwyllys }
86399ebb4caSwyllys
86499ebb4caSwyllys /* Skip any leading white space. */
86599ebb4caSwyllys while (isspace(*response))
86699ebb4caSwyllys response++;
86799ebb4caSwyllys if (*response == '\0') {
86899ebb4caSwyllys if (default_str != NULL) {
86999ebb4caSwyllys ret = strdup(default_str);
87099ebb4caSwyllys }
87199ebb4caSwyllys break;
87299ebb4caSwyllys }
87399ebb4caSwyllys
87499ebb4caSwyllys len = strlen(response);
87599ebb4caSwyllys response[len-1] = '\0'; /* get rid of "LF" */
87699ebb4caSwyllys len--;
87799ebb4caSwyllys if (len >= min_len && len <= max_len) {
87899ebb4caSwyllys ret = strdup(response);
87999ebb4caSwyllys break;
8807711facfSdinak }
8817711facfSdinak
88299ebb4caSwyllys (void) printf("%s\n", INVALID_INPUT);
88399ebb4caSwyllys
8847711facfSdinak }
8857711facfSdinak
88699ebb4caSwyllys return (ret);
88799ebb4caSwyllys }
8887711facfSdinak
8892cbed729Swyllys int
get_filename(char * txt,char ** result)8902cbed729Swyllys get_filename(char *txt, char **result)
8912cbed729Swyllys {
8922cbed729Swyllys char prompt[1024];
8932cbed729Swyllys char *fname = NULL;
8942cbed729Swyllys
8952cbed729Swyllys (void) snprintf(prompt, sizeof (prompt),
8962cbed729Swyllys gettext("Enter filename for the %s: "),
8972cbed729Swyllys txt);
8982cbed729Swyllys fname = get_input_string(prompt, NULL,
8992cbed729Swyllys FILENAME_MINLEN, FILENAME_MAXLEN);
9002cbed729Swyllys *result = fname;
9012cbed729Swyllys return (0);
9022cbed729Swyllys }
9032cbed729Swyllys
9042cbed729Swyllys int
get_certlabel(char ** result)9052cbed729Swyllys get_certlabel(char **result)
9062cbed729Swyllys {
9072cbed729Swyllys char *label = NULL;
9082cbed729Swyllys
9092cbed729Swyllys label = get_input_string(LABEL_PROMPT, NULL,
9102cbed729Swyllys LABEL_MINLEN, LABEL_MAXLEN);
9112cbed729Swyllys *result = label;
9122cbed729Swyllys return (0);
9132cbed729Swyllys }
9142cbed729Swyllys
9152cbed729Swyllys int
get_serial(char ** result)9162cbed729Swyllys get_serial(char **result)
9172cbed729Swyllys {
9182cbed729Swyllys char *serial = NULL;
9192cbed729Swyllys
9202cbed729Swyllys serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN,
9212cbed729Swyllys SERNO_MAXLEN);
9222cbed729Swyllys
9232cbed729Swyllys *result = serial;
9242cbed729Swyllys return (0);
9252cbed729Swyllys }
9262cbed729Swyllys
92799ebb4caSwyllys int
get_subname(char ** result)92899ebb4caSwyllys get_subname(char **result)
92999ebb4caSwyllys {
93099ebb4caSwyllys char *country = NULL;
93199ebb4caSwyllys char *state = NULL;
93299ebb4caSwyllys char *locality = NULL;
93399ebb4caSwyllys char *org = NULL;
93499ebb4caSwyllys char *unit = NULL;
93599ebb4caSwyllys char *name = NULL;
93699ebb4caSwyllys char *email = NULL;
93799ebb4caSwyllys char *subname = NULL;
93899ebb4caSwyllys
93999ebb4caSwyllys (void) printf("Entering following fields for subject (a DN) ...\n");
94099ebb4caSwyllys country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT,
94199ebb4caSwyllys COUNTRYNAME_MIN, COUNTRYNAME_MAX);
94299ebb4caSwyllys if (country == NULL)
94399ebb4caSwyllys return (-1);
94499ebb4caSwyllys
94599ebb4caSwyllys state = get_input_string(STATE_PROMPT, STATE_DEFAULT,
94699ebb4caSwyllys RDN_MIN, RDN_MAX);
9477711facfSdinak
94899ebb4caSwyllys locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX);
94999ebb4caSwyllys org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX);
95099ebb4caSwyllys unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX);
95199ebb4caSwyllys name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX);
95299ebb4caSwyllys email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX);
9537711facfSdinak
95499ebb4caSwyllys /* Now create a subject name from the input strings */
95599ebb4caSwyllys if ((subname = malloc(SUBNAMESIZ)) == NULL)
95699ebb4caSwyllys goto out;
95799ebb4caSwyllys
95899ebb4caSwyllys (void) memset(subname, 0, SUBNAMESIZ);
95999ebb4caSwyllys (void) strlcpy(subname, "C=", SUBNAMESIZ);
96099ebb4caSwyllys (void) strlcat(subname, country, SUBNAMESIZ);
9612cbed729Swyllys if (state != NULL) {
9622cbed729Swyllys (void) strlcat(subname, ", ST=", SUBNAMESIZ);
9632cbed729Swyllys (void) strlcat(subname, state, SUBNAMESIZ);
9642cbed729Swyllys }
9657711facfSdinak
9662cbed729Swyllys if (locality != NULL) {
9672cbed729Swyllys (void) strlcat(subname, ", L=", SUBNAMESIZ);
96899ebb4caSwyllys (void) strlcat(subname, locality, SUBNAMESIZ);
9697711facfSdinak }
9707711facfSdinak
9712cbed729Swyllys if (org != NULL) {
9722cbed729Swyllys (void) strlcat(subname, ", O=", SUBNAMESIZ);
97399ebb4caSwyllys (void) strlcat(subname, org, SUBNAMESIZ);
9747711facfSdinak }
9757711facfSdinak
9762cbed729Swyllys if (unit != NULL) {
9772cbed729Swyllys (void) strlcat(subname, ", OU=", SUBNAMESIZ);
97899ebb4caSwyllys (void) strlcat(subname, unit, SUBNAMESIZ);
97999ebb4caSwyllys }
9807711facfSdinak
9812cbed729Swyllys if (name != NULL) {
9822cbed729Swyllys (void) strlcat(subname, ", CN=", SUBNAMESIZ);
98399ebb4caSwyllys (void) strlcat(subname, name, SUBNAMESIZ);
9847711facfSdinak }
9857711facfSdinak
9862cbed729Swyllys if (email != NULL) {
9872cbed729Swyllys (void) strlcat(subname, ", E=", SUBNAMESIZ);
98899ebb4caSwyllys (void) strlcat(subname, email, SUBNAMESIZ);
9897c478bd9Sstevel@tonic-gate }
9907c478bd9Sstevel@tonic-gate
99199ebb4caSwyllys out:
99299ebb4caSwyllys if (country)
99399ebb4caSwyllys free(country);
99499ebb4caSwyllys if (state)
99599ebb4caSwyllys free(state);
99699ebb4caSwyllys if (locality)
99799ebb4caSwyllys free(locality);
99899ebb4caSwyllys if (org)
99999ebb4caSwyllys free(org);
100099ebb4caSwyllys if (unit)
100199ebb4caSwyllys free(unit);
100299ebb4caSwyllys if (name)
100399ebb4caSwyllys free(name);
100499ebb4caSwyllys if (email)
100599ebb4caSwyllys free(email);
100699ebb4caSwyllys
100799ebb4caSwyllys if (subname == NULL)
100899ebb4caSwyllys return (-1);
100999ebb4caSwyllys else {
101099ebb4caSwyllys *result = subname;
101199ebb4caSwyllys return (0);
10127711facfSdinak }
10137c478bd9Sstevel@tonic-gate }
10147c478bd9Sstevel@tonic-gate
10157c478bd9Sstevel@tonic-gate /*
101699ebb4caSwyllys * Parse a string of KeyUsage values and convert
101799ebb4caSwyllys * them to the correct KU Bits.
101899ebb4caSwyllys * The field may be marked "critical" by prepending
101999ebb4caSwyllys * "critical:" to the list.
102099ebb4caSwyllys * EX: critical:digitialSignature,keyEncipherment
10217c478bd9Sstevel@tonic-gate */
102299ebb4caSwyllys KMF_RETURN
verify_keyusage(char * kustr,uint16_t * kubits,int * critical)102399ebb4caSwyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical)
10247c478bd9Sstevel@tonic-gate {
102599ebb4caSwyllys KMF_RETURN ret = KMF_OK;
102699ebb4caSwyllys uint16_t kuval;
102799ebb4caSwyllys char *k;
102899ebb4caSwyllys
102999ebb4caSwyllys *kubits = 0;
1030d00756ccSwyllys if (kustr == NULL || strlen(kustr) == 0)
103199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
103299ebb4caSwyllys
103399ebb4caSwyllys /* Check to see if this is critical */
1034d00756ccSwyllys if (strncasecmp(kustr, "critical:", strlen("critical:")) == 0) {
103599ebb4caSwyllys *critical = TRUE;
103699ebb4caSwyllys kustr += strlen("critical:");
103799ebb4caSwyllys } else {
103899ebb4caSwyllys *critical = FALSE;
10397c478bd9Sstevel@tonic-gate }
10407711facfSdinak
104199ebb4caSwyllys k = strtok(kustr, ",");
104299ebb4caSwyllys while (k != NULL) {
104330a5e8faSwyllys kuval = kmf_string_to_ku(k);
104499ebb4caSwyllys if (kuval == 0) {
104599ebb4caSwyllys *kubits = 0;
104699ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
10477711facfSdinak }
104899ebb4caSwyllys *kubits |= kuval;
104999ebb4caSwyllys k = strtok(NULL, ",");
10507711facfSdinak }
10517711facfSdinak
105299ebb4caSwyllys return (ret);
10537711facfSdinak }
10547711facfSdinak
10557711facfSdinak /*
105699ebb4caSwyllys * Verify the alternate subject label is real or invalid.
105799ebb4caSwyllys *
105899ebb4caSwyllys * The field may be marked "critical" by prepending
105999ebb4caSwyllys * "critical:" to the list.
106099ebb4caSwyllys * EX: "critical:IP=1.2.3.4"
10617711facfSdinak */
106299ebb4caSwyllys KMF_RETURN
verify_altname(char * arg,KMF_GENERALNAMECHOICES * type,int * critical)106399ebb4caSwyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical)
10647711facfSdinak {
106599ebb4caSwyllys char *p;
106699ebb4caSwyllys KMF_RETURN rv = KMF_OK;
10677711facfSdinak
106899ebb4caSwyllys /* Check to see if this is critical */
1069d00756ccSwyllys if (strncasecmp(arg, "critical:", strlen("critical:")) == 0) {
107099ebb4caSwyllys *critical = TRUE;
107199ebb4caSwyllys arg += strlen("critical:");
107299ebb4caSwyllys } else {
107399ebb4caSwyllys *critical = FALSE;
107499ebb4caSwyllys }
10757711facfSdinak
107699ebb4caSwyllys /* Make sure there is an "=" sign */
107799ebb4caSwyllys p = strchr(arg, '=');
107899ebb4caSwyllys if (p == NULL)
107999ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER);
10807711facfSdinak
108199ebb4caSwyllys p[0] = '\0';
108299ebb4caSwyllys
108399ebb4caSwyllys if (strcmp(arg, "IP") == 0)
108499ebb4caSwyllys *type = GENNAME_IPADDRESS;
108599ebb4caSwyllys else if (strcmp(arg, "DNS") == 0)
108699ebb4caSwyllys *type = GENNAME_DNSNAME;
108799ebb4caSwyllys else if (strcmp(arg, "EMAIL") == 0)
108899ebb4caSwyllys *type = GENNAME_RFC822NAME;
108999ebb4caSwyllys else if (strcmp(arg, "URI") == 0)
109099ebb4caSwyllys *type = GENNAME_URI;
109199ebb4caSwyllys else if (strcmp(arg, "DN") == 0)
109299ebb4caSwyllys *type = GENNAME_DIRECTORYNAME;
109399ebb4caSwyllys else if (strcmp(arg, "RID") == 0)
109499ebb4caSwyllys *type = GENNAME_REGISTEREDID;
1095d00756ccSwyllys else if (strcmp(arg, "KRB") == 0)
1096d00756ccSwyllys *type = GENNAME_KRB5PRINC;
1097d00756ccSwyllys else if (strcmp(arg, "UPN") == 0)
1098d00756ccSwyllys *type = GENNAME_SCLOGON_UPN;
109999ebb4caSwyllys else
110099ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER;
110199ebb4caSwyllys
110299ebb4caSwyllys p[0] = '=';
110399ebb4caSwyllys
110499ebb4caSwyllys return (rv);
11057c478bd9Sstevel@tonic-gate }
110649e21299Sdinak
110799ebb4caSwyllys int
get_token_password(KMF_KEYSTORE_TYPE kstype,char * token_spec,KMF_CREDENTIAL * cred)110899ebb4caSwyllys get_token_password(KMF_KEYSTORE_TYPE kstype,
110999ebb4caSwyllys char *token_spec, KMF_CREDENTIAL *cred)
111049e21299Sdinak {
111199ebb4caSwyllys char prompt[1024];
111272ca8cc9SWyllys Ingersoll char temptoken[32];
111399ebb4caSwyllys char *p = NULL;
111472ca8cc9SWyllys Ingersoll char *t = NULL;
111547e946e7SWyllys Ingersoll int len;
111649e21299Sdinak
111747e946e7SWyllys Ingersoll (void) memset(temptoken, 0, sizeof (temptoken));
111899ebb4caSwyllys if (kstype == KMF_KEYSTORE_PK11TOKEN) {
111999ebb4caSwyllys p = strchr(token_spec, ':');
112099ebb4caSwyllys if (p != NULL)
112172ca8cc9SWyllys Ingersoll *p = 0;
112272ca8cc9SWyllys Ingersoll }
112347e946e7SWyllys Ingersoll len = strlen(token_spec);
112447e946e7SWyllys Ingersoll if (len > sizeof (temptoken))
112547e946e7SWyllys Ingersoll len = sizeof (temptoken);
112647e946e7SWyllys Ingersoll
112747e946e7SWyllys Ingersoll (void) strncpy(temptoken, token_spec, len);
112872ca8cc9SWyllys Ingersoll
112972ca8cc9SWyllys Ingersoll /*
113072ca8cc9SWyllys Ingersoll * Strip trailing whitespace
113172ca8cc9SWyllys Ingersoll */
113247e946e7SWyllys Ingersoll t = temptoken + (len - 1);
113372ca8cc9SWyllys Ingersoll while (isspace(*t) && t >= temptoken) {
113472ca8cc9SWyllys Ingersoll *t = 0x00;
113572ca8cc9SWyllys Ingersoll t--;
113699ebb4caSwyllys }
113772ca8cc9SWyllys Ingersoll
113849e21299Sdinak /*
113999ebb4caSwyllys * Login to the token first.
114049e21299Sdinak */
114199ebb4caSwyllys (void) snprintf(prompt, sizeof (prompt),
114272ca8cc9SWyllys Ingersoll gettext(DEFAULT_TOKEN_PROMPT), temptoken);
114349e21299Sdinak
114499ebb4caSwyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred,
114530a5e8faSwyllys (ulong_t *)&cred->credlen) != CKR_OK) {
114699ebb4caSwyllys cred->cred = NULL;
114799ebb4caSwyllys cred->credlen = 0;
114849e21299Sdinak }
114949e21299Sdinak
115099ebb4caSwyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL)
115199ebb4caSwyllys *p = ':';
115299ebb4caSwyllys return (KMF_OK);
115349e21299Sdinak }
115449e21299Sdinak
115599ebb4caSwyllys KMF_RETURN
verify_file(char * filename)115699ebb4caSwyllys verify_file(char *filename)
115749e21299Sdinak {
115899ebb4caSwyllys KMF_RETURN ret = KMF_OK;
115999ebb4caSwyllys int fd;
116049e21299Sdinak
116199ebb4caSwyllys /*
116299ebb4caSwyllys * Attempt to open with the EXCL flag so that if
116399ebb4caSwyllys * it already exists, the open will fail. It will
116499ebb4caSwyllys * also fail if the file cannot be created due to
116599ebb4caSwyllys * permissions on the parent directory, or if the
116699ebb4caSwyllys * parent directory itself does not exist.
116799ebb4caSwyllys */
116899ebb4caSwyllys fd = open(filename, O_CREAT | O_EXCL, 0600);
11692c9a247fSWyllys Ingersoll if (fd == -1) {
11702c9a247fSWyllys Ingersoll if (errno == EEXIST)
11712c9a247fSWyllys Ingersoll return (KMF_ERR_OPEN_FILE);
11722c9a247fSWyllys Ingersoll else
11732c9a247fSWyllys Ingersoll return (KMF_ERR_WRITE_FILE);
11742c9a247fSWyllys Ingersoll }
117549e21299Sdinak
117699ebb4caSwyllys /* If we were able to create it, delete it. */
117799ebb4caSwyllys (void) close(fd);
117899ebb4caSwyllys (void) unlink(filename);
117949e21299Sdinak
118099ebb4caSwyllys return (ret);
118199ebb4caSwyllys }
118249e21299Sdinak
118399ebb4caSwyllys void
display_error(void * handle,KMF_RETURN errcode,char * prefix)118499ebb4caSwyllys display_error(void *handle, KMF_RETURN errcode, char *prefix)
118599ebb4caSwyllys {
118699ebb4caSwyllys KMF_RETURN rv1, rv2;
118799ebb4caSwyllys char *plugin_errmsg = NULL;
118899ebb4caSwyllys char *kmf_errmsg = NULL;
118949e21299Sdinak
119030a5e8faSwyllys rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg);
119130a5e8faSwyllys rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg);
119249e21299Sdinak
119399ebb4caSwyllys cryptoerror(LOG_STDERR, "%s:", prefix);
119499ebb4caSwyllys if (rv1 == KMF_OK && plugin_errmsg) {
119530a5e8faSwyllys cryptoerror(LOG_STDERR, gettext("keystore error: %s"),
119630a5e8faSwyllys plugin_errmsg);
119730a5e8faSwyllys kmf_free_str(plugin_errmsg);
119899ebb4caSwyllys }
119949e21299Sdinak
120099ebb4caSwyllys if (rv2 == KMF_OK && kmf_errmsg) {
120130a5e8faSwyllys cryptoerror(LOG_STDERR, gettext("libkmf error: %s"),
120230a5e8faSwyllys kmf_errmsg);
120330a5e8faSwyllys kmf_free_str(kmf_errmsg);
120449e21299Sdinak }
120549e21299Sdinak
120699ebb4caSwyllys if (rv1 != KMF_OK && rv2 != KMF_OK)
120799ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("<unknown error>\n"));
120899ebb4caSwyllys
120949e21299Sdinak }
1210d00756ccSwyllys
1211d00756ccSwyllys static KMF_RETURN
addToEKUList(EKU_LIST * ekus,int critical,KMF_OID * newoid)1212d00756ccSwyllys addToEKUList(EKU_LIST *ekus, int critical, KMF_OID *newoid)
1213d00756ccSwyllys {
1214d00756ccSwyllys if (newoid != NULL && ekus != NULL) {
1215d00756ccSwyllys ekus->eku_count++;
1216d00756ccSwyllys
1217d00756ccSwyllys ekus->critlist = realloc(ekus->critlist,
1218d00756ccSwyllys ekus->eku_count * sizeof (int));
1219d00756ccSwyllys if (ekus->critlist != NULL)
1220d00756ccSwyllys ekus->critlist[ekus->eku_count-1] = critical;
1221d00756ccSwyllys else
1222d00756ccSwyllys return (KMF_ERR_MEMORY);
1223d00756ccSwyllys
1224d00756ccSwyllys ekus->ekulist = realloc(
1225d00756ccSwyllys ekus->ekulist, ekus->eku_count * sizeof (KMF_OID));
1226d00756ccSwyllys if (ekus->ekulist != NULL)
1227d00756ccSwyllys ekus->ekulist[ekus->eku_count-1] = *newoid;
1228d00756ccSwyllys else
1229d00756ccSwyllys return (KMF_ERR_MEMORY);
1230d00756ccSwyllys }
1231d00756ccSwyllys return (KMF_OK);
1232d00756ccSwyllys }
1233d00756ccSwyllys
1234d00756ccSwyllys void
free_eku_list(EKU_LIST * ekus)1235d00756ccSwyllys free_eku_list(EKU_LIST *ekus)
1236d00756ccSwyllys {
1237d00756ccSwyllys if (ekus != NULL && ekus->eku_count > 0) {
1238d00756ccSwyllys int i;
1239d00756ccSwyllys for (i = 0; i < ekus->eku_count; i++) {
1240d00756ccSwyllys kmf_free_data(&ekus->ekulist[i]);
1241d00756ccSwyllys }
1242d00756ccSwyllys free(ekus->ekulist);
1243d00756ccSwyllys free(ekus->critlist);
124456664548SWyllys Ingersoll free(ekus);
1245d00756ccSwyllys }
1246d00756ccSwyllys }
1247d00756ccSwyllys
1248d00756ccSwyllys static KMF_RETURN
parse_ekus(char * ekustr,EKU_LIST * ekus)1249d00756ccSwyllys parse_ekus(char *ekustr, EKU_LIST *ekus)
1250d00756ccSwyllys {
1251d00756ccSwyllys KMF_RETURN rv = KMF_OK;
1252d00756ccSwyllys KMF_OID *newoid;
1253d00756ccSwyllys int critical;
1254d00756ccSwyllys
1255d00756ccSwyllys if (strncasecmp(ekustr, "critical:",
1256d00756ccSwyllys strlen("critical:")) == 0) {
1257d00756ccSwyllys critical = TRUE;
1258d00756ccSwyllys ekustr += strlen("critical:");
1259d00756ccSwyllys } else {
1260d00756ccSwyllys critical = FALSE;
1261d00756ccSwyllys }
1262d00756ccSwyllys newoid = kmf_ekuname_to_oid(ekustr);
1263d00756ccSwyllys if (newoid != NULL) {
1264d00756ccSwyllys rv = addToEKUList(ekus, critical, newoid);
1265d00756ccSwyllys free(newoid);
1266d00756ccSwyllys } else {
1267d00756ccSwyllys rv = PK_ERR_USAGE;
1268d00756ccSwyllys }
1269d00756ccSwyllys
1270d00756ccSwyllys return (rv);
1271d00756ccSwyllys }
1272d00756ccSwyllys
1273d00756ccSwyllys KMF_RETURN
verify_ekunames(char * ekuliststr,EKU_LIST ** ekulist)1274d00756ccSwyllys verify_ekunames(char *ekuliststr, EKU_LIST **ekulist)
1275d00756ccSwyllys {
1276d00756ccSwyllys KMF_RETURN rv = KMF_OK;
1277d00756ccSwyllys char *p;
1278d00756ccSwyllys EKU_LIST *ekus = NULL;
1279d00756ccSwyllys
1280d00756ccSwyllys if (ekuliststr == NULL || strlen(ekuliststr) == 0)
1281d00756ccSwyllys return (0);
1282d00756ccSwyllys
128356664548SWyllys Ingersoll ekus = calloc(sizeof (EKU_LIST), 1);
128456664548SWyllys Ingersoll if (ekus == NULL)
128556664548SWyllys Ingersoll return (KMF_ERR_MEMORY);
128656664548SWyllys Ingersoll
1287d00756ccSwyllys /*
1288d00756ccSwyllys * The list should be comma separated list of EKU Names.
1289d00756ccSwyllys */
1290d00756ccSwyllys p = strtok(ekuliststr, ",");
1291d00756ccSwyllys
1292d00756ccSwyllys /* If no tokens found, then maybe it's just a single EKU value */
1293d00756ccSwyllys if (p == NULL) {
1294d00756ccSwyllys rv = parse_ekus(ekuliststr, ekus);
1295d00756ccSwyllys }
1296d00756ccSwyllys
1297d00756ccSwyllys while (p != NULL) {
1298d00756ccSwyllys rv = parse_ekus(p, ekus);
1299d00756ccSwyllys
1300d00756ccSwyllys if (rv != KMF_OK)
1301d00756ccSwyllys break;
1302d00756ccSwyllys p = strtok(NULL, ",");
1303d00756ccSwyllys }
1304d00756ccSwyllys
1305d00756ccSwyllys if (rv != KMF_OK)
1306d00756ccSwyllys free_eku_list(ekus);
1307d00756ccSwyllys else
1308d00756ccSwyllys *ekulist = ekus;
1309d00756ccSwyllys
1310d00756ccSwyllys return (rv);
1311d00756ccSwyllys }
1312fa60c371Swyllys
1313fa60c371Swyllys KMF_RETURN
token_auth_needed(KMF_HANDLE_T handle,char * tokenlabel,int * auth)1314fa60c371Swyllys token_auth_needed(KMF_HANDLE_T handle, char *tokenlabel, int *auth)
1315fa60c371Swyllys {
1316fa60c371Swyllys CK_TOKEN_INFO info;
1317fa60c371Swyllys CK_SLOT_ID slot;
1318fa60c371Swyllys CK_RV ckrv;
1319fa60c371Swyllys KMF_RETURN rv;
1320fa60c371Swyllys
1321fa60c371Swyllys *auth = 0;
1322fa60c371Swyllys rv = kmf_pk11_token_lookup(handle, tokenlabel, &slot);
1323fa60c371Swyllys if (rv != KMF_OK)
1324fa60c371Swyllys return (rv);
1325fa60c371Swyllys
1326fa60c371Swyllys ckrv = C_GetTokenInfo(slot, &info);
1327fa60c371Swyllys if (ckrv != KMF_OK)
1328fa60c371Swyllys return (KMF_ERR_INTERNAL);
1329fa60c371Swyllys
1330fa60c371Swyllys *auth = (info.flags & CKF_LOGIN_REQUIRED);
1331fa60c371Swyllys
1332fa60c371Swyllys return (KMF_OK);
1333fa60c371Swyllys }
1334e65e5c2dSWyllys Ingersoll
1335e65e5c2dSWyllys Ingersoll void
show_ecc_curves()1336e65e5c2dSWyllys Ingersoll show_ecc_curves()
1337e65e5c2dSWyllys Ingersoll {
1338e65e5c2dSWyllys Ingersoll int i;
1339e65e5c2dSWyllys Ingersoll
1340e65e5c2dSWyllys Ingersoll (void) printf(gettext("Supported ECC curve names:\n"));
1341e65e5c2dSWyllys Ingersoll for (i = 0; i < number_of_curves; i++) {
1342e65e5c2dSWyllys Ingersoll (void) printf("%s", oid_table[i].name);
1343e65e5c2dSWyllys Ingersoll if (i > 0 && ((i+1) % 5) == 0)
1344e65e5c2dSWyllys Ingersoll (void) printf("\n");
1345e65e5c2dSWyllys Ingersoll else if (i+1 < number_of_curves)
1346e65e5c2dSWyllys Ingersoll (void) printf(", ");
1347e65e5c2dSWyllys Ingersoll }
1348e65e5c2dSWyllys Ingersoll (void) printf("\n");
1349e65e5c2dSWyllys Ingersoll }
1350e65e5c2dSWyllys Ingersoll
1351e65e5c2dSWyllys Ingersoll KMF_OID *
ecc_name_to_oid(char * name)1352e65e5c2dSWyllys Ingersoll ecc_name_to_oid(char *name)
1353e65e5c2dSWyllys Ingersoll {
1354e65e5c2dSWyllys Ingersoll int i;
1355e65e5c2dSWyllys Ingersoll for (i = 0; i < number_of_oids; i++) {
1356e65e5c2dSWyllys Ingersoll if (strcasecmp(name, oid_table[i].name) == 0)
1357e65e5c2dSWyllys Ingersoll return ((KMF_OID *)oid_table[i].oid);
1358e65e5c2dSWyllys Ingersoll }
1359e65e5c2dSWyllys Ingersoll return (NULL);
1360e65e5c2dSWyllys Ingersoll }
1361