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 5*99ebb4caSwyllys * Common Development and Distribution License (the "License"). 6*99ebb4caSwyllys * 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*99ebb4caSwyllys * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * This file contains the functions that are shared among 307c478bd9Sstevel@tonic-gate * the various services this tool will ultimately provide. 317711facfSdinak * The functions in this file return PKCS#11 CK_RV errors. 327711facfSdinak * Only one session and one login per token is supported 337711facfSdinak * at this time. 347c478bd9Sstevel@tonic-gate */ 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #include <stdio.h> 377c478bd9Sstevel@tonic-gate #include <stdlib.h> 387c478bd9Sstevel@tonic-gate #include <string.h> 397c478bd9Sstevel@tonic-gate #include <ctype.h> 40*99ebb4caSwyllys #include <sys/types.h> 41*99ebb4caSwyllys #include <sys/stat.h> 42*99ebb4caSwyllys #include <fcntl.h> 43*99ebb4caSwyllys #include <tzfile.h> 447c478bd9Sstevel@tonic-gate #include <cryptoutil.h> 457c478bd9Sstevel@tonic-gate #include <security/cryptoki.h> 46*99ebb4caSwyllys #include <kmfapi.h> 477c478bd9Sstevel@tonic-gate 48*99ebb4caSwyllys #include "common.h" 497711facfSdinak 507711facfSdinak /* Local status variables. */ 517711facfSdinak static boolean_t initialized = B_FALSE; 527711facfSdinak static boolean_t session_opened = B_FALSE; 537711facfSdinak static boolean_t logged_in = B_FALSE; 547c478bd9Sstevel@tonic-gate 5549e21299Sdinak /* Supporting structures and global variables for getopt_av(). */ 5649e21299Sdinak typedef struct av_opts_s { 5749e21299Sdinak int shortnm; /* short name character */ 5849e21299Sdinak char *longnm; /* long name string, NOT terminated */ 5949e21299Sdinak int longnm_len; /* length of long name string */ 6049e21299Sdinak boolean_t has_arg; /* takes optional argument */ 6149e21299Sdinak } av_opts; 6249e21299Sdinak static av_opts *opts_av = NULL; 6349e21299Sdinak static const char *_save_optstr = NULL; 6449e21299Sdinak static int _save_numopts = 0; 6549e21299Sdinak 6649e21299Sdinak int optind_av = 1; 6749e21299Sdinak char *optarg_av = NULL; 6849e21299Sdinak 69*99ebb4caSwyllys static void close_sess(CK_SESSION_HANDLE); 70*99ebb4caSwyllys static void logout_token(CK_SESSION_HANDLE); 71*99ebb4caSwyllys 727c478bd9Sstevel@tonic-gate /* 737711facfSdinak * Perform PKCS#11 setup here. Currently only C_Initialize is required, 747711facfSdinak * along with setting/resetting state variables. 757c478bd9Sstevel@tonic-gate */ 767711facfSdinak CK_RV 777711facfSdinak init_pk11(void) 787c478bd9Sstevel@tonic-gate { 797711facfSdinak CK_RV rv = CKR_OK; 807711facfSdinak 817711facfSdinak /* If C_Initialize() already called, nothing to do here. */ 827711facfSdinak if (initialized == B_TRUE) 837711facfSdinak return (CKR_OK); 847c478bd9Sstevel@tonic-gate 857711facfSdinak /* Reset state variables because C_Initialize() not yet done. */ 867711facfSdinak session_opened = B_FALSE; 877711facfSdinak logged_in = B_FALSE; 887c478bd9Sstevel@tonic-gate 897711facfSdinak /* Initialize PKCS#11 library. */ 907711facfSdinak if ((rv = C_Initialize(NULL_PTR)) != CKR_OK && 917711facfSdinak rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { 927711facfSdinak return (rv); 937711facfSdinak } 947c478bd9Sstevel@tonic-gate 957711facfSdinak initialized = B_TRUE; 967711facfSdinak return (CKR_OK); 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate /* 1007711facfSdinak * Finalize PKCS#11 library and reset state variables. Open sessions, 1017711facfSdinak * if any, are closed, and thereby any logins are logged out also. 1027c478bd9Sstevel@tonic-gate */ 1037711facfSdinak void 1047711facfSdinak final_pk11(CK_SESSION_HANDLE sess) 1057c478bd9Sstevel@tonic-gate { 1067c478bd9Sstevel@tonic-gate 1077711facfSdinak /* If the library wasn't initialized, nothing to do here. */ 1087711facfSdinak if (!initialized) 1097711facfSdinak return; 1107c478bd9Sstevel@tonic-gate 1117711facfSdinak /* Make sure the sesion is closed first. */ 1127711facfSdinak close_sess(sess); 1137711facfSdinak 1147711facfSdinak (void) C_Finalize(NULL); 1157711facfSdinak initialized = B_FALSE; 1167711facfSdinak } 1177711facfSdinak 1187711facfSdinak /* 1197711facfSdinak * Close PKCS#11 session and reset state variables. Any logins are 1207711facfSdinak * logged out. 1217711facfSdinak */ 122*99ebb4caSwyllys static void 1237711facfSdinak close_sess(CK_SESSION_HANDLE sess) 1247711facfSdinak { 1257711facfSdinak 1267711facfSdinak if (sess == NULL) { 1277711facfSdinak return; 1287711facfSdinak } 1297711facfSdinak 1307711facfSdinak /* If session is already closed, nothing to do here. */ 1317711facfSdinak if (!session_opened) 1327711facfSdinak return; 1337711facfSdinak 1347711facfSdinak /* Make sure user is logged out of token. */ 1357711facfSdinak logout_token(sess); 1367711facfSdinak 1377711facfSdinak (void) C_CloseSession(sess); 1387711facfSdinak session_opened = B_FALSE; 1397711facfSdinak } 1407711facfSdinak 1417711facfSdinak /* 1427711facfSdinak * Log user out of token and reset status variable. 1437711facfSdinak */ 144*99ebb4caSwyllys static void 1457711facfSdinak logout_token(CK_SESSION_HANDLE sess) 1467711facfSdinak { 1477711facfSdinak 1487711facfSdinak if (sess == NULL) { 1497711facfSdinak return; 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate 1527711facfSdinak /* If already logged out, nothing to do here. */ 1537711facfSdinak if (!logged_in) 1547711facfSdinak return; 1557711facfSdinak 1567711facfSdinak (void) C_Logout(sess); 1577711facfSdinak logged_in = B_FALSE; 1587711facfSdinak } 1597711facfSdinak 1607711facfSdinak /* 1617711facfSdinak * Gets PIN from user. Caller needs to free the returned PIN when done. 1627711facfSdinak * If two prompts are given, the PIN is confirmed with second prompt. 1637711facfSdinak * Note that getphassphrase() may return data in static memory area. 1647711facfSdinak */ 1657711facfSdinak CK_RV 1667711facfSdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen) 1677711facfSdinak { 1687711facfSdinak char *save_phrase, *phrase1, *phrase2; 1697711facfSdinak 170*99ebb4caSwyllys 171*99ebb4caSwyllys #ifdef DEBUG 172*99ebb4caSwyllys if (getenv("TOKENPIN") != NULL) { 173*99ebb4caSwyllys *pin = (CK_UTF8CHAR_PTR)strdup(getenv("TOKENPIN")); 174*99ebb4caSwyllys *pinlen = strlen((char *)(*pin)); 175*99ebb4caSwyllys return (CKR_OK); 176*99ebb4caSwyllys } 177*99ebb4caSwyllys #endif /* DEBUG */ 1787711facfSdinak 1797711facfSdinak /* Prompt user for a PIN. */ 1807711facfSdinak if (prompt1 == NULL) { 1817711facfSdinak return (CKR_ARGUMENTS_BAD); 1827711facfSdinak } 1837711facfSdinak if ((phrase1 = getpassphrase(prompt1)) == NULL) { 1847711facfSdinak return (CKR_FUNCTION_FAILED); 1857711facfSdinak } 1867711facfSdinak 1877711facfSdinak /* Duplicate 1st PIN in separate chunk of memory. */ 1887711facfSdinak if ((save_phrase = strdup(phrase1)) == NULL) 1897711facfSdinak return (CKR_HOST_MEMORY); 1907711facfSdinak 1917711facfSdinak /* If second prompt given, PIN confirmation is requested. */ 1927711facfSdinak if (prompt2 != NULL) { 1937711facfSdinak if ((phrase2 = getpassphrase(prompt2)) == NULL) { 1947711facfSdinak free(save_phrase); 1957711facfSdinak return (CKR_FUNCTION_FAILED); 1967711facfSdinak } 1977711facfSdinak if (strcmp(save_phrase, phrase2) != 0) { 1987711facfSdinak free(save_phrase); 1997711facfSdinak return (CKR_PIN_INCORRECT); 2007711facfSdinak } 2017711facfSdinak } 2027711facfSdinak 2037711facfSdinak *pin = (CK_UTF8CHAR_PTR)save_phrase; 2047711facfSdinak *pinlen = strlen(save_phrase); 2057711facfSdinak return (CKR_OK); 2067711facfSdinak } 2077711facfSdinak 2087711facfSdinak /* 2097711facfSdinak * Gets yes/no response from user. If either no prompt is supplied, a 2107711facfSdinak * default prompt is used. If not message for invalid input is supplied, 2117711facfSdinak * a default will not be provided. If the user provides no response, 2127711facfSdinak * the input default B_TRUE == yes, B_FALSE == no is returned. 2137711facfSdinak * Otherwise, B_TRUE is returned for yes, and B_FALSE for no. 2147711facfSdinak */ 2157711facfSdinak boolean_t 2167711facfSdinak yesno(char *prompt, char *invalid, boolean_t dflt) 2177711facfSdinak { 2187711facfSdinak char *response, buf[1024]; 2197711facfSdinak char *yes = gettext("yes"); 2207711facfSdinak char *no = gettext("no"); 2217711facfSdinak 222*99ebb4caSwyllys 223*99ebb4caSwyllys #ifdef DEBUG 224*99ebb4caSwyllys /* If debugging or testing, return TRUE and avoid prompting */ 225*99ebb4caSwyllys if (getenv("TOKENPIN") != NULL) { 226*99ebb4caSwyllys return (B_TRUE); 227*99ebb4caSwyllys } 228*99ebb4caSwyllys #endif /* DEBUG */ 2297711facfSdinak 2307711facfSdinak if (prompt == NULL) 2317711facfSdinak prompt = gettext("Enter (y)es or (n)o? "); 2327711facfSdinak 2337711facfSdinak for (;;) { 2347711facfSdinak /* Prompt user. */ 2357711facfSdinak (void) printf("%s", prompt); 2367711facfSdinak (void) fflush(stdout); 2377711facfSdinak 2387711facfSdinak /* Get the response. */ 2397711facfSdinak if ((response = fgets(buf, sizeof (buf), stdin)) == NULL) 2407711facfSdinak break; /* go to default response */ 2417711facfSdinak 2427711facfSdinak /* Skip any leading white space. */ 2437711facfSdinak while (isspace(*response)) 2447711facfSdinak response++; 2457711facfSdinak if (*response == '\0') 2467711facfSdinak break; /* go to default response */ 2477711facfSdinak 2487711facfSdinak /* Is it valid input? Return appropriately. */ 2497711facfSdinak if (strncasecmp(response, yes, 1) == 0) 2507711facfSdinak return (B_TRUE); 2517711facfSdinak if (strncasecmp(response, no, 1) == 0) 2527711facfSdinak return (B_FALSE); 2537711facfSdinak 2547711facfSdinak /* Indicate invalid input, and try again. */ 2557711facfSdinak if (invalid != NULL) 2567711facfSdinak (void) printf("%s", invalid); 2577711facfSdinak } 2587711facfSdinak return (dflt); 2597711facfSdinak } 2607711facfSdinak 2617711facfSdinak /* 2627711facfSdinak * Gets the list of slots which have tokens in them. Keeps adjusting 2637711facfSdinak * the size of the slot list buffer until the call is successful or an 2647711facfSdinak * irrecoverable error occurs. 2657711facfSdinak */ 2667711facfSdinak CK_RV 2677711facfSdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count) 2687711facfSdinak { 2697711facfSdinak CK_ULONG tmp_count = 0; 2707711facfSdinak CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR; 2717711facfSdinak int rv = CKR_OK; 2727711facfSdinak 2737711facfSdinak if (!initialized) 2747711facfSdinak if ((rv = init_pk11()) != CKR_OK) 2757711facfSdinak return (rv); 2767711facfSdinak 2777711facfSdinak /* 2787711facfSdinak * Get the slot count first because we don't know how many 2797711facfSdinak * slots there are and how many of those slots even have tokens. 2807711facfSdinak * Don't specify an arbitrary buffer size for the slot list; 2817711facfSdinak * it may be too small (see section 11.5 of PKCS#11 spec). 2827711facfSdinak * Also select only those slots that have tokens in them, 2837711facfSdinak * because this tool has no need to know about empty slots. 2847711facfSdinak */ 2857711facfSdinak if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK) 2867711facfSdinak return (rv); 2877711facfSdinak 2887711facfSdinak if (tmp_count == 0) { 2897711facfSdinak *slot_list = NULL_PTR; 2907711facfSdinak *slot_count = 0; 2917711facfSdinak return (CKR_OK); 2927711facfSdinak } 2937711facfSdinak 2947711facfSdinak /* Allocate initial space for the slot list. */ 2957711facfSdinak if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count * 2967711facfSdinak sizeof (CK_SLOT_ID))) == NULL) 2977711facfSdinak return (CKR_HOST_MEMORY); 2987711facfSdinak 2997711facfSdinak /* Then get the slot list itself. */ 3007711facfSdinak for (;;) { 3017711facfSdinak if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) { 3027711facfSdinak *slot_list = tmp_list; 3037711facfSdinak *slot_count = tmp_count; 3047711facfSdinak break; 3057711facfSdinak } 3067711facfSdinak 3077711facfSdinak if (rv != CKR_BUFFER_TOO_SMALL) { 3087711facfSdinak free(tmp_list); 3097711facfSdinak break; 3107711facfSdinak } 3117711facfSdinak 3127711facfSdinak /* If the number of slots grew, try again. */ 3137711facfSdinak if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list, 3147711facfSdinak tmp_count * sizeof (CK_SLOT_ID))) == NULL) { 3157711facfSdinak free(tmp_list); 3167711facfSdinak rv = CKR_HOST_MEMORY; 3177711facfSdinak break; 3187711facfSdinak } 3197711facfSdinak tmp_list = tmp2_list; 3207711facfSdinak } 3217711facfSdinak 3227711facfSdinak return (rv); 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate /* 326*99ebb4caSwyllys * Breaks out the getopt-style option string into a structure that can be 327*99ebb4caSwyllys * traversed later for calls to getopt_av(). Option string is NOT altered, 328*99ebb4caSwyllys * but the struct fields point to locations within option string. 3297c478bd9Sstevel@tonic-gate */ 3307c478bd9Sstevel@tonic-gate static int 331*99ebb4caSwyllys populate_opts(char *optstring) 3327c478bd9Sstevel@tonic-gate { 333*99ebb4caSwyllys int i; 334*99ebb4caSwyllys av_opts *temp; 3357c478bd9Sstevel@tonic-gate char *marker; 3367c478bd9Sstevel@tonic-gate 337*99ebb4caSwyllys if (optstring == NULL || *optstring == '\0') 338*99ebb4caSwyllys return (0); 339*99ebb4caSwyllys 340*99ebb4caSwyllys /* 341*99ebb4caSwyllys * This tries to imitate getopt(3c) Each option must conform to: 342*99ebb4caSwyllys * <short name char> [ ':' ] [ '(' <long name string> ')' ] 343*99ebb4caSwyllys * If long name is missing, the short name is used for long name. 344*99ebb4caSwyllys */ 345*99ebb4caSwyllys for (i = 0; *optstring != '\0'; i++) { 346*99ebb4caSwyllys if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) : 347*99ebb4caSwyllys realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) { 348*99ebb4caSwyllys if (opts_av != NULL) 349*99ebb4caSwyllys free(opts_av); 350*99ebb4caSwyllys opts_av = NULL; 351*99ebb4caSwyllys return (0); 352*99ebb4caSwyllys } else { 353*99ebb4caSwyllys opts_av = (av_opts *)temp; 354*99ebb4caSwyllys } 3557c478bd9Sstevel@tonic-gate 356*99ebb4caSwyllys (void) memset(&opts_av[i], 0, sizeof (av_opts)); 357*99ebb4caSwyllys marker = optstring; /* may need optstring later */ 3587c478bd9Sstevel@tonic-gate 359*99ebb4caSwyllys opts_av[i].shortnm = *marker++; /* set short name */ 360*99ebb4caSwyllys 361*99ebb4caSwyllys if (*marker == ':') { /* check for opt arg */ 362*99ebb4caSwyllys marker++; 363*99ebb4caSwyllys opts_av[i].has_arg = B_TRUE; 364*99ebb4caSwyllys } 365*99ebb4caSwyllys 366*99ebb4caSwyllys if (*marker == '(') { /* check and set long name */ 367*99ebb4caSwyllys marker++; 368*99ebb4caSwyllys opts_av[i].longnm = marker; 369*99ebb4caSwyllys opts_av[i].longnm_len = strcspn(marker, ")"); 370*99ebb4caSwyllys optstring = marker + opts_av[i].longnm_len + 1; 371*99ebb4caSwyllys } else { 372*99ebb4caSwyllys /* use short name option character */ 373*99ebb4caSwyllys opts_av[i].longnm = optstring; 374*99ebb4caSwyllys opts_av[i].longnm_len = 1; 375*99ebb4caSwyllys optstring = marker; 376*99ebb4caSwyllys } 377*99ebb4caSwyllys } 378*99ebb4caSwyllys 379*99ebb4caSwyllys return (i); 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate /* 383*99ebb4caSwyllys * getopt_av() is very similar to getopt(3c) in that the takes an option 384*99ebb4caSwyllys * string, compares command line arguments for matches, and returns a single 385*99ebb4caSwyllys * letter option when a match is found. However, getopt_av() differs from 386*99ebb4caSwyllys * getopt(3c) by requiring that only longname options and values be found 387*99ebb4caSwyllys * on the command line and all leading dashes are omitted. In other words, 388*99ebb4caSwyllys * it tries to enforce only longname "option=value" arguments on the command 389*99ebb4caSwyllys * line. Boolean options are not allowed either. 3907c478bd9Sstevel@tonic-gate */ 391*99ebb4caSwyllys int 392*99ebb4caSwyllys getopt_av(int argc, char * const *argv, const char *optstring) 3937c478bd9Sstevel@tonic-gate { 394*99ebb4caSwyllys int i; 395*99ebb4caSwyllys int len; 396*99ebb4caSwyllys char *cur_option; 3977c478bd9Sstevel@tonic-gate 398*99ebb4caSwyllys if (optind_av >= argc) 399*99ebb4caSwyllys return (EOF); 4007c478bd9Sstevel@tonic-gate 401*99ebb4caSwyllys /* First time or when optstring changes from previous one */ 402*99ebb4caSwyllys if (_save_optstr != optstring) { 403*99ebb4caSwyllys if (opts_av != NULL) 404*99ebb4caSwyllys free(opts_av); 405*99ebb4caSwyllys opts_av = NULL; 406*99ebb4caSwyllys _save_optstr = optstring; 407*99ebb4caSwyllys _save_numopts = populate_opts((char *)optstring); 408*99ebb4caSwyllys } 4097c478bd9Sstevel@tonic-gate 410*99ebb4caSwyllys for (i = 0; i < _save_numopts; i++) { 411*99ebb4caSwyllys cur_option = argv[optind_av]; 4127c478bd9Sstevel@tonic-gate 413*99ebb4caSwyllys if (strcmp(cur_option, "--") == 0) { 414*99ebb4caSwyllys optind_av++; 415*99ebb4caSwyllys break; 4167c478bd9Sstevel@tonic-gate } 4177c478bd9Sstevel@tonic-gate 418*99ebb4caSwyllys if (cur_option[0] == '-' && strlen(cur_option) == 2) { 419*99ebb4caSwyllys len = 1; 420*99ebb4caSwyllys cur_option++; /* remove "-" */ 421*99ebb4caSwyllys } else { 422*99ebb4caSwyllys len = strcspn(cur_option, "="); 423*99ebb4caSwyllys } 4247c478bd9Sstevel@tonic-gate 425*99ebb4caSwyllys if (len == opts_av[i].longnm_len && strncmp(cur_option, 426*99ebb4caSwyllys opts_av[i].longnm, opts_av[i].longnm_len) == 0) { 427*99ebb4caSwyllys /* matched */ 428*99ebb4caSwyllys if (!opts_av[i].has_arg) { 429*99ebb4caSwyllys optind_av++; 430*99ebb4caSwyllys return (opts_av[i].shortnm); 431*99ebb4caSwyllys } 432*99ebb4caSwyllys 433*99ebb4caSwyllys /* needs optarg */ 434*99ebb4caSwyllys if (cur_option[len] == '=') { 435*99ebb4caSwyllys optarg_av = &(cur_option[len+1]); 436*99ebb4caSwyllys optind_av++; 437*99ebb4caSwyllys return (opts_av[i].shortnm); 438*99ebb4caSwyllys } 439*99ebb4caSwyllys 440*99ebb4caSwyllys optarg_av = NULL; 441*99ebb4caSwyllys optind_av++; 442*99ebb4caSwyllys return ((int)'?'); 443*99ebb4caSwyllys } 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 446*99ebb4caSwyllys return (EOF); 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 449*99ebb4caSwyllys KMF_KEYSTORE_TYPE 450*99ebb4caSwyllys KS2Int(char *keystore_str) 45149e21299Sdinak { 452*99ebb4caSwyllys if (keystore_str == NULL) 453*99ebb4caSwyllys return (0); 454*99ebb4caSwyllys if (!strcasecmp(keystore_str, "pkcs11")) 455*99ebb4caSwyllys return (KMF_KEYSTORE_PK11TOKEN); 456*99ebb4caSwyllys else if (!strcasecmp(keystore_str, "nss")) 457*99ebb4caSwyllys return (KMF_KEYSTORE_NSS); 458*99ebb4caSwyllys else if (!strcasecmp(keystore_str, "file")) 459*99ebb4caSwyllys return (KMF_KEYSTORE_OPENSSL); 460*99ebb4caSwyllys else 461*99ebb4caSwyllys return (0); 462*99ebb4caSwyllys } 46349e21299Sdinak 46449e21299Sdinak 465*99ebb4caSwyllys int 466*99ebb4caSwyllys Str2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg) 467*99ebb4caSwyllys { 468*99ebb4caSwyllys if (algm == NULL) { 469*99ebb4caSwyllys *sigAlg = KMF_ALGID_MD5WithRSA; 470*99ebb4caSwyllys *ktype = KMF_RSA; 471*99ebb4caSwyllys } else if (strcasecmp(algm, "DSA") == 0) { 472*99ebb4caSwyllys *sigAlg = KMF_ALGID_SHA1WithDSA; 473*99ebb4caSwyllys *ktype = KMF_DSA; 474*99ebb4caSwyllys } else if (strcasecmp(algm, "RSA") == 0) { 475*99ebb4caSwyllys *sigAlg = KMF_ALGID_MD5WithRSA; 476*99ebb4caSwyllys *ktype = KMF_RSA; 477*99ebb4caSwyllys } else { 478*99ebb4caSwyllys return (-1); 47949e21299Sdinak } 480*99ebb4caSwyllys return (0); 48149e21299Sdinak } 48249e21299Sdinak 483*99ebb4caSwyllys int 484*99ebb4caSwyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype) 48549e21299Sdinak { 486*99ebb4caSwyllys if (algm == NULL) 487*99ebb4caSwyllys *ktype = KMF_AES; 488*99ebb4caSwyllys else if (strcasecmp(algm, "aes") == 0) 489*99ebb4caSwyllys *ktype = KMF_AES; 490*99ebb4caSwyllys else if (strcasecmp(algm, "arcfour") == 0) 491*99ebb4caSwyllys *ktype = KMF_RC4; 492*99ebb4caSwyllys else if (strcasecmp(algm, "des") == 0) 493*99ebb4caSwyllys *ktype = KMF_DES; 494*99ebb4caSwyllys else if (strcasecmp(algm, "3des") == 0) 495*99ebb4caSwyllys *ktype = KMF_DES3; 496*99ebb4caSwyllys else 497*99ebb4caSwyllys return (-1); 49849e21299Sdinak 499*99ebb4caSwyllys return (0); 50049e21299Sdinak } 50149e21299Sdinak 50249e21299Sdinak int 503*99ebb4caSwyllys Str2Lifetime(char *ltimestr, uint32_t *ltime) 50449e21299Sdinak { 505*99ebb4caSwyllys int num; 506*99ebb4caSwyllys char timetok[6]; 50749e21299Sdinak 508*99ebb4caSwyllys if (ltimestr == NULL || !strlen(ltimestr)) { 509*99ebb4caSwyllys /* default to 1 year lifetime */ 510*99ebb4caSwyllys *ltime = SECSPERDAY * DAYSPERNYEAR; 511*99ebb4caSwyllys return (0); 51249e21299Sdinak } 51349e21299Sdinak 514*99ebb4caSwyllys (void) memset(timetok, 0, sizeof (timetok)); 515*99ebb4caSwyllys if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2) 516*99ebb4caSwyllys return (-1); 51749e21299Sdinak 518*99ebb4caSwyllys if (!strcasecmp(timetok, "day") || 519*99ebb4caSwyllys !strcasecmp(timetok, "days")) { 520*99ebb4caSwyllys *ltime = num * SECSPERDAY; 521*99ebb4caSwyllys } else if (!strcasecmp(timetok, "hour") || 522*99ebb4caSwyllys !strcasecmp(timetok, "hours")) { 523*99ebb4caSwyllys *ltime = num * SECSPERHOUR; 524*99ebb4caSwyllys } else if (!strcasecmp(timetok, "year") || 525*99ebb4caSwyllys !strcasecmp(timetok, "years")) { 526*99ebb4caSwyllys *ltime = num * SECSPERDAY * DAYSPERNYEAR; 527*99ebb4caSwyllys } else { 528*99ebb4caSwyllys *ltime = 0; 52949e21299Sdinak return (-1); 53049e21299Sdinak } 53149e21299Sdinak 532*99ebb4caSwyllys return (0); 533*99ebb4caSwyllys } 53449e21299Sdinak 535*99ebb4caSwyllys int 536*99ebb4caSwyllys OT2Int(char *objclass) 537*99ebb4caSwyllys { 538*99ebb4caSwyllys char *c = NULL; 539*99ebb4caSwyllys int retval = 0; 54049e21299Sdinak 541*99ebb4caSwyllys if (objclass == NULL) 542*99ebb4caSwyllys return (-1); 54349e21299Sdinak 544*99ebb4caSwyllys c = strchr(objclass, ':'); 545*99ebb4caSwyllys if (c != NULL) { 546*99ebb4caSwyllys if (!strcasecmp(c, ":private")) 547*99ebb4caSwyllys retval = PK_PRIVATE_OBJ; 548*99ebb4caSwyllys else if (!strcasecmp(c, ":public")) 549*99ebb4caSwyllys retval = PK_PUBLIC_OBJ; 550*99ebb4caSwyllys else if (!strcasecmp(c, ":both")) 551*99ebb4caSwyllys retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ; 552*99ebb4caSwyllys else /* unrecognized option */ 553*99ebb4caSwyllys return (-1); 554*99ebb4caSwyllys 555*99ebb4caSwyllys *c = '\0'; 556*99ebb4caSwyllys } 557*99ebb4caSwyllys 558*99ebb4caSwyllys if (!strcasecmp(objclass, "public")) { 559*99ebb4caSwyllys if (retval) 560*99ebb4caSwyllys return (-1); 561*99ebb4caSwyllys return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | 562*99ebb4caSwyllys PK_PUBKEY_OBJ); 563*99ebb4caSwyllys } else if (!strcasecmp(objclass, "private")) { 564*99ebb4caSwyllys if (retval) 565*99ebb4caSwyllys return (-1); 566*99ebb4caSwyllys return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ); 567*99ebb4caSwyllys } else if (!strcasecmp(objclass, "both")) { 568*99ebb4caSwyllys if (retval) 569*99ebb4caSwyllys return (-1); 570*99ebb4caSwyllys return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ); 571*99ebb4caSwyllys } else if (!strcasecmp(objclass, "cert")) { 572*99ebb4caSwyllys return (retval | PK_CERT_OBJ); 573*99ebb4caSwyllys } else if (!strcasecmp(objclass, "key")) { 574*99ebb4caSwyllys if (retval == 0) /* return all keys */ 575*99ebb4caSwyllys return (retval | PK_KEY_OBJ); 576*99ebb4caSwyllys else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ)) 577*99ebb4caSwyllys /* return all keys */ 578*99ebb4caSwyllys return (retval | PK_KEY_OBJ); 579*99ebb4caSwyllys else if (retval & PK_PUBLIC_OBJ) 580*99ebb4caSwyllys /* Only return public keys */ 581*99ebb4caSwyllys return (retval | PK_PUBKEY_OBJ); 582*99ebb4caSwyllys else if (retval & PK_PRIVATE_OBJ) 583*99ebb4caSwyllys /* Only return private keys */ 584*99ebb4caSwyllys return (retval | PK_PRIKEY_OBJ); 585*99ebb4caSwyllys } else if (!strcasecmp(objclass, "crl")) { 586*99ebb4caSwyllys if (retval) 587*99ebb4caSwyllys return (-1); 588*99ebb4caSwyllys return (retval | PK_CRL_OBJ); 589*99ebb4caSwyllys } 590*99ebb4caSwyllys 591*99ebb4caSwyllys if (retval == 0) /* No matches found */ 592*99ebb4caSwyllys retval = -1; 593*99ebb4caSwyllys return (retval); 59449e21299Sdinak } 59549e21299Sdinak 596*99ebb4caSwyllys KMF_ENCODE_FORMAT 597*99ebb4caSwyllys Str2Format(char *formstr) 5987c478bd9Sstevel@tonic-gate { 599*99ebb4caSwyllys if (formstr == NULL || !strcasecmp(formstr, "der")) 600*99ebb4caSwyllys return (KMF_FORMAT_ASN1); 601*99ebb4caSwyllys if (!strcasecmp(formstr, "pem")) 602*99ebb4caSwyllys return (KMF_FORMAT_PEM); 603*99ebb4caSwyllys if (!strcasecmp(formstr, "pkcs12")) 604*99ebb4caSwyllys return (KMF_FORMAT_PKCS12); 605*99ebb4caSwyllys 606*99ebb4caSwyllys return (KMF_FORMAT_UNDEF); 607*99ebb4caSwyllys } 6087c478bd9Sstevel@tonic-gate 6097711facfSdinak 610*99ebb4caSwyllys KMF_RETURN 611*99ebb4caSwyllys select_token(void *kmfhandle, char *token, 612*99ebb4caSwyllys int readonly) 613*99ebb4caSwyllys { 614*99ebb4caSwyllys KMF_RETURN rv = KMF_OK; 615*99ebb4caSwyllys KMF_CONFIG_PARAMS config; 6167711facfSdinak 617*99ebb4caSwyllys if (token == NULL) 618*99ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 6197c478bd9Sstevel@tonic-gate 620*99ebb4caSwyllys (void) memset(&config, 0, sizeof (config)); 621*99ebb4caSwyllys config.kstype = KMF_KEYSTORE_PK11TOKEN; 622*99ebb4caSwyllys config.pkcs11config.label = token; 623*99ebb4caSwyllys config.pkcs11config.readonly = readonly; 6247711facfSdinak 625*99ebb4caSwyllys rv = KMF_ConfigureKeystore(kmfhandle, &config); 626*99ebb4caSwyllys if (rv == KMF_ERR_TOKEN_SELECTED) 627*99ebb4caSwyllys rv = KMF_OK; 628*99ebb4caSwyllys return (rv); 6297711facfSdinak } 6307711facfSdinak 631*99ebb4caSwyllys 632*99ebb4caSwyllys KMF_RETURN 633*99ebb4caSwyllys configure_nss(void *kmfhandle, char *dir, char *prefix) 6347711facfSdinak { 635*99ebb4caSwyllys KMF_RETURN rv = KMF_OK; 636*99ebb4caSwyllys KMF_CONFIG_PARAMS config; 6377711facfSdinak 638*99ebb4caSwyllys (void) memset(&config, 0, sizeof (config)); 639*99ebb4caSwyllys config.kstype = KMF_KEYSTORE_NSS; 640*99ebb4caSwyllys config.nssconfig.configdir = dir; 641*99ebb4caSwyllys config.nssconfig.certPrefix = prefix; 642*99ebb4caSwyllys config.nssconfig.keyPrefix = prefix; 643*99ebb4caSwyllys config.nssconfig.secModName = NULL; 6447711facfSdinak 645*99ebb4caSwyllys rv = KMF_ConfigureKeystore(kmfhandle, &config); 646*99ebb4caSwyllys if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED) 647*99ebb4caSwyllys rv = KMF_OK; 6487c478bd9Sstevel@tonic-gate 649*99ebb4caSwyllys return (rv); 650*99ebb4caSwyllys } 6517711facfSdinak 652*99ebb4caSwyllys 653*99ebb4caSwyllys KMF_RETURN 654*99ebb4caSwyllys get_pk12_password(KMF_CREDENTIAL *cred) 655*99ebb4caSwyllys { 656*99ebb4caSwyllys KMF_RETURN rv = KMF_OK; 657*99ebb4caSwyllys char prompt[1024]; 6587711facfSdinak 6597711facfSdinak /* 660*99ebb4caSwyllys * Get the password to use for the PK12 encryption. 6617711facfSdinak */ 662*99ebb4caSwyllys (void) strlcpy(prompt, 663*99ebb4caSwyllys gettext("Enter password to use for " 664*99ebb4caSwyllys "accessing the PKCS12 file: "), 665*99ebb4caSwyllys sizeof (prompt)); 6667711facfSdinak 667*99ebb4caSwyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 668*99ebb4caSwyllys (ulong_t *)&cred->credlen) != CKR_OK) { 669*99ebb4caSwyllys cred->cred = NULL; 670*99ebb4caSwyllys cred->credlen = 0; 6717711facfSdinak } 6727711facfSdinak 6737711facfSdinak return (rv); 6747711facfSdinak } 6757711facfSdinak 6767711facfSdinak 677*99ebb4caSwyllys #define COUNTRY_PROMPT "Country Name (2 letter code) [US]:" 678*99ebb4caSwyllys #define STATE_PROMPT "State or Province Name (full name) [Some-State]:" 679*99ebb4caSwyllys #define LOCALITY_PROMPT "Locality Name (eg, city) []:" 680*99ebb4caSwyllys #define ORG_PROMPT "Organization Name (eg, company) []:" 681*99ebb4caSwyllys #define UNIT_PROMPT "Organizational Unit Name (eg, section) []:" 682*99ebb4caSwyllys #define NAME_PROMPT "Common Name (eg, YOUR name) []:" 683*99ebb4caSwyllys #define EMAIL_PROMPT "Email Address []:" 6847711facfSdinak 685*99ebb4caSwyllys #define COUNTRY_DEFAULT "US" 686*99ebb4caSwyllys #define STATE_DEFAULT "Some-State" 687*99ebb4caSwyllys #define INVALID_INPUT "Invalid input; please re-enter ..." 6887711facfSdinak 689*99ebb4caSwyllys #define SUBNAMESIZ 1024 690*99ebb4caSwyllys #define RDN_MIN 1 691*99ebb4caSwyllys #define RDN_MAX 64 692*99ebb4caSwyllys #define COUNTRYNAME_MIN 2 693*99ebb4caSwyllys #define COUNTRYNAME_MAX 2 6947711facfSdinak 695*99ebb4caSwyllys static char * 696*99ebb4caSwyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len) 697*99ebb4caSwyllys { 698*99ebb4caSwyllys char buf[1024]; 699*99ebb4caSwyllys char *response = NULL; 700*99ebb4caSwyllys char *ret = NULL; 701*99ebb4caSwyllys int len; 7027711facfSdinak 703*99ebb4caSwyllys for (;;) { 704*99ebb4caSwyllys (void) printf("\t%s", prompt); 705*99ebb4caSwyllys (void) fflush(stdout); 706*99ebb4caSwyllys 707*99ebb4caSwyllys response = fgets(buf, sizeof (buf), stdin); 708*99ebb4caSwyllys if (response == NULL) { 709*99ebb4caSwyllys if (default_str != NULL) { 710*99ebb4caSwyllys ret = strdup(default_str); 711*99ebb4caSwyllys } 712*99ebb4caSwyllys break; 713*99ebb4caSwyllys } 714*99ebb4caSwyllys 715*99ebb4caSwyllys /* Skip any leading white space. */ 716*99ebb4caSwyllys while (isspace(*response)) 717*99ebb4caSwyllys response++; 718*99ebb4caSwyllys if (*response == '\0') { 719*99ebb4caSwyllys if (default_str != NULL) { 720*99ebb4caSwyllys ret = strdup(default_str); 721*99ebb4caSwyllys } 722*99ebb4caSwyllys break; 723*99ebb4caSwyllys } 724*99ebb4caSwyllys 725*99ebb4caSwyllys len = strlen(response); 726*99ebb4caSwyllys response[len-1] = '\0'; /* get rid of "LF" */ 727*99ebb4caSwyllys len--; 728*99ebb4caSwyllys if (len >= min_len && len <= max_len) { 729*99ebb4caSwyllys ret = strdup(response); 730*99ebb4caSwyllys break; 7317711facfSdinak } 7327711facfSdinak 733*99ebb4caSwyllys (void) printf("%s\n", INVALID_INPUT); 734*99ebb4caSwyllys 7357711facfSdinak } 7367711facfSdinak 737*99ebb4caSwyllys return (ret); 738*99ebb4caSwyllys } 7397711facfSdinak 740*99ebb4caSwyllys int 741*99ebb4caSwyllys get_subname(char **result) 742*99ebb4caSwyllys { 743*99ebb4caSwyllys char *country = NULL; 744*99ebb4caSwyllys char *state = NULL; 745*99ebb4caSwyllys char *locality = NULL; 746*99ebb4caSwyllys char *org = NULL; 747*99ebb4caSwyllys char *unit = NULL; 748*99ebb4caSwyllys char *name = NULL; 749*99ebb4caSwyllys char *email = NULL; 750*99ebb4caSwyllys char *subname = NULL; 751*99ebb4caSwyllys 752*99ebb4caSwyllys (void) printf("Entering following fields for subject (a DN) ...\n"); 753*99ebb4caSwyllys country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT, 754*99ebb4caSwyllys COUNTRYNAME_MIN, COUNTRYNAME_MAX); 755*99ebb4caSwyllys if (country == NULL) 756*99ebb4caSwyllys return (-1); 757*99ebb4caSwyllys 758*99ebb4caSwyllys state = get_input_string(STATE_PROMPT, STATE_DEFAULT, 759*99ebb4caSwyllys RDN_MIN, RDN_MAX); 760*99ebb4caSwyllys if (state == NULL) { 761*99ebb4caSwyllys goto out; 7627711facfSdinak } 7637711facfSdinak 764*99ebb4caSwyllys locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX); 765*99ebb4caSwyllys org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX); 766*99ebb4caSwyllys unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX); 767*99ebb4caSwyllys name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX); 768*99ebb4caSwyllys email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX); 7697711facfSdinak 770*99ebb4caSwyllys /* Now create a subject name from the input strings */ 771*99ebb4caSwyllys if ((subname = malloc(SUBNAMESIZ)) == NULL) 772*99ebb4caSwyllys goto out; 773*99ebb4caSwyllys 774*99ebb4caSwyllys (void) memset(subname, 0, SUBNAMESIZ); 775*99ebb4caSwyllys (void) strlcpy(subname, "C=", SUBNAMESIZ); 776*99ebb4caSwyllys (void) strlcat(subname, country, SUBNAMESIZ); 777*99ebb4caSwyllys (void) strlcat(subname, ", ", SUBNAMESIZ); 778*99ebb4caSwyllys (void) strlcat(subname, "ST=", SUBNAMESIZ); 779*99ebb4caSwyllys (void) strlcat(subname, state, SUBNAMESIZ); 7807711facfSdinak 781*99ebb4caSwyllys if (locality) { 782*99ebb4caSwyllys (void) strlcat(subname, ", ", SUBNAMESIZ); 783*99ebb4caSwyllys (void) strlcat(subname, "L=", SUBNAMESIZ); 784*99ebb4caSwyllys (void) strlcat(subname, locality, SUBNAMESIZ); 7857711facfSdinak } 7867711facfSdinak 787*99ebb4caSwyllys if (org) { 788*99ebb4caSwyllys (void) strlcat(subname, ", ", SUBNAMESIZ); 789*99ebb4caSwyllys (void) strlcat(subname, "O=", SUBNAMESIZ); 790*99ebb4caSwyllys (void) strlcat(subname, org, SUBNAMESIZ); 7917711facfSdinak } 7927711facfSdinak 793*99ebb4caSwyllys if (unit) { 794*99ebb4caSwyllys (void) strlcat(subname, ", ", SUBNAMESIZ); 795*99ebb4caSwyllys (void) strlcat(subname, "OU=", SUBNAMESIZ); 796*99ebb4caSwyllys (void) strlcat(subname, unit, SUBNAMESIZ); 797*99ebb4caSwyllys } 7987711facfSdinak 799*99ebb4caSwyllys if (name) { 800*99ebb4caSwyllys (void) strlcat(subname, ", ", SUBNAMESIZ); 801*99ebb4caSwyllys (void) strlcat(subname, "CN=", SUBNAMESIZ); 802*99ebb4caSwyllys (void) strlcat(subname, name, SUBNAMESIZ); 8037711facfSdinak } 8047711facfSdinak 805*99ebb4caSwyllys if (email) { 806*99ebb4caSwyllys (void) strlcat(subname, ", ", SUBNAMESIZ); 807*99ebb4caSwyllys (void) strlcat(subname, "E=", SUBNAMESIZ); 808*99ebb4caSwyllys (void) strlcat(subname, email, SUBNAMESIZ); 8097c478bd9Sstevel@tonic-gate } 8107c478bd9Sstevel@tonic-gate 811*99ebb4caSwyllys out: 812*99ebb4caSwyllys if (country) 813*99ebb4caSwyllys free(country); 814*99ebb4caSwyllys if (state) 815*99ebb4caSwyllys free(state); 816*99ebb4caSwyllys if (locality) 817*99ebb4caSwyllys free(locality); 818*99ebb4caSwyllys if (org) 819*99ebb4caSwyllys free(org); 820*99ebb4caSwyllys if (unit) 821*99ebb4caSwyllys free(unit); 822*99ebb4caSwyllys if (name) 823*99ebb4caSwyllys free(name); 824*99ebb4caSwyllys if (email) 825*99ebb4caSwyllys free(email); 826*99ebb4caSwyllys 827*99ebb4caSwyllys if (subname == NULL) 828*99ebb4caSwyllys return (-1); 829*99ebb4caSwyllys else { 830*99ebb4caSwyllys *result = subname; 831*99ebb4caSwyllys return (0); 8327711facfSdinak } 8337c478bd9Sstevel@tonic-gate } 8347c478bd9Sstevel@tonic-gate 8357c478bd9Sstevel@tonic-gate /* 836*99ebb4caSwyllys * Parse a string of KeyUsage values and convert 837*99ebb4caSwyllys * them to the correct KU Bits. 838*99ebb4caSwyllys * The field may be marked "critical" by prepending 839*99ebb4caSwyllys * "critical:" to the list. 840*99ebb4caSwyllys * EX: critical:digitialSignature,keyEncipherment 8417c478bd9Sstevel@tonic-gate */ 842*99ebb4caSwyllys KMF_RETURN 843*99ebb4caSwyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical) 8447c478bd9Sstevel@tonic-gate { 845*99ebb4caSwyllys KMF_RETURN ret = KMF_OK; 846*99ebb4caSwyllys uint16_t kuval; 847*99ebb4caSwyllys char *k; 848*99ebb4caSwyllys 849*99ebb4caSwyllys *kubits = 0; 850*99ebb4caSwyllys if (kustr == NULL || !strlen(kustr)) 851*99ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 852*99ebb4caSwyllys 853*99ebb4caSwyllys /* Check to see if this is critical */ 854*99ebb4caSwyllys if (!strncasecmp(kustr, "critical:", strlen("critical:"))) { 855*99ebb4caSwyllys *critical = TRUE; 856*99ebb4caSwyllys kustr += strlen("critical:"); 857*99ebb4caSwyllys } else { 858*99ebb4caSwyllys *critical = FALSE; 8597c478bd9Sstevel@tonic-gate } 8607711facfSdinak 861*99ebb4caSwyllys k = strtok(kustr, ","); 862*99ebb4caSwyllys while (k != NULL) { 863*99ebb4caSwyllys kuval = KMF_StringToKeyUsage(k); 864*99ebb4caSwyllys if (kuval == 0) { 865*99ebb4caSwyllys *kubits = 0; 866*99ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 8677711facfSdinak } 868*99ebb4caSwyllys *kubits |= kuval; 869*99ebb4caSwyllys k = strtok(NULL, ","); 8707711facfSdinak } 8717711facfSdinak 872*99ebb4caSwyllys return (ret); 8737711facfSdinak } 8747711facfSdinak 8757711facfSdinak /* 876*99ebb4caSwyllys * Verify the alternate subject label is real or invalid. 877*99ebb4caSwyllys * 878*99ebb4caSwyllys * The field may be marked "critical" by prepending 879*99ebb4caSwyllys * "critical:" to the list. 880*99ebb4caSwyllys * EX: "critical:IP=1.2.3.4" 8817711facfSdinak */ 882*99ebb4caSwyllys KMF_RETURN 883*99ebb4caSwyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical) 8847711facfSdinak { 885*99ebb4caSwyllys char *p; 886*99ebb4caSwyllys KMF_RETURN rv = KMF_OK; 8877711facfSdinak 888*99ebb4caSwyllys /* Check to see if this is critical */ 889*99ebb4caSwyllys if (!strncasecmp(arg, "critical:", strlen("critical:"))) { 890*99ebb4caSwyllys *critical = TRUE; 891*99ebb4caSwyllys arg += strlen("critical:"); 892*99ebb4caSwyllys } else { 893*99ebb4caSwyllys *critical = FALSE; 894*99ebb4caSwyllys } 8957711facfSdinak 896*99ebb4caSwyllys /* Make sure there is an "=" sign */ 897*99ebb4caSwyllys p = strchr(arg, '='); 898*99ebb4caSwyllys if (p == NULL) 899*99ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 9007711facfSdinak 901*99ebb4caSwyllys p[0] = '\0'; 902*99ebb4caSwyllys 903*99ebb4caSwyllys if (strcmp(arg, "IP") == 0) 904*99ebb4caSwyllys *type = GENNAME_IPADDRESS; 905*99ebb4caSwyllys else if (strcmp(arg, "DNS") == 0) 906*99ebb4caSwyllys *type = GENNAME_DNSNAME; 907*99ebb4caSwyllys else if (strcmp(arg, "EMAIL") == 0) 908*99ebb4caSwyllys *type = GENNAME_RFC822NAME; 909*99ebb4caSwyllys else if (strcmp(arg, "URI") == 0) 910*99ebb4caSwyllys *type = GENNAME_URI; 911*99ebb4caSwyllys else if (strcmp(arg, "DN") == 0) 912*99ebb4caSwyllys *type = GENNAME_DIRECTORYNAME; 913*99ebb4caSwyllys else if (strcmp(arg, "RID") == 0) 914*99ebb4caSwyllys *type = GENNAME_REGISTEREDID; 915*99ebb4caSwyllys else 916*99ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 917*99ebb4caSwyllys 918*99ebb4caSwyllys p[0] = '='; 919*99ebb4caSwyllys 920*99ebb4caSwyllys return (rv); 9217c478bd9Sstevel@tonic-gate } 92249e21299Sdinak 923*99ebb4caSwyllys int 924*99ebb4caSwyllys get_token_password(KMF_KEYSTORE_TYPE kstype, 925*99ebb4caSwyllys char *token_spec, KMF_CREDENTIAL *cred) 92649e21299Sdinak { 927*99ebb4caSwyllys char prompt[1024]; 928*99ebb4caSwyllys char *p = NULL; 92949e21299Sdinak 930*99ebb4caSwyllys if (kstype == KMF_KEYSTORE_PK11TOKEN) { 931*99ebb4caSwyllys p = strchr(token_spec, ':'); 932*99ebb4caSwyllys if (p != NULL) 933*99ebb4caSwyllys *p = 0; 934*99ebb4caSwyllys } 93549e21299Sdinak /* 936*99ebb4caSwyllys * Login to the token first. 93749e21299Sdinak */ 938*99ebb4caSwyllys (void) snprintf(prompt, sizeof (prompt), 939*99ebb4caSwyllys gettext(DEFAULT_TOKEN_PROMPT), 940*99ebb4caSwyllys token_spec); 94149e21299Sdinak 942*99ebb4caSwyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 943*99ebb4caSwyllys (ulong_t *)&cred->credlen) != CKR_OK) { 944*99ebb4caSwyllys cred->cred = NULL; 945*99ebb4caSwyllys cred->credlen = 0; 94649e21299Sdinak } 94749e21299Sdinak 948*99ebb4caSwyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL) 949*99ebb4caSwyllys *p = ':'; 950*99ebb4caSwyllys return (KMF_OK); 95149e21299Sdinak } 95249e21299Sdinak 953*99ebb4caSwyllys KMF_RETURN 954*99ebb4caSwyllys verify_file(char *filename) 95549e21299Sdinak { 956*99ebb4caSwyllys KMF_RETURN ret = KMF_OK; 957*99ebb4caSwyllys int fd; 95849e21299Sdinak 959*99ebb4caSwyllys /* 960*99ebb4caSwyllys * Attempt to open with the EXCL flag so that if 961*99ebb4caSwyllys * it already exists, the open will fail. It will 962*99ebb4caSwyllys * also fail if the file cannot be created due to 963*99ebb4caSwyllys * permissions on the parent directory, or if the 964*99ebb4caSwyllys * parent directory itself does not exist. 965*99ebb4caSwyllys */ 966*99ebb4caSwyllys fd = open(filename, O_CREAT | O_EXCL, 0600); 967*99ebb4caSwyllys if (fd == -1) 968*99ebb4caSwyllys return (KMF_ERR_OPEN_FILE); 96949e21299Sdinak 970*99ebb4caSwyllys /* If we were able to create it, delete it. */ 971*99ebb4caSwyllys (void) close(fd); 972*99ebb4caSwyllys (void) unlink(filename); 97349e21299Sdinak 974*99ebb4caSwyllys return (ret); 975*99ebb4caSwyllys } 97649e21299Sdinak 977*99ebb4caSwyllys void 978*99ebb4caSwyllys display_error(void *handle, KMF_RETURN errcode, char *prefix) 979*99ebb4caSwyllys { 980*99ebb4caSwyllys KMF_RETURN rv1, rv2; 981*99ebb4caSwyllys char *plugin_errmsg = NULL; 982*99ebb4caSwyllys char *kmf_errmsg = NULL; 98349e21299Sdinak 984*99ebb4caSwyllys rv1 = KMF_GetPluginErrorString(handle, &plugin_errmsg); 985*99ebb4caSwyllys rv2 = KMF_GetKMFErrorString(errcode, &kmf_errmsg); 98649e21299Sdinak 987*99ebb4caSwyllys cryptoerror(LOG_STDERR, "%s:", prefix); 988*99ebb4caSwyllys if (rv1 == KMF_OK && plugin_errmsg) { 989*99ebb4caSwyllys cryptoerror(LOG_STDERR, 990*99ebb4caSwyllys gettext("keystore error: %s"), 991*99ebb4caSwyllys plugin_errmsg); 992*99ebb4caSwyllys KMF_FreeString(plugin_errmsg); 993*99ebb4caSwyllys } 99449e21299Sdinak 995*99ebb4caSwyllys if (rv2 == KMF_OK && kmf_errmsg) { 996*99ebb4caSwyllys cryptoerror(LOG_STDERR, 997*99ebb4caSwyllys gettext("libkmf error: %s"), 998*99ebb4caSwyllys kmf_errmsg); 999*99ebb4caSwyllys KMF_FreeString(kmf_errmsg); 100049e21299Sdinak } 100149e21299Sdinak 1002*99ebb4caSwyllys if (rv1 != KMF_OK && rv2 != KMF_OK) 1003*99ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("<unknown error>\n")); 1004*99ebb4caSwyllys 100549e21299Sdinak } 1006