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*47e946e7SWyllys Ingersoll * Copyright 2009 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 707c478bd9Sstevel@tonic-gate /* 717711facfSdinak * Perform PKCS#11 setup here. Currently only C_Initialize is required, 727711facfSdinak * along with setting/resetting state variables. 737c478bd9Sstevel@tonic-gate */ 74448b8615Swyllys static CK_RV 75448b8615Swyllys init_pkcs11(void) 767c478bd9Sstevel@tonic-gate { 777711facfSdinak CK_RV rv = CKR_OK; 787c478bd9Sstevel@tonic-gate 797711facfSdinak /* If C_Initialize() already called, nothing to do here. */ 807711facfSdinak if (initialized == B_TRUE) 817711facfSdinak return (CKR_OK); 827711facfSdinak 837711facfSdinak /* Reset state variables because C_Initialize() not yet done. */ 847711facfSdinak session_opened = B_FALSE; 857711facfSdinak logged_in = B_FALSE; 867711facfSdinak 877c478bd9Sstevel@tonic-gate /* Initialize PKCS#11 library. */ 887c478bd9Sstevel@tonic-gate if ((rv = C_Initialize(NULL_PTR)) != CKR_OK && 897c478bd9Sstevel@tonic-gate rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) { 907711facfSdinak return (rv); 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate 937711facfSdinak initialized = B_TRUE; 947711facfSdinak return (CKR_OK); 957711facfSdinak } 967711facfSdinak 977711facfSdinak /* 987711facfSdinak * Finalize PKCS#11 library and reset state variables. Open sessions, 997711facfSdinak * if any, are closed, and thereby any logins are logged out also. 1007711facfSdinak */ 1017711facfSdinak void 1027711facfSdinak final_pk11(CK_SESSION_HANDLE sess) 1037711facfSdinak { 1047711facfSdinak 1057711facfSdinak /* If the library wasn't initialized, nothing to do here. */ 1067711facfSdinak if (!initialized) 1077711facfSdinak return; 1087711facfSdinak 1097711facfSdinak /* Make sure the sesion is closed first. */ 1107711facfSdinak close_sess(sess); 1117711facfSdinak 1127711facfSdinak (void) C_Finalize(NULL); 1137711facfSdinak initialized = B_FALSE; 1147711facfSdinak } 1157711facfSdinak 1167711facfSdinak /* 1177711facfSdinak * Close PKCS#11 session and reset state variables. Any logins are 1187711facfSdinak * logged out. 1197711facfSdinak */ 12099ebb4caSwyllys static void 1217711facfSdinak close_sess(CK_SESSION_HANDLE sess) 1227711facfSdinak { 1237711facfSdinak 1247711facfSdinak if (sess == NULL) { 1257711facfSdinak return; 1267711facfSdinak } 1277711facfSdinak 1287711facfSdinak /* If session is already closed, nothing to do here. */ 1297711facfSdinak if (!session_opened) 1307711facfSdinak return; 1317711facfSdinak 1327711facfSdinak /* Make sure user is logged out of token. */ 1337711facfSdinak logout_token(sess); 1347711facfSdinak 1357711facfSdinak (void) C_CloseSession(sess); 1367711facfSdinak session_opened = B_FALSE; 1377711facfSdinak } 1387711facfSdinak 1397711facfSdinak /* 1407711facfSdinak * Log user out of token and reset status variable. 1417711facfSdinak */ 14299ebb4caSwyllys static void 1437711facfSdinak logout_token(CK_SESSION_HANDLE sess) 1447711facfSdinak { 1457711facfSdinak 1467711facfSdinak if (sess == NULL) { 1477711facfSdinak return; 1487711facfSdinak } 1497711facfSdinak 1507711facfSdinak /* If already logged out, nothing to do here. */ 1517711facfSdinak if (!logged_in) 1527711facfSdinak return; 1537711facfSdinak 1547711facfSdinak (void) C_Logout(sess); 1557711facfSdinak logged_in = B_FALSE; 1567711facfSdinak } 1577711facfSdinak 1587711facfSdinak /* 1597711facfSdinak * Gets PIN from user. Caller needs to free the returned PIN when done. 1607711facfSdinak * If two prompts are given, the PIN is confirmed with second prompt. 1617711facfSdinak * Note that getphassphrase() may return data in static memory area. 1627711facfSdinak */ 1637711facfSdinak CK_RV 1647711facfSdinak get_pin(char *prompt1, char *prompt2, CK_UTF8CHAR_PTR *pin, CK_ULONG *pinlen) 1657711facfSdinak { 1667711facfSdinak char *save_phrase, *phrase1, *phrase2; 1677711facfSdinak 1687711facfSdinak /* Prompt user for a PIN. */ 1697711facfSdinak if (prompt1 == NULL) { 1707711facfSdinak return (CKR_ARGUMENTS_BAD); 1717711facfSdinak } 1727711facfSdinak if ((phrase1 = getpassphrase(prompt1)) == NULL) { 1737711facfSdinak return (CKR_FUNCTION_FAILED); 1747711facfSdinak } 1757711facfSdinak 1767711facfSdinak /* Duplicate 1st PIN in separate chunk of memory. */ 1777711facfSdinak if ((save_phrase = strdup(phrase1)) == NULL) 1787711facfSdinak return (CKR_HOST_MEMORY); 1797711facfSdinak 1807711facfSdinak /* If second prompt given, PIN confirmation is requested. */ 1817711facfSdinak if (prompt2 != NULL) { 1827711facfSdinak if ((phrase2 = getpassphrase(prompt2)) == NULL) { 1837711facfSdinak free(save_phrase); 1847711facfSdinak return (CKR_FUNCTION_FAILED); 1857711facfSdinak } 1867711facfSdinak if (strcmp(save_phrase, phrase2) != 0) { 1877711facfSdinak free(save_phrase); 1887711facfSdinak return (CKR_PIN_INCORRECT); 1897711facfSdinak } 1907711facfSdinak } 1917711facfSdinak 1927711facfSdinak *pin = (CK_UTF8CHAR_PTR)save_phrase; 1937711facfSdinak *pinlen = strlen(save_phrase); 1947711facfSdinak return (CKR_OK); 1957711facfSdinak } 1967711facfSdinak 197d00756ccSwyllys int 198d00756ccSwyllys yn_to_int(char *ynstr) 199d00756ccSwyllys { 200d00756ccSwyllys char *y = gettext("yes"); 201d00756ccSwyllys char *n = gettext("no"); 202d00756ccSwyllys if (ynstr == NULL) 203d00756ccSwyllys return (-1); 204d00756ccSwyllys 205d00756ccSwyllys if (strncasecmp(ynstr, y, 1) == 0) 206d00756ccSwyllys return (1); 207d00756ccSwyllys else if (strncasecmp(ynstr, n, 1) == 0) 208d00756ccSwyllys return (0); 209d00756ccSwyllys else 210d00756ccSwyllys return (-1); 211d00756ccSwyllys } 212d00756ccSwyllys 2137711facfSdinak /* 2147711facfSdinak * Gets yes/no response from user. If either no prompt is supplied, a 2157711facfSdinak * default prompt is used. If not message for invalid input is supplied, 2167711facfSdinak * a default will not be provided. If the user provides no response, 2177711facfSdinak * the input default B_TRUE == yes, B_FALSE == no is returned. 2187711facfSdinak * Otherwise, B_TRUE is returned for yes, and B_FALSE for no. 2197711facfSdinak */ 2207711facfSdinak boolean_t 2217711facfSdinak yesno(char *prompt, char *invalid, boolean_t dflt) 2227711facfSdinak { 2237711facfSdinak char *response, buf[1024]; 224d00756ccSwyllys int ans; 2257711facfSdinak 2267711facfSdinak if (prompt == NULL) 2277711facfSdinak prompt = gettext("Enter (y)es or (n)o? "); 2287711facfSdinak 2297711facfSdinak for (;;) { 2307711facfSdinak /* Prompt user. */ 2317711facfSdinak (void) printf("%s", prompt); 2327711facfSdinak (void) fflush(stdout); 2337711facfSdinak 2347711facfSdinak /* Get the response. */ 2357711facfSdinak if ((response = fgets(buf, sizeof (buf), stdin)) == NULL) 2367711facfSdinak break; /* go to default response */ 2377711facfSdinak 2387711facfSdinak /* Skip any leading white space. */ 2397711facfSdinak while (isspace(*response)) 2407711facfSdinak response++; 2417711facfSdinak if (*response == '\0') 2427711facfSdinak break; /* go to default response */ 2437711facfSdinak 244d00756ccSwyllys ans = yn_to_int(response); 245d00756ccSwyllys if (ans == 1) 2467711facfSdinak return (B_TRUE); 247d00756ccSwyllys else if (ans == 0) 2487711facfSdinak return (B_FALSE); 2497711facfSdinak 2507711facfSdinak /* Indicate invalid input, and try again. */ 2517711facfSdinak if (invalid != NULL) 2527711facfSdinak (void) printf("%s", invalid); 2537711facfSdinak } 2547711facfSdinak return (dflt); 2557711facfSdinak } 2567711facfSdinak 2577711facfSdinak /* 2587711facfSdinak * Gets the list of slots which have tokens in them. Keeps adjusting 2597711facfSdinak * the size of the slot list buffer until the call is successful or an 2607711facfSdinak * irrecoverable error occurs. 2617711facfSdinak */ 2627711facfSdinak CK_RV 2637711facfSdinak get_token_slots(CK_SLOT_ID_PTR *slot_list, CK_ULONG *slot_count) 2647711facfSdinak { 2657711facfSdinak CK_ULONG tmp_count = 0; 2667711facfSdinak CK_SLOT_ID_PTR tmp_list = NULL_PTR, tmp2_list = NULL_PTR; 2677711facfSdinak int rv = CKR_OK; 2687711facfSdinak 2697711facfSdinak if (!initialized) 270448b8615Swyllys if ((rv = init_pkcs11()) != CKR_OK) 2717711facfSdinak return (rv); 2727711facfSdinak 2737711facfSdinak /* 2747711facfSdinak * Get the slot count first because we don't know how many 2757711facfSdinak * slots there are and how many of those slots even have tokens. 2767711facfSdinak * Don't specify an arbitrary buffer size for the slot list; 2777711facfSdinak * it may be too small (see section 11.5 of PKCS#11 spec). 2787711facfSdinak * Also select only those slots that have tokens in them, 2797711facfSdinak * because this tool has no need to know about empty slots. 2807711facfSdinak */ 2817711facfSdinak if ((rv = C_GetSlotList(1, NULL_PTR, &tmp_count)) != CKR_OK) 2827711facfSdinak return (rv); 2837711facfSdinak 2847711facfSdinak if (tmp_count == 0) { 2857711facfSdinak *slot_list = NULL_PTR; 2867711facfSdinak *slot_count = 0; 2877711facfSdinak return (CKR_OK); 2887711facfSdinak } 2897711facfSdinak 2907711facfSdinak /* Allocate initial space for the slot list. */ 2917711facfSdinak if ((tmp_list = (CK_SLOT_ID_PTR) malloc(tmp_count * 2927711facfSdinak sizeof (CK_SLOT_ID))) == NULL) 2937711facfSdinak return (CKR_HOST_MEMORY); 2947711facfSdinak 2957711facfSdinak /* Then get the slot list itself. */ 2967711facfSdinak for (;;) { 2977711facfSdinak if ((rv = C_GetSlotList(1, tmp_list, &tmp_count)) == CKR_OK) { 2987711facfSdinak *slot_list = tmp_list; 2997711facfSdinak *slot_count = tmp_count; 3007711facfSdinak break; 3017711facfSdinak } 3027711facfSdinak 3037711facfSdinak if (rv != CKR_BUFFER_TOO_SMALL) { 3047711facfSdinak free(tmp_list); 3057711facfSdinak break; 3067711facfSdinak } 3077711facfSdinak 3087711facfSdinak /* If the number of slots grew, try again. */ 3097711facfSdinak if ((tmp2_list = (CK_SLOT_ID_PTR) realloc(tmp_list, 3107711facfSdinak tmp_count * sizeof (CK_SLOT_ID))) == NULL) { 3117711facfSdinak free(tmp_list); 3127711facfSdinak rv = CKR_HOST_MEMORY; 3137711facfSdinak break; 3147711facfSdinak } 3157711facfSdinak tmp_list = tmp2_list; 3167711facfSdinak } 3177711facfSdinak 3187711facfSdinak return (rv); 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate /* 32249e21299Sdinak * Breaks out the getopt-style option string into a structure that can be 32349e21299Sdinak * traversed later for calls to getopt_av(). Option string is NOT altered, 32449e21299Sdinak * but the struct fields point to locations within option string. 32549e21299Sdinak */ 32649e21299Sdinak static int 32749e21299Sdinak populate_opts(char *optstring) 32849e21299Sdinak { 32949e21299Sdinak int i; 33049e21299Sdinak av_opts *temp; 33149e21299Sdinak char *marker; 33249e21299Sdinak 33349e21299Sdinak if (optstring == NULL || *optstring == '\0') 33449e21299Sdinak return (0); 33549e21299Sdinak 33649e21299Sdinak /* 33749e21299Sdinak * This tries to imitate getopt(3c) Each option must conform to: 33849e21299Sdinak * <short name char> [ ':' ] [ '(' <long name string> ')' ] 33949e21299Sdinak * If long name is missing, the short name is used for long name. 34049e21299Sdinak */ 34149e21299Sdinak for (i = 0; *optstring != '\0'; i++) { 34249e21299Sdinak if ((temp = (av_opts *)((i == 0) ? malloc(sizeof (av_opts)) : 34349e21299Sdinak realloc(opts_av, (i+1) * sizeof (av_opts)))) == NULL) { 34499ebb4caSwyllys if (opts_av != NULL) 34549e21299Sdinak free(opts_av); 34649e21299Sdinak opts_av = NULL; 34749e21299Sdinak return (0); 34899ebb4caSwyllys } else { 34949e21299Sdinak opts_av = (av_opts *)temp; 35099ebb4caSwyllys } 35149e21299Sdinak 35299ebb4caSwyllys (void) memset(&opts_av[i], 0, sizeof (av_opts)); 35349e21299Sdinak marker = optstring; /* may need optstring later */ 35449e21299Sdinak 35549e21299Sdinak opts_av[i].shortnm = *marker++; /* set short name */ 35649e21299Sdinak 35749e21299Sdinak if (*marker == ':') { /* check for opt arg */ 35849e21299Sdinak marker++; 35949e21299Sdinak opts_av[i].has_arg = B_TRUE; 36049e21299Sdinak } 36149e21299Sdinak 36249e21299Sdinak if (*marker == '(') { /* check and set long name */ 36349e21299Sdinak marker++; 36449e21299Sdinak opts_av[i].longnm = marker; 36549e21299Sdinak opts_av[i].longnm_len = strcspn(marker, ")"); 36649e21299Sdinak optstring = marker + opts_av[i].longnm_len + 1; 36749e21299Sdinak } else { 36849e21299Sdinak /* use short name option character */ 36949e21299Sdinak opts_av[i].longnm = optstring; 37049e21299Sdinak opts_av[i].longnm_len = 1; 37149e21299Sdinak optstring = marker; 37249e21299Sdinak } 37349e21299Sdinak } 37449e21299Sdinak 37549e21299Sdinak return (i); 37649e21299Sdinak } 37749e21299Sdinak 37849e21299Sdinak /* 37949e21299Sdinak * getopt_av() is very similar to getopt(3c) in that the takes an option 38049e21299Sdinak * string, compares command line arguments for matches, and returns a single 38149e21299Sdinak * letter option when a match is found. However, getopt_av() differs from 38249e21299Sdinak * getopt(3c) by requiring that only longname options and values be found 38349e21299Sdinak * on the command line and all leading dashes are omitted. In other words, 38449e21299Sdinak * it tries to enforce only longname "option=value" arguments on the command 38549e21299Sdinak * line. Boolean options are not allowed either. 38649e21299Sdinak */ 38749e21299Sdinak int 38849e21299Sdinak getopt_av(int argc, char * const *argv, const char *optstring) 38949e21299Sdinak { 39049e21299Sdinak int i; 39149e21299Sdinak int len; 39299ebb4caSwyllys char *cur_option; 39349e21299Sdinak 39449e21299Sdinak if (optind_av >= argc) 39549e21299Sdinak return (EOF); 39649e21299Sdinak 39749e21299Sdinak /* First time or when optstring changes from previous one */ 39849e21299Sdinak if (_save_optstr != optstring) { 39949e21299Sdinak if (opts_av != NULL) 40049e21299Sdinak free(opts_av); 40149e21299Sdinak opts_av = NULL; 40249e21299Sdinak _save_optstr = optstring; 40349e21299Sdinak _save_numopts = populate_opts((char *)optstring); 40449e21299Sdinak } 40549e21299Sdinak 40649e21299Sdinak for (i = 0; i < _save_numopts; i++) { 40799ebb4caSwyllys cur_option = argv[optind_av]; 40899ebb4caSwyllys 40999ebb4caSwyllys if (strcmp(cur_option, "--") == 0) { 41049e21299Sdinak optind_av++; 41149e21299Sdinak break; 41249e21299Sdinak } 41349e21299Sdinak 41499ebb4caSwyllys if (cur_option[0] == '-' && strlen(cur_option) == 2) { 41599ebb4caSwyllys len = 1; 41699ebb4caSwyllys cur_option++; /* remove "-" */ 41799ebb4caSwyllys } else { 41899ebb4caSwyllys len = strcspn(cur_option, "="); 41999ebb4caSwyllys } 42049e21299Sdinak 42199ebb4caSwyllys if (len == opts_av[i].longnm_len && strncmp(cur_option, 42249e21299Sdinak opts_av[i].longnm, opts_av[i].longnm_len) == 0) { 42349e21299Sdinak /* matched */ 42449e21299Sdinak if (!opts_av[i].has_arg) { 42549e21299Sdinak optind_av++; 42649e21299Sdinak return (opts_av[i].shortnm); 42749e21299Sdinak } 42849e21299Sdinak 42949e21299Sdinak /* needs optarg */ 43099ebb4caSwyllys if (cur_option[len] == '=') { 43199ebb4caSwyllys optarg_av = &(cur_option[len+1]); 43249e21299Sdinak optind_av++; 43349e21299Sdinak return (opts_av[i].shortnm); 43449e21299Sdinak } 43549e21299Sdinak 43649e21299Sdinak optarg_av = NULL; 43749e21299Sdinak optind_av++; 43849e21299Sdinak return ((int)'?'); 43949e21299Sdinak } 44049e21299Sdinak } 44149e21299Sdinak 44249e21299Sdinak return (EOF); 44349e21299Sdinak } 44499ebb4caSwyllys 44599ebb4caSwyllys KMF_KEYSTORE_TYPE 44699ebb4caSwyllys KS2Int(char *keystore_str) 44799ebb4caSwyllys { 44899ebb4caSwyllys if (keystore_str == NULL) 44999ebb4caSwyllys return (0); 450d00756ccSwyllys if (strcasecmp(keystore_str, "pkcs11") == 0) 45199ebb4caSwyllys return (KMF_KEYSTORE_PK11TOKEN); 452d00756ccSwyllys else if (strcasecmp(keystore_str, "nss") == 0) 45399ebb4caSwyllys return (KMF_KEYSTORE_NSS); 454d00756ccSwyllys else if (strcasecmp(keystore_str, "file") == 0) 45599ebb4caSwyllys return (KMF_KEYSTORE_OPENSSL); 45699ebb4caSwyllys else 45799ebb4caSwyllys return (0); 45899ebb4caSwyllys } 45999ebb4caSwyllys 46099ebb4caSwyllys 46199ebb4caSwyllys int 46299ebb4caSwyllys Str2KeyType(char *algm, KMF_KEY_ALG *ktype, KMF_ALGORITHM_INDEX *sigAlg) 46399ebb4caSwyllys { 46499ebb4caSwyllys if (algm == NULL) { 46599ebb4caSwyllys *sigAlg = KMF_ALGID_MD5WithRSA; 46699ebb4caSwyllys *ktype = KMF_RSA; 46799ebb4caSwyllys } else if (strcasecmp(algm, "DSA") == 0) { 46899ebb4caSwyllys *sigAlg = KMF_ALGID_SHA1WithDSA; 46999ebb4caSwyllys *ktype = KMF_DSA; 47099ebb4caSwyllys } else if (strcasecmp(algm, "RSA") == 0) { 47199ebb4caSwyllys *sigAlg = KMF_ALGID_MD5WithRSA; 47299ebb4caSwyllys *ktype = KMF_RSA; 47399ebb4caSwyllys } else { 47499ebb4caSwyllys return (-1); 47599ebb4caSwyllys } 47699ebb4caSwyllys return (0); 47799ebb4caSwyllys } 47899ebb4caSwyllys 47999ebb4caSwyllys int 48099ebb4caSwyllys Str2SymKeyType(char *algm, KMF_KEY_ALG *ktype) 48199ebb4caSwyllys { 48299ebb4caSwyllys if (algm == NULL) 48399ebb4caSwyllys *ktype = KMF_AES; 48499ebb4caSwyllys else if (strcasecmp(algm, "aes") == 0) 48599ebb4caSwyllys *ktype = KMF_AES; 48699ebb4caSwyllys else if (strcasecmp(algm, "arcfour") == 0) 48799ebb4caSwyllys *ktype = KMF_RC4; 48899ebb4caSwyllys else if (strcasecmp(algm, "des") == 0) 48999ebb4caSwyllys *ktype = KMF_DES; 49099ebb4caSwyllys else if (strcasecmp(algm, "3des") == 0) 49199ebb4caSwyllys *ktype = KMF_DES3; 492c197cb9dShylee else if (strcasecmp(algm, "generic") == 0) 493c197cb9dShylee *ktype = KMF_GENERIC_SECRET; 49499ebb4caSwyllys else 49599ebb4caSwyllys return (-1); 49699ebb4caSwyllys 49799ebb4caSwyllys return (0); 49899ebb4caSwyllys } 49999ebb4caSwyllys 50099ebb4caSwyllys int 50199ebb4caSwyllys Str2Lifetime(char *ltimestr, uint32_t *ltime) 50299ebb4caSwyllys { 50399ebb4caSwyllys int num; 50499ebb4caSwyllys char timetok[6]; 50599ebb4caSwyllys 506d00756ccSwyllys if (ltimestr == NULL || strlen(ltimestr) == 0) { 50799ebb4caSwyllys /* default to 1 year lifetime */ 50899ebb4caSwyllys *ltime = SECSPERDAY * DAYSPERNYEAR; 50999ebb4caSwyllys return (0); 51099ebb4caSwyllys } 51199ebb4caSwyllys 51299ebb4caSwyllys (void) memset(timetok, 0, sizeof (timetok)); 51399ebb4caSwyllys if (sscanf(ltimestr, "%d-%06s", &num, timetok) != 2) 51499ebb4caSwyllys return (-1); 51599ebb4caSwyllys 516d00756ccSwyllys if (strcasecmp(timetok, "day") == 0|| 517d00756ccSwyllys strcasecmp(timetok, "days") == 0) { 51899ebb4caSwyllys *ltime = num * SECSPERDAY; 519d00756ccSwyllys } else if (strcasecmp(timetok, "hour") == 0|| 520d00756ccSwyllys strcasecmp(timetok, "hours") == 0) { 52199ebb4caSwyllys *ltime = num * SECSPERHOUR; 522d00756ccSwyllys } else if (strcasecmp(timetok, "year") == 0 || 523d00756ccSwyllys strcasecmp(timetok, "years") == 0) { 52499ebb4caSwyllys *ltime = num * SECSPERDAY * DAYSPERNYEAR; 52599ebb4caSwyllys } else { 52699ebb4caSwyllys *ltime = 0; 52799ebb4caSwyllys return (-1); 52899ebb4caSwyllys } 52999ebb4caSwyllys 53099ebb4caSwyllys return (0); 53199ebb4caSwyllys } 53299ebb4caSwyllys 53399ebb4caSwyllys int 53499ebb4caSwyllys OT2Int(char *objclass) 53599ebb4caSwyllys { 53699ebb4caSwyllys char *c = NULL; 53799ebb4caSwyllys int retval = 0; 53899ebb4caSwyllys 53999ebb4caSwyllys if (objclass == NULL) 54099ebb4caSwyllys return (-1); 54199ebb4caSwyllys 54299ebb4caSwyllys c = strchr(objclass, ':'); 54399ebb4caSwyllys if (c != NULL) { 544d00756ccSwyllys if (strcasecmp(c, ":private") == 0) 54599ebb4caSwyllys retval = PK_PRIVATE_OBJ; 546d00756ccSwyllys else if (strcasecmp(c, ":public") == 0) 54799ebb4caSwyllys retval = PK_PUBLIC_OBJ; 548d00756ccSwyllys else if (strcasecmp(c, ":both") == 0) 54999ebb4caSwyllys retval = PK_PRIVATE_OBJ | PK_PUBLIC_OBJ; 55099ebb4caSwyllys else /* unrecognized option */ 55199ebb4caSwyllys return (-1); 55299ebb4caSwyllys 55399ebb4caSwyllys *c = '\0'; 55499ebb4caSwyllys } 55599ebb4caSwyllys 556d00756ccSwyllys if (strcasecmp(objclass, "public") == 0) { 55799ebb4caSwyllys if (retval) 55899ebb4caSwyllys return (-1); 55930a5e8faSwyllys return (retval | PK_PUBLIC_OBJ | PK_CERT_OBJ | PK_PUBKEY_OBJ); 560d00756ccSwyllys } else if (strcasecmp(objclass, "private") == 0) { 56199ebb4caSwyllys if (retval) 56299ebb4caSwyllys return (-1); 56399ebb4caSwyllys return (retval | PK_PRIKEY_OBJ | PK_PRIVATE_OBJ); 564d00756ccSwyllys } else if (strcasecmp(objclass, "both") == 0) { 56599ebb4caSwyllys if (retval) 56699ebb4caSwyllys return (-1); 56799ebb4caSwyllys return (PK_KEY_OBJ | PK_PUBLIC_OBJ | PK_PRIVATE_OBJ); 568d00756ccSwyllys } else if (strcasecmp(objclass, "cert") == 0) { 56999ebb4caSwyllys return (retval | PK_CERT_OBJ); 570d00756ccSwyllys } else if (strcasecmp(objclass, "key") == 0) { 57199ebb4caSwyllys if (retval == 0) /* return all keys */ 57299ebb4caSwyllys return (retval | PK_KEY_OBJ); 57399ebb4caSwyllys else if (retval == (PK_PRIVATE_OBJ | PK_PUBLIC_OBJ)) 57499ebb4caSwyllys /* return all keys */ 57599ebb4caSwyllys return (retval | PK_KEY_OBJ); 57699ebb4caSwyllys else if (retval & PK_PUBLIC_OBJ) 57799ebb4caSwyllys /* Only return public keys */ 57899ebb4caSwyllys return (retval | PK_PUBKEY_OBJ); 57999ebb4caSwyllys else if (retval & PK_PRIVATE_OBJ) 58099ebb4caSwyllys /* Only return private keys */ 58199ebb4caSwyllys return (retval | PK_PRIKEY_OBJ); 582d00756ccSwyllys } else if (strcasecmp(objclass, "crl") == 0) { 58399ebb4caSwyllys if (retval) 58499ebb4caSwyllys return (-1); 58599ebb4caSwyllys return (retval | PK_CRL_OBJ); 58699ebb4caSwyllys } 58799ebb4caSwyllys 58899ebb4caSwyllys if (retval == 0) /* No matches found */ 58999ebb4caSwyllys retval = -1; 59099ebb4caSwyllys return (retval); 59199ebb4caSwyllys } 59299ebb4caSwyllys 59399ebb4caSwyllys KMF_ENCODE_FORMAT 59499ebb4caSwyllys Str2Format(char *formstr) 59599ebb4caSwyllys { 596d00756ccSwyllys if (formstr == NULL || strcasecmp(formstr, "der") == 0) 59799ebb4caSwyllys return (KMF_FORMAT_ASN1); 598d00756ccSwyllys if (strcasecmp(formstr, "pem") == 0) 59999ebb4caSwyllys return (KMF_FORMAT_PEM); 600d00756ccSwyllys if (strcasecmp(formstr, "pkcs12") == 0) 60199ebb4caSwyllys return (KMF_FORMAT_PKCS12); 602d00756ccSwyllys if (strcasecmp(formstr, "raw") == 0) 60330a5e8faSwyllys return (KMF_FORMAT_RAWKEY); 60499ebb4caSwyllys 60599ebb4caSwyllys return (KMF_FORMAT_UNDEF); 60699ebb4caSwyllys } 60799ebb4caSwyllys 60899ebb4caSwyllys KMF_RETURN 609d00756ccSwyllys select_token(void *kmfhandle, char *token, int readonly) 61099ebb4caSwyllys { 61130a5e8faSwyllys KMF_ATTRIBUTE attlist[10]; 61230a5e8faSwyllys int i = 0; 61330a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 61499ebb4caSwyllys KMF_RETURN rv = KMF_OK; 61599ebb4caSwyllys 61699ebb4caSwyllys if (token == NULL) 61799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 61899ebb4caSwyllys 61930a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 62030a5e8faSwyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 62130a5e8faSwyllys sizeof (kstype)); 62230a5e8faSwyllys i++; 62399ebb4caSwyllys 62430a5e8faSwyllys if (token) { 62530a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 62630a5e8faSwyllys KMF_TOKEN_LABEL_ATTR, token, 62730a5e8faSwyllys strlen(token)); 62830a5e8faSwyllys i++; 62930a5e8faSwyllys } 63030a5e8faSwyllys 63130a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 63230a5e8faSwyllys KMF_READONLY_ATTR, &readonly, 63330a5e8faSwyllys sizeof (readonly)); 63430a5e8faSwyllys i++; 63530a5e8faSwyllys 63630a5e8faSwyllys rv = kmf_configure_keystore(kmfhandle, i, attlist); 63799ebb4caSwyllys if (rv == KMF_ERR_TOKEN_SELECTED) 63899ebb4caSwyllys rv = KMF_OK; 63999ebb4caSwyllys return (rv); 64099ebb4caSwyllys } 64199ebb4caSwyllys 64299ebb4caSwyllys KMF_RETURN 64399ebb4caSwyllys configure_nss(void *kmfhandle, char *dir, char *prefix) 64499ebb4caSwyllys { 64530a5e8faSwyllys KMF_ATTRIBUTE attlist[10]; 64630a5e8faSwyllys int i = 0; 64730a5e8faSwyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 64899ebb4caSwyllys KMF_RETURN rv = KMF_OK; 64999ebb4caSwyllys 65030a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 65130a5e8faSwyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 65230a5e8faSwyllys sizeof (kstype)); 65330a5e8faSwyllys i++; 65499ebb4caSwyllys 65530a5e8faSwyllys if (dir) { 65630a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 65730a5e8faSwyllys KMF_DIRPATH_ATTR, dir, 65830a5e8faSwyllys strlen(dir)); 65930a5e8faSwyllys i++; 66030a5e8faSwyllys } 66130a5e8faSwyllys 66230a5e8faSwyllys if (prefix) { 66330a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 66430a5e8faSwyllys KMF_CERTPREFIX_ATTR, prefix, 66530a5e8faSwyllys strlen(prefix)); 66630a5e8faSwyllys i++; 66730a5e8faSwyllys 66830a5e8faSwyllys kmf_set_attr_at_index(attlist, i, 66930a5e8faSwyllys KMF_KEYPREFIX_ATTR, prefix, 67030a5e8faSwyllys strlen(prefix)); 67130a5e8faSwyllys i++; 67230a5e8faSwyllys } 67330a5e8faSwyllys 67430a5e8faSwyllys rv = kmf_configure_keystore(kmfhandle, i, attlist); 67599ebb4caSwyllys if (rv == KMF_KEYSTORE_ALREADY_INITIALIZED) 67699ebb4caSwyllys rv = KMF_OK; 67799ebb4caSwyllys 67899ebb4caSwyllys return (rv); 67999ebb4caSwyllys } 68099ebb4caSwyllys 68199ebb4caSwyllys KMF_RETURN 68299ebb4caSwyllys get_pk12_password(KMF_CREDENTIAL *cred) 68399ebb4caSwyllys { 68499ebb4caSwyllys KMF_RETURN rv = KMF_OK; 68599ebb4caSwyllys char prompt[1024]; 68699ebb4caSwyllys 68799ebb4caSwyllys /* 68899ebb4caSwyllys * Get the password to use for the PK12 encryption. 68999ebb4caSwyllys */ 69099ebb4caSwyllys (void) strlcpy(prompt, 69199ebb4caSwyllys gettext("Enter password to use for " 69230a5e8faSwyllys "accessing the PKCS12 file: "), sizeof (prompt)); 69399ebb4caSwyllys 69499ebb4caSwyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 69599ebb4caSwyllys (ulong_t *)&cred->credlen) != CKR_OK) { 69699ebb4caSwyllys cred->cred = NULL; 69799ebb4caSwyllys cred->credlen = 0; 69899ebb4caSwyllys } 69999ebb4caSwyllys 70099ebb4caSwyllys return (rv); 70199ebb4caSwyllys } 70299ebb4caSwyllys 7032cbed729Swyllys #define FILENAME_PROMPT gettext("Filename:") 7042cbed729Swyllys #define FILENAME_MINLEN 1 7052cbed729Swyllys #define FILENAME_MAXLEN MAXPATHLEN 70699ebb4caSwyllys 7072cbed729Swyllys #define COUNTRY_PROMPT gettext("Country Name (2 letter code) [US]:") 7082cbed729Swyllys #define STATE_PROMPT gettext("State or Province Name (full name) " \ 7092cbed729Swyllys "[Some-State]:") 7102cbed729Swyllys #define LOCALITY_PROMPT gettext("Locality Name (eg, city) []:") 7112cbed729Swyllys #define ORG_PROMPT gettext("Organization Name (eg, company) []:") 7122cbed729Swyllys #define UNIT_PROMPT gettext("Organizational Unit Name (eg, section) []:") 7132cbed729Swyllys #define NAME_PROMPT gettext("Common Name (eg, YOUR name) []:") 7142cbed729Swyllys #define EMAIL_PROMPT gettext("Email Address []:") 7152cbed729Swyllys 7162cbed729Swyllys #define SERNO_PROMPT gettext("Serial Number (hex value, example: " \ 7172cbed729Swyllys "0x01020304):") 7182cbed729Swyllys #define SERNO_MINLEN 3 7192cbed729Swyllys #define SERNO_MAXLEN 42 7202cbed729Swyllys 7212cbed729Swyllys #define LABEL_PROMPT gettext("Enter a label for the certificate:") 7222cbed729Swyllys #define LABEL_MINLEN 1 7232cbed729Swyllys #define LABEL_MAXLEN 1024 72499ebb4caSwyllys 72599ebb4caSwyllys #define COUNTRY_DEFAULT "US" 7262cbed729Swyllys #define STATE_DEFAULT NULL 7272cbed729Swyllys #define INVALID_INPUT gettext("Invalid input; please re-enter ...") 72899ebb4caSwyllys 72999ebb4caSwyllys #define SUBNAMESIZ 1024 73099ebb4caSwyllys #define RDN_MIN 1 73199ebb4caSwyllys #define RDN_MAX 64 73299ebb4caSwyllys #define COUNTRYNAME_MIN 2 73399ebb4caSwyllys #define COUNTRYNAME_MAX 2 73499ebb4caSwyllys 73599ebb4caSwyllys static char * 73699ebb4caSwyllys get_input_string(char *prompt, char *default_str, int min_len, int max_len) 73799ebb4caSwyllys { 73899ebb4caSwyllys char buf[1024]; 73999ebb4caSwyllys char *response = NULL; 74099ebb4caSwyllys char *ret = NULL; 74199ebb4caSwyllys int len; 74299ebb4caSwyllys 74399ebb4caSwyllys for (;;) { 74499ebb4caSwyllys (void) printf("\t%s", prompt); 74599ebb4caSwyllys (void) fflush(stdout); 74699ebb4caSwyllys 74799ebb4caSwyllys response = fgets(buf, sizeof (buf), stdin); 74899ebb4caSwyllys if (response == NULL) { 74999ebb4caSwyllys if (default_str != NULL) { 75099ebb4caSwyllys ret = strdup(default_str); 75199ebb4caSwyllys } 75299ebb4caSwyllys break; 75399ebb4caSwyllys } 75499ebb4caSwyllys 75599ebb4caSwyllys /* Skip any leading white space. */ 75699ebb4caSwyllys while (isspace(*response)) 75799ebb4caSwyllys response++; 75899ebb4caSwyllys if (*response == '\0') { 75999ebb4caSwyllys if (default_str != NULL) { 76099ebb4caSwyllys ret = strdup(default_str); 76199ebb4caSwyllys } 76299ebb4caSwyllys break; 76399ebb4caSwyllys } 76499ebb4caSwyllys 76599ebb4caSwyllys len = strlen(response); 76699ebb4caSwyllys response[len-1] = '\0'; /* get rid of "LF" */ 76799ebb4caSwyllys len--; 76899ebb4caSwyllys if (len >= min_len && len <= max_len) { 76999ebb4caSwyllys ret = strdup(response); 77099ebb4caSwyllys break; 77199ebb4caSwyllys } 77299ebb4caSwyllys 77399ebb4caSwyllys (void) printf("%s\n", INVALID_INPUT); 77499ebb4caSwyllys 77599ebb4caSwyllys } 77699ebb4caSwyllys 77799ebb4caSwyllys return (ret); 77899ebb4caSwyllys } 77999ebb4caSwyllys 78099ebb4caSwyllys int 7812cbed729Swyllys get_filename(char *txt, char **result) 7822cbed729Swyllys { 7832cbed729Swyllys char prompt[1024]; 7842cbed729Swyllys char *fname = NULL; 7852cbed729Swyllys 7862cbed729Swyllys (void) snprintf(prompt, sizeof (prompt), 7872cbed729Swyllys gettext("Enter filename for the %s: "), 7882cbed729Swyllys txt); 7892cbed729Swyllys fname = get_input_string(prompt, NULL, 7902cbed729Swyllys FILENAME_MINLEN, FILENAME_MAXLEN); 7912cbed729Swyllys *result = fname; 7922cbed729Swyllys return (0); 7932cbed729Swyllys } 7942cbed729Swyllys 7952cbed729Swyllys int 7962cbed729Swyllys get_certlabel(char **result) 7972cbed729Swyllys { 7982cbed729Swyllys char *label = NULL; 7992cbed729Swyllys 8002cbed729Swyllys label = get_input_string(LABEL_PROMPT, NULL, 8012cbed729Swyllys LABEL_MINLEN, LABEL_MAXLEN); 8022cbed729Swyllys *result = label; 8032cbed729Swyllys return (0); 8042cbed729Swyllys } 8052cbed729Swyllys 8062cbed729Swyllys int 8072cbed729Swyllys get_serial(char **result) 8082cbed729Swyllys { 8092cbed729Swyllys char *serial = NULL; 8102cbed729Swyllys 8112cbed729Swyllys serial = get_input_string(SERNO_PROMPT, NULL, SERNO_MINLEN, 8122cbed729Swyllys SERNO_MAXLEN); 8132cbed729Swyllys 8142cbed729Swyllys *result = serial; 8152cbed729Swyllys return (0); 8162cbed729Swyllys } 8172cbed729Swyllys 8182cbed729Swyllys int 81999ebb4caSwyllys get_subname(char **result) 82099ebb4caSwyllys { 82199ebb4caSwyllys char *country = NULL; 82299ebb4caSwyllys char *state = NULL; 82399ebb4caSwyllys char *locality = NULL; 82499ebb4caSwyllys char *org = NULL; 82599ebb4caSwyllys char *unit = NULL; 82699ebb4caSwyllys char *name = NULL; 82799ebb4caSwyllys char *email = NULL; 82899ebb4caSwyllys char *subname = NULL; 82999ebb4caSwyllys 83099ebb4caSwyllys (void) printf("Entering following fields for subject (a DN) ...\n"); 83199ebb4caSwyllys country = get_input_string(COUNTRY_PROMPT, COUNTRY_DEFAULT, 83299ebb4caSwyllys COUNTRYNAME_MIN, COUNTRYNAME_MAX); 83399ebb4caSwyllys if (country == NULL) 83499ebb4caSwyllys return (-1); 83599ebb4caSwyllys 83699ebb4caSwyllys state = get_input_string(STATE_PROMPT, STATE_DEFAULT, 83799ebb4caSwyllys RDN_MIN, RDN_MAX); 83899ebb4caSwyllys 83999ebb4caSwyllys locality = get_input_string(LOCALITY_PROMPT, NULL, RDN_MIN, RDN_MAX); 84099ebb4caSwyllys org = get_input_string(ORG_PROMPT, NULL, RDN_MIN, RDN_MAX); 84199ebb4caSwyllys unit = get_input_string(UNIT_PROMPT, NULL, RDN_MIN, RDN_MAX); 84299ebb4caSwyllys name = get_input_string(NAME_PROMPT, NULL, RDN_MIN, RDN_MAX); 84399ebb4caSwyllys email = get_input_string(EMAIL_PROMPT, NULL, RDN_MIN, RDN_MAX); 84499ebb4caSwyllys 84599ebb4caSwyllys /* Now create a subject name from the input strings */ 84699ebb4caSwyllys if ((subname = malloc(SUBNAMESIZ)) == NULL) 84799ebb4caSwyllys goto out; 84899ebb4caSwyllys 84999ebb4caSwyllys (void) memset(subname, 0, SUBNAMESIZ); 85099ebb4caSwyllys (void) strlcpy(subname, "C=", SUBNAMESIZ); 85199ebb4caSwyllys (void) strlcat(subname, country, SUBNAMESIZ); 8522cbed729Swyllys if (state != NULL) { 8532cbed729Swyllys (void) strlcat(subname, ", ST=", SUBNAMESIZ); 85499ebb4caSwyllys (void) strlcat(subname, state, SUBNAMESIZ); 8552cbed729Swyllys } 85699ebb4caSwyllys 8572cbed729Swyllys if (locality != NULL) { 8582cbed729Swyllys (void) strlcat(subname, ", L=", SUBNAMESIZ); 85999ebb4caSwyllys (void) strlcat(subname, locality, SUBNAMESIZ); 86099ebb4caSwyllys } 86199ebb4caSwyllys 8622cbed729Swyllys if (org != NULL) { 8632cbed729Swyllys (void) strlcat(subname, ", O=", SUBNAMESIZ); 86499ebb4caSwyllys (void) strlcat(subname, org, SUBNAMESIZ); 86599ebb4caSwyllys } 86699ebb4caSwyllys 8672cbed729Swyllys if (unit != NULL) { 8682cbed729Swyllys (void) strlcat(subname, ", OU=", SUBNAMESIZ); 86999ebb4caSwyllys (void) strlcat(subname, unit, SUBNAMESIZ); 87099ebb4caSwyllys } 87199ebb4caSwyllys 8722cbed729Swyllys if (name != NULL) { 8732cbed729Swyllys (void) strlcat(subname, ", CN=", SUBNAMESIZ); 87499ebb4caSwyllys (void) strlcat(subname, name, SUBNAMESIZ); 87599ebb4caSwyllys } 87699ebb4caSwyllys 8772cbed729Swyllys if (email != NULL) { 8782cbed729Swyllys (void) strlcat(subname, ", E=", SUBNAMESIZ); 87999ebb4caSwyllys (void) strlcat(subname, email, SUBNAMESIZ); 88099ebb4caSwyllys } 88199ebb4caSwyllys 88299ebb4caSwyllys out: 88399ebb4caSwyllys if (country) 88499ebb4caSwyllys free(country); 88599ebb4caSwyllys if (state) 88699ebb4caSwyllys free(state); 88799ebb4caSwyllys if (locality) 88899ebb4caSwyllys free(locality); 88999ebb4caSwyllys if (org) 89099ebb4caSwyllys free(org); 89199ebb4caSwyllys if (unit) 89299ebb4caSwyllys free(unit); 89399ebb4caSwyllys if (name) 89499ebb4caSwyllys free(name); 89599ebb4caSwyllys if (email) 89699ebb4caSwyllys free(email); 89799ebb4caSwyllys 89899ebb4caSwyllys if (subname == NULL) 89999ebb4caSwyllys return (-1); 90099ebb4caSwyllys else { 90199ebb4caSwyllys *result = subname; 90299ebb4caSwyllys return (0); 90399ebb4caSwyllys } 90499ebb4caSwyllys } 90599ebb4caSwyllys 90699ebb4caSwyllys /* 90799ebb4caSwyllys * Parse a string of KeyUsage values and convert 90899ebb4caSwyllys * them to the correct KU Bits. 90999ebb4caSwyllys * The field may be marked "critical" by prepending 91099ebb4caSwyllys * "critical:" to the list. 91199ebb4caSwyllys * EX: critical:digitialSignature,keyEncipherment 91299ebb4caSwyllys */ 91399ebb4caSwyllys KMF_RETURN 91499ebb4caSwyllys verify_keyusage(char *kustr, uint16_t *kubits, int *critical) 91599ebb4caSwyllys { 91699ebb4caSwyllys KMF_RETURN ret = KMF_OK; 91799ebb4caSwyllys uint16_t kuval; 91899ebb4caSwyllys char *k; 91999ebb4caSwyllys 92099ebb4caSwyllys *kubits = 0; 921d00756ccSwyllys if (kustr == NULL || strlen(kustr) == 0) 92299ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 92399ebb4caSwyllys 92499ebb4caSwyllys /* Check to see if this is critical */ 925d00756ccSwyllys if (strncasecmp(kustr, "critical:", strlen("critical:")) == 0) { 92699ebb4caSwyllys *critical = TRUE; 92799ebb4caSwyllys kustr += strlen("critical:"); 92899ebb4caSwyllys } else { 92999ebb4caSwyllys *critical = FALSE; 93099ebb4caSwyllys } 93199ebb4caSwyllys 93299ebb4caSwyllys k = strtok(kustr, ","); 93399ebb4caSwyllys while (k != NULL) { 93430a5e8faSwyllys kuval = kmf_string_to_ku(k); 93599ebb4caSwyllys if (kuval == 0) { 93699ebb4caSwyllys *kubits = 0; 93799ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 93899ebb4caSwyllys } 93999ebb4caSwyllys *kubits |= kuval; 94099ebb4caSwyllys k = strtok(NULL, ","); 94199ebb4caSwyllys } 94299ebb4caSwyllys 94399ebb4caSwyllys return (ret); 94499ebb4caSwyllys } 94599ebb4caSwyllys 94699ebb4caSwyllys /* 94799ebb4caSwyllys * Verify the alternate subject label is real or invalid. 94899ebb4caSwyllys * 94999ebb4caSwyllys * The field may be marked "critical" by prepending 95099ebb4caSwyllys * "critical:" to the list. 95199ebb4caSwyllys * EX: "critical:IP=1.2.3.4" 95299ebb4caSwyllys */ 95399ebb4caSwyllys KMF_RETURN 95499ebb4caSwyllys verify_altname(char *arg, KMF_GENERALNAMECHOICES *type, int *critical) 95599ebb4caSwyllys { 95699ebb4caSwyllys char *p; 95799ebb4caSwyllys KMF_RETURN rv = KMF_OK; 95899ebb4caSwyllys 95999ebb4caSwyllys /* Check to see if this is critical */ 960d00756ccSwyllys if (strncasecmp(arg, "critical:", strlen("critical:")) == 0) { 96199ebb4caSwyllys *critical = TRUE; 96299ebb4caSwyllys arg += strlen("critical:"); 96399ebb4caSwyllys } else { 96499ebb4caSwyllys *critical = FALSE; 96599ebb4caSwyllys } 96699ebb4caSwyllys 96799ebb4caSwyllys /* Make sure there is an "=" sign */ 96899ebb4caSwyllys p = strchr(arg, '='); 96999ebb4caSwyllys if (p == NULL) 97099ebb4caSwyllys return (KMF_ERR_BAD_PARAMETER); 97199ebb4caSwyllys 97299ebb4caSwyllys p[0] = '\0'; 97399ebb4caSwyllys 97499ebb4caSwyllys if (strcmp(arg, "IP") == 0) 97599ebb4caSwyllys *type = GENNAME_IPADDRESS; 97699ebb4caSwyllys else if (strcmp(arg, "DNS") == 0) 97799ebb4caSwyllys *type = GENNAME_DNSNAME; 97899ebb4caSwyllys else if (strcmp(arg, "EMAIL") == 0) 97999ebb4caSwyllys *type = GENNAME_RFC822NAME; 98099ebb4caSwyllys else if (strcmp(arg, "URI") == 0) 98199ebb4caSwyllys *type = GENNAME_URI; 98299ebb4caSwyllys else if (strcmp(arg, "DN") == 0) 98399ebb4caSwyllys *type = GENNAME_DIRECTORYNAME; 98499ebb4caSwyllys else if (strcmp(arg, "RID") == 0) 98599ebb4caSwyllys *type = GENNAME_REGISTEREDID; 986d00756ccSwyllys else if (strcmp(arg, "KRB") == 0) 987d00756ccSwyllys *type = GENNAME_KRB5PRINC; 988d00756ccSwyllys else if (strcmp(arg, "UPN") == 0) 989d00756ccSwyllys *type = GENNAME_SCLOGON_UPN; 99099ebb4caSwyllys else 99199ebb4caSwyllys rv = KMF_ERR_BAD_PARAMETER; 99299ebb4caSwyllys 99399ebb4caSwyllys p[0] = '='; 99499ebb4caSwyllys 99599ebb4caSwyllys return (rv); 99699ebb4caSwyllys } 99799ebb4caSwyllys 99899ebb4caSwyllys int 99999ebb4caSwyllys get_token_password(KMF_KEYSTORE_TYPE kstype, 100099ebb4caSwyllys char *token_spec, KMF_CREDENTIAL *cred) 100199ebb4caSwyllys { 100299ebb4caSwyllys char prompt[1024]; 100372ca8cc9SWyllys Ingersoll char temptoken[32]; 100499ebb4caSwyllys char *p = NULL; 100572ca8cc9SWyllys Ingersoll char *t = NULL; 1006*47e946e7SWyllys Ingersoll int len; 100799ebb4caSwyllys 1008*47e946e7SWyllys Ingersoll (void) memset(temptoken, 0, sizeof (temptoken)); 100999ebb4caSwyllys if (kstype == KMF_KEYSTORE_PK11TOKEN) { 101099ebb4caSwyllys p = strchr(token_spec, ':'); 101199ebb4caSwyllys if (p != NULL) 101299ebb4caSwyllys *p = 0; 101399ebb4caSwyllys } 1014*47e946e7SWyllys Ingersoll len = strlen(token_spec); 1015*47e946e7SWyllys Ingersoll if (len > sizeof (temptoken)) 1016*47e946e7SWyllys Ingersoll len = sizeof (temptoken); 1017*47e946e7SWyllys Ingersoll 1018*47e946e7SWyllys Ingersoll (void) strncpy(temptoken, token_spec, len); 101972ca8cc9SWyllys Ingersoll 102072ca8cc9SWyllys Ingersoll /* 102172ca8cc9SWyllys Ingersoll * Strip trailing whitespace 102272ca8cc9SWyllys Ingersoll */ 1023*47e946e7SWyllys Ingersoll t = temptoken + (len - 1); 102472ca8cc9SWyllys Ingersoll while (isspace(*t) && t >= temptoken) { 102572ca8cc9SWyllys Ingersoll *t = 0x00; 102672ca8cc9SWyllys Ingersoll t--; 102772ca8cc9SWyllys Ingersoll } 102872ca8cc9SWyllys Ingersoll 102999ebb4caSwyllys /* 103099ebb4caSwyllys * Login to the token first. 103199ebb4caSwyllys */ 103299ebb4caSwyllys (void) snprintf(prompt, sizeof (prompt), 103372ca8cc9SWyllys Ingersoll gettext(DEFAULT_TOKEN_PROMPT), temptoken); 103499ebb4caSwyllys 103599ebb4caSwyllys if (get_pin(prompt, NULL, (uchar_t **)&cred->cred, 103699ebb4caSwyllys (ulong_t *)&cred->credlen) != CKR_OK) { 103799ebb4caSwyllys cred->cred = NULL; 103899ebb4caSwyllys cred->credlen = 0; 103999ebb4caSwyllys } 104099ebb4caSwyllys 104199ebb4caSwyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && p != NULL) 104299ebb4caSwyllys *p = ':'; 104399ebb4caSwyllys return (KMF_OK); 104499ebb4caSwyllys } 104599ebb4caSwyllys 104699ebb4caSwyllys KMF_RETURN 104799ebb4caSwyllys verify_file(char *filename) 104899ebb4caSwyllys { 104999ebb4caSwyllys KMF_RETURN ret = KMF_OK; 105099ebb4caSwyllys int fd; 105199ebb4caSwyllys 105299ebb4caSwyllys /* 105399ebb4caSwyllys * Attempt to open with the EXCL flag so that if 105499ebb4caSwyllys * it already exists, the open will fail. It will 105599ebb4caSwyllys * also fail if the file cannot be created due to 105699ebb4caSwyllys * permissions on the parent directory, or if the 105799ebb4caSwyllys * parent directory itself does not exist. 105899ebb4caSwyllys */ 105999ebb4caSwyllys fd = open(filename, O_CREAT | O_EXCL, 0600); 106099ebb4caSwyllys if (fd == -1) 106199ebb4caSwyllys return (KMF_ERR_OPEN_FILE); 106299ebb4caSwyllys 106399ebb4caSwyllys /* If we were able to create it, delete it. */ 106499ebb4caSwyllys (void) close(fd); 106599ebb4caSwyllys (void) unlink(filename); 106699ebb4caSwyllys 106799ebb4caSwyllys return (ret); 106899ebb4caSwyllys } 106999ebb4caSwyllys 107099ebb4caSwyllys void 107199ebb4caSwyllys display_error(void *handle, KMF_RETURN errcode, char *prefix) 107299ebb4caSwyllys { 107399ebb4caSwyllys KMF_RETURN rv1, rv2; 107499ebb4caSwyllys char *plugin_errmsg = NULL; 107599ebb4caSwyllys char *kmf_errmsg = NULL; 107699ebb4caSwyllys 107730a5e8faSwyllys rv1 = kmf_get_plugin_error_str(handle, &plugin_errmsg); 107830a5e8faSwyllys rv2 = kmf_get_kmf_error_str(errcode, &kmf_errmsg); 107999ebb4caSwyllys 108099ebb4caSwyllys cryptoerror(LOG_STDERR, "%s:", prefix); 108199ebb4caSwyllys if (rv1 == KMF_OK && plugin_errmsg) { 108230a5e8faSwyllys cryptoerror(LOG_STDERR, gettext("keystore error: %s"), 108399ebb4caSwyllys plugin_errmsg); 108430a5e8faSwyllys kmf_free_str(plugin_errmsg); 108599ebb4caSwyllys } 108699ebb4caSwyllys 108799ebb4caSwyllys if (rv2 == KMF_OK && kmf_errmsg) { 108830a5e8faSwyllys cryptoerror(LOG_STDERR, gettext("libkmf error: %s"), 108999ebb4caSwyllys kmf_errmsg); 109030a5e8faSwyllys kmf_free_str(kmf_errmsg); 109199ebb4caSwyllys } 109299ebb4caSwyllys 109399ebb4caSwyllys if (rv1 != KMF_OK && rv2 != KMF_OK) 109499ebb4caSwyllys cryptoerror(LOG_STDERR, gettext("<unknown error>\n")); 109599ebb4caSwyllys 109699ebb4caSwyllys } 1097d00756ccSwyllys 1098d00756ccSwyllys static KMF_RETURN 1099d00756ccSwyllys addToEKUList(EKU_LIST *ekus, int critical, KMF_OID *newoid) 1100d00756ccSwyllys { 1101d00756ccSwyllys if (newoid != NULL && ekus != NULL) { 1102d00756ccSwyllys ekus->eku_count++; 1103d00756ccSwyllys 1104d00756ccSwyllys ekus->critlist = realloc(ekus->critlist, 1105d00756ccSwyllys ekus->eku_count * sizeof (int)); 1106d00756ccSwyllys if (ekus->critlist != NULL) 1107d00756ccSwyllys ekus->critlist[ekus->eku_count-1] = critical; 1108d00756ccSwyllys else 1109d00756ccSwyllys return (KMF_ERR_MEMORY); 1110d00756ccSwyllys 1111d00756ccSwyllys ekus->ekulist = realloc( 1112d00756ccSwyllys ekus->ekulist, ekus->eku_count * sizeof (KMF_OID)); 1113d00756ccSwyllys if (ekus->ekulist != NULL) 1114d00756ccSwyllys ekus->ekulist[ekus->eku_count-1] = *newoid; 1115d00756ccSwyllys else 1116d00756ccSwyllys return (KMF_ERR_MEMORY); 1117d00756ccSwyllys } 1118d00756ccSwyllys return (KMF_OK); 1119d00756ccSwyllys } 1120d00756ccSwyllys 1121d00756ccSwyllys void 1122d00756ccSwyllys free_eku_list(EKU_LIST *ekus) 1123d00756ccSwyllys { 1124d00756ccSwyllys if (ekus != NULL && ekus->eku_count > 0) { 1125d00756ccSwyllys int i; 1126d00756ccSwyllys for (i = 0; i < ekus->eku_count; i++) { 1127d00756ccSwyllys kmf_free_data(&ekus->ekulist[i]); 1128d00756ccSwyllys } 1129d00756ccSwyllys free(ekus->ekulist); 1130d00756ccSwyllys free(ekus->critlist); 1131d00756ccSwyllys } 1132d00756ccSwyllys } 1133d00756ccSwyllys 1134d00756ccSwyllys static KMF_RETURN 1135d00756ccSwyllys parse_ekus(char *ekustr, EKU_LIST *ekus) 1136d00756ccSwyllys { 1137d00756ccSwyllys KMF_RETURN rv = KMF_OK; 1138d00756ccSwyllys KMF_OID *newoid; 1139d00756ccSwyllys int critical; 1140d00756ccSwyllys 1141d00756ccSwyllys if (strncasecmp(ekustr, "critical:", 1142d00756ccSwyllys strlen("critical:")) == 0) { 1143d00756ccSwyllys critical = TRUE; 1144d00756ccSwyllys ekustr += strlen("critical:"); 1145d00756ccSwyllys } else { 1146d00756ccSwyllys critical = FALSE; 1147d00756ccSwyllys } 1148d00756ccSwyllys newoid = kmf_ekuname_to_oid(ekustr); 1149d00756ccSwyllys if (newoid != NULL) { 1150d00756ccSwyllys rv = addToEKUList(ekus, critical, newoid); 1151d00756ccSwyllys free(newoid); 1152d00756ccSwyllys } else { 1153d00756ccSwyllys rv = PK_ERR_USAGE; 1154d00756ccSwyllys } 1155d00756ccSwyllys 1156d00756ccSwyllys return (rv); 1157d00756ccSwyllys } 1158d00756ccSwyllys 1159d00756ccSwyllys KMF_RETURN 1160d00756ccSwyllys verify_ekunames(char *ekuliststr, EKU_LIST **ekulist) 1161d00756ccSwyllys { 1162d00756ccSwyllys KMF_RETURN rv = KMF_OK; 1163d00756ccSwyllys char *p; 1164d00756ccSwyllys EKU_LIST *ekus = NULL; 1165d00756ccSwyllys 1166d00756ccSwyllys if (ekuliststr == NULL || strlen(ekuliststr) == 0) 1167d00756ccSwyllys return (0); 1168d00756ccSwyllys 1169d00756ccSwyllys /* 1170d00756ccSwyllys * The list should be comma separated list of EKU Names. 1171d00756ccSwyllys */ 1172d00756ccSwyllys p = strtok(ekuliststr, ","); 1173d00756ccSwyllys 1174d00756ccSwyllys /* If no tokens found, then maybe it's just a single EKU value */ 1175d00756ccSwyllys if (p == NULL) { 1176d00756ccSwyllys rv = parse_ekus(ekuliststr, ekus); 1177d00756ccSwyllys } 1178d00756ccSwyllys 1179d00756ccSwyllys while (p != NULL) { 1180d00756ccSwyllys rv = parse_ekus(p, ekus); 1181d00756ccSwyllys 1182d00756ccSwyllys if (rv != KMF_OK) 1183d00756ccSwyllys break; 1184d00756ccSwyllys p = strtok(NULL, ","); 1185d00756ccSwyllys } 1186d00756ccSwyllys 1187d00756ccSwyllys if (rv != KMF_OK) 1188d00756ccSwyllys free_eku_list(ekus); 1189d00756ccSwyllys else 1190d00756ccSwyllys *ekulist = ekus; 1191d00756ccSwyllys 1192d00756ccSwyllys return (rv); 1193d00756ccSwyllys } 1194fa60c371Swyllys 1195fa60c371Swyllys KMF_RETURN 1196fa60c371Swyllys token_auth_needed(KMF_HANDLE_T handle, char *tokenlabel, int *auth) 1197fa60c371Swyllys { 1198fa60c371Swyllys CK_TOKEN_INFO info; 1199fa60c371Swyllys CK_SLOT_ID slot; 1200fa60c371Swyllys CK_RV ckrv; 1201fa60c371Swyllys KMF_RETURN rv; 1202fa60c371Swyllys 1203fa60c371Swyllys *auth = 0; 1204fa60c371Swyllys rv = kmf_pk11_token_lookup(handle, tokenlabel, &slot); 1205fa60c371Swyllys if (rv != KMF_OK) 1206fa60c371Swyllys return (rv); 1207fa60c371Swyllys 1208fa60c371Swyllys ckrv = C_GetTokenInfo(slot, &info); 1209fa60c371Swyllys if (ckrv != KMF_OK) 1210fa60c371Swyllys return (KMF_ERR_INTERNAL); 1211fa60c371Swyllys 1212fa60c371Swyllys *auth = (info.flags & CKF_LOGIN_REQUIRED); 1213fa60c371Swyllys 1214fa60c371Swyllys return (KMF_OK); 1215fa60c371Swyllys } 1216