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 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*e65e5c2dSWyllys Ingersoll * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * This file contains the functions that are shared among 287c478bd9Sstevel@tonic-gate * the various services this tool will ultimately provide. 297711facfSdinak * The functions in this file return PKCS#11 CK_RV errors. 307711facfSdinak * Only one session and one login per token is supported 317711facfSdinak * at this time. 327c478bd9Sstevel@tonic-gate */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include <stdio.h> 357c478bd9Sstevel@tonic-gate #include <stdlib.h> 367c478bd9Sstevel@tonic-gate #include <string.h> 377c478bd9Sstevel@tonic-gate #include <ctype.h> 3899ebb4caSwyllys #include <sys/types.h> 3999ebb4caSwyllys #include <sys/stat.h> 4099ebb4caSwyllys #include <fcntl.h> 4199ebb4caSwyllys #include <tzfile.h> 427c478bd9Sstevel@tonic-gate #include <cryptoutil.h> 437c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 4499ebb4caSwyllys #include <kmfapi.h> 457c478bd9Sstevel@tonic-gate 4699ebb4caSwyllys #include "common.h" 477711facfSdinak 487711facfSdinak /* Local status variables. */ 497711facfSdinak static boolean_t initialized = B_FALSE; 507711facfSdinak static boolean_t session_opened = B_FALSE; 517711facfSdinak static boolean_t logged_in = B_FALSE; 527c478bd9Sstevel@tonic-gate 5349e21299Sdinak /* Supporting structures and global variables for getopt_av(). */ 5449e21299Sdinak typedef struct av_opts_s { 5549e21299Sdinak int shortnm; /* short name character */ 5649e21299Sdinak char *longnm; /* long name string, NOT terminated */ 5749e21299Sdinak int longnm_len; /* length of long name string */ 5849e21299Sdinak boolean_t has_arg; /* takes optional argument */ 5949e21299Sdinak } av_opts; 6049e21299Sdinak static av_opts *opts_av = NULL; 6149e21299Sdinak static const char *_save_optstr = NULL; 6249e21299Sdinak static int _save_numopts = 0; 6349e21299Sdinak 6449e21299Sdinak int optind_av = 1; 6549e21299Sdinak char *optarg_av = NULL; 6649e21299Sdinak 6799ebb4caSwyllys static void close_sess(CK_SESSION_HANDLE); 6899ebb4caSwyllys static void logout_token(CK_SESSION_HANDLE); 6999ebb4caSwyllys 70*e65e5c2dSWyllys Ingersoll struct oid_table_entry { 71*e65e5c2dSWyllys Ingersoll const KMF_OID *oid; 72*e65e5c2dSWyllys Ingersoll char *name; 73*e65e5c2dSWyllys Ingersoll }; 74*e65e5c2dSWyllys Ingersoll 75*e65e5c2dSWyllys Ingersoll struct oid_table_entry oid_table[] = { 76*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp112r1, "secp112r1"}, 77*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp112r2, "secp112r2"}, 78*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp128r1, "secp128r1"}, 79*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp128r2, "secp128r2"}, 80*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp160k1, "secp160k1"}, 81*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp160r1, "secp160r1"}, 82*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp160r2, "secp160r2"}, 83*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp192k1, "secp192k1"}, 84*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp192r1, "secp192r1"}, 85*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp224k1, "secp224k1"}, 86*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp224r1, "secp224r1"}, 87*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp256k1, "secp256k1"}, 88*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp256r1, "secp256r1"}, 89*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp384r1, "secp384r1"}, 90*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_secp521r1, "secp521r1"}, 91*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect113r1, "sect113r1"}, 92*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect113r2, "sect113r2"}, 93*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect131r1, "sect131r1"}, 94*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect131r2, "sect131r2"}, 95*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect163k1, "sect163k1"}, 96*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect163r1, "sect163r1"}, 97*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect163r2, "sect163r2"}, 98*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect193r1, "sect193r1"}, 99*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect193r2, "sect193r2"}, 100*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect233k1, "sect233k1"}, 101*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect233r1, "sect233r1"}, 102*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect239k1, "sect239k1"}, 103*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect283k1, "sect283k1"}, 104*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect283r1, "sect283r1"}, 105*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect409k1, "sect409k1"}, 106*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect409r1, "sect409r1"}, 107*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect571k1, "sect571k1"}, 108*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_sect571r1, "sect571r1"}, 109*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb163v1, "c2pnb163v1"}, 110*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb163v2, "c2pnb163v2"}, 111*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb163v3, "c2pnb163v3"}, 112*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb176v1, "c2pnb176v1"}, 113*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb191v1, "c2tnb191v1"}, 114*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb191v2, "c2tnb191v2"}, 115*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb191v3, "c2tnb191v3"}, 116*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb208w1, "c2pnb208w1"}, 117*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb239v1, "c2tnb239v1"}, 118*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb239v2, "c2tnb239v2"}, 119*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb239v3, "c2tnb239v3"}, 120*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb272w1, "c2pnb272w1"}, 121*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb304w1, "c2pnb304w1"}, 122*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb359v1, "c2tnb359v1"}, 123*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2pnb368w1, "c2pnb368w1"}, 124*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_c2tnb431r1, "c2tnb431r1"}, 125*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_prime192v2, "prime192v2"}, 126*e65e5c2dSWyllys Ingersoll { &KMFOID_ECC_prime192v3, "prime192v3"}, 127*e65e5c2dSWyllys Ingersoll { &KMFOID_MD5, "md5"}, 128*e65e5c2dSWyllys Ingersoll { &KMFOID_SHA1, "sha1"}, 129*e65e5c2dSWyllys Ingersoll { &KMFOID_SHA256, "sha256"}, 130*e65e5c2dSWyllys Ingersoll { &KMFOID_SHA384, "sha384"}, 131*e65e5c2dSWyllys Ingersoll { &KMFOID_SHA512, "sha512"} 132*e65e5c2dSWyllys Ingersoll }; 133*e65e5c2dSWyllys Ingersoll int number_of_oids = sizeof (oid_table) / sizeof (struct oid_table_entry); 134*e65e5c2dSWyllys Ingersoll #define number_of_curves (number_of_oids - 5) 135*e65e5c2dSWyllys Ingersoll 1367c478bd9Sstevel@tonic-gate /* 1377711facfSdinak * Perform PKCS#11 setup here. Currently only C_Initialize is required, 1387711facfSdinak * along with setting/resetting state variables. 1397c478bd9Sstevel@tonic-gate */ 140448b8615Swyllys static CK_RV 141448b8615Swyllys init_pkcs11(void) 1427c478bd9Sstevel@tonic-gate { 1437711facfSdinak CK_RV rv = CKR_OK; 1447711facfSdinak 1457711facfSdinak /* If C_Initialize() already called, nothing to do here. */ 1467711facfSdinak if (initialized == B_TRUE) 1477711facfSdinak return (CKR_OK); 1487c478bd9Sstevel@tonic-gate 1497711facfSdinak /* Reset state variables because C_Initialize() not yet done. */ 1507711facfSdinak session_opened = B_FALSE; 1517711facfSdinak logged_in = B_FALSE; 1527c478bd9Sstevel@tonic-gate 1537711facfSdinak /* Initialize PKCS#11 library. */ 1547711facfSdinak if ((rv = C_Initialize(NULL_PTR)) != CKR_OK && 1557711facfSdinak rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { 1567711facfSdinak return (rv); 1577711facfSdinak } 1587c478bd9Sstevel@tonic-gate 1597711facfSdinak initialized = B_TRUE; 1607711facfSdinak return (CKR_OK); 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate /* 1647711facfSdinak * Finalize PKCS#11 library and reset state variables. Open sessions, 1657711facfSdinak * if any, are closed, and thereby any logins are logged out also. 1667c478bd9Sstevel@tonic-gate */ 1677711facfSdinak void 1687711facfSdinak final_pk11(CK_SESSION_HANDLE sess) 1697c478bd9Sstevel@tonic-gate { 1707c478bd9Sstevel@tonic-gate 1717711facfSdinak /* If the library wasn't initialized, nothing to do here. */ 1727711facfSdinak if (!initialized) 1737711facfSdinak return; 1747c478bd9Sstevel@tonic-gate 1757711facfSdinak /* Make sure the sesion is closed first. */ 1767711facfSdinak close_sess(sess); 1777711facfSdinak 1787711facfSdinak (void) C_Finalize(NULL); 1797711facfSdinak initialized = B_FALSE; 1807711facfSdinak } 1817711facfSdinak 1827711facfSdinak /* 1837711facfSdinak * Close PKCS#11 session and reset state variables. Any logins are 1847711facfSdinak * logged out. 1857711facfSdinak */ 18699ebb4caSwyllys static void 1877711facfSdinak close_sess(CK_SESSION_HANDLE sess) 1887711facfSdinak { 1897711facfSdinak 1907711facfSdinak if (sess == NULL) { 1917711facfSdinak return; 1927711facfSdinak } 1937711facfSdinak 1947711facfSdinak /* If session is already closed, nothing to do here. */ 1957711facfSdinak if (!session_opened) 1967711facfSdinak return; 1977711facfSdinak 1987711facfSdinak /* Make sure user is logged out of token. */ 1997711facfSdinak logout_token(sess); 2007711facfSdinak 2017711facfSdinak (void) C_CloseSession(sess); 2027711facfSdinak session_opened = B_FALSE; 2037711facfSdinak } 2047711facfSdinak 2057711facfSdinak /* 2067711facfSdinak * Log user out of token and reset status variable. 2077711facfSdinak */ 20899ebb4caSwyllys static void 2097711facfSdinak logout_token(CK_SESSION_HANDLE sess) 2107711facfSdinak { 2117711facfSdinak 2127711facfSdinak if (sess == NULL) { 2137711facfSdinak return; 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167711facfSdinak /* If already logged out, nothing to do here. */ 2177711facfSdinak if (!logged_in) 2187711facfSdinak return; 2197711facfSdinak 2207711facfSdinak (void) C_Logout(sess); 2217711facfSdinak logged_in = B_FALSE; 2227711facfSdinak } 2237711facfSdinak 2247711facfSdinak /* 2257711facfSdinak * Gets PIN from user. Caller needs to free the returned PIN when done. 2267711facfSdinak * If two prompts are given, the PIN is confirmed with second prompt. 2277711facfSdinak * Note that getphassphrase() may return data in static memory area. 2287711facfSdinak */ 2297711facfSdinak CK_RV 2307711facfSdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen) 2317711facfSdinak { 232d00756ccSwyllys char *save_phrase, *phrase1, *phrase2; 2337711facfSdinak 2347711facfSdinak /* Prompt user for a PIN. */ 2357711facfSdinak if (prompt1 == NULL) { 2367711facfSdinak return (CKR_ARGUMENTS_BAD); 2377711facfSdinak } 2387711facfSdinak if ((phrase1 = getpassphrase(prompt1)) == NULL) { 2397711facfSdinak return (CKR_FUNCTION_FAILED); 2407711facfSdinak } 2417711facfSdinak 2427711facfSdinak /* Duplicate 1st PIN in separate chunk of memory. */ 2437711facfSdinak if ((save_phrase = strdup(phrase1)) == NULL) 2447711facfSdinak return (CKR_HOST_MEMORY); 2457711facfSdinak 2467711facfSdinak /* If second prompt given, PIN confirmation is requested. */ 2477711facfSdinak if (prompt2 != NULL) { 2487711facfSdinak if ((phrase2 = getpassphrase(prompt2)) == NULL) { 2497711facfSdinak free(save_phrase); 2507711facfSdinak return (CKR_FUNCTION_FAILED); 2517711facfSdinak } 2527711facfSdinak if (strcmp(save_phrase, phrase2) != 0) { 2537711facfSdinak free(save_phrase); 2547711facfSdinak return (CKR_PIN_INCORRECT); 2557711facfSdinak } 2567711facfSdinak } 2577711facfSdinak 2587711facfSdinak *pin = (CK_UTF8CHAR_PTR)save_phrase; 2597711facfSdinak *pinlen = strlen(save_phrase); 2607711facfSdinak return (CKR_OK); 2617711facfSdinak } 2627711facfSdinak 263d00756ccSwyllys int 264d00756ccSwyllys yn_to_int(char *ynstr) 265d00756ccSwyllys { 266d00756ccSwyllys char *y = gettext("yes"); 267d00756ccSwyllys char *n = gettext("no"); 268d00756ccSwyllys if (ynstr == NULL) 269d00756ccSwyllys return (-1); 270d00756ccSwyllys 271d00756ccSwyllys if (strncasecmp(ynstr, y, 1) == 0) 272d00756ccSwyllys return (1); 273d00756ccSwyllys else if (strncasecmp(ynstr, n, 1) == 0) 274d00756ccSwyllys return (0); 275d00756ccSwyllys else 276d00756ccSwyllys return (-1); 277d00756ccSwyllys } 278d00756ccSwyllys 2797711facfSdinak /* 2807711facfSdinak * Gets yes/no response from user. If either no prompt is supplied, a 2817711facfSdinak * default prompt is used. If not message for invalid input is supplied, 2827711facfSdinak * a default will not be provided. If the user provides no response, 2837711facfSdinak * the input default B_TRUE == yes, B_FALSE == no is returned. 2847711facfSdinak * Otherwise, B_TRUE is returned for yes, and B_FALSE for no. 2857711facfSdinak */ 2867711facfSdinak boolean_t 2877711facfSdinak yesno(char *prompt, char *invalid, boolean_t dflt) 2887711facfSdinak { 289d00756ccSwyllys char *response, buf[1024]; 290d00756ccSwyllys int ans; 2917711facfSdinak 2927711facfSdinak if (prompt == NULL) 2937711facfSdinak prompt = gettext("Enter (y)es or (n)o? "); 2947711facfSdinak 2957711facfSdinak for (;;) { 2967711facfSdinak /* Prompt user. */ 2977711facfSdinak (void) printf("%s", prompt); 2987711facfSdinak (void) fflush(stdout); 2997711facfSdinak 3007711facfSdinak /* Get the response. */ 3017711facfSdinak if ((response = fgets(buf, sizeof (buf), stdin)) == NULL) 3027711facfSdinak break; /* go to default response */ 3037711facfSdinak 3047711facfSdinak /* Skip any leading white space. */ 3057711facfSdinak while (isspace(*response)) 3067711facfSdinak response++; 3077711facfSdinak if (*response == '\0') 3087711facfSdinak break; /* go to default response */ 3097711facfSdinak 310d00756ccSwyllys ans = yn_to_int(response); 311d00756ccSwyllys if (ans == 1) 3127711facfSdinak return (B_TRUE); 313d00756ccSwyllys else if (ans == 0) 3147711facfSdinak return (B_FALSE); 3157711facfSdinak 3167711facfSdinak /* Indicate invalid input, and try again. */ 3177711facfSdinak if (invalid != NULL) 31830a5e8faSwyllys (void) printf("%s", invalid); 3197711facfSdinak } 3207711facfSdinak return (dflt); 3217711facfSdinak } 3227711facfSdinak 3237711facfSdinak /* 3247711facfSdinak * Gets the list of slots which have tokens in them. Keeps adjusting 3257711facfSdinak * the size of the slot list buffer until the call is successful or an 3267711facfSdinak * irrecoverable error occurs. 3277711facfSdinak */ 3287711facfSdinak CK_RV 3297711facfSdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count) 3307711facfSdinak { 3317711facfSdinak CK_ULONG tmp_count = 0; 3327711facfSdinak CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR; 3337711facfSdinak int rv = CKR_OK; 3347711facfSdinak 3357711facfSdinak if (!initialized) 336448b8615Swyllys if ((rv = init_pkcs11()) != CKR_OK) 3377711facfSdinak return (rv); 3387711facfSdinak 3397711facfSdinak /* 3407711facfSdinak * Get the slot count first because we don't know how many 3417711facfSdinak * slots there are and how many of those slots even have tokens. 3427711facfSdinak * Don't specify an arbitrary buffer size for the slot list; 3437711facfSdinak * it may be too small (see section 11.5 of PKCS#11 spec). 3447711facfSdinak * Also select only those slots that have tokens in them, 3457711facfSdinak * because this tool has no need to know about empty slots. 3467711facfSdinak */ 3477711facfSdinak if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK) 3487711facfSdinak return (rv); 3497711facfSdinak 3507711facfSdinak if (tmp_count == 0) { 3517711facfSdinak *slot_list = NULL_PTR; 3527711facfSdinak *slot_count = 0; 3537711facfSdinak return (CKR_OK); 3547711facfSdinak } 3557711facfSdinak 3567711facfSdinak /* Allocate initial space for the slot list. */ 3577711facfSdinak if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count * 3587711facfSdinak sizeof (CK_SLOT_ID))) == NULL) 3597711facfSdinak return (CKR_HOST_MEMORY); 3607711facfSdinak 3617711facfSdinak /* Then get the slot list itself. */ 3627711facfSdinak for (;;) { 3637711facfSdinak if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) { 3647711facfSdinak *slot_list = tmp_list; 3657711facfSdinak *slot_count = tmp_count; 3667711facfSdinak break; 3677711facfSdinak } 3687711facfSdinak 3697711facfSdinak if (rv != CKR_BUFFER_TOO_SMALL) { 3707711facfSdinak free(tmp_list); 3717711facfSdinak break; 3727711facfSdinak } 3737711facfSdinak 3747711facfSdinak /* If the number of slots grew, try again. */ 3757711facfSdinak if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list, 3767711facfSdinak tmp_count * sizeof (CK_SLOT_ID))) == NULL) { 3777711facfSdinak free(tmp_list); 3787711facfSdinak rv = CKR_HOST_MEMORY; 3797711facfSdinak break; 3807711facfSdinak } 3817711facfSdinak tmp_list = tmp2_list; 3827711facfSdinak } 3837711facfSdinak 3847711facfSdinak return (rv); 3857c478bd9Sstevel@tonic-gate } 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate /* 38899ebb4caSwyllys * Breaks out the getopt-style option string into a structure that can be 38999ebb4caSwyllys * traversed later for calls to getopt_av(). Option string is NOT altered, 39099ebb4caSwyllys * but the struct fields point to locations within option string. 3917c478bd9Sstevel@tonic-gate */ 3927c478bd9Sstevel@tonic-gate static int 39399ebb4caSwyllys populate_opts(char *optstring) 3947c478bd9Sstevel@tonic-gate { 39599ebb4caSwyllys int i; 39699ebb4caSwyllys av_opts *temp; 3977c478bd9Sstevel@tonic-gate char *marker; 3987c478bd9Sstevel@tonic-gate 39999ebb4caSwyllys if (optstring == NULL || *optstring == '\0') 40099ebb4caSwyllys return (0); 40199ebb4caSwyllys 40299ebb4caSwyllys /* 40399ebb4caSwyllys * This tries to imitate getopt(3c) Each option must conform to: 40499ebb4caSwyllys * <short name char> [ ':' ] [ '(' <long name string> ')' ] 40599ebb4caSwyllys * If long name is missing, the short name is used for long name. 40699ebb4caSwyllys */ 40799ebb4caSwyllys for (i = 0; *optstring != '\0'; i++) { 40899ebb4caSwyllys if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) : 40999ebb4caSwyllys realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) { 41099ebb4caSwyllys if (opts_av != NULL) 41199ebb4caSwyllys free(opts_av); 41299ebb4caSwyllys opts_av = NULL; 41399ebb4caSwyllys return (0); 41499ebb4caSwyllys } else { 41599ebb4caSwyllys opts_av = (av_opts *)temp; 41699ebb4caSwyllys } 4177c478bd9Sstevel@tonic-gate 41899ebb4caSwyllys (void) memset(&opts_av[i], 0, sizeof (av_opts)); 41999ebb4caSwyllys marker = optstring; /* may need optstring later */ 4207c478bd9Sstevel@tonic-gate 42199ebb4caSwyllys opts_av[i].shortnm = *marker++; /* set short name */ 42299ebb4caSwyllys 42399ebb4caSwyllys if (*marker == ':') { /* check for opt arg */ 42499ebb4caSwyllys marker++; 42599ebb4caSwyllys opts_av[i].has_arg = B_TRUE; 42699ebb4caSwyllys } 42799ebb4caSwyllys 42899ebb4caSwyllys if (*marker == '(') { /* check and set long name */ 42999ebb4caSwyllys marker++; 43099ebb4caSwyllys opts_av[i].longnm = marker; 43199ebb4caSwyllys opts_av[i].longnm_len = strcspn(marker, ")"); 43299ebb4caSwyllys optstring = marker + opts_av[i].longnm_len + 1; 43399ebb4caSwyllys } else { 43499ebb4caSwyllys /* use short name option character */ 43599ebb4caSwyllys opts_av[i].longnm = optstring; 43699ebb4caSwyllys opts_av[i].longnm_len = 1; 43799ebb4caSwyllys optstring = marker; 43899ebb4caSwyllys } 43999ebb4caSwyllys } 44099ebb4caSwyllys 44199ebb4caSwyllys return (i); 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate /* 44599ebb4caSwyllys * getopt_av() is very similar to getopt(3c) in that the takes an option 44699ebb4caSwyllys * string, compares command line arguments for matches, and returns a single 44799ebb4caSwyllys * letter option when a match is found. However, getopt_av() differs from 44899ebb4caSwyllys * getopt(3c) by requiring that only longname options and values be found 44999ebb4caSwyllys * on the command line and all leading dashes are omitted. In other words, 45099ebb4caSwyllys * it tries to enforce only longname "option=value" arguments on the command 45199ebb4caSwyllys * line. Boolean options are not allowed either. 4527c478bd9Sstevel@tonic-gate */ 45399ebb4caSwyllys int 45499ebb4caSwyllys getopt_av(int argc, char * const *argv, const char *optstring) 4557c478bd9Sstevel@tonic-gate { 45699ebb4caSwyllys int i; 45799ebb4caSwyllys int len; 45899ebb4caSwyllys char *cur_option; 4597c478bd9Sstevel@tonic-gate 46099ebb4caSwyllys if (optind_av >= argc) 46199ebb4caSwyllys return (EOF); 4627c478bd9Sstevel@tonic-gate 46399ebb4caSwyllys /* First time or when optstring changes from previous one */ 46499ebb4caSwyllys if (_save_optstr != optstring) { 46599ebb4caSwyllys if (opts_av != NULL) 46630a5e8faSwyllys free(opts_av); 46799ebb4caSwyllys opts_av = NULL; 46899ebb4caSwyllys _save_optstr = optstring; 46999ebb4caSwyllys _save_numopts = populate_opts((char *)optstring); 47099ebb4caSwyllys } 4717c478bd9Sstevel@tonic-gate 47299ebb4caSwyllys for (i = 0; i < _save_numopts; i++) { 47399ebb4caSwyllys cur_option = argv[optind_av]; 4747c478bd9Sstevel@tonic-gate 47599ebb4caSwyllys if (strcmp(cur_option, "--") == 0) { 47699ebb4caSwyllys optind_av++; 47799ebb4caSwyllys break; 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 48099ebb4caSwyllys if (cur_option[0] == '-' && strlen(cur_option) == 2) { 48199ebb4caSwyllys len = 1; 48299ebb4caSwyllys cur_option++; /* remove "-" */ 48399ebb4caSwyllys } else { 48499ebb4caSwyllys len = strcspn(cur_option, "="); 48599ebb4caSwyllys } 4867c478bd9Sstevel@tonic-gate 48799ebb4caSwyllys if (len == opts_av[i].longnm_len && strncmp(cur_option, 48899ebb4caSwyllys opts_av[i].longnm, opts_av[i].longnm_len) == 0) { 48999ebb4caSwyllys /* matched */ 49099ebb4caSwyllys if (!opts_av[i].has_arg) { 49199ebb4caSwyllys optind_av++; 49299ebb4caSwyllys return (opts_av[i].shortnm); 49399ebb4caSwyllys } 49499ebb4caSwyllys 49599ebb4caSwyllys /* needs optarg */ 49699ebb4caSwyllys if (cur_option[len] == '=') { 49799ebb4caSwyllys optarg_av = &(cur_option[len+1]); 49899ebb4caSwyllys optind_av++; 49999ebb4caSwyllys return (opts_av[i].shortnm); 50099ebb4caSwyllys } 50199ebb4caSwyllys 50299ebb4caSwyllys optarg_av = NULL; 50399ebb4caSwyllys optind_av++; 50499ebb4caSwyllys return ((int)'?'); 50599ebb4caSwyllys } 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate 50899ebb4caSwyllys return (EOF); 5097c478bd9Sstevel@tonic-gate } 5107c478bd9Sstevel@tonic-gate 51199ebb4caSwyllys KMF_KEYSTORE_TYPE 51299ebb4caSwyllys KS2Int(char *keystore_str) 51349e21299Sdinak { 51499ebb4caSwyllys if (keystore_str == NULL) 51599ebb4caSwyllys return (0); 516d00756ccSwyllys if (strcasecmp(keystore_str, "pkcs11") == 0) 51799ebb4caSwyllys return (KMF_KEYSTORE_PK11TOKEN); 518d00756ccSwyllys else if (strcasecmp(keystore_str, "nss") == 0) 51999ebb4caSwyllys return (KMF_KEYSTORE_NSS); 520d00756ccSwyllys else if (strcasecmp(keystore_str, "file") == 0) 52199ebb4caSwyllys return (KMF_KEYSTORE_OPENSSL); 52299ebb4caSwyllys else 52399ebb4caSwyllys return (0); 52499ebb4caSwyllys } 52549e21299Sdinak 526*e65e5c2dSWyllys Ingersoll /* 527*e65e5c2dSWyllys Ingersoll * compare_oids 528*e65e5c2dSWyllys Ingersoll * return 1 if equal 529*e65e5c2dSWyllys Ingersoll */ 530*e65e5c2dSWyllys Ingersoll boolean_t 531*e65e5c2dSWyllys Ingersoll compare_oids(KMF_OID *oid1, const KMF_OID *oid2) 532*e65e5c2dSWyllys Ingersoll { 533*e65e5c2dSWyllys Ingersoll return ((oid1->Length == oid2->Length) && 534*e65e5c2dSWyllys Ingersoll !memcmp(oid1->Data, oid2->Data, oid1->Length)); 535*e65e5c2dSWyllys Ingersoll } 53649e21299Sdinak 53799ebb4caSwyllys int 538*e65e5c2dSWyllys Ingersoll Str2KeyType(char *algm, KMF_OID *hashoid, KMF_KEY_ALG *ktype, 539*e65e5c2dSWyllys Ingersoll KMF_ALGORITHM_INDEX *sigAlg) 54099ebb4caSwyllys { 54199ebb4caSwyllys if (algm == NULL) { 542*e65e5c2dSWyllys Ingersoll /* Default to SHA1+RSA */ 5434165f465SWyllys Ingersoll *sigAlg = KMF_ALGID_SHA1WithRSA; 54499ebb4caSwyllys *ktype = KMF_RSA; 54599ebb4caSwyllys } else if (strcasecmp(algm, "DSA") == 0) { 546*e65e5c2dSWyllys Ingersoll if (hashoid == NULL || 547*e65e5c2dSWyllys Ingersoll compare_oids(hashoid, &KMFOID_SHA1)) 548*e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA1WithDSA; 549*e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA256)) 550*e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA256WithDSA; 551*e65e5c2dSWyllys Ingersoll else 552*e65e5c2dSWyllys Ingersoll return (-1); /* unsupported hash/key combo */ 55399ebb4caSwyllys *ktype = KMF_DSA; 55499ebb4caSwyllys } else if (strcasecmp(algm, "RSA") == 0) { 555*e65e5c2dSWyllys Ingersoll if (hashoid == NULL || 556*e65e5c2dSWyllys Ingersoll compare_oids(hashoid, &KMFOID_SHA1)) 557*e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA1WithRSA; 558*e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA256)) 559*e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA256WithRSA; 560*e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA384)) 561*e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA384WithRSA; 562*e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA512)) 563*e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA512WithRSA; 564*e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_MD5)) 565*e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_MD5WithRSA; 566*e65e5c2dSWyllys Ingersoll else 567*e65e5c2dSWyllys Ingersoll return (-1); /* unsupported hash/key combo */ 56899ebb4caSwyllys *ktype = KMF_RSA; 569*e65e5c2dSWyllys Ingersoll } else if (strcasecmp(algm, "EC") == 0) { 570*e65e5c2dSWyllys Ingersoll /* EC keys may be used with some SHA2 hashes */ 571*e65e5c2dSWyllys Ingersoll if (hashoid == NULL || 572*e65e5c2dSWyllys Ingersoll compare_oids(hashoid, &KMFOID_SHA1)) 573*e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA1WithECDSA; 574*e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA256)) 575*e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA256WithECDSA; 576*e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA384)) 577*e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA384WithECDSA; 578*e65e5c2dSWyllys Ingersoll else if (compare_oids(hashoid, &KMFOID_SHA512)) 579*e65e5c2dSWyllys Ingersoll *sigAlg = KMF_ALGID_SHA512WithECDSA; 580*e65e5c2dSWyllys Ingersoll else 581*e65e5c2dSWyllys Ingersoll return (-1); /* unsupported hash/key combo */ 582*e65e5c2dSWyllys Ingersoll 583*e65e5c2dSWyllys Ingersoll *ktype = KMF_ECDSA; 58499ebb4caSwyllys } else { 58599ebb4caSwyllys return (-1); 58649e21299Sdinak } 58799ebb4caSwyllys return (0); 58849e21299Sdinak } 58949e21299Sdinak 59099ebb4caSwyllys int 59199ebb4caSwyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype) 59249e21299Sdinak { 59399ebb4caSwyllys if (algm == NULL) 59499ebb4caSwyllys *ktype = KMF_AES; 59599ebb4caSwyllys else if (strcasecmp(algm, "aes") == 0) 59699ebb4caSwyllys *ktype = KMF_AES; 59799ebb4caSwyllys else if (strcasecmp(algm, "arcfour") == 0) 59899ebb4caSwyllys *ktype = KMF_RC4; 59999ebb4caSwyllys else if (strcasecmp(algm, "des") == 0) 60099ebb4caSwyllys *ktype = KMF_DES; 60199ebb4caSwyllys else if (strcasecmp(algm, "3des") == 0) 60299ebb4caSwyllys *ktype = KMF_DES3; 603c197cb9dShylee else if (strcasecmp(algm, "generic") == 0) 604c197cb9dShylee *ktype = KMF_GENERIC_SECRET; 60599ebb4caSwyllys else 60699ebb4caSwyllys return (-1); 60749e21299Sdinak 60899ebb4caSwyllys return (0); 60949e21299Sdinak } 61049e21299Sdinak 61149e21299Sdinak int 61299ebb4caSwyllys Str2Lifetime(char *ltimestr, uint32_t *ltime) 61349e21299Sdinak { 61499ebb4caSwyllys int num; 61599ebb4caSwyllys char timetok[6]; 61649e21299Sdinak 617d00756ccSwyllys if (ltimestr == NULL || strlen(ltimestr) == 0) { 61899ebb4caSwyllys /* default to 1 year lifetime */ 61999ebb4caSwyllys *ltime = SECSPERDAY * DAYSPERNYEAR; 62099ebb4caSwyllys return (0); 62149e21299Sdinak } 62249e21299Sdinak 62399ebb4caSwyllys (void) memset(timetok, 0, sizeof (timetok)); 62499ebb4caSwyllys if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2) 62599ebb4caSwyllys return (-1); 62649e21299Sdinak 627d00756ccSwyllys if (strcasecmp(timetok, "day") == 0|| 628d00756ccSwyllys strcasecmp(timetok, "days") == 0) { 62999ebb4caSwyllys *ltime = num * SECSPERDAY; 630d00756ccSwyllys } else if (strcasecmp(timetok, "hour") == 0|| 631d00756ccSwyllys strcasecmp(timetok, "hours") == 0) { 63299ebb4caSwyllys *ltime = num * SECSPERHOUR; 633d00756ccSwyllys } else if (strcasecmp(timetok, "year") == 0 || 634d00756ccSwyllys strcasecmp(timetok, "years") == 0) { 63599ebb4caSwyllys *ltime = num * SECSPERDAY * DAYSPERNYEAR; 63699ebb4caSwyllys } else { 63799ebb4caSwyllys *ltime = 0; 63849e21299Sdinak return (-1); 63949e21299Sdinak } 64049e21299Sdinak 64199ebb4caSwyllys return (0); 64299ebb4caSwyllys } 64349e21299Sdinak 64499ebb4caSwyllys int 64599ebb4caSwyllys OT2Int(char *objclass) 64699ebb4caSwyllys { 64799ebb4caSwyllys char *c = NULL; 64899ebb4caSwyllys int retval = 0; 64949e21299Sdinak 65099ebb4caSwyllys if (objclass == NULL) 65199ebb4caSwyllys return (-1); 65249e21299Sdinak 65399ebb4caSwyllys c = strchr(objclass, ':'); 65499ebb4caSwyllys if (c != NULL) { 655d00756ccSwyllys if (strcasecmp(c, ":private") == 0) 65699ebb4caSwyllys retval = PK_PRIVATE_OBJ; 657d00756ccSwyllys else if (strcasecmp(c, ":public") == 0) 65899ebb4caSwyllys retval = PK_PUBLIC_OBJ; 659d00756ccSwyllys else if (strcasecmp(c, ":both") == 0) 66099ebb4caSwyllys retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ; 66199ebb4caSwyllys else /* unrecognized option */ 66299ebb4caSwyllys return (-1); 66399ebb4caSwyllys 66499ebb4caSwyllys *c = '\0'; 66599ebb4caSwyllys } 66699ebb4caSwyllys 667d00756ccSwyllys if (strcasecmp(objclass, "public") == 0) { 66899ebb4caSwyllys if (retval) 66999ebb4caSwyllys return (-1); 67030a5e8faSwyllys return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ); 671d00756ccSwyllys } else if (strcasecmp(objclass, "private") == 0) { 67299ebb4caSwyllys if (retval) 67399ebb4caSwyllys return (-1); 67499ebb4caSwyllys return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ); 675d00756ccSwyllys } else if (strcasecmp(objclass, "both") == 0) { 67699ebb4caSwyllys if (retval) 67799ebb4caSwyllys return (-1); 67899ebb4caSwyllys return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ); 679d00756ccSwyllys } else if (strcasecmp(objclass, "cert") == 0) { 68099ebb4caSwyllys return (retval | PK_CERT_OBJ); 681d00756ccSwyllys } else if (strcasecmp(objclass, "key") == 0) { 68299ebb4caSwyllys if (retval == 0) /* return all keys */ 68399ebb4caSwyllys return (retval | PK_KEY_OBJ); 68499ebb4caSwyllys else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ)) 68599ebb4caSwyllys /* return all keys */ 68699ebb4caSwyllys return (retval | PK_KEY_OBJ); 68799ebb4caSwyllys else if (retval & PK_PUBLIC_OBJ) 68899ebb4caSwyllys /* Only return public keys */ 68999ebb4caSwyllys return (retval | PK_PUBKEY_OBJ); 69099ebb4caSwyllys else if (retval & PK_PRIVATE_OBJ) 69199ebb4caSwyllys /* Only return private keys */ 69299ebb4caSwyllys return (retval | PK_PRIKEY_OBJ); 693d00756ccSwyllys } else if (strcasecmp(objclass, "crl") == 0) { 69499ebb4caSwyllys if (retval) 69599ebb4caSwyllys return (-1); 69699ebb4caSwyllys return (retval | PK_CRL_OBJ); 69799ebb4caSwyllys } 69899ebb4caSwyllys 69999ebb4caSwyllys if (retval == 0) /* No matches found */ 70099ebb4caSwyllys retval = -1; 70199ebb4caSwyllys return (retval); 70249e21299Sdinak } 70349e21299Sdinak 70499ebb4caSwyllys KMF_ENCODE_FORMAT 70599ebb4caSwyllys Str2Format(char *formstr) 7067c478bd9Sstevel@tonic-gate { 707d00756ccSwyllys if (formstr == NULL || strcasecmp(formstr, "der") == 0) 70899ebb4caSwyllys return (KMF_FORMAT_ASN1); 709d00756ccSwyllys if (strcasecmp(formstr, "pem") == 0) 71099ebb4caSwyllys return (KMF_FORMAT_PEM); 711d00756ccSwyllys if (strcasecmp(formstr, "pkcs12") == 0) 71299ebb4caSwyllys return (KMF_FORMAT_PKCS12); 713d00756ccSwyllys if (strcasecmp(formstr, "raw") == 0) 71430a5e8faSwyllys return (KMF_FORMAT_RAWKEY); 71599ebb4caSwyllys 71699ebb4caSwyllys return (KMF_FORMAT_UNDEF); 71799ebb4caSwyllys } 7187c478bd9Sstevel@tonic-gate 71999ebb4caSwyllys KMF_RETURN 720d00756ccSwyllys select_token(void *kmfhandle, char *token, int readonly) 72199ebb4caSwyllys { 72230a5e8faSwyllys KMF_ATTRIBUTE attlist[10]; 72330a5e8faSwyllys int i = 0; 72430a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 72599ebb4caSwyllys KMF_RETURN rv = KMF_OK; 7267711facfSdinak 72799ebb4caSwyllys if (token == NULL) 72899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 7297c478bd9Sstevel@tonic-gate 73030a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 73130a5e8faSwyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 73230a5e8faSwyllys sizeof (kstype)); 73330a5e8faSwyllys i++; 7347711facfSdinak 73530a5e8faSwyllys if (token) { 73630a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 73730a5e8faSwyllys KMF_TOKEN_LABEL_ATTR, token, 73830a5e8faSwyllys strlen(token)); 73930a5e8faSwyllys i++; 74030a5e8faSwyllys } 74130a5e8faSwyllys 74230a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 74330a5e8faSwyllys KMF_READONLY_ATTR, &readonly, 74430a5e8faSwyllys sizeof (readonly)); 74530a5e8faSwyllys i++; 74630a5e8faSwyllys 74730a5e8faSwyllys rv = kmf_configure_keystore(kmfhandle, i, attlist); 74899ebb4caSwyllys if (rv == KMF_ERR_TOKEN_SELECTED) 74999ebb4caSwyllys rv = KMF_OK; 75099ebb4caSwyllys return (rv); 7517711facfSdinak } 7527711facfSdinak 75399ebb4caSwyllys KMF_RETURN 75499ebb4caSwyllys configure_nss(void *kmfhandle, char *dir, char *prefix) 7557711facfSdinak { 75630a5e8faSwyllys KMF_ATTRIBUTE attlist[10]; 75730a5e8faSwyllys int i = 0; 75830a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 75999ebb4caSwyllys KMF_RETURN rv = KMF_OK; 7607711facfSdinak 76130a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 76230a5e8faSwyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 76330a5e8faSwyllys sizeof (kstype)); 76430a5e8faSwyllys i++; 76530a5e8faSwyllys 76630a5e8faSwyllys if (dir) { 76730a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 76830a5e8faSwyllys KMF_DIRPATH_ATTR, dir, 76930a5e8faSwyllys strlen(dir)); 77030a5e8faSwyllys i++; 77130a5e8faSwyllys } 77230a5e8faSwyllys 77330a5e8faSwyllys if (prefix) { 77430a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 77530a5e8faSwyllys KMF_CERTPREFIX_ATTR, prefix, 77630a5e8faSwyllys strlen(prefix)); 77730a5e8faSwyllys i++; 77830a5e8faSwyllys 77930a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 78030a5e8faSwyllys KMF_KEYPREFIX_ATTR, prefix, 78130a5e8faSwyllys strlen(prefix)); 78230a5e8faSwyllys i++; 78330a5e8faSwyllys } 7847711facfSdinak 78530a5e8faSwyllys rv = kmf_configure_keystore(kmfhandle, i, attlist); 78699ebb4caSwyllys if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED) 78799ebb4caSwyllys rv = KMF_OK; 7887c478bd9Sstevel@tonic-gate 78999ebb4caSwyllys return (rv); 79099ebb4caSwyllys } 7917711facfSdinak 79299ebb4caSwyllys KMF_RETURN 79399ebb4caSwyllys get_pk12_password(KMF_CREDENTIAL *cred) 79499ebb4caSwyllys { 79599ebb4caSwyllys KMF_RETURN rv = KMF_OK; 79699ebb4caSwyllys char prompt[1024]; 7977711facfSdinak 7987711facfSdinak /* 79999ebb4caSwyllys * Get the password to use for the PK12 encryption. 8007711facfSdinak */ 80199ebb4caSwyllys (void) strlcpy(prompt, 80230a5e8faSwyllys gettext("Enter password to use for " 80330a5e8faSwyllys "accessing the PKCS12 file: "), sizeof (prompt)); 8047711facfSdinak 80599ebb4caSwyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 80630a5e8faSwyllys (ulong_t *)&cred->credlen) != CKR_OK) { 80799ebb4caSwyllys cred->cred = NULL; 80899ebb4caSwyllys cred->credlen = 0; 8097711facfSdinak } 8107711facfSdinak 8117711facfSdinak return (rv); 8127711facfSdinak } 8137711facfSdinak 8142cbed729Swyllys #define FILENAME_PROMPT gettext("Filename:") 8152cbed729Swyllys #define FILENAME_MINLEN 1 8162cbed729Swyllys #define FILENAME_MAXLEN MAXPATHLEN 8172cbed729Swyllys 8182cbed729Swyllys #define COUNTRY_PROMPT gettext("Country Name (2 letter code) [US]:") 8192cbed729Swyllys #define STATE_PROMPT gettext("State or Province Name (full name) " \ 8202cbed729Swyllys "[Some-State]:") 8212cbed729Swyllys #define LOCALITY_PROMPT gettext("Locality Name (eg, city) []:") 8222cbed729Swyllys #define ORG_PROMPT gettext("Organization Name (eg, company) []:") 8232cbed729Swyllys #define UNIT_PROMPT gettext("Organizational Unit Name (eg, section) []:") 8242cbed729Swyllys #define NAME_PROMPT gettext("Common Name (eg, YOUR name) []:") 8252cbed729Swyllys #define EMAIL_PROMPT gettext("Email Address []:") 8262cbed729Swyllys 8272cbed729Swyllys #define SERNO_PROMPT gettext("Serial Number (hex value, example: " \ 8282cbed729Swyllys "0x01020304):") 8292cbed729Swyllys #define SERNO_MINLEN 3 8302cbed729Swyllys #define SERNO_MAXLEN 42 8312cbed729Swyllys 8322cbed729Swyllys #define LABEL_PROMPT gettext("Enter a label for the certificate:") 8332cbed729Swyllys #define LABEL_MINLEN 1 8342cbed729Swyllys #define LABEL_MAXLEN 1024 8357711facfSdinak 83699ebb4caSwyllys #define COUNTRY_DEFAULT "US" 8372cbed729Swyllys #define STATE_DEFAULT NULL 8382cbed729Swyllys #define INVALID_INPUT gettext("Invalid input; please re-enter ...") 8397711facfSdinak 84099ebb4caSwyllys #define SUBNAMESIZ 1024 84199ebb4caSwyllys #define RDN_MIN 1 84299ebb4caSwyllys #define RDN_MAX 64 84399ebb4caSwyllys #define COUNTRYNAME_MIN 2 84499ebb4caSwyllys #define COUNTRYNAME_MAX 2 8457711facfSdinak 84699ebb4caSwyllys static char * 84799ebb4caSwyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len) 84899ebb4caSwyllys { 84999ebb4caSwyllys char buf[1024]; 85099ebb4caSwyllys char *response = NULL; 85199ebb4caSwyllys char *ret = NULL; 85299ebb4caSwyllys int len; 8537711facfSdinak 85499ebb4caSwyllys for (;;) { 85599ebb4caSwyllys (void) printf("\t%s", prompt); 85699ebb4caSwyllys (void) fflush(stdout); 85799ebb4caSwyllys 85899ebb4caSwyllys response = fgets(buf, sizeof (buf), stdin); 85999ebb4caSwyllys if (response == NULL) { 86099ebb4caSwyllys if (default_str != NULL) { 86199ebb4caSwyllys ret = strdup(default_str); 86299ebb4caSwyllys } 86399ebb4caSwyllys break; 86499ebb4caSwyllys } 86599ebb4caSwyllys 86699ebb4caSwyllys /* Skip any leading white space. */ 86799ebb4caSwyllys while (isspace(*response)) 86899ebb4caSwyllys response++; 86999ebb4caSwyllys if (*response == '\0') { 87099ebb4caSwyllys if (default_str != NULL) { 87199ebb4caSwyllys ret = strdup(default_str); 87299ebb4caSwyllys } 87399ebb4caSwyllys break; 87499ebb4caSwyllys } 87599ebb4caSwyllys 87699ebb4caSwyllys len = strlen(response); 87799ebb4caSwyllys response[len-1] = '\0'; /* get rid of "LF" */ 87899ebb4caSwyllys len--; 87999ebb4caSwyllys if (len >= min_len && len <= max_len) { 88099ebb4caSwyllys ret = strdup(response); 88199ebb4caSwyllys break; 8827711facfSdinak } 8837711facfSdinak 88499ebb4caSwyllys (void) printf("%s\n", INVALID_INPUT); 88599ebb4caSwyllys 8867711facfSdinak } 8877711facfSdinak 88899ebb4caSwyllys return (ret); 88999ebb4caSwyllys } 8907711facfSdinak 8912cbed729Swyllys int 8922cbed729Swyllys get_filename(char *txt, char **result) 8932cbed729Swyllys { 8942cbed729Swyllys char prompt[1024]; 8952cbed729Swyllys char *fname = NULL; 8962cbed729Swyllys 8972cbed729Swyllys (void) snprintf(prompt, sizeof (prompt), 8982cbed729Swyllys gettext("Enter filename for the %s: "), 8992cbed729Swyllys txt); 9002cbed729Swyllys fname = get_input_string(prompt, NULL, 9012cbed729Swyllys FILENAME_MINLEN, FILENAME_MAXLEN); 9022cbed729Swyllys *result = fname; 9032cbed729Swyllys return (0); 9042cbed729Swyllys } 9052cbed729Swyllys 9062cbed729Swyllys int 9072cbed729Swyllys get_certlabel(char **result) 9082cbed729Swyllys { 9092cbed729Swyllys char *label = NULL; 9102cbed729Swyllys 9112cbed729Swyllys label = get_input_string(LABEL_PROMPT, NULL, 9122cbed729Swyllys LABEL_MINLEN, LABEL_MAXLEN); 9132cbed729Swyllys *result = label; 9142cbed729Swyllys return (0); 9152cbed729Swyllys } 9162cbed729Swyllys 9172cbed729Swyllys int 9182cbed729Swyllys get_serial(char **result) 9192cbed729Swyllys { 9202cbed729Swyllys char *serial = NULL; 9212cbed729Swyllys 9222cbed729Swyllys serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN, 9232cbed729Swyllys SERNO_MAXLEN); 9242cbed729Swyllys 9252cbed729Swyllys *result = serial; 9262cbed729Swyllys return (0); 9272cbed729Swyllys } 9282cbed729Swyllys 92999ebb4caSwyllys int 93099ebb4caSwyllys get_subname(char **result) 93199ebb4caSwyllys { 93299ebb4caSwyllys char *country = NULL; 93399ebb4caSwyllys char *state = NULL; 93499ebb4caSwyllys char *locality = NULL; 93599ebb4caSwyllys char *org = NULL; 93699ebb4caSwyllys char *unit = NULL; 93799ebb4caSwyllys char *name = NULL; 93899ebb4caSwyllys char *email = NULL; 93999ebb4caSwyllys char *subname = NULL; 94099ebb4caSwyllys 94199ebb4caSwyllys (void) printf("Entering following fields for subject (a DN) ...\n"); 94299ebb4caSwyllys country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT, 94399ebb4caSwyllys COUNTRYNAME_MIN, COUNTRYNAME_MAX); 94499ebb4caSwyllys if (country == NULL) 94599ebb4caSwyllys return (-1); 94699ebb4caSwyllys 94799ebb4caSwyllys state = get_input_string(STATE_PROMPT, STATE_DEFAULT, 94899ebb4caSwyllys RDN_MIN, RDN_MAX); 9497711facfSdinak 95099ebb4caSwyllys locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX); 95199ebb4caSwyllys org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX); 95299ebb4caSwyllys unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX); 95399ebb4caSwyllys name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX); 95499ebb4caSwyllys email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX); 9557711facfSdinak 95699ebb4caSwyllys /* Now create a subject name from the input strings */ 95799ebb4caSwyllys if ((subname = malloc(SUBNAMESIZ)) == NULL) 95899ebb4caSwyllys goto out; 95999ebb4caSwyllys 96099ebb4caSwyllys (void) memset(subname, 0, SUBNAMESIZ); 96199ebb4caSwyllys (void) strlcpy(subname, "C=", SUBNAMESIZ); 96299ebb4caSwyllys (void) strlcat(subname, country, SUBNAMESIZ); 9632cbed729Swyllys if (state != NULL) { 9642cbed729Swyllys (void) strlcat(subname, ", ST=", SUBNAMESIZ); 9652cbed729Swyllys (void) strlcat(subname, state, SUBNAMESIZ); 9662cbed729Swyllys } 9677711facfSdinak 9682cbed729Swyllys if (locality != NULL) { 9692cbed729Swyllys (void) strlcat(subname, ", L=", SUBNAMESIZ); 97099ebb4caSwyllys (void) strlcat(subname, locality, SUBNAMESIZ); 9717711facfSdinak } 9727711facfSdinak 9732cbed729Swyllys if (org != NULL) { 9742cbed729Swyllys (void) strlcat(subname, ", O=", SUBNAMESIZ); 97599ebb4caSwyllys (void) strlcat(subname, org, SUBNAMESIZ); 9767711facfSdinak } 9777711facfSdinak 9782cbed729Swyllys if (unit != NULL) { 9792cbed729Swyllys (void) strlcat(subname, ", OU=", SUBNAMESIZ); 98099ebb4caSwyllys (void) strlcat(subname, unit, SUBNAMESIZ); 98199ebb4caSwyllys } 9827711facfSdinak 9832cbed729Swyllys if (name != NULL) { 9842cbed729Swyllys (void) strlcat(subname, ", CN=", SUBNAMESIZ); 98599ebb4caSwyllys (void) strlcat(subname, name, SUBNAMESIZ); 9867711facfSdinak } 9877711facfSdinak 9882cbed729Swyllys if (email != NULL) { 9892cbed729Swyllys (void) strlcat(subname, ", E=", SUBNAMESIZ); 99099ebb4caSwyllys (void) strlcat(subname, email, SUBNAMESIZ); 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate 99399ebb4caSwyllys out: 99499ebb4caSwyllys if (country) 99599ebb4caSwyllys free(country); 99699ebb4caSwyllys if (state) 99799ebb4caSwyllys free(state); 99899ebb4caSwyllys if (locality) 99999ebb4caSwyllys free(locality); 100099ebb4caSwyllys if (org) 100199ebb4caSwyllys free(org); 100299ebb4caSwyllys if (unit) 100399ebb4caSwyllys free(unit); 100499ebb4caSwyllys if (name) 100599ebb4caSwyllys free(name); 100699ebb4caSwyllys if (email) 100799ebb4caSwyllys free(email); 100899ebb4caSwyllys 100999ebb4caSwyllys if (subname == NULL) 101099ebb4caSwyllys return (-1); 101199ebb4caSwyllys else { 101299ebb4caSwyllys *result = subname; 101399ebb4caSwyllys return (0); 10147711facfSdinak } 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate /* 101899ebb4caSwyllys * Parse a string of KeyUsage values and convert 101999ebb4caSwyllys * them to the correct KU Bits. 102099ebb4caSwyllys * The field may be marked "critical" by prepending 102199ebb4caSwyllys * "critical:" to the list. 102299ebb4caSwyllys * EX: critical:digitialSignature,keyEncipherment 10237c478bd9Sstevel@tonic-gate */ 102499ebb4caSwyllys KMF_RETURN 102599ebb4caSwyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical) 10267c478bd9Sstevel@tonic-gate { 102799ebb4caSwyllys KMF_RETURN ret = KMF_OK; 102899ebb4caSwyllys uint16_t kuval; 102999ebb4caSwyllys char *k; 103099ebb4caSwyllys 103199ebb4caSwyllys *kubits = 0; 1032d00756ccSwyllys if (kustr == NULL || strlen(kustr) == 0) 103399ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 103499ebb4caSwyllys 103599ebb4caSwyllys /* Check to see if this is critical */ 1036d00756ccSwyllys if (strncasecmp(kustr, "critical:", strlen("critical:")) == 0) { 103799ebb4caSwyllys *critical = TRUE; 103899ebb4caSwyllys kustr += strlen("critical:"); 103999ebb4caSwyllys } else { 104099ebb4caSwyllys *critical = FALSE; 10417c478bd9Sstevel@tonic-gate } 10427711facfSdinak 104399ebb4caSwyllys k = strtok(kustr, ","); 104499ebb4caSwyllys while (k != NULL) { 104530a5e8faSwyllys kuval = kmf_string_to_ku(k); 104699ebb4caSwyllys if (kuval == 0) { 104799ebb4caSwyllys *kubits = 0; 104899ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 10497711facfSdinak } 105099ebb4caSwyllys *kubits |= kuval; 105199ebb4caSwyllys k = strtok(NULL, ","); 10527711facfSdinak } 10537711facfSdinak 105499ebb4caSwyllys return (ret); 10557711facfSdinak } 10567711facfSdinak 10577711facfSdinak /* 105899ebb4caSwyllys * Verify the alternate subject label is real or invalid. 105999ebb4caSwyllys * 106099ebb4caSwyllys * The field may be marked "critical" by prepending 106199ebb4caSwyllys * "critical:" to the list. 106299ebb4caSwyllys * EX: "critical:IP=1.2.3.4" 10637711facfSdinak */ 106499ebb4caSwyllys KMF_RETURN 106599ebb4caSwyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical) 10667711facfSdinak { 106799ebb4caSwyllys char *p; 106899ebb4caSwyllys KMF_RETURN rv = KMF_OK; 10697711facfSdinak 107099ebb4caSwyllys /* Check to see if this is critical */ 1071d00756ccSwyllys if (strncasecmp(arg, "critical:", strlen("critical:")) == 0) { 107299ebb4caSwyllys *critical = TRUE; 107399ebb4caSwyllys arg += strlen("critical:"); 107499ebb4caSwyllys } else { 107599ebb4caSwyllys *critical = FALSE; 107699ebb4caSwyllys } 10777711facfSdinak 107899ebb4caSwyllys /* Make sure there is an "=" sign */ 107999ebb4caSwyllys p = strchr(arg, '='); 108099ebb4caSwyllys if (p == NULL) 108199ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 10827711facfSdinak 108399ebb4caSwyllys p[0] = '\0'; 108499ebb4caSwyllys 108599ebb4caSwyllys if (strcmp(arg, "IP") == 0) 108699ebb4caSwyllys *type = GENNAME_IPADDRESS; 108799ebb4caSwyllys else if (strcmp(arg, "DNS") == 0) 108899ebb4caSwyllys *type = GENNAME_DNSNAME; 108999ebb4caSwyllys else if (strcmp(arg, "EMAIL") == 0) 109099ebb4caSwyllys *type = GENNAME_RFC822NAME; 109199ebb4caSwyllys else if (strcmp(arg, "URI") == 0) 109299ebb4caSwyllys *type = GENNAME_URI; 109399ebb4caSwyllys else if (strcmp(arg, "DN") == 0) 109499ebb4caSwyllys *type = GENNAME_DIRECTORYNAME; 109599ebb4caSwyllys else if (strcmp(arg, "RID") == 0) 109699ebb4caSwyllys *type = GENNAME_REGISTEREDID; 1097d00756ccSwyllys else if (strcmp(arg, "KRB") == 0) 1098d00756ccSwyllys *type = GENNAME_KRB5PRINC; 1099d00756ccSwyllys else if (strcmp(arg, "UPN") == 0) 1100d00756ccSwyllys *type = GENNAME_SCLOGON_UPN; 110199ebb4caSwyllys else 110299ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 110399ebb4caSwyllys 110499ebb4caSwyllys p[0] = '='; 110599ebb4caSwyllys 110699ebb4caSwyllys return (rv); 11077c478bd9Sstevel@tonic-gate } 110849e21299Sdinak 110999ebb4caSwyllys int 111099ebb4caSwyllys get_token_password(KMF_KEYSTORE_TYPE kstype, 111199ebb4caSwyllys char *token_spec, KMF_CREDENTIAL *cred) 111249e21299Sdinak { 111399ebb4caSwyllys char prompt[1024]; 111472ca8cc9SWyllys Ingersoll char temptoken[32]; 111599ebb4caSwyllys char *p = NULL; 111672ca8cc9SWyllys Ingersoll char *t = NULL; 111747e946e7SWyllys Ingersoll int len; 111849e21299Sdinak 111947e946e7SWyllys Ingersoll (void) memset(temptoken, 0, sizeof (temptoken)); 112099ebb4caSwyllys if (kstype == KMF_KEYSTORE_PK11TOKEN) { 112199ebb4caSwyllys p = strchr(token_spec, ':'); 112299ebb4caSwyllys if (p != NULL) 112372ca8cc9SWyllys Ingersoll *p = 0; 112472ca8cc9SWyllys Ingersoll } 112547e946e7SWyllys Ingersoll len = strlen(token_spec); 112647e946e7SWyllys Ingersoll if (len > sizeof (temptoken)) 112747e946e7SWyllys Ingersoll len = sizeof (temptoken); 112847e946e7SWyllys Ingersoll 112947e946e7SWyllys Ingersoll (void) strncpy(temptoken, token_spec, len); 113072ca8cc9SWyllys Ingersoll 113172ca8cc9SWyllys Ingersoll /* 113272ca8cc9SWyllys Ingersoll * Strip trailing whitespace 113372ca8cc9SWyllys Ingersoll */ 113447e946e7SWyllys Ingersoll t = temptoken + (len - 1); 113572ca8cc9SWyllys Ingersoll while (isspace(*t) && t >= temptoken) { 113672ca8cc9SWyllys Ingersoll *t = 0x00; 113772ca8cc9SWyllys Ingersoll t--; 113899ebb4caSwyllys } 113972ca8cc9SWyllys Ingersoll 114049e21299Sdinak /* 114199ebb4caSwyllys * Login to the token first. 114249e21299Sdinak */ 114399ebb4caSwyllys (void) snprintf(prompt, sizeof (prompt), 114472ca8cc9SWyllys Ingersoll gettext(DEFAULT_TOKEN_PROMPT), temptoken); 114549e21299Sdinak 114699ebb4caSwyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 114730a5e8faSwyllys (ulong_t *)&cred->credlen) != CKR_OK) { 114899ebb4caSwyllys cred->cred = NULL; 114999ebb4caSwyllys cred->credlen = 0; 115049e21299Sdinak } 115149e21299Sdinak 115299ebb4caSwyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL) 115399ebb4caSwyllys *p = ':'; 115499ebb4caSwyllys return (KMF_OK); 115549e21299Sdinak } 115649e21299Sdinak 115799ebb4caSwyllys KMF_RETURN 115899ebb4caSwyllys verify_file(char *filename) 115949e21299Sdinak { 116099ebb4caSwyllys KMF_RETURN ret = KMF_OK; 116199ebb4caSwyllys int fd; 116249e21299Sdinak 116399ebb4caSwyllys /* 116499ebb4caSwyllys * Attempt to open with the EXCL flag so that if 116599ebb4caSwyllys * it already exists, the open will fail. It will 116699ebb4caSwyllys * also fail if the file cannot be created due to 116799ebb4caSwyllys * permissions on the parent directory, or if the 116899ebb4caSwyllys * parent directory itself does not exist. 116999ebb4caSwyllys */ 117099ebb4caSwyllys fd = open(filename, O_CREAT | O_EXCL, 0600); 117199ebb4caSwyllys if (fd == -1) 117299ebb4caSwyllys return (KMF_ERR_OPEN_FILE); 117349e21299Sdinak 117499ebb4caSwyllys /* If we were able to create it, delete it. */ 117599ebb4caSwyllys (void) close(fd); 117699ebb4caSwyllys (void) unlink(filename); 117749e21299Sdinak 117899ebb4caSwyllys return (ret); 117999ebb4caSwyllys } 118049e21299Sdinak 118199ebb4caSwyllys void 118299ebb4caSwyllys display_error(void *handle, KMF_RETURN errcode, char *prefix) 118399ebb4caSwyllys { 118499ebb4caSwyllys KMF_RETURN rv1, rv2; 118599ebb4caSwyllys char *plugin_errmsg = NULL; 118699ebb4caSwyllys char *kmf_errmsg = NULL; 118749e21299Sdinak 118830a5e8faSwyllys rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg); 118930a5e8faSwyllys rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg); 119049e21299Sdinak 119199ebb4caSwyllys cryptoerror(LOG_STDERR, "%s:", prefix); 119299ebb4caSwyllys if (rv1 == KMF_OK && plugin_errmsg) { 119330a5e8faSwyllys cryptoerror(LOG_STDERR, gettext("keystore error: %s"), 119430a5e8faSwyllys plugin_errmsg); 119530a5e8faSwyllys kmf_free_str(plugin_errmsg); 119699ebb4caSwyllys } 119749e21299Sdinak 119899ebb4caSwyllys if (rv2 == KMF_OK && kmf_errmsg) { 119930a5e8faSwyllys cryptoerror(LOG_STDERR, gettext("libkmf error: %s"), 120030a5e8faSwyllys kmf_errmsg); 120130a5e8faSwyllys kmf_free_str(kmf_errmsg); 120249e21299Sdinak } 120349e21299Sdinak 120499ebb4caSwyllys if (rv1 != KMF_OK && rv2 != KMF_OK) 120599ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("<unknown error>\n")); 120699ebb4caSwyllys 120749e21299Sdinak } 1208d00756ccSwyllys 1209d00756ccSwyllys static KMF_RETURN 1210d00756ccSwyllys addToEKUList(EKU_LIST *ekus, int critical, KMF_OID *newoid) 1211d00756ccSwyllys { 1212d00756ccSwyllys if (newoid != NULL && ekus != NULL) { 1213d00756ccSwyllys ekus->eku_count++; 1214d00756ccSwyllys 1215d00756ccSwyllys ekus->critlist = realloc(ekus->critlist, 1216d00756ccSwyllys ekus->eku_count * sizeof (int)); 1217d00756ccSwyllys if (ekus->critlist != NULL) 1218d00756ccSwyllys ekus->critlist[ekus->eku_count-1] = critical; 1219d00756ccSwyllys else 1220d00756ccSwyllys return (KMF_ERR_MEMORY); 1221d00756ccSwyllys 1222d00756ccSwyllys ekus->ekulist = realloc( 1223d00756ccSwyllys ekus->ekulist, ekus->eku_count * sizeof (KMF_OID)); 1224d00756ccSwyllys if (ekus->ekulist != NULL) 1225d00756ccSwyllys ekus->ekulist[ekus->eku_count-1] = *newoid; 1226d00756ccSwyllys else 1227d00756ccSwyllys return (KMF_ERR_MEMORY); 1228d00756ccSwyllys } 1229d00756ccSwyllys return (KMF_OK); 1230d00756ccSwyllys } 1231d00756ccSwyllys 1232d00756ccSwyllys void 1233d00756ccSwyllys free_eku_list(EKU_LIST *ekus) 1234d00756ccSwyllys { 1235d00756ccSwyllys if (ekus != NULL && ekus->eku_count > 0) { 1236d00756ccSwyllys int i; 1237d00756ccSwyllys for (i = 0; i < ekus->eku_count; i++) { 1238d00756ccSwyllys kmf_free_data(&ekus->ekulist[i]); 1239d00756ccSwyllys } 1240d00756ccSwyllys free(ekus->ekulist); 1241d00756ccSwyllys free(ekus->critlist); 124256664548SWyllys Ingersoll free(ekus); 1243d00756ccSwyllys } 1244d00756ccSwyllys } 1245d00756ccSwyllys 1246d00756ccSwyllys static KMF_RETURN 1247d00756ccSwyllys parse_ekus(char *ekustr, EKU_LIST *ekus) 1248d00756ccSwyllys { 1249d00756ccSwyllys KMF_RETURN rv = KMF_OK; 1250d00756ccSwyllys KMF_OID *newoid; 1251d00756ccSwyllys int critical; 1252d00756ccSwyllys 1253d00756ccSwyllys if (strncasecmp(ekustr, "critical:", 1254d00756ccSwyllys strlen("critical:")) == 0) { 1255d00756ccSwyllys critical = TRUE; 1256d00756ccSwyllys ekustr += strlen("critical:"); 1257d00756ccSwyllys } else { 1258d00756ccSwyllys critical = FALSE; 1259d00756ccSwyllys } 1260d00756ccSwyllys newoid = kmf_ekuname_to_oid(ekustr); 1261d00756ccSwyllys if (newoid != NULL) { 1262d00756ccSwyllys rv = addToEKUList(ekus, critical, newoid); 1263d00756ccSwyllys free(newoid); 1264d00756ccSwyllys } else { 1265d00756ccSwyllys rv = PK_ERR_USAGE; 1266d00756ccSwyllys } 1267d00756ccSwyllys 1268d00756ccSwyllys return (rv); 1269d00756ccSwyllys } 1270d00756ccSwyllys 1271d00756ccSwyllys KMF_RETURN 1272d00756ccSwyllys verify_ekunames(char *ekuliststr, EKU_LIST **ekulist) 1273d00756ccSwyllys { 1274d00756ccSwyllys KMF_RETURN rv = KMF_OK; 1275d00756ccSwyllys char *p; 1276d00756ccSwyllys EKU_LIST *ekus = NULL; 1277d00756ccSwyllys 1278d00756ccSwyllys if (ekuliststr == NULL || strlen(ekuliststr) == 0) 1279d00756ccSwyllys return (0); 1280d00756ccSwyllys 128156664548SWyllys Ingersoll ekus = calloc(sizeof (EKU_LIST), 1); 128256664548SWyllys Ingersoll if (ekus == NULL) 128356664548SWyllys Ingersoll return (KMF_ERR_MEMORY); 128456664548SWyllys Ingersoll 1285d00756ccSwyllys /* 1286d00756ccSwyllys * The list should be comma separated list of EKU Names. 1287d00756ccSwyllys */ 1288d00756ccSwyllys p = strtok(ekuliststr, ","); 1289d00756ccSwyllys 1290d00756ccSwyllys /* If no tokens found, then maybe it's just a single EKU value */ 1291d00756ccSwyllys if (p == NULL) { 1292d00756ccSwyllys rv = parse_ekus(ekuliststr, ekus); 1293d00756ccSwyllys } 1294d00756ccSwyllys 1295d00756ccSwyllys while (p != NULL) { 1296d00756ccSwyllys rv = parse_ekus(p, ekus); 1297d00756ccSwyllys 1298d00756ccSwyllys if (rv != KMF_OK) 1299d00756ccSwyllys break; 1300d00756ccSwyllys p = strtok(NULL, ","); 1301d00756ccSwyllys } 1302d00756ccSwyllys 1303d00756ccSwyllys if (rv != KMF_OK) 1304d00756ccSwyllys free_eku_list(ekus); 1305d00756ccSwyllys else 1306d00756ccSwyllys *ekulist = ekus; 1307d00756ccSwyllys 1308d00756ccSwyllys return (rv); 1309d00756ccSwyllys } 1310fa60c371Swyllys 1311fa60c371Swyllys KMF_RETURN 1312fa60c371Swyllys token_auth_needed(KMF_HANDLE_T handle, char *tokenlabel, int *auth) 1313fa60c371Swyllys { 1314fa60c371Swyllys CK_TOKEN_INFO info; 1315fa60c371Swyllys CK_SLOT_ID slot; 1316fa60c371Swyllys CK_RV ckrv; 1317fa60c371Swyllys KMF_RETURN rv; 1318fa60c371Swyllys 1319fa60c371Swyllys *auth = 0; 1320fa60c371Swyllys rv = kmf_pk11_token_lookup(handle, tokenlabel, &slot); 1321fa60c371Swyllys if (rv != KMF_OK) 1322fa60c371Swyllys return (rv); 1323fa60c371Swyllys 1324fa60c371Swyllys ckrv = C_GetTokenInfo(slot, &info); 1325fa60c371Swyllys if (ckrv != KMF_OK) 1326fa60c371Swyllys return (KMF_ERR_INTERNAL); 1327fa60c371Swyllys 1328fa60c371Swyllys *auth = (info.flags & CKF_LOGIN_REQUIRED); 1329fa60c371Swyllys 1330fa60c371Swyllys return (KMF_OK); 1331fa60c371Swyllys } 1332*e65e5c2dSWyllys Ingersoll 1333*e65e5c2dSWyllys Ingersoll void 1334*e65e5c2dSWyllys Ingersoll show_ecc_curves() 1335*e65e5c2dSWyllys Ingersoll { 1336*e65e5c2dSWyllys Ingersoll int i; 1337*e65e5c2dSWyllys Ingersoll 1338*e65e5c2dSWyllys Ingersoll (void) printf(gettext("Supported ECC curve names:\n")); 1339*e65e5c2dSWyllys Ingersoll for (i = 0; i < number_of_curves; i++) { 1340*e65e5c2dSWyllys Ingersoll (void) printf("%s", oid_table[i].name); 1341*e65e5c2dSWyllys Ingersoll if (i > 0 && ((i+1) % 5) == 0) 1342*e65e5c2dSWyllys Ingersoll (void) printf("\n"); 1343*e65e5c2dSWyllys Ingersoll else if (i+1 < number_of_curves) 1344*e65e5c2dSWyllys Ingersoll (void) printf(", "); 1345*e65e5c2dSWyllys Ingersoll } 1346*e65e5c2dSWyllys Ingersoll (void) printf("\n"); 1347*e65e5c2dSWyllys Ingersoll } 1348*e65e5c2dSWyllys Ingersoll 1349*e65e5c2dSWyllys Ingersoll KMF_OID * 1350*e65e5c2dSWyllys Ingersoll ecc_name_to_oid(char *name) 1351*e65e5c2dSWyllys Ingersoll { 1352*e65e5c2dSWyllys Ingersoll int i; 1353*e65e5c2dSWyllys Ingersoll for (i = 0; i < number_of_oids; i++) { 1354*e65e5c2dSWyllys Ingersoll if (strcasecmp(name, oid_table[i].name) == 0) 1355*e65e5c2dSWyllys Ingersoll return ((KMF_OID *)oid_table[i].oid); 1356*e65e5c2dSWyllys Ingersoll } 1357*e65e5c2dSWyllys Ingersoll return (NULL); 1358*e65e5c2dSWyllys Ingersoll } 1359